Bladeren bron

Refactor and extract ViewThemeUtils to common library

Signed-off-by: Álvaro Brey <alvaro.brey@nextcloud.com>
Álvaro Brey 2 jaren geleden
bovenliggende
commit
704df25a6d
61 gewijzigde bestanden met toevoegingen van 488 en 1075 verwijderingen
  1. 0 3
      .idea/codeStyles/Project.xml
  2. 2 2
      app/build.gradle
  3. 3 3
      app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt
  4. 1 1
      app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt
  5. 2 2
      app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java
  6. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java
  7. 8 8
      app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java
  8. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java
  9. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java
  10. 3 5
      app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt
  11. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java
  12. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt
  13. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt
  14. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt
  15. 2 2
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt
  16. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt
  17. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java
  18. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt
  19. 4 4
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt
  20. 6 6
      app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt
  21. 1 1
      app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt
  22. 8 7
      app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt
  23. 4 4
      app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt
  24. 15 12
      app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt
  25. 28 20
      app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt
  26. 6 6
      app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt
  27. 6 6
      app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt
  28. 6 6
      app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt
  29. 3 3
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt
  30. 1 1
      app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt
  31. 1 1
      app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt
  32. 3 3
      app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt
  33. 1 1
      app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt
  34. 10 10
      app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt
  35. 1 1
      app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt
  36. 5 5
      app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt
  37. 4 4
      app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt
  38. 7 7
      app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt
  39. 5 5
      app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt
  40. 2 2
      app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt
  41. 4 4
      app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt
  42. 1 1
      app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt
  43. 1 1
      app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt
  44. 14 9
      app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt
  45. 10 10
      app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java
  46. 1 1
      app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt
  47. 1 1
      app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt
  48. 2 2
      app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt
  49. 1 1
      app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt
  50. 7 7
      app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt
  51. 2 2
      app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt
  52. 4 4
      app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java
  53. 240 0
      app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt
  54. 18 818
      app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt
  55. 1 1
      app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java
  56. 3 3
      app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java
  57. 0 33
      app/src/main/java/com/nextcloud/talk/utils/ui/PlatformThemeUtil.kt
  58. 0 3
      app/src/main/res/values-night/colors.xml
  59. 1 3
      app/src/main/res/values/colors.xml
  60. 0 2
      app/src/main/res/values/dimens.xml
  61. 6 5
      settings.gradle

+ 0 - 3
.idea/codeStyles/Project.xml

@@ -66,9 +66,6 @@
     <MarkdownNavigatorCodeStyleSettings>
       <option name="RIGHT_MARGIN" value="120" />
     </MarkdownNavigatorCodeStyleSettings>
-    <XML>
-      <option name="XML_LEGACY_SETTINGS_IMPORTED" value="true" />
-    </XML>
     <codeStyleSettings language="JAVA">
       <option name="ALIGN_MULTILINE_PARAMETERS_IN_CALLS" value="true" />
       <option name="ALIGN_MULTILINE_METHOD_BRACKETS" value="true" />

+ 2 - 2
app/build.gradle

@@ -332,8 +332,8 @@ dependencies {
 
     // implementation 'androidx.activity:activity-ktx:1.4.0'
 
-    //
-    implementation 'com.github.nextcloud.android-common:ui:4da3363e61ed646e091754147558ee3be346abc5'
+    // TODO substitute for tag after first common release
+    implementation 'com.github.nextcloud.android-common:ui:82f6da3e9638e7578a8df8f6e52884e2923b2760'
 }
 
 task installGitHooks(type: Copy, group: "development") {

+ 3 - 3
app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt

@@ -117,7 +117,7 @@ open class BaseActivity : AppCompatActivity() {
             )
 
             val dialogBuilder = MaterialAlertDialogBuilder(this)
-                .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_security_white_24dp))
+                .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_security_white_24dp))
                 .setTitle(R.string.nc_certificate_dialog_title)
                 .setMessage(dialogText)
                 .setPositiveButton(R.string.nc_yes) { _, _ ->
@@ -128,11 +128,11 @@ open class BaseActivity : AppCompatActivity() {
                     sslErrorHandler?.cancel()
                 }
 
-            viewThemeUtils.colorMaterialAlertDialogBackground(context, dialogBuilder)
+            viewThemeUtils.dialog.colorMaterialAlertDialogBackground(context, dialogBuilder)
 
             val dialog = dialogBuilder.show()
 
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )

+ 1 - 1
app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt

@@ -104,7 +104,7 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
         supportActionBar?.title = fileName
         supportActionBar?.setDisplayHomeAsUpEnabled(true)
 
-        viewThemeUtils.themeStatusBar(this, binding.textviewToolbar)
+        viewThemeUtils.platform.themeStatusBar(this, binding.textviewToolbar)
 
         if (resources != null) {
             DisplayUtils.applyColorToNavigationBar(

+ 2 - 2
app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java

@@ -105,8 +105,8 @@ public class TakePhotoActivity extends AppCompatActivity {
 
         setContentView(binding.getRoot());
 
-        viewThemeUtils.themeFAB(binding.takePhoto);
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.send);
+        viewThemeUtils.material.themeFAB(binding.takePhoto);
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.send);
 
         cameraProviderFuture = ProcessCameraProvider.getInstance(this);
         cameraProviderFuture.addListener(() -> {

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/items/ContactItem.java

@@ -113,7 +113,7 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
         holder.binding.avatarDraweeView.setController(null);
 
         if (participant.getSelected()) {
-            viewThemeUtils.colorImageView(holder.binding.checkedImageView);
+            viewThemeUtils.platform.colorImageView(holder.binding.checkedImageView);
             holder.binding.checkedImageView.setVisibility(View.VISIBLE);
         } else {
             holder.binding.checkedImageView.setVisibility(View.GONE);
@@ -206,7 +206,7 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
             holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
                 DisplayUtils.getRoundedDrawable(
-                    viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView,
+                    viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
                                                           roundPlaceholderDrawable)));
         } else {
             holder.binding.avatarDraweeView.setImageResource(fallbackImageResource);

+ 8 - 8
app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java

@@ -143,7 +143,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                                                                         null));
 
         if (adapter.hasFilter()) {
-            viewThemeUtils.highlightText(holder.binding.dialogName,
+            viewThemeUtils.platform.highlightText(holder.binding.dialogName,
                                          conversation.getDisplayName(),
                                          String.valueOf(adapter.getFilter(String.class)));
         } else {
@@ -168,16 +168,16 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                 R.color.conversation_unread_bubble_text);
 
             if (conversation.getType() == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
-                viewThemeUtils.colorChipBackground(holder.binding.dialogUnreadBubble);
+                viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
             } else if (conversation.getUnreadMention()) {
                 if (CapabilitiesUtilNew.hasSpreedFeatureCapability(user, "direct-mention-flag")) {
                     if (conversation.getUnreadMentionDirect()) {
-                        viewThemeUtils.colorChipBackground(holder.binding.dialogUnreadBubble);
+                        viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
                     } else {
-                        viewThemeUtils.colorChipOutlined(holder.binding.dialogUnreadBubble, 6.0f);
+                        viewThemeUtils.material.colorChipOutlined(holder.binding.dialogUnreadBubble, 6.0f);
                     }
                 } else {
-                    viewThemeUtils.colorChipBackground(holder.binding.dialogUnreadBubble);
+                    viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble);
                 }
             } else {
                 holder.binding.dialogUnreadBubble.setChipBackgroundColor(lightBubbleFillColor);
@@ -266,7 +266,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                         holder.binding.dialogAvatar.setImageDrawable(
                             DisplayUtils.getRoundedDrawable(
-                                viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar,
+                                viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
                                                                       R.drawable.ic_avatar_document)));
                     } else {
                         holder.binding.dialogAvatar.setImageDrawable(
@@ -316,7 +316,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                         holder.binding.dialogAvatar.setImageDrawable(
                             DisplayUtils.getRoundedDrawable(
-                                viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar,
+                                viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
                                                                       R.drawable.ic_avatar_group)));
                     } else {
                         holder.binding.dialogAvatar.setImageDrawable(
@@ -327,7 +327,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
                     if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                         holder.binding.dialogAvatar.setImageDrawable(
                             DisplayUtils.getRoundedDrawable(
-                                viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar,
+                                viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.dialogAvatar,
                                                                       R.drawable.ic_avatar_link)));
                     } else {
                         holder.binding.dialogAvatar.setImageDrawable(

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java

@@ -74,7 +74,7 @@ public class GenericTextHeaderItem extends AbstractHeaderItem<GenericTextHeaderI
             Log.d(TAG, "We have payloads, so ignoring!");
         } else {
             holder.binding.titleTextView.setText(title);
-            viewThemeUtils.colorPrimaryTextViewElement(holder.binding.titleTextView);
+            viewThemeUtils.platform.colorPrimaryTextViewElement(holder.binding.titleTextView);
         }
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/items/MentionAutocompleteItem.java

@@ -153,7 +153,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
                     DisplayUtils.getRoundedDrawable(
-                        viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView,
+                        viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
                                                               R.drawable.ic_avatar_group)));
             } else {
                 holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);

+ 3 - 5
app/src/main/java/com/nextcloud/talk/adapters/items/MessageResultItem.kt

@@ -22,7 +22,6 @@
 package com.nextcloud.talk.adapters.items
 
 import android.content.Context
-import android.text.SpannableString
 import android.view.View
 import androidx.recyclerview.widget.RecyclerView
 import com.nextcloud.talk.R
@@ -77,12 +76,11 @@ data class MessageResultItem constructor(
     }
 
     private fun bindMessageExcerpt(holder: ViewHolder) {
-        val highlightedSpan = viewThemeUtils.createHighlightedSpan(
-            holder.binding.messageExcerpt.context,
-            SpannableString(messageEntry.messageExcerpt),
+        viewThemeUtils.platform.highlightText(
+            holder.binding.messageExcerpt,
+            messageEntry.messageExcerpt,
             messageEntry.searchTerm
         )
-        holder.binding.messageExcerpt.text = highlightedSpan
     }
 
     private fun loadImage(holder: ViewHolder) {

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/items/ParticipantItem.java

@@ -155,7 +155,7 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
                     DisplayUtils.getRoundedDrawable(
-                        viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView,
+                        viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
                                                               R.drawable.ic_avatar_group)));
             } else {
                 holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);
@@ -164,7 +164,7 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
             if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                 holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
                     DisplayUtils.getRoundedDrawable(
-                        viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView,
+                        viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
                                                               R.drawable.ic_avatar_mail)));
             } else {
                 holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail);

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt

@@ -161,7 +161,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@@ -187,7 +187,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
                 .setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast))
 
             if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
-                viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
+                viewThemeUtils.platform.colorPrimaryView(binding.messageQuote.quoteColoredView)
             } else {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
             }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt

@@ -191,7 +191,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@@ -217,7 +217,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
                 .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
 
             if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
-                viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
+                viewThemeUtils.platform.colorPrimaryView(binding.messageQuote.quoteColoredView)
             } else {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
             }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt

@@ -95,8 +95,8 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
 
         updateDownloadState(message)
         binding.seekbar.max = message.voiceMessageDuration
-        viewThemeUtils.themeHorizontalSeekBar(binding.seekbar)
-        viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
+        viewThemeUtils.platform.themeHorizontalSeekBar(binding.seekbar)
+        viewThemeUtils.platform.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
 
         if (message.isPlayingVoiceMessage) {
             showPlayButton()
@@ -266,7 +266,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@@ -292,7 +292,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
                 .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
 
             if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
-                viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
+                viewThemeUtils.platform.colorPrimaryView(binding.messageQuote.quoteColoredView)
             } else {
                 binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
             }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt

@@ -87,7 +87,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
             binding.messageAuthor.visibility = View.GONE
         }
 
-        viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
 
         itemView.isSelected = false
 
@@ -163,7 +163,7 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
         binding.messageQuote.quotedMessage.text = parentChatMessage.text
 
         if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
-            viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
+            viewThemeUtils.platform.colorPrimaryView(binding.messageQuote.quoteColoredView)
         } else {
             binding.messageQuote.quoteColoredView.setBackgroundColor(
                 ContextCompat.getColor(binding.messageQuote.quoteColoredView.context, R.color.high_emphasis_text)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt

@@ -156,7 +156,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
     }
 
     private fun setBubbleOnChatMessage(message: ChatMessage) {
-        viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     private fun processMessageParameters(

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java

@@ -150,7 +150,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
         }
 
         progressBar = getProgressBar();
-        viewThemeUtils.colorCircularProgressBar(getProgressBar());
+        viewThemeUtils.platform.colorCircularProgressBar(getProgressBar());
         image = getImage();
         clickView = getImage();
         getMessageText().setVisibility(View.VISIBLE);
@@ -167,9 +167,9 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
                 progressBar = getPreviewContactProgressBar();
                 getMessageText().setVisibility(View.INVISIBLE);
                 clickView = getPreviewContactContainer();
-                viewThemeUtils.colorContactChatItemBackground(getPreviewContactContainer());
-                viewThemeUtils.colorContactChatItemName(getPreviewContactName());
-                viewThemeUtils.colorCircularProgressBarOnPrimaryContainer(getPreviewContactProgressBar());
+                viewThemeUtils.talk.colorContactChatItemBackground(getPreviewContactContainer());
+                viewThemeUtils.talk.colorContactChatItemName(getPreviewContactName());
+                viewThemeUtils.platform.colorCircularProgressBarOnPrimaryContainer(getPreviewContactProgressBar());
             } else {
                 getPreviewContainer().setVisibility(View.VISIBLE);
                 getPreviewContactContainer().setVisibility(View.GONE);

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt

@@ -212,9 +212,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
             binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
                 ?: context!!.getText(R.string.nc_nick_guest)
             binding.messageQuote.quotedMessage.text = parentChatMessage.text
-            viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
-            viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
-            viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
+            viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
+            viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
+            viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
 
             binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
         } else {
@@ -223,7 +223,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     private fun openGeoLink() {

+ 4 - 4
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt

@@ -176,9 +176,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
             binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
                 ?: context.getText(R.string.nc_nick_guest)
             binding.messageQuote.quotedMessage.text = parentChatMessage.text
-            viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
-            viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
-            viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
+            viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
+            viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
+            viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
 
             binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
         } else {
@@ -187,7 +187,7 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     fun assignReactionInterface(reactionsInterface: ReactionsInterface) {

+ 6 - 6
app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt

@@ -90,8 +90,8 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
 
         updateDownloadState(message)
         binding.seekbar.max = message.voiceMessageDuration
-        viewThemeUtils.themeHorizontalSeekBar(binding.seekbar)
-        viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
+        viewThemeUtils.platform.themeHorizontalSeekBar(binding.seekbar)
+        viewThemeUtils.platform.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
 
         handleIsPlayingVoiceMessageState(message)
 
@@ -263,9 +263,9 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
             binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
                 ?: context!!.getText(R.string.nc_nick_guest)
             binding.messageQuote.quotedMessage.text = parentChatMessage.text
-            viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
-            viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
-            viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
+            viewThemeUtils.talk.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
+            viewThemeUtils.talk.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
+            viewThemeUtils.talk.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
 
             binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
         } else {
@@ -274,7 +274,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
     }
 
     private fun colorizeMessageBubble(message: ChatMessage) {
-        viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
+        viewThemeUtils.talk.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
     }
 
     fun assignVoiceMessageInterface(voiceMessageInterface: VoiceMessageInterface) {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt

@@ -112,7 +112,7 @@ class Reaction {
             } else {
                 layoutInfo.viewThemeUtils.getScheme(emojiWithAmountWrapper.context).primaryContainer
             }
-            layoutInfo.viewThemeUtils.setCheckedBackground(emojiWithAmountWrapper, color)
+            layoutInfo.viewThemeUtils.talk.setCheckedBackground(emojiWithAmountWrapper, color)
 
             emojiWithAmountWrapper.setPaddingRelative(
                 layoutInfo.paddingSide,

+ 8 - 7
app/src/main/java/com/nextcloud/talk/controllers/ChatController.kt

@@ -653,7 +653,7 @@ class ChatController(args: Bundle) :
             }
         }
 
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.popupBubbleView)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.popupBubbleView)
 
         binding.messageInputView.setPadding(0, 0, 0, 0)
 
@@ -877,7 +877,7 @@ class ChatController(args: Bundle) :
                 .nc_description_send_message_button
         )
 
-        viewThemeUtils.colorImageView(binding.messageInputView.button)
+        viewThemeUtils.platform.colorImageView(binding.messageInputView.button)
 
         if (currentConversation != null && currentConversation?.roomId != null) {
             loadAvatarForStatusBar()
@@ -1433,14 +1433,14 @@ class ChatController(args: Bundle) :
                             // unused atm
                         }
 
-                    viewThemeUtils.colorMaterialAlertDialogBackground(
+                    viewThemeUtils.dialog.colorMaterialAlertDialogBackground(
                         binding.messageInputView.context,
                         materialAlertDialogBuilder
                     )
 
                     val dialog = materialAlertDialogBuilder.show()
 
-                    viewThemeUtils.colorTextButtons(
+                    viewThemeUtils.platform.colorTextButtons(
                         dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                         dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                     )
@@ -1772,7 +1772,8 @@ class ChatController(args: Bundle) :
             cancelReply()
         }
 
-        viewThemeUtils.themeImageButton(binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton))
+        viewThemeUtils.platform
+            .themeImageButton(binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton))
 
         cancelNotificationsForCurrentConversation()
 
@@ -2523,12 +2524,12 @@ class ChatController(args: Bundle) :
         super.onCreateOptionsMenu(menu, inflater)
         inflater.inflate(R.menu.menu_conversation, menu)
 
-        viewThemeUtils.colorToolbarMenuIcon(
+        viewThemeUtils.platform.colorToolbarMenuIcon(
             binding.messageInputView.context,
             menu.findItem(R.id.conversation_voice_call)
         )
 
-        viewThemeUtils.colorToolbarMenuIcon(
+        viewThemeUtils.platform.colorToolbarMenuIcon(
             binding.messageInputView.context,
             menu.findItem(R.id.conversation_video_call)
         )

+ 4 - 4
app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt

@@ -334,7 +334,7 @@ class ContactsController(args: Bundle) :
             val searchManager: SearchManager? = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager?
             if (searchItem != null) {
                 searchView = MenuItemCompat.getActionView(searchItem) as SearchView
-                viewThemeUtils.themeSearchView(searchView!!)
+                viewThemeUtils.talk.themeSearchView(searchView!!)
                 searchView!!.maxWidth = Int.MAX_VALUE
                 searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
                 var imeOptions: Int = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
@@ -380,7 +380,7 @@ class ContactsController(args: Bundle) :
         super.onPrepareOptionsMenu(menu)
 
         if (searchItem != null) {
-            viewThemeUtils.colorToolbarMenuIcon(
+            viewThemeUtils.platform.colorToolbarMenuIcon(
                 binding.titleTextView.context,
                 searchItem!!
             )
@@ -629,7 +629,7 @@ class ContactsController(args: Bundle) :
         binding.controllerGenericRv.recyclerView.adapter = adapter
         binding.controllerGenericRv.swipeRefreshLayout.setOnRefreshListener { fetchData() }
 
-        viewThemeUtils.themeSwipeRefreshLayout(binding.controllerGenericRv.swipeRefreshLayout)
+        viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.controllerGenericRv.swipeRefreshLayout)
 
         binding.joinConversationViaLink.joinConversationViaLinkImageView
             .background
@@ -638,7 +638,7 @@ class ContactsController(args: Bundle) :
                 PorterDuff.Mode.SRC_IN
             )
 
-        viewThemeUtils.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink)
+        viewThemeUtils.platform.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink)
         disengageProgressBar()
     }
 

+ 15 - 12
app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt

@@ -201,7 +201,7 @@ class ConversationInfoController(args: Bundle) :
                 binding.notificationSettingsView.conversationInfoPriorityConversation,
                 binding.guestAccessView.guestAccessAllowSwitch,
                 binding.guestAccessView.guestAccessPasswordSwitch
-            ).forEach(viewThemeUtils::colorSwitchPreference)
+            ).forEach(viewThemeUtils.talk::colorSwitchPreference)
         }
     }
 
@@ -218,7 +218,7 @@ class ConversationInfoController(args: Bundle) :
                 binding.guestAccessView.guestAccessCategory,
                 binding.webinarInfoView.conversationInfoWebinar,
                 binding.notificationSettingsView.notificationSettingsCategory
-            ).forEach(viewThemeUtils::colorPreferenceCategory)
+            ).forEach(viewThemeUtils.talk::colorPreferenceCategory)
         }
     }
 
@@ -238,7 +238,7 @@ class ConversationInfoController(args: Bundle) :
 
         binding.addParticipantsAction.visibility = GONE
 
-        viewThemeUtils.colorCircularProgressBar(binding.progressBar)
+        viewThemeUtils.platform.colorCircularProgressBar(binding.progressBar)
     }
 
     private fun setupWebinaryView() {
@@ -376,7 +376,7 @@ class ConversationInfoController(args: Bundle) :
     private fun showDeleteConversationDialog() {
         if (activity != null) {
             val dialogBuilder = MaterialAlertDialogBuilder(binding.conversationInfoName.context)
-                .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
+                .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
                 .setTitle(R.string.nc_delete_call)
                 .setMessage(R.string.nc_delete_conversation_more)
                 .setPositiveButton(R.string.nc_delete) { _, _ ->
@@ -385,9 +385,10 @@ class ConversationInfoController(args: Bundle) :
                 .setNegativeButton(R.string.nc_cancel) { _, _ ->
                     // unused atm
                 }
-            viewThemeUtils.colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder)
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder)
             val dialog = dialogBuilder.show()
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )
@@ -547,7 +548,7 @@ class ConversationInfoController(args: Bundle) :
     private fun showClearHistoryDialog() {
         if (activity != null) {
             val dialogBuilder = MaterialAlertDialogBuilder(binding.conversationInfoName.context)
-                .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
+                .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
                 .setTitle(R.string.nc_clear_history)
                 .setMessage(R.string.nc_clear_history_warning)
                 .setPositiveButton(R.string.nc_delete_all) { _, _ ->
@@ -556,9 +557,10 @@ class ConversationInfoController(args: Bundle) :
                 .setNegativeButton(R.string.nc_cancel) { _, _ ->
                     // unused atm
                 }
-            viewThemeUtils.colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder)
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(binding.conversationInfoName.context, dialogBuilder)
             val dialog = dialogBuilder.show()
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )
@@ -783,7 +785,8 @@ class ConversationInfoController(args: Bundle) :
                         DisplayUtils.getImageRequestForUrl(
                             ApiUtils.getUrlForAvatar(
                                 conversationUser!!.baseUrl,
-                                conversation!!.name, true
+                                conversation!!.name,
+                                true
                             ),
                             conversationUser
                         )
@@ -795,7 +798,7 @@ class ConversationInfoController(args: Bundle) :
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                     binding.avatarImage.hierarchy.setPlaceholderImage(
                         DisplayUtils.getRoundedDrawable(
-                            viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_group)
+                            viewThemeUtils.talk.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_group)
                         )
                     )
                 } else {
@@ -808,7 +811,7 @@ class ConversationInfoController(args: Bundle) :
                 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
                     binding.avatarImage.hierarchy.setPlaceholderImage(
                         DisplayUtils.getRoundedDrawable(
-                            viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_link)
+                            viewThemeUtils.talk.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_link)
                         )
                     )
                 } else {

+ 28 - 20
app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.kt

@@ -274,7 +274,8 @@ class ConversationsListController(bundle: Bundle) :
             credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
             if (activity != null && activity is MainActivity) {
                 loadUserAvatar((activity as MainActivity?)!!.binding.switchAccountButton)
-                viewThemeUtils.colorMaterialTextButton((activity as MainActivity?)!!.binding.switchAccountButton)
+                viewThemeUtils.material
+                    .colorMaterialTextButton((activity as MainActivity?)!!.binding.switchAccountButton)
             }
             fetchData()
         }
@@ -295,7 +296,7 @@ class ConversationsListController(bundle: Bundle) :
             val searchManager = activity!!.getSystemService(Context.SEARCH_SERVICE) as SearchManager?
             if (searchItem != null) {
                 searchView = MenuItemCompat.getActionView(searchItem) as SearchView
-                viewThemeUtils.themeSearchView(searchView!!)
+                viewThemeUtils.talk.themeSearchView(searchView!!)
                 searchView!!.maxWidth = Int.MAX_VALUE
                 searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
                 var imeOptions = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN
@@ -353,14 +354,14 @@ class ConversationsListController(bundle: Bundle) :
                 }
                 activity.binding.searchText.setOnClickListener {
                     showSearchView(activity, searchView, searchItem)
-                    viewThemeUtils.themeStatusBar(activity, searchView!!)
+                    viewThemeUtils.platform.themeStatusBar(activity, searchView!!)
                 }
             }
             searchView!!.setOnCloseListener {
                 if (TextUtils.isEmpty(searchView!!.query.toString())) {
                     searchView!!.onActionViewCollapsed()
                     if (activity != null) {
-                        viewThemeUtils.resetStatusBar(activity, searchView!!)
+                        viewThemeUtils.platform.resetStatusBar(activity)
                     }
                 } else {
                     searchView!!.post { searchView!!.setQuery(TAG, true) }
@@ -400,7 +401,8 @@ class ConversationsListController(bundle: Bundle) :
                         mainActivity.binding.toolbar.visibility = View.GONE
                         mainActivity.binding.searchToolbar.visibility = View.VISIBLE
                         if (resources != null) {
-                            viewThemeUtils.resetStatusBar(mainActivity, mainActivity.binding.searchToolbar)
+                            viewThemeUtils.platform
+                                .resetStatusBar(mainActivity)
                         }
                     }
                     val layoutManager = binding.recyclerView.layoutManager as SmoothScrollLinearLayoutManager?
@@ -664,13 +666,13 @@ class ConversationsListController(bundle: Bundle) :
             false
         }
         binding.swipeRefreshLayoutView.setOnRefreshListener { fetchData() }
-        viewThemeUtils.themeSwipeRefreshLayout(binding.swipeRefreshLayoutView)
+        viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshLayoutView)
         binding.emptyLayout.setOnClickListener { showNewConversationsScreen() }
         binding.floatingActionButton.setOnClickListener {
             run(context)
             showNewConversationsScreen()
         }
-        viewThemeUtils.themeFAB(binding.floatingActionButton)
+        viewThemeUtils.material.themeFAB(binding.floatingActionButton)
         if (activity != null && activity is MainActivity) {
             val activity = activity as MainActivity?
             activity!!.binding.switchAccountButton.setOnClickListener {
@@ -695,7 +697,7 @@ class ConversationsListController(bundle: Bundle) :
                 nextUnreadConversationScrollPosition
             )
         }
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.newMentionPopupBubble)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.newMentionPopupBubble)
     }
 
     @Suppress("Detekt.TooGenericExceptionCaught")
@@ -937,7 +939,7 @@ class ConversationsListController(bundle: Bundle) :
                 )
             }
             val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context)
-                .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.upload))
+                .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.upload))
                 .setTitle(confirmationQuestion)
                 .setMessage(fileNamesWithLineBreaks.toString())
                 .setPositiveButton(R.string.nc_yes) { _, _ ->
@@ -948,9 +950,10 @@ class ConversationsListController(bundle: Bundle) :
                     Log.d(TAG, "sharing files aborted, going back to share-to screen")
                     showShareToScreen = true
                 }
-            viewThemeUtils.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
             val dialog = dialogBuilder.show()
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )
@@ -1128,7 +1131,10 @@ class ConversationsListController(bundle: Bundle) :
             val conversation = Parcels.unwrap<Conversation>(conversationMenuBundle!!.getParcelable(KEY_ROOM))
             if (conversation != null) {
                 val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context)
-                    .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
+                    .setIcon(
+                        viewThemeUtils.dialog
+                            .colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp)
+                    )
                     .setTitle(R.string.nc_delete_call)
                     .setMessage(R.string.nc_delete_conversation_more)
                     .setPositiveButton(R.string.nc_delete) { _, _ ->
@@ -1144,9 +1150,10 @@ class ConversationsListController(bundle: Bundle) :
                     .setNegativeButton(R.string.nc_cancel) { _, _ ->
                         conversationMenuBundle = null
                     }
-                viewThemeUtils.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
+                viewThemeUtils.dialog
+                    .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
                 val dialog = dialogBuilder.show()
-                viewThemeUtils.colorTextButtons(
+                viewThemeUtils.platform.colorTextButtons(
                     dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                     dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                 )
@@ -1157,7 +1164,7 @@ class ConversationsListController(bundle: Bundle) :
     private fun showUnauthorizedDialog() {
         if (activity != null) {
             val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context)
-                .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
+                .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_delete_black_24dp))
                 .setTitle(R.string.nc_dialog_invalid_password)
                 .setMessage(R.string.nc_dialog_reauth_or_delete)
                 .setCancelable(false)
@@ -1187,9 +1194,10 @@ class ConversationsListController(bundle: Bundle) :
                             .popChangeHandler(VerticalChangeHandler())
                     )
                 }
-            viewThemeUtils.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
+            viewThemeUtils.dialog
+                .colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
             val dialog = dialogBuilder.show()
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )
@@ -1198,7 +1206,7 @@ class ConversationsListController(bundle: Bundle) :
 
     private fun showServerEOLDialog() {
         val dialogBuilder = MaterialAlertDialogBuilder(binding.floatingActionButton.context)
-            .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white))
+            .setIcon(viewThemeUtils.dialog.colorMaterialAlertDialogIcon(context, R.drawable.ic_warning_white))
             .setTitle(R.string.nc_settings_server_eol_title)
             .setMessage(R.string.nc_settings_server_eol)
             .setCancelable(false)
@@ -1229,9 +1237,9 @@ class ConversationsListController(bundle: Bundle) :
                     activity!!.finish()
                 }
             }
-        viewThemeUtils.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.floatingActionButton.context, dialogBuilder)
         val dialog = dialogBuilder.show()
-        viewThemeUtils.colorTextButtons(
+        viewThemeUtils.platform.colorTextButtons(
             dialog.getButton(AlertDialog.BUTTON_POSITIVE),
             dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
         )

+ 6 - 6
app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt

@@ -261,10 +261,10 @@ class ProfileController : BaseController(R.layout.controller_profile) {
     }
 
     private fun colorIcons() {
-        viewThemeUtils.themeFAB(binding.avatarChoose)
-        viewThemeUtils.themeFAB(binding.avatarCamera)
-        viewThemeUtils.themeFAB(binding.avatarUpload)
-        viewThemeUtils.themeFAB(binding.avatarDelete)
+        viewThemeUtils.material.themeFAB(binding.avatarChoose)
+        viewThemeUtils.material.themeFAB(binding.avatarCamera)
+        viewThemeUtils.material.themeFAB(binding.avatarUpload)
+        viewThemeUtils.material.themeFAB(binding.avatarDelete)
     }
 
     private fun isAllEmpty(items: Array<String?>): Boolean {
@@ -755,10 +755,10 @@ class ProfileController : BaseController(R.layout.controller_profile) {
             initUserInfoEditText(holder, item)
 
             holder.binding.icon.contentDescription = item.hint
-            viewThemeUtils.colorImageView(holder.binding.icon)
+            viewThemeUtils.platform.colorImageView(holder.binding.icon)
             if (!TextUtils.isEmpty(item.text) || controller.edit) {
                 holder.binding.userInfoDetailContainer.visibility = View.VISIBLE
-                controller.viewThemeUtils.colorTextInputLayout(holder.binding.userInfoInputLayout)
+                controller.viewThemeUtils.material.colorTextInputLayout(holder.binding.userInfoInputLayout)
                 if (controller.edit &&
                     controller.editableFields.contains(item.field.toString().lowercase())
                 ) {

+ 6 - 6
app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt

@@ -385,14 +385,14 @@ class SettingsController : BaseController(R.layout.controller_settings) {
                     // unused atm
                 }
 
-            viewThemeUtils.colorMaterialAlertDialogBackground(
+            viewThemeUtils.dialog.colorMaterialAlertDialogBackground(
                 binding.messageText.context,
                 materialAlertDialogBuilder
             )
 
             val dialog = materialAlertDialogBuilder.show()
 
-            viewThemeUtils.colorTextButtons(
+            viewThemeUtils.platform.colorTextButtons(
                 dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                 dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
             )
@@ -508,7 +508,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
                 settingsPhoneBookIntegration,
                 settingsReadPrivacy,
                 settingsProxyUseCredentials
-            ).forEach(viewThemeUtils::colorSwitchPreference)
+            ).forEach(viewThemeUtils.talk::colorSwitchPreference)
         }
     }
 
@@ -520,7 +520,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
                 settingsAdvancedCategory,
                 settingsAppearanceCategory,
                 settingsPrivacyCategory
-            ).forEach(viewThemeUtils::colorPreferenceCategory)
+            ).forEach(viewThemeUtils.talk::colorPreferenceCategory)
         }
     }
 
@@ -952,7 +952,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
             .setPositiveButton(context!!.resources.getString(R.string.nc_common_set), null)
             .setNegativeButton(context!!.resources.getString(R.string.nc_common_skip), null)
 
-        viewThemeUtils.colorMaterialAlertDialogBackground(phoneNumberInputLayout.context, dialogBuilder)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(phoneNumberInputLayout.context, dialogBuilder)
 
         val dialog = dialogBuilder.create()
         dialog.setOnShowListener(object : OnShowListener {
@@ -968,7 +968,7 @@ class SettingsController : BaseController(R.layout.controller_settings) {
 
         dialog.show()
 
-        viewThemeUtils.colorTextButtons(
+        viewThemeUtils.platform.colorTextButtons(
             dialog.getButton(AlertDialog.BUTTON_POSITIVE),
             dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
         )

+ 6 - 6
app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.kt

@@ -123,9 +123,9 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul
 
         if (getActivity() != null && getActivity() is MainActivity) {
             activity = getActivity() as MainActivity?
-            viewThemeUtils.themeCardView(activity!!.binding.searchToolbar)
-            viewThemeUtils.themeToolbar(activity.binding.toolbar)
-            viewThemeUtils.themeSearchBarText(activity.binding.searchText)
+            viewThemeUtils.material.themeCardView(activity!!.binding.searchToolbar)
+            viewThemeUtils.material.themeToolbar(activity.binding.toolbar)
+            viewThemeUtils.material.themeSearchBarText(activity.binding.searchText)
         }
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) {
@@ -188,7 +188,7 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul
         val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
         binding.searchToolbar.visibility = View.GONE
         binding.toolbar.visibility = View.VISIBLE
-        viewThemeUtils.colorToolbarOverflowIcon(binding.toolbar)
+        viewThemeUtils.material.colorToolbarOverflowIcon(binding.toolbar)
         layoutParams.scrollFlags = 0
         binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator(
             binding.appBar.context,
@@ -217,9 +217,9 @@ abstract class BaseController(@LayoutRes var layoutRes: Int, args: Bundle? = nul
     private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) {
         if (activity != null && resources != null) {
             if (showSearchBar) {
-                view?.let { viewThemeUtils.resetStatusBar(activity, it) }
+                view?.let { viewThemeUtils.platform.resetStatusBar(activity) }
             } else {
-                view?.let { viewThemeUtils.themeStatusBar(activity, it) }
+                view?.let { viewThemeUtils.platform.themeStatusBar(activity, it) }
             }
         }
     }

+ 3 - 3
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt

@@ -124,7 +124,7 @@ class EntryMenuController(args: Bundle) :
                     rootView = view,
                     editText = binding.textEdit,
                     onEmojiPopupShownListener = {
-                        viewThemeUtils.colorImageView(binding.smileyButton)
+                        viewThemeUtils.platform.colorImageView(binding.smileyButton)
                     },
                     onEmojiPopupDismissListener = {
                         binding.smileyButton.imageTintList = ColorStateList.valueOf(
@@ -157,8 +157,8 @@ class EntryMenuController(args: Bundle) :
             binding.textInputLayout.endIconMode = TextInputLayout.END_ICON_NONE
         }
 
-        viewThemeUtils.colorTextInputLayout(binding.textInputLayout)
-        viewThemeUtils.colorMaterialButtonText(binding.okButton)
+        viewThemeUtils.material.colorTextInputLayout(binding.textInputLayout)
+        viewThemeUtils.material.colorMaterialButtonText(binding.okButton)
 
         binding.textInputLayout.hint = labelText
         binding.textInputLayout.requestFocus()

+ 1 - 1
app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt

@@ -117,7 +117,7 @@ class OperationsMenuController(args: Bundle) : BaseController(
         sharedApplication!!.componentApplication.inject(this)
         currentUser = userManager.currentUser.blockingGet()
 
-        viewThemeUtils.colorCircularProgressBar(binding.progressBar)
+        viewThemeUtils.platform.colorCircularProgressBar(binding.progressBar)
 
         if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) {
             conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt

@@ -50,7 +50,7 @@ class PollCreateOptionViewHolder(
         }
 
         binding.pollOptionTextEdit.setText(pollCreateOptionItem.pollOption)
-        viewThemeUtils.colorTextInputLayout(binding.pollOptionTextInputLayout)
+        viewThemeUtils.material.colorTextInputLayout(binding.pollOptionTextInputLayout)
 
         if (focus) {
             itemsListener.requestFocus(binding.pollOptionTextEdit)

+ 3 - 3
app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt

@@ -34,15 +34,15 @@ class PollResultHeaderViewHolder(
     override fun bind(pollResultItem: PollResultItem, clickListener: PollResultItemClickListener) {
         val item = pollResultItem as PollResultHeaderItem
 
-        viewThemeUtils.colorProgressBar(binding.pollOptionBar)
+        viewThemeUtils.material.colorProgressBar(binding.pollOptionBar)
 
         binding.root.setOnClickListener { clickListener.onClick() }
 
         binding.pollOptionText.text = item.name
         binding.pollOptionPercentText.text = "${item.percent}%"
 
-        viewThemeUtils.colorDialogSupportingText(binding.pollOptionText)
-        viewThemeUtils.colorDialogSupportingText(binding.pollOptionPercentText)
+        viewThemeUtils.dialog.colorDialogSupportingText(binding.pollOptionText)
+        viewThemeUtils.dialog.colorDialogSupportingText(binding.pollOptionPercentText)
 
         if (item.selfVoted) {
             binding.pollOptionText.setTypeface(null, Typeface.BOLD)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt

@@ -47,7 +47,7 @@ class PollResultVoterViewHolder(
 
         binding.pollVoterName.text = item.details.actorDisplayName
         binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details)
-        viewThemeUtils.colorDialogSupportingText(binding.pollVoterName)
+        viewThemeUtils.dialog.colorDialogSupportingText(binding.pollVoterName)
     }
 
     private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? {

+ 10 - 10
app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt

@@ -75,7 +75,7 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener
 
         val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context)
             .setView(binding.root)
-        viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
 
         return dialogBuilder.create()
     }
@@ -101,18 +101,18 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener
     }
 
     private fun themeDialog() {
-        viewThemeUtils.colorPrimaryTextViewElement(binding.pollQuestion)
-        viewThemeUtils.colorPrimaryTextViewElement(binding.pollOptions)
-        viewThemeUtils.colorPrimaryTextViewElement(binding.pollSettings)
+        viewThemeUtils.platform.colorPrimaryTextViewElement(binding.pollQuestion)
+        viewThemeUtils.platform.colorPrimaryTextViewElement(binding.pollOptions)
+        viewThemeUtils.platform.colorPrimaryTextViewElement(binding.pollSettings)
 
-        viewThemeUtils.colorTextInputLayout(binding.pollCreateQuestionTextInputLayout)
+        viewThemeUtils.material.colorTextInputLayout(binding.pollCreateQuestionTextInputLayout)
 
-        viewThemeUtils.colorMaterialButtonText(binding.pollAddOptionsItem)
-        viewThemeUtils.colorMaterialButtonText(binding.pollDismiss)
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollCreateButton)
+        viewThemeUtils.material.colorMaterialButtonText(binding.pollAddOptionsItem)
+        viewThemeUtils.material.colorMaterialButtonText(binding.pollDismiss)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.pollCreateButton)
 
-        viewThemeUtils.themeCheckbox(binding.pollPrivatePollCheckbox)
-        viewThemeUtils.themeCheckbox(binding.pollMultipleAnswersCheckbox)
+        viewThemeUtils.platform.themeCheckbox(binding.pollPrivatePollCheckbox)
+        viewThemeUtils.platform.themeCheckbox(binding.pollMultipleAnswersCheckbox)
     }
 
     private fun setupListeners() {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt

@@ -55,7 +55,7 @@ class PollLoadingFragment : Fragment() {
     ): View {
         binding = DialogPollLoadingBinding.inflate(inflater, container, false)
         binding.root.layoutParams.height = fragmentHeight
-        viewThemeUtils.colorCircularProgressBar(binding.pollLoadingProgressbar)
+        viewThemeUtils.platform.colorCircularProgressBar(binding.pollLoadingProgressbar)
         return binding.root
     }
 

+ 5 - 5
app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt

@@ -72,13 +72,13 @@ class PollMainDialogFragment : DialogFragment() {
 
         val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root)
 
-        viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
 
         val dialog = dialogBuilder.create()
 
         binding.messagePollTitle.text = viewModel.pollTitle
-        viewThemeUtils.colorDialogHeadline(binding.messagePollTitle)
-        viewThemeUtils.colorDialogIcon(binding.messagePollIcon)
+        viewThemeUtils.dialog.colorDialogHeadline(binding.messagePollTitle)
+        viewThemeUtils.dialog.colorDialogIcon(binding.messagePollIcon)
 
         return dialog
     }
@@ -143,7 +143,7 @@ class PollMainDialogFragment : DialogFragment() {
 
     private fun initVotersAmount(showVotersAmount: Boolean, numVoters: Int, showResultSubtitle: Boolean) {
         if (showVotersAmount) {
-            viewThemeUtils.colorDialogSupportingText(binding.pollVotesAmount)
+            viewThemeUtils.dialog.colorDialogSupportingText(binding.pollVotesAmount)
             binding.pollVotesAmount.visibility = View.VISIBLE
             binding.pollVotesAmount.text = resources.getQuantityString(
                 R.plurals.polls_amount_voters,
@@ -155,7 +155,7 @@ class PollMainDialogFragment : DialogFragment() {
         }
 
         if (showResultSubtitle) {
-            viewThemeUtils.colorDialogSupportingText(binding.pollResultsSubtitle)
+            viewThemeUtils.dialog.colorDialogSupportingText(binding.pollResultsSubtitle)
             binding.pollResultsSubtitle.visibility = View.VISIBLE
             binding.pollResultsSubtitleSeperator.visibility = View.VISIBLE
         } else {

+ 4 - 4
app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt

@@ -99,8 +99,8 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener {
     }
 
     private fun themeDialog() {
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.editVoteButton)
-        viewThemeUtils.colorMaterialButtonPrimaryBorderless(binding.pollResultsEndPollButton)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.editVoteButton)
+        viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(binding.pollResultsEndPollButton)
     }
 
     private fun initAdapter() {
@@ -132,14 +132,14 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener {
                     }
                     .setNegativeButton(R.string.nc_cancel, null)
 
-                viewThemeUtils.colorMaterialAlertDialogBackground(
+                viewThemeUtils.dialog.colorMaterialAlertDialogBackground(
                     binding.pollResultsEndPollButton.context,
                     dialogBuilder
                 )
 
                 val dialog = dialogBuilder.show()
 
-                viewThemeUtils.colorTextButtons(
+                viewThemeUtils.platform.colorTextButtons(
                     dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                     dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                 )

+ 7 - 7
app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt

@@ -127,9 +127,9 @@ class PollVoteFragment : Fragment() {
     }
 
     private fun themeDialog() {
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollVoteSubmitButton)
-        viewThemeUtils.colorMaterialButtonText(binding.pollVoteEndPollButton)
-        viewThemeUtils.colorMaterialButtonPrimaryOutlined(binding.pollVoteEditDismiss)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.pollVoteSubmitButton)
+        viewThemeUtils.material.colorMaterialButtonText(binding.pollVoteEndPollButton)
+        viewThemeUtils.material.colorMaterialButtonPrimaryOutlined(binding.pollVoteEditDismiss)
     }
 
     private fun updateDismissEditButton(showDismissEditButton: Boolean) {
@@ -149,7 +149,7 @@ class PollVoteFragment : Fragment() {
                 RadioButton(context).apply { text = option }
             }?.forEachIndexed { index, radioButton ->
                 radioButton.id = index
-                viewThemeUtils.themeRadioButton(radioButton)
+                viewThemeUtils.platform.themeRadioButton(radioButton)
                 makeOptionBoldIfSelfVoted(radioButton, poll, index)
                 binding.pollVoteRadioGroup.addView(radioButton)
 
@@ -170,7 +170,7 @@ class PollVoteFragment : Fragment() {
                     setLayoutParams(layoutParams)
                 }
             }?.forEachIndexed { index, checkBox ->
-                viewThemeUtils.themeCheckbox(checkBox)
+                viewThemeUtils.platform.themeCheckbox(checkBox)
                 checkBox.id = index
                 makeOptionBoldIfSelfVoted(checkBox, poll, index)
                 binding.voteOptionsCheckboxesWrapper.addView(checkBox)
@@ -215,14 +215,14 @@ class PollVoteFragment : Fragment() {
                     }
                     .setNegativeButton(R.string.nc_cancel, null)
 
-                viewThemeUtils.colorMaterialAlertDialogBackground(
+                viewThemeUtils.dialog.colorMaterialAlertDialogBackground(
                     binding.pollVoteEndPollButton.context,
                     dialogBuilder
                 )
 
                 val dialog = dialogBuilder.show()
 
-                viewThemeUtils.colorTextButtons(
+                viewThemeUtils.platform.colorTextButtons(
                     dialog.getButton(AlertDialog.BUTTON_POSITIVE),
                     dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
                 )

+ 5 - 5
app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt

@@ -75,16 +75,16 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
 
         binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater)
         setSupportActionBar(binding.remoteFileBrowserItemsToolbar)
-        viewThemeUtils.themeToolbar(binding.remoteFileBrowserItemsToolbar)
+        viewThemeUtils.material.themeToolbar(binding.remoteFileBrowserItemsToolbar)
         val scheme = viewThemeUtils.getScheme(binding.sortListButtonGroup.context)
         binding.sortListButtonGroup.setBackgroundColor(scheme.surface)
         binding.sortButton.iconTint = ColorStateList.valueOf(scheme.onSurface)
         binding.sortButton.setTextColor(scheme.onSurface)
-        viewThemeUtils.colorMaterialTextButton(binding.sortButton)
+        viewThemeUtils.material.colorMaterialTextButton(binding.sortButton)
         binding.pathNavigationBackButton.iconTint = ColorStateList.valueOf(scheme.onSurface)
         binding.pathNavigationBackButton.setTextColor(scheme.onSurface)
-        viewThemeUtils.colorMaterialTextButton(binding.pathNavigationBackButton)
-        viewThemeUtils.themeStatusBar(this, binding.remoteFileBrowserItemsToolbar)
+        viewThemeUtils.material.colorMaterialTextButton(binding.pathNavigationBackButton)
+        viewThemeUtils.platform.themeStatusBar(this, binding.remoteFileBrowserItemsToolbar)
         setContentView(binding.root)
 
         DisplayUtils.applyColorToNavigationBar(
@@ -100,7 +100,7 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
         initViewModel(mimeTypeSelectionFilter)
 
         binding.swipeRefreshList.setOnRefreshListener(this)
-        viewThemeUtils.themeSwipeRefreshLayout(binding.swipeRefreshList)
+        viewThemeUtils.androidx.themeSwipeRefreshLayout(binding.swipeRefreshList)
 
         binding.pathNavigationBackButton.setOnClickListener { viewModel.navigateUp() }
         binding.sortButton.setOnClickListener { changeSorting() }

+ 2 - 2
app/src/main/java/com/nextcloud/talk/remotefilebrowser/adapters/RemoteFileBrowserItemsListViewHolder.kt

@@ -98,7 +98,7 @@ class RemoteFileBrowserItemsListViewHolder(
         binding.fileIcon
             .hierarchy
             .setPlaceholderImage(
-                viewThemeUtils.getPlaceholderImage(binding.root.context, item.mimeType)
+                viewThemeUtils.talk.getPlaceholderImage(binding.root.context, item.mimeType)
             )
 
         if (item.hasPreview) {
@@ -129,7 +129,7 @@ class RemoteFileBrowserItemsListViewHolder(
     private fun setSelectability() {
         if (selectable) {
             binding.selectFileCheckbox.visibility = View.VISIBLE
-            viewThemeUtils.themeCheckbox(binding.selectFileCheckbox)
+            viewThemeUtils.platform.themeCheckbox(binding.selectFileCheckbox)
         } else {
             binding.selectFileCheckbox.visibility = View.GONE
         }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt

@@ -73,9 +73,9 @@ class SharedItemsActivity : AppCompatActivity() {
         setSupportActionBar(binding.sharedItemsToolbar)
         setContentView(binding.root)
 
-        viewThemeUtils.themeStatusBar(this, binding.sharedItemsToolbar)
-        viewThemeUtils.themeToolbar(binding.sharedItemsToolbar)
-        viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs)
+        viewThemeUtils.platform.themeStatusBar(this, binding.sharedItemsToolbar)
+        viewThemeUtils.material.themeToolbar(binding.sharedItemsToolbar)
+        viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs)
 
         DisplayUtils.applyColorToNavigationBar(
             this.window,
@@ -146,7 +146,7 @@ class SharedItemsActivity : AppCompatActivity() {
             else -> {}
         }
 
-        viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs)
+        viewThemeUtils.material.themeTabLayoutOnSurface(binding.sharedItemsTabs)
     }
 
     private fun clearEmptyLoading() {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/shareditems/adapters/SharedItemsViewHolder.kt

@@ -70,7 +70,7 @@ abstract class SharedItemsViewHolder(
     )
 
     open fun onBind(item: SharedFileItem) {
-        image.hierarchy.setPlaceholderImage(viewThemeUtils.getPlaceholderImage(image.context, item.mimeType))
+        image.hierarchy.setPlaceholderImage(viewThemeUtils.talk.getPlaceholderImage(image.context, item.mimeType))
         if (item.previewAvailable) {
             image.controller = configurePreview(item)
         }

+ 1 - 1
app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt

@@ -53,7 +53,7 @@ class AttachmentDialog(val activity: Activity, var chatController: ChatControlle
         setContentView(dialogAttachmentBinding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialog(dialogAttachmentBinding.root)
+        viewThemeUtils.platform.themeDialog(dialogAttachmentBinding.root)
         initItemsStrings()
         initItemsVisibility()
         initItemsClickListeners()

+ 14 - 9
app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt

@@ -51,7 +51,7 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call
         setContentView(dialogAudioOutputBinding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialogDark(dialogAudioOutputBinding.root)
+        viewThemeUtils.platform.themeDialogDark(dialogAudioOutputBinding.root)
         updateOutputDeviceList()
         initClickListeners()
     }
@@ -92,23 +92,28 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call
     private fun highlightActiveOutputChannel() {
         when (callActivity.audioManager?.currentAudioDevice) {
             WebRtcAudioManager.AudioDevice.BLUETOOTH -> {
-                viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputBluetoothIcon)
-                viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputBluetoothText)
+                viewThemeUtils.platform.colorImageView(dialogAudioOutputBinding.audioOutputBluetoothIcon)
+                viewThemeUtils.platform
+                    .colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputBluetoothText)
             }
 
             WebRtcAudioManager.AudioDevice.SPEAKER_PHONE -> {
-                viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputSpeakerIcon)
-                viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputSpeakerText)
+                viewThemeUtils.platform.colorImageView(dialogAudioOutputBinding.audioOutputSpeakerIcon)
+                viewThemeUtils.platform
+                    .colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputSpeakerText)
             }
 
             WebRtcAudioManager.AudioDevice.EARPIECE -> {
-                viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputEarspeakerIcon)
-                viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputEarspeakerText)
+                viewThemeUtils.platform.colorImageView(dialogAudioOutputBinding.audioOutputEarspeakerIcon)
+                viewThemeUtils.platform
+                    .colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputEarspeakerText)
             }
 
             WebRtcAudioManager.AudioDevice.WIRED_HEADSET -> {
-                viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputWiredHeadsetIcon)
-                viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputWiredHeadsetText)
+                viewThemeUtils.platform
+                    .colorImageView(dialogAudioOutputBinding.audioOutputWiredHeadsetIcon)
+                viewThemeUtils.platform
+                    .colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputWiredHeadsetText)
             }
 
             else -> Log.d(TAG, "AudioOutputDialog doesn't know this AudioDevice")

+ 10 - 10
app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java

@@ -129,7 +129,7 @@ public class ChooseAccountDialogFragment extends DialogFragment {
             binding.currentAccount.ticker.setVisibility(View.GONE);
             binding.currentAccount.account.setText((Uri.parse(user.getBaseUrl()).getHost()));
 
-            viewThemeUtils.colorImageView(binding.currentAccount.accountMenu);
+            viewThemeUtils.platform.colorImageView(binding.currentAccount.accountMenu);
 
 
             if (user.getBaseUrl() != null &&
@@ -213,15 +213,15 @@ public class ChooseAccountDialogFragment extends DialogFragment {
     }
 
     private void themeViews() {
-        viewThemeUtils.themeDialog(binding.getRoot());
-        viewThemeUtils.themeDialogDivider(binding.divider);
-
-        viewThemeUtils.colorMaterialTextButton(binding.setStatus);
-        viewThemeUtils.colorDialogMenuText(binding.setStatus);
-        viewThemeUtils.colorMaterialTextButton(binding.addAccount);
-        viewThemeUtils.colorDialogMenuText(binding.addAccount);
-        viewThemeUtils.colorMaterialTextButton(binding.manageSettings);
-        viewThemeUtils.colorDialogMenuText(binding.manageSettings);
+        viewThemeUtils.platform.themeDialog(binding.getRoot());
+        viewThemeUtils.platform.themeDialogDivider(binding.divider);
+
+        viewThemeUtils.material.colorMaterialTextButton(binding.setStatus);
+        viewThemeUtils.dialog.colorDialogMenuText(binding.setStatus);
+        viewThemeUtils.material.colorMaterialTextButton(binding.addAccount);
+        viewThemeUtils.dialog.colorDialogMenuText(binding.addAccount);
+        viewThemeUtils.material.colorMaterialTextButton(binding.manageSettings);
+        viewThemeUtils.dialog.colorDialogMenuText(binding.manageSettings);
     }
 
     private void loadCurrentStatus(User user) {

+ 1 - 1
app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt

@@ -59,7 +59,7 @@ class ContactsBottomDialog(
         setContentView(binding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialog(binding.root)
+        viewThemeUtils.platform.themeDialog(binding.root)
         executeEntryMenuController(bundle)
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt

@@ -89,7 +89,7 @@ class ConversationsListBottomDialog(
         setContentView(binding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialog(binding.root)
+        viewThemeUtils.platform.themeDialog(binding.root)
         initHeaderDescription()
         initItemsVisibility()
         initClickListeners()

+ 2 - 2
app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt

@@ -83,7 +83,7 @@ class MessageActionsDialog(
         setContentView(dialogMessageActionsBinding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialog(dialogMessageActionsBinding.root)
+        viewThemeUtils.platform.themeDialog(dialogMessageActionsBinding.root)
         initEmojiBar(hasChatPermission)
         initMenuItemCopy(!message.isDeleted)
         initMenuReplyToMessage(message.replyable && hasChatPermission)
@@ -225,7 +225,7 @@ class MessageActionsDialog(
 
     private fun checkAndSetEmojiSelfReaction(emoji: EmojiTextView) {
         if (emoji.text?.toString() != null && message.reactionsSelf?.contains(emoji.text?.toString()) == true) {
-            viewThemeUtils.setCheckedBackground(emoji)
+            viewThemeUtils.talk.setCheckedBackground(emoji)
         }
     }
 

+ 1 - 1
app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt

@@ -59,7 +59,7 @@ class ScopeDialog(
 
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
 
-        viewThemeUtils.themeDialog(dialogScopeBinding.root)
+        viewThemeUtils.platform.themeDialog(dialogScopeBinding.root)
 
         if (field == ProfileController.Field.DISPLAYNAME || field == ProfileController.Field.EMAIL) {
             dialogScopeBinding.scopePrivate.visibility = View.GONE

+ 7 - 7
app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt

@@ -167,7 +167,7 @@ class SetStatusDialogFragment :
         binding = DialogSetStatusBinding.inflate(LayoutInflater.from(context))
 
         val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root)
-        viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
 
         return dialogBuilder.create()
     }
@@ -242,12 +242,12 @@ class SetStatusDialogFragment :
             }
         }
 
-        viewThemeUtils.themeDialog(binding.root)
+        viewThemeUtils.platform.themeDialog(binding.root)
 
-        viewThemeUtils.colorMaterialButtonText(binding.clearStatus)
-        viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.setStatus)
+        viewThemeUtils.material.colorMaterialButtonText(binding.clearStatus)
+        viewThemeUtils.material.colorMaterialButtonPrimaryFilled(binding.setStatus)
 
-        viewThemeUtils.colorTextInputLayout(binding.customStatusInputContainer)
+        viewThemeUtils.material.colorTextInputLayout(binding.customStatusInputContainer)
 
         binding.customStatusInput.doAfterTextChanged { text ->
             binding.setStatus.isEnabled = !text.isNullOrEmpty()
@@ -418,8 +418,8 @@ class SetStatusDialogFragment :
                 return
             }
         }
-        viewThemeUtils.colorCardViewBackground(views.first)
-        viewThemeUtils.colorPrimaryTextViewElement(views.second)
+        viewThemeUtils.material.colorCardViewBackground(views.first)
+        viewThemeUtils.platform.colorPrimaryTextViewElement(views.second)
     }
 
     private fun clearTopStatus() {

+ 2 - 2
app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt

@@ -86,7 +86,7 @@ class ShowReactionsDialog(
         binding = DialogMessageReactionsBinding.inflate(layoutInflater)
         setContentView(binding.root)
         window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
-        viewThemeUtils.themeDialog(binding.root)
+        viewThemeUtils.platform.themeDialog(binding.root)
         adapter = ReactionsAdapter(this, user)
         binding.reactionsList.adapter = adapter
         binding.reactionsList.layoutManager = LinearLayoutManager(context)
@@ -144,7 +144,7 @@ class ShowReactionsDialog(
                 }
             })
 
-            viewThemeUtils.themeTabLayoutOnSurface(binding.emojiReactionsTabs)
+            viewThemeUtils.material.themeTabLayoutOnSurface(binding.emojiReactionsTabs)
 
             updateParticipantsForEmoji(chatMessage, tagAll)
         }

+ 4 - 4
app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java

@@ -120,8 +120,8 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
      * find all relevant UI elements and set their values.
      */
     private void setupDialogElements() {
-        viewThemeUtils.themeDialog(binding.root);
-        viewThemeUtils.colorMaterialButtonPrimaryBorderless(binding.cancel);
+        viewThemeUtils.platform.themeDialog(binding.root);
+        viewThemeUtils.material.colorMaterialButtonPrimaryBorderless(binding.cancel);
 
         taggedViews = new View[12];
         taggedViews[0] = binding.sortByNameAscending;
@@ -163,10 +163,10 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O
                 continue;
             }
             if (view instanceof MaterialButton) {
-                viewThemeUtils.colorMaterialButtonText((MaterialButton) view);
+                viewThemeUtils.material.colorMaterialButtonText((MaterialButton) view);
             }
             if (view instanceof TextView) {
-                viewThemeUtils.colorPrimaryTextViewElement((TextView) view);
+                viewThemeUtils.platform.colorPrimaryTextViewElement((TextView) view);
                 ((TextView) view).setTypeface(Typeface.DEFAULT_BOLD);
             }
         }

+ 240 - 0
app/src/main/java/com/nextcloud/talk/ui/theme/TalkSpecificViewThemeUtils.kt

@@ -0,0 +1,240 @@
+/*
+ * Nextcloud Talk application
+ *
+ * @author Álvaro Brey
+ * Copyright (C) 2022 Álvaro Brey
+ * Copyright (C) 2022 Nextcloud GmbH
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+package com.nextcloud.talk.ui.theme
+
+import android.annotation.TargetApi
+import android.content.Context
+import android.content.res.ColorStateList
+import android.graphics.drawable.Drawable
+import android.graphics.drawable.LayerDrawable
+import android.os.Build
+import android.view.View
+import android.view.ViewGroup
+import android.widget.LinearLayout
+import android.widget.TextView
+import androidx.annotation.ColorInt
+import androidx.annotation.DrawableRes
+import androidx.appcompat.content.res.AppCompatResources
+import androidx.appcompat.widget.SearchView
+import androidx.appcompat.widget.SwitchCompat
+import androidx.core.content.ContextCompat
+import androidx.core.content.res.ResourcesCompat
+import androidx.core.graphics.ColorUtils
+import androidx.core.graphics.drawable.DrawableCompat
+import androidx.core.view.ViewCompat
+import androidx.core.view.children
+import com.google.android.material.card.MaterialCardView
+import com.nextcloud.android.common.ui.theme.MaterialSchemes
+import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase
+import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils
+import com.nextcloud.talk.R
+import com.nextcloud.talk.utils.DisplayUtils
+import com.nextcloud.talk.utils.DrawableUtils
+import com.vanniktech.emoji.EmojiTextView
+import com.yarolegovich.mp.MaterialPreferenceCategory
+import com.yarolegovich.mp.MaterialSwitchPreference
+import javax.inject.Inject
+import kotlin.math.roundToInt
+
+/**
+ * View theme utils specific for the Talk app.
+ *
+ */
+@Suppress("TooManyFunctions")
+class TalkSpecificViewThemeUtils @Inject constructor(
+    schemes: MaterialSchemes,
+    private val appcompat: AndroidXViewThemeUtils
+) :
+    ViewThemeUtilsBase(schemes) {
+    fun themeIncomingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
+        val resources = bubble.resources
+
+        var bubbleResource = R.drawable.shape_incoming_message
+
+        if (grouped) {
+            bubbleResource = R.drawable.shape_grouped_incoming_message
+        }
+
+        val bgBubbleColor = if (deleted) {
+            resources.getColor(R.color.bg_message_list_incoming_bubble_deleted)
+        } else {
+            resources.getColor(R.color.bg_message_list_incoming_bubble)
+        }
+        val bubbleDrawable = DisplayUtils.getMessageSelector(
+            bgBubbleColor,
+            resources.getColor(R.color.transparent),
+            bgBubbleColor,
+            bubbleResource
+        )
+        ViewCompat.setBackground(bubble, bubbleDrawable)
+    }
+
+    fun themeOutgoingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
+        withScheme(bubble) { scheme ->
+            val bgBubbleColor = if (deleted) {
+                ColorUtils.setAlphaComponent(scheme.surfaceVariant, HALF_ALPHA_INT)
+            } else {
+                scheme.surfaceVariant
+            }
+
+            val layout = if (grouped) {
+                R.drawable.shape_grouped_outcoming_message
+            } else {
+                R.drawable.shape_outcoming_message
+            }
+            val bubbleDrawable = DisplayUtils.getMessageSelector(
+                bgBubbleColor,
+                ResourcesCompat.getColor(bubble.resources, R.color.transparent, null),
+                bgBubbleColor,
+                layout
+            )
+            ViewCompat.setBackground(bubble, bubbleDrawable)
+        }
+    }
+
+    fun colorOutgoingQuoteText(textView: TextView) {
+        withScheme(textView) { scheme ->
+            textView.setTextColor(scheme.onSurfaceVariant)
+        }
+    }
+
+    fun colorOutgoingQuoteAuthorText(textView: TextView) {
+        withScheme(textView) { scheme ->
+            ColorUtils.setAlphaComponent(scheme.onSurfaceVariant, ALPHA_80_INT)
+        }
+    }
+
+    fun colorOutgoingQuoteBackground(view: View) {
+        withScheme(view) { scheme ->
+            view.setBackgroundColor(scheme.onSurfaceVariant)
+        }
+    }
+
+    fun colorContactChatItemName(contactName: androidx.emoji.widget.EmojiTextView) {
+        withScheme(contactName) { scheme ->
+            contactName.setTextColor(scheme.onPrimaryContainer)
+        }
+    }
+
+    fun colorContactChatItemBackground(card: MaterialCardView) {
+        withScheme(card) { scheme ->
+            card.setCardBackgroundColor(scheme.primaryContainer)
+        }
+    }
+
+    fun colorPreferenceCategory(category: MaterialPreferenceCategory) {
+        withScheme(category) { scheme ->
+            category.setTitleColor(scheme.primary)
+        }
+    }
+
+    fun colorSwitchPreference(preference: MaterialSwitchPreference) {
+        val children = preference.children
+        val switch = children.find { it is SwitchCompat }
+        if (switch != null) {
+            val switchCompat = (switch as SwitchCompat)
+            appcompat.colorSwitchCompat(switchCompat)
+        }
+    }
+
+    fun setCheckedBackground(emoji: EmojiTextView) {
+        withScheme(emoji) { scheme ->
+            val drawable = AppCompatResources
+                .getDrawable(emoji.context, R.drawable.reaction_self_bottom_sheet_background)!!
+                .mutate()
+            DrawableCompat.setTintList(
+                drawable,
+                ColorStateList.valueOf(scheme.primary)
+            )
+            emoji.background = drawable
+        }
+    }
+
+    fun setCheckedBackground(linearLayout: LinearLayout, @ColorInt backgroundColor: Int) {
+        withScheme(linearLayout) { scheme ->
+            val drawable = AppCompatResources
+                .getDrawable(linearLayout.context, R.drawable.reaction_self_background)!!
+                .mutate()
+            DrawableCompat.setTintList(
+                drawable,
+                ColorStateList.valueOf(backgroundColor)
+            )
+            linearLayout.background = drawable
+        }
+    }
+
+    fun getPlaceholderImage(context: Context, mimetype: String?): Drawable? {
+        val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype)
+        val drawable = AppCompatResources.getDrawable(
+            context,
+            drawableResourceId
+        )
+        if (drawable != null && THEMEABLE_PLACEHOLDER_IDS.contains(drawableResourceId)) {
+            colorDrawable(context, drawable)
+        }
+        return drawable
+    }
+
+    private fun colorDrawable(context: Context, drawable: Drawable) {
+        val scheme = getScheme(context)
+        drawable.setTint(scheme.primary)
+    }
+
+    @TargetApi(Build.VERSION_CODES.O)
+    fun themePlaceholderAvatar(avatar: View, @DrawableRes foreground: Int): Drawable? {
+        var drawable: LayerDrawable? = null
+        withScheme(avatar) { scheme ->
+            val layers = arrayOfNulls<Drawable>(2)
+            layers[0] = ContextCompat.getDrawable(avatar.context, R.drawable.ic_avatar_background)
+            layers[0]?.setTint(scheme.surfaceVariant)
+            layers[1] = ContextCompat.getDrawable(avatar.context, foreground)
+            layers[1]?.setTint(scheme.onSurfaceVariant)
+            drawable = LayerDrawable(layers)
+        }
+
+        return drawable
+    }
+
+    fun themeSearchView(searchView: SearchView) {
+        withScheme(searchView) { scheme ->
+            // hacky as no default way is provided
+            val editText = searchView.findViewById<SearchView.SearchAutoComplete>(R.id.search_src_text)
+            val searchPlate = searchView.findViewById<LinearLayout>(R.id.search_plate)
+            editText.setHintTextColor(scheme.onSurfaceVariant)
+            editText.setTextColor(scheme.onSurface)
+            editText.setBackgroundColor(scheme.surface)
+            searchPlate.setBackgroundColor(scheme.surface)
+        }
+    }
+
+    companion object {
+        private val THEMEABLE_PLACEHOLDER_IDS = listOf(
+            R.drawable.ic_mimetype_package_x_generic,
+            R.drawable.ic_mimetype_folder
+        )
+
+        private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt()
+
+        private const val HALF_ALPHA_INT: Int = 255 / 2
+        private const val SEARCH_TEXT_SIZE: Float = 16f
+    }
+}

+ 18 - 818
app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt

@@ -21,825 +21,25 @@
 
 package com.nextcloud.talk.ui.theme
 
-import android.annotation.TargetApi
-import android.app.Activity
-import android.content.Context
-import android.content.res.ColorStateList
-import android.graphics.Color
-import android.graphics.PorterDuff
-import android.graphics.drawable.Drawable
-import android.graphics.drawable.LayerDrawable
-import android.os.Build
-import android.text.Spannable
-import android.text.SpannableString
-import android.view.MenuItem
-import android.view.View
-import android.view.ViewGroup
-import android.widget.Button
-import android.widget.CheckBox
-import android.widget.EditText
-import android.widget.ImageButton
-import android.widget.ImageView
-import android.widget.LinearLayout
-import android.widget.ProgressBar
-import android.widget.RadioButton
-import android.widget.SeekBar
-import android.widget.TextView
-import androidx.annotation.ColorInt
-import androidx.annotation.DrawableRes
-import androidx.appcompat.content.res.AppCompatResources
-import androidx.appcompat.widget.SearchView
-import androidx.appcompat.widget.SearchView.SearchAutoComplete
-import androidx.appcompat.widget.SwitchCompat
-import androidx.core.content.ContextCompat
-import androidx.core.content.res.ResourcesCompat
-import androidx.core.graphics.ColorUtils
-import androidx.core.graphics.drawable.DrawableCompat
-import androidx.core.view.ViewCompat
-import androidx.core.view.children
-import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
-import com.google.android.material.appbar.MaterialToolbar
-import com.google.android.material.button.MaterialButton
-import com.google.android.material.card.MaterialCardView
-import com.google.android.material.chip.Chip
-import com.google.android.material.chip.ChipDrawable
-import com.google.android.material.dialog.MaterialAlertDialogBuilder
-import com.google.android.material.floatingactionbutton.FloatingActionButton
-import com.google.android.material.progressindicator.LinearProgressIndicator
-import com.google.android.material.shape.MaterialShapeDrawable
-import com.google.android.material.tabs.TabLayout
-import com.google.android.material.textfield.TextInputLayout
-import com.google.android.material.textview.MaterialTextView
 import com.nextcloud.android.common.ui.theme.MaterialSchemes
-import com.nextcloud.talk.R
-import com.nextcloud.talk.utils.DisplayUtils
-import com.nextcloud.talk.utils.DrawableUtils
-import com.nextcloud.android.common.ui.color.ColorUtil
-import com.nextcloud.talk.utils.ui.PlatformThemeUtil.isDarkMode
-import com.vanniktech.emoji.EmojiTextView
-import com.yarolegovich.mp.MaterialPreferenceCategory
-import com.yarolegovich.mp.MaterialSwitchPreference
-import eu.davidea.flexibleadapter.utils.FlexibleUtils
-import scheme.Scheme
+import com.nextcloud.android.common.ui.theme.ViewThemeUtilsBase
+import com.nextcloud.android.common.ui.theme.utils.AndroidViewThemeUtils
+import com.nextcloud.android.common.ui.theme.utils.AndroidXViewThemeUtils
+import com.nextcloud.android.common.ui.theme.utils.DialogViewThemeUtils
+import com.nextcloud.android.common.ui.theme.utils.MaterialViewThemeUtils
 import javax.inject.Inject
-import kotlin.math.roundToInt
 
 @Suppress("TooManyFunctions")
-class ViewThemeUtils @Inject constructor(private val schemes: MaterialSchemes, private val colorUtil: ColorUtil) {
-
-    /**
-     * Scheme for painting elements
-     */
-    fun getScheme(context: Context): Scheme = when {
-        isDarkMode(context) -> schemes.darkScheme
-        else -> schemes.lightScheme
-    }
-
-    private fun getSchemeDark(): Scheme = schemes.darkScheme
-
-    private fun withScheme(view: View, block: (Scheme) -> Unit) {
-        block(getScheme(view.context))
-    }
-
-    private fun withScheme(context: Context, block: (Scheme) -> Unit) {
-        block(getScheme(context))
-    }
-
-    private fun withSchemeDark(block: (Scheme) -> Unit) {
-        block(getSchemeDark())
-    }
-
-    fun themeToolbar(toolbar: MaterialToolbar) {
-        withScheme(toolbar) { scheme ->
-            toolbar.setBackgroundColor(scheme.surface)
-            toolbar.setNavigationIconTint(scheme.onSurface)
-            toolbar.setTitleTextColor(scheme.onSurface)
-        }
-    }
-
-    fun colorViewBackground(view: View) {
-        withScheme(view) { scheme ->
-            view.setBackgroundColor(scheme.surface)
-        }
-    }
-
-    fun colorToolbarMenuIcon(context: Context, item: MenuItem) {
-        withScheme(context) { scheme ->
-            item.icon.setColorFilter(scheme.onSurface, PorterDuff.Mode.SRC_ATOP)
-        }
-    }
-
-    fun colorToolbarOverflowIcon(toolbar: MaterialToolbar) {
-        withScheme(toolbar) { scheme ->
-            toolbar.overflowIcon?.setColorFilter(scheme.onSurface, PorterDuff.Mode.SRC_ATOP)
-        }
-    }
-
-    fun themeSearchView(searchView: SearchView) {
-        withScheme(searchView) { scheme ->
-            // hacky as no default way is provided
-            val editText = searchView.findViewById<SearchAutoComplete>(R.id.search_src_text)
-            val searchPlate = searchView.findViewById<LinearLayout>(R.id.search_plate)
-            editText.textSize = SEARCH_TEXT_SIZE
-            editText.setHintTextColor(scheme.onSurfaceVariant)
-            editText.setTextColor(scheme.onSurface)
-            editText.setBackgroundColor(scheme.surface)
-            searchPlate.setBackgroundColor(scheme.surface)
-        }
-    }
-
-    fun themeSearchBarText(searchText: MaterialTextView) {
-        withScheme(searchText) { scheme ->
-            searchText.setHintTextColor(scheme.onSurfaceVariant)
-        }
-    }
-
-    fun themeStatusBar(activity: Activity, view: View) {
-        withScheme(view) { scheme ->
-            DisplayUtils.applyColorToStatusBar(activity, scheme.surface)
-        }
-    }
-
-    fun resetStatusBar(activity: Activity, view: View) {
-        DisplayUtils.applyColorToStatusBar(
-            activity,
-            ResourcesCompat.getColor(
-                activity.resources,
-                R.color.bg_default,
-                activity.theme
-            )
-        )
-    }
-
-    fun themeDialog(view: View) {
-        withScheme(view) { scheme ->
-            view.setBackgroundColor(scheme.surface)
-        }
-    }
-
-    fun themeDialogDark(view: View) {
-        withSchemeDark { scheme ->
-            view.setBackgroundColor(scheme.surface)
-        }
-    }
-
-    fun themeDialogDivider(view: View) {
-        withScheme(view) { scheme ->
-            view.setBackgroundColor(scheme.surfaceVariant)
-        }
-    }
-
-    fun themeFAB(fab: FloatingActionButton) {
-        withScheme(fab) { scheme ->
-            fab.backgroundTintList = ColorStateList.valueOf(scheme.primaryContainer)
-            fab.imageTintList = ColorStateList.valueOf(scheme.onPrimaryContainer)
-        }
-    }
-
-    fun themeCardView(cardView: MaterialCardView) {
-        withScheme(cardView) { scheme ->
-            cardView.backgroundTintList = ColorStateList.valueOf(scheme.surface)
-        }
-    }
-
-    fun themeHorizontalSeekBar(seekBar: SeekBar) {
-        withScheme(seekBar) { scheme ->
-            themeHorizontalProgressBar(seekBar, scheme.primary)
-            seekBar.thumb.setColorFilter(scheme.primary, PorterDuff.Mode.SRC_IN)
-        }
-    }
-
-    fun themeHorizontalProgressBar(progressBar: ProgressBar?, @ColorInt color: Int) {
-        if (progressBar != null) {
-            progressBar.indeterminateDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN)
-            progressBar.progressDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN)
-        }
-    }
-
-    fun colorPrimaryTextViewElement(textView: TextView) {
-        withScheme(textView) { scheme ->
-            textView.setTextColor(scheme.primary)
-        }
-    }
-
-    fun colorPrimaryTextViewElementDarkMode(textView: TextView) {
-        withSchemeDark { scheme ->
-            textView.setTextColor(scheme.primary)
-        }
-    }
-
-    fun colorPrimaryView(view: View) {
-        withScheme(view) { scheme ->
-            view.setBackgroundColor(scheme.primary)
-        }
-    }
-
-    /**
-     * Colors the background as element color and the foreground as text color.
-     */
-    fun colorImageViewButton(imageView: ImageView) {
-        withScheme(imageView) { scheme ->
-            imageView.imageTintList = ColorStateList.valueOf(scheme.onPrimaryContainer)
-            imageView.backgroundTintList = ColorStateList.valueOf(scheme.primaryContainer)
-        }
-    }
-
-    fun themeImageButton(imageButton: ImageButton) {
-        withScheme(imageButton) { scheme ->
-            imageButton.imageTintList = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_selected),
-                    intArrayOf(-android.R.attr.state_selected),
-                    intArrayOf(android.R.attr.state_enabled),
-                    intArrayOf(-android.R.attr.state_enabled)
-                ),
-                intArrayOf(
-                    scheme.primary,
-                    scheme.onSurfaceVariant,
-                    scheme.onSurfaceVariant,
-                    colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                )
-            )
-        }
-    }
-
-    /**
-     * Tints the image with element color
-     */
-    fun colorImageView(imageView: ImageView) {
-        withScheme(imageView) { scheme ->
-            imageView.imageTintList = ColorStateList.valueOf(scheme.primary)
-        }
-    }
-
-    fun colorOutgoingQuoteText(textView: TextView) {
-        withScheme(textView) { scheme ->
-            textView.setTextColor(scheme.onSurfaceVariant)
-        }
-    }
-
-    fun colorOutgoingQuoteAuthorText(textView: TextView) {
-        withScheme(textView) { scheme ->
-            ColorUtils.setAlphaComponent(scheme.onSurfaceVariant, ALPHA_80_INT)
-        }
-    }
-
-    fun colorOutgoingQuoteBackground(view: View) {
-        withScheme(view) { scheme ->
-            view.setBackgroundColor(scheme.onSurfaceVariant)
-        }
-    }
-
-    fun colorMaterialTextButton(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            button.rippleColor = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_pressed)
-                ),
-                intArrayOf(
-                    colorUtil.adjustOpacity(scheme.primary, SURFACE_OPACITY_BUTTON_DISABLED)
-                )
-            )
-        }
-    }
-
-    fun colorMaterialButtonText(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            val disabledColor = ContextCompat.getColor(button.context, R.color.disabled_text)
-            val colorStateList = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_enabled),
-                    intArrayOf(-android.R.attr.state_enabled)
-                ),
-                intArrayOf(scheme.primary, disabledColor)
-            )
-            button.setTextColor(colorStateList)
-            button.iconTint = colorStateList
-        }
-    }
-
-    fun colorTextButtons(vararg buttons: Button) {
-        withScheme(buttons[0]) { scheme ->
-            for (button in buttons) {
-                button.setTextColor(
-                    ColorStateList(
-                        arrayOf(
-                            intArrayOf(android.R.attr.state_enabled),
-                            intArrayOf(-android.R.attr.state_enabled)
-                        ),
-                        intArrayOf(
-                            scheme.primary,
-                            colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                        )
-                    )
-                )
-            }
-        }
-    }
-
-    fun colorMaterialButtonPrimaryFilled(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            button.backgroundTintList =
-                ColorStateList(
-                    arrayOf(
-                        intArrayOf(android.R.attr.state_enabled),
-                        intArrayOf(-android.R.attr.state_enabled)
-                    ),
-                    intArrayOf(
-                        scheme.primary,
-                        colorUtil.adjustOpacity(scheme.onSurface, SURFACE_OPACITY_BUTTON_DISABLED)
-                    )
-                )
-
-            button.setTextColor(
-                ColorStateList(
-                    arrayOf(
-                        intArrayOf(android.R.attr.state_enabled),
-                        intArrayOf(-android.R.attr.state_enabled)
-                    ),
-                    intArrayOf(
-                        scheme.onPrimary,
-                        colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                    )
-                )
-            )
-
-            button.iconTint = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_enabled),
-                    intArrayOf(-android.R.attr.state_enabled)
-                ),
-                intArrayOf(
-                    scheme.onPrimary,
-                    colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                )
-            )
-        }
-    }
-
-    fun colorMaterialButtonPrimaryOutlined(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            button.strokeColor = ColorStateList.valueOf(scheme.outline)
-            button.setTextColor(
-                ColorStateList(
-                    arrayOf(
-                        intArrayOf(android.R.attr.state_enabled),
-                        intArrayOf(-android.R.attr.state_enabled)
-                    ),
-                    intArrayOf(
-                        scheme.primary,
-                        colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                    )
-                )
-            )
-            button.iconTint = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_enabled),
-                    intArrayOf(-android.R.attr.state_enabled)
-                ),
-                intArrayOf(
-                    scheme.primary,
-                    colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                )
-            )
-        }
-    }
-
-    fun colorMaterialButtonPrimaryBorderless(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            button.setTextColor(
-                ColorStateList(
-                    arrayOf(
-                        intArrayOf(android.R.attr.state_enabled),
-                        intArrayOf(-android.R.attr.state_enabled)
-                    ),
-                    intArrayOf(
-                        scheme.primary,
-                        colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                    )
-                )
-            )
-            button.iconTint = ColorStateList(
-                arrayOf(
-                    intArrayOf(android.R.attr.state_enabled),
-                    intArrayOf(-android.R.attr.state_enabled)
-                ),
-                intArrayOf(
-                    scheme.primary,
-                    colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED)
-                )
-            )
-        }
-    }
-
-    fun themeIncomingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
-        val resources = bubble.resources
-
-        var bubbleResource = R.drawable.shape_incoming_message
-
-        if (grouped) {
-            bubbleResource = R.drawable.shape_grouped_incoming_message
-        }
-
-        val bgBubbleColor = if (deleted) {
-            resources.getColor(R.color.bg_message_list_incoming_bubble_deleted)
-        } else {
-            resources.getColor(R.color.bg_message_list_incoming_bubble)
-        }
-        val bubbleDrawable = DisplayUtils.getMessageSelector(
-            bgBubbleColor,
-            resources.getColor(R.color.transparent),
-            bgBubbleColor, bubbleResource
-        )
-        ViewCompat.setBackground(bubble, bubbleDrawable)
-    }
-
-    fun themeOutgoingMessageBubble(bubble: ViewGroup, grouped: Boolean, deleted: Boolean) {
-        withScheme(bubble) { scheme ->
-            val bgBubbleColor = if (deleted) {
-                ColorUtils.setAlphaComponent(scheme.surfaceVariant, HALF_ALPHA_INT)
-            } else {
-                scheme.surfaceVariant
-            }
-
-            val layout = if (grouped) {
-                R.drawable.shape_grouped_outcoming_message
-            } else {
-                R.drawable.shape_outcoming_message
-            }
-            val bubbleDrawable = DisplayUtils.getMessageSelector(
-                bgBubbleColor,
-                ResourcesCompat.getColor(bubble.resources, R.color.transparent, null),
-                bgBubbleColor,
-                layout
-            )
-            ViewCompat.setBackground(bubble, bubbleDrawable)
-        }
-    }
-
-    fun colorCardViewBackground(card: MaterialCardView) {
-        withScheme(card) { scheme ->
-            card.setCardBackgroundColor(scheme.surfaceVariant)
-        }
-    }
-
-    fun colorContactChatItemName(contactName: androidx.emoji.widget.EmojiTextView) {
-        withScheme(contactName) { scheme ->
-            contactName.setTextColor(scheme.onPrimaryContainer)
-        }
-    }
-
-    fun colorContactChatItemBackground(card: MaterialCardView) {
-        withScheme(card) { scheme ->
-            card.setCardBackgroundColor(scheme.primaryContainer)
-        }
-    }
-
-    fun colorCircularProgressBarOnPrimaryContainer(progressBar: ProgressBar) {
-        withScheme(progressBar) { scheme ->
-            progressBar.indeterminateDrawable.setColorFilter(scheme.onPrimaryContainer, PorterDuff.Mode.SRC_ATOP)
-        }
-    }
-
-    fun colorCircularProgressBar(progressBar: ProgressBar) {
-        withScheme(progressBar) { scheme ->
-            progressBar.indeterminateDrawable.setColorFilter(scheme.primary, PorterDuff.Mode.SRC_ATOP)
-        }
-    }
-
-    fun colorCircularProgressBarOnSurfaceVariant(progressBar: ProgressBar) {
-        withScheme(progressBar) { scheme ->
-            progressBar.indeterminateDrawable.setColorFilter(scheme.onSurfaceVariant, PorterDuff.Mode.SRC_ATOP)
-        }
-    }
-
-    // TODO split this util into classes depending on framework views vs library views
-    fun colorPreferenceCategory(category: MaterialPreferenceCategory) {
-        withScheme(category) { scheme ->
-            category.setTitleColor(scheme.primary)
-        }
-    }
-
-    fun colorSwitchPreference(preference: MaterialSwitchPreference) {
-        val children = preference.children
-        val switch = children.find { it is SwitchCompat }
-        if (switch != null) {
-            val switchCompat = (switch as SwitchCompat)
-            colorSwitchCompat(switchCompat)
-        }
-    }
-
-    fun colorSwitchCompat(switchCompat: SwitchCompat) {
-        withScheme(switchCompat) { scheme ->
-
-            val context = switchCompat.context
-
-            val thumbUncheckedColor = ResourcesCompat.getColor(
-                context.resources,
-                R.color.switch_thumb_color_unchecked,
-                context.theme
-            )
-            val trackUncheckedColor = ResourcesCompat.getColor(
-                context.resources,
-                R.color.switch_track_color_unchecked,
-                context.theme
-            )
-
-            val trackColor = Color.argb(
-                SWITCH_COMPAT_TRACK_ALPHA,
-                Color.red(scheme.primary),
-                Color.green(scheme.primary),
-                Color.blue(scheme.primary)
-            )
-
-            switchCompat.thumbTintList = ColorStateList(
-                arrayOf(intArrayOf(android.R.attr.state_checked), intArrayOf()),
-                intArrayOf(scheme.primary, thumbUncheckedColor)
-            )
-
-            switchCompat.trackTintList = ColorStateList(
-                arrayOf(intArrayOf(android.R.attr.state_checked), intArrayOf()),
-                intArrayOf(trackColor, trackUncheckedColor)
-            )
-        }
-    }
-
-    fun colorDrawable(context: Context, drawable: Drawable) {
-        val scheme = getScheme(context)
-        drawable.setTint(scheme.primary)
-    }
-
-    fun themeCheckbox(checkbox: CheckBox) {
-        withScheme(checkbox) { scheme ->
-            checkbox.buttonTintList = ColorStateList(
-                arrayOf(
-                    intArrayOf(-android.R.attr.state_checked),
-                    intArrayOf(android.R.attr.state_checked)
-                ),
-                intArrayOf(Color.GRAY, scheme.primary)
-            )
-        }
-    }
-
-    fun themeRadioButton(radioButton: RadioButton) {
-        withScheme(radioButton) { scheme ->
-            radioButton.buttonTintList = ColorStateList(
-                arrayOf(
-                    intArrayOf(-android.R.attr.state_checked),
-                    intArrayOf(android.R.attr.state_checked)
-                ),
-                intArrayOf(Color.GRAY, scheme.primary)
-            )
-        }
-    }
-
-    fun themeSwipeRefreshLayout(swipeRefreshLayout: SwipeRefreshLayout) {
-        withScheme(swipeRefreshLayout) { scheme ->
-            swipeRefreshLayout.setColorSchemeColors(scheme.primary)
-            swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background)
-        }
-    }
-
-    fun colorProgressBar(progressIndicator: LinearProgressIndicator) {
-        withScheme(progressIndicator) { scheme ->
-            progressIndicator.setIndicatorColor(scheme.primary)
-        }
-    }
-
-    fun colorEditText(editText: EditText) {
-        withScheme(editText) { scheme ->
-            // TODO check API-level compatibility
-            // editText.background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
-            editText.backgroundTintList = ColorStateList(
-                arrayOf(
-                    intArrayOf(-android.R.attr.state_focused),
-                    intArrayOf(android.R.attr.state_focused)
-                ),
-                intArrayOf(
-                    scheme.outline,
-                    scheme.primary
-                )
-            )
-            editText.setHintTextColor(scheme.onSurfaceVariant)
-            editText.setTextColor(scheme.onSurface)
-        }
-    }
-
-    fun colorTextInputLayout(textInputLayout: TextInputLayout) {
-        withScheme(textInputLayout) { scheme ->
-            val errorColor = scheme.onSurfaceVariant
-
-            val errorColorStateList = ColorStateList(
-                arrayOf(
-                    intArrayOf(-android.R.attr.state_focused),
-                    intArrayOf(android.R.attr.state_focused)
-                ),
-                intArrayOf(
-                    errorColor,
-                    errorColor
-                )
-            )
-            val coloredColorStateList = ColorStateList(
-                arrayOf(
-                    intArrayOf(-android.R.attr.state_focused),
-                    intArrayOf(android.R.attr.state_focused)
-                ),
-                intArrayOf(
-                    scheme.outline,
-                    scheme.primary
-                )
-            )
-
-            textInputLayout.setBoxStrokeColorStateList(coloredColorStateList)
-            textInputLayout.setErrorIconTintList(errorColorStateList)
-            textInputLayout.setErrorTextColor(errorColorStateList)
-            textInputLayout.boxStrokeErrorColor = errorColorStateList
-            textInputLayout.defaultHintTextColor = coloredColorStateList
-        }
-    }
-
-    fun themeTabLayoutOnSurface(tabLayout: TabLayout) {
-        withScheme(tabLayout) { scheme ->
-            tabLayout.setBackgroundColor(scheme.surface)
-            colorTabLayout(tabLayout, scheme)
-        }
-    }
-
-    fun colorTabLayout(tabLayout: TabLayout, scheme: Scheme) {
-        tabLayout.setSelectedTabIndicatorColor(scheme.primary)
-        tabLayout.tabTextColors = ColorStateList(
-            arrayOf(
-                intArrayOf(android.R.attr.state_selected),
-                intArrayOf(-android.R.attr.state_selected)
-            ),
-            intArrayOf(scheme.primary, ContextCompat.getColor(tabLayout.context, R.color.high_emphasis_text))
-        )
-        tabLayout.tabRippleColor = ColorStateList(
-            arrayOf(
-                intArrayOf(android.R.attr.state_pressed)
-            ),
-            intArrayOf(
-                colorUtil.adjustOpacity(scheme.primary, SURFACE_OPACITY_BUTTON_DISABLED)
-            )
-        )
-    }
-
-    fun getPlaceholderImage(context: Context, mimetype: String?): Drawable? {
-        val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype)
-        val drawable = AppCompatResources.getDrawable(
-            context,
-            drawableResourceId
-        )
-        if (drawable != null && THEMEABLE_PLACEHOLDER_IDS.contains(drawableResourceId)) {
-            colorDrawable(context, drawable)
-        }
-        return drawable
-    }
-
-    fun colorChipBackground(chip: Chip) {
-        withScheme(chip) { scheme ->
-            chip.chipBackgroundColor = ColorStateList.valueOf(scheme.primary)
-            chip.setTextColor(scheme.onPrimary)
-        }
-    }
-
-    fun colorChipOutlined(chip: Chip, strokeWidth: Float) {
-        withScheme(chip) { scheme ->
-            chip.chipBackgroundColor = ColorStateList.valueOf(Color.TRANSPARENT)
-            chip.chipStrokeWidth = strokeWidth
-            chip.chipStrokeColor = ColorStateList.valueOf(scheme.primary)
-            chip.setTextColor(scheme.primary)
-        }
-    }
-
-    @TargetApi(Build.VERSION_CODES.O)
-    fun themePlaceholderAvatar(avatar: View, @DrawableRes foreground: Int): Drawable? {
-        var drawable: LayerDrawable? = null
-        withScheme(avatar) { scheme ->
-            val layers = arrayOfNulls<Drawable>(2)
-            layers[0] = ContextCompat.getDrawable(avatar.context, R.drawable.ic_avatar_background)
-            layers[0]?.setTint(scheme.surfaceVariant)
-            layers[1] = ContextCompat.getDrawable(avatar.context, foreground)
-            layers[1]?.setTint(scheme.onSurfaceVariant)
-            drawable = LayerDrawable(layers)
-        }
-
-        return drawable
-    }
-
-    fun themePrimaryMentionChip(context: Context, chip: ChipDrawable) {
-        withScheme(context) { scheme ->
-            chip.chipBackgroundColor = ColorStateList.valueOf(scheme.primary)
-            chip.setTextColor(scheme.onPrimary)
-        }
-    }
-
-    fun setCheckedBackground(emoji: EmojiTextView) {
-        withScheme(emoji) { scheme ->
-            val drawable = AppCompatResources
-                .getDrawable(emoji.context, R.drawable.reaction_self_bottom_sheet_background)!!
-                .mutate()
-            DrawableCompat.setTintList(
-                drawable,
-                ColorStateList.valueOf(scheme.primary)
-            )
-            emoji.background = drawable
-        }
-    }
-
-    fun setCheckedBackground(linearLayout: LinearLayout, @ColorInt backgroundColor: Int) {
-        withScheme(linearLayout) { scheme ->
-            val drawable = AppCompatResources
-                .getDrawable(linearLayout.context, R.drawable.reaction_self_background)!!
-                .mutate()
-            DrawableCompat.setTintList(
-                drawable,
-                ColorStateList.valueOf(backgroundColor)
-            )
-            linearLayout.background = drawable
-        }
-    }
-
-    fun colorDialogMenuText(button: MaterialButton) {
-        withScheme(button) { scheme ->
-            button.setTextColor(scheme.onSurface)
-            button.iconTint = ColorStateList.valueOf(scheme.onSurface)
-        }
-    }
-
-    fun colorMaterialAlertDialogBackground(context: Context, dialogBuilder: MaterialAlertDialogBuilder) {
-        withScheme(dialogBuilder.context) { scheme ->
-            val materialShapeDrawable = MaterialShapeDrawable(
-                context,
-                null,
-                com.google.android.material.R.attr.alertDialogStyle,
-                com.google.android.material.R.style.MaterialAlertDialog_MaterialComponents
-            )
-            materialShapeDrawable.initializeElevationOverlay(context)
-            materialShapeDrawable.fillColor = ColorStateList.valueOf(scheme.surface)
-
-            // dialogCornerRadius first appeared in Android Pie
-            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
-                val radius = context.resources.getDimension(R.dimen.dialogBorderRadius)
-                materialShapeDrawable.setCornerSize(radius)
-            }
-
-            dialogBuilder.background = materialShapeDrawable
-        }
-    }
-
-    fun colorDialogHeadline(textView: TextView) {
-        withScheme(textView) { scheme ->
-            textView.setTextColor(scheme.onSurface)
-        }
-    }
-
-    fun colorDialogSupportingText(textView: TextView) {
-        withScheme(textView) { scheme ->
-            textView.setTextColor(scheme.onSurfaceVariant)
-        }
-    }
-
-    fun colorDialogIcon(icon: ImageView) {
-        withScheme(icon) { scheme ->
-            icon.setColorFilter(scheme.secondary)
-        }
-    }
-
-    fun highlightText(textView: TextView, originalText: String, constraint: String) {
-        withScheme(textView) { scheme ->
-            FlexibleUtils.highlightText(textView, originalText, constraint, scheme.primary)
-        }
-    }
-
-    fun createHighlightedSpan(context: Context, messageSpannable: SpannableString, searchTerm: String): Spannable {
-        var spannable: Spannable = messageSpannable
-        withScheme(context) { scheme ->
-            spannable = DisplayUtils.searchAndColor(messageSpannable, searchTerm, scheme.primary)
-        }
-        return spannable
-    }
-
-    fun colorMaterialAlertDialogIcon(context: Context, drawableId: Int): Drawable {
-        val drawable = AppCompatResources.getDrawable(context, drawableId)!!
-        withScheme(context) { scheme ->
-            DrawableCompat.setTint(drawable, scheme.secondary)
-        }
-        return drawable
-    }
-
-    companion object {
-        private val THEMEABLE_PLACEHOLDER_IDS = listOf(
-            R.drawable.ic_mimetype_package_x_generic,
-            R.drawable.ic_mimetype_folder
-        )
-
-        private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt()
-
-        private const val SWITCH_COMPAT_TRACK_ALPHA: Int = 77
-        private const val HALF_ALPHA_INT: Int = 255 / 2
-        private const val SURFACE_OPACITY_BUTTON_DISABLED: Float = 0.12f
-        private const val ON_SURFACE_OPACITY_BUTTON_DISABLED: Float = 0.38f
-        private const val SEARCH_TEXT_SIZE: Float = 16f
-    }
-}
+class ViewThemeUtils @Inject constructor(
+    schemes: MaterialSchemes,
+    @JvmField
+    val platform: AndroidViewThemeUtils,
+    @JvmField
+    val material: MaterialViewThemeUtils,
+    @JvmField
+    val androidx: AndroidXViewThemeUtils,
+    @JvmField
+    val talk: TalkSpecificViewThemeUtils,
+    @JvmField
+    val dialog: DialogViewThemeUtils
+) : ViewThemeUtilsBase(schemes)

+ 1 - 1
app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java

@@ -304,7 +304,7 @@ public class DisplayUtils {
         chip.setEllipsize(TextUtils.TruncateAt.MIDDLE);
 
         if (chipResource == R.xml.chip_you) {
-            viewThemeUtils.themePrimaryMentionChip(context, chip);
+            viewThemeUtils.material.colorChipDrawable(context, chip);
         }
 
         if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {

+ 3 - 3
app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java

@@ -73,7 +73,7 @@ public class MagicUserInputModule extends StandardUserInputModule {
             final Listener<String> listener) {
         final View view = LayoutInflater.from(context).inflate(R.layout.dialog_edittext, null);
         final EditText inputField = view.findViewById(R.id.mp_text_input);
-        viewThemeUtils.colorEditText(inputField);
+        viewThemeUtils.platform.colorEditText(inputField);
 
         int paddingStartEnd = Math.round(view.getResources().getDimension(R.dimen.standard_padding));
         int paddingTopBottom = Math.round(view.getResources().getDimension(R.dimen.dialog_padding_top_bottom));
@@ -96,12 +96,12 @@ public class MagicUserInputModule extends StandardUserInputModule {
             .setTitle(title)
             .setView(view);
 
-        viewThemeUtils.colorMaterialAlertDialogBackground(view.getContext(), dialogBuilder);
+        viewThemeUtils.dialog.colorMaterialAlertDialogBackground(view.getContext(), dialogBuilder);
 
         final Dialog dialog = dialogBuilder.show();
 
         TextView button = view.findViewById(R.id.mp_btn_confirm);
-        viewThemeUtils.colorPrimaryTextViewElement(button);
+        viewThemeUtils.platform.colorPrimaryTextViewElement(button);
         button.setOnClickListener(new View.OnClickListener() {
             @Override
             public void onClick(View v) {

+ 0 - 33
app/src/main/java/com/nextcloud/talk/utils/ui/PlatformThemeUtil.kt

@@ -1,33 +0,0 @@
-/*
- * Nextcloud Talk application
- *
- * @author Álvaro Brey
- * Copyright (C) 2022 Álvaro Brey
- * Copyright (C) 2022 Nextcloud GmbH
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
- */
-
-package com.nextcloud.talk.utils.ui
-
-import android.content.Context
-import android.content.res.Configuration
-
-object PlatformThemeUtil {
-    fun isDarkMode(context: Context): Boolean =
-        when (context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK) {
-            Configuration.UI_MODE_NIGHT_YES -> true
-            else -> false
-        }
-}

+ 0 - 3
app/src/main/res/values-night/colors.xml

@@ -32,7 +32,6 @@
     <!-- App bar -->
     <color name="appbar">#1E1E1E</color>
     <color name="fontAppbar">#FFFFFF</color>
-    <color name="refresh_spinner_background">#222222</color>
 
     <!-- general text colors -->
     <color name="no_emphasis_text">#ffffff</color>
@@ -78,7 +77,5 @@
     <color name="dialog_background">#353535</color>
     <color name="vote_dialog_background">#424242</color>
 
-    <color name="switch_thumb_color_unchecked">#cbcbcb</color>
-    <color name="switch_track_color_unchecked">#5a5a5a</color>
 
 </resources>

+ 1 - 3
app/src/main/res/values/colors.xml

@@ -33,7 +33,6 @@
     <color name="appbar">@android:color/white</color>
     <color name="fontAppbar">#666666</color>
     <color name="fontSecondaryAppbar">#A5A5A5</color>
-    <color name="refresh_spinner_background">#ffffff</color>
 
     <!-- general text colors -->
     <color name="no_emphasis_text">#000000</color>
@@ -108,7 +107,6 @@
     <color name="dialog_background">#FFFFFF</color>
     <color name="vote_dialog_background">#FFFFFF</color>
 
-    <color name="switch_thumb_color_unchecked">#ececec</color>
-    <color name="switch_track_color_unchecked">#b2b2b2</color>
+
 
 </resources>

+ 0 - 2
app/src/main/res/values/dimens.xml

@@ -74,8 +74,6 @@
     <dimen name="standard_eighth_margin">2dp</dimen>
     <dimen name="scope_padding">12dp</dimen>
 
-    <dimen name="dialogBorderRadius">28dp</dimen>
-
     <dimen name="default_checkbox_dialog_start_margin">18dp</dimen>
 
     <dimen name="mediatab_file_icon_size">50dp</dimen>

+ 6 - 5
settings.gradle

@@ -20,8 +20,9 @@
 
 include ':app'
 
-includeBuild('../android-common') {
-    dependencySubstitution {
-        substitute module('com.github.nextcloud.android-common:ui') using project(':ui')
-    }
-}
+//// uncomment to use local build of common-ui
+//includeBuild('../android-common') {
+//    dependencySubstitution {
+//        substitute module('com.github.nextcloud.android-common:ui') using project(':ui')
+//    }
+//}