diff --git a/app/build.gradle b/app/build.gradle index 6cfdbf526..0c81509ad 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -335,6 +335,7 @@ dependencies { gplayImplementation "com.google.firebase:firebase-messaging:23.0.7" // implementation 'androidx.activity:activity-ktx:1.4.0' + implementation project(':material-color-utilities') } task installGitHooks(type: Copy, group: "development") { diff --git a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt index 7a36c608a..fe115f100 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/BaseActivity.kt @@ -27,15 +27,17 @@ import android.os.Bundle import android.util.Log import android.view.WindowManager import android.webkit.SslErrorHandler +import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AppCompatActivity import autodagger.AutoInjector +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.events.CertificateEvent +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.SecurityUtils import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.ssl.MagicTrustManager -import com.yarolegovich.lovelydialog.LovelyStandardDialog import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.ThreadMode @@ -53,6 +55,9 @@ open class BaseActivity : AppCompatActivity() { @Inject lateinit var appPreferences: AppPreferences + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + @Inject lateinit var context: Context @@ -110,21 +115,26 @@ open class BaseActivity : AppCompatActivity() { issuedBy, issuedFor, validFrom, validUntil ) - LovelyStandardDialog(this) - .setTopColorRes(R.color.nc_darkRed) - .setNegativeButtonColorRes(R.color.nc_darkRed) - .setPositiveButtonColorRes(R.color.colorPrimary) - .setIcon(R.drawable.ic_security_white_24dp) + val dialogBuilder = MaterialAlertDialogBuilder(this) + .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_security_white_24dp)) .setTitle(R.string.nc_certificate_dialog_title) .setMessage(dialogText) - .setPositiveButton(R.string.nc_yes) { v -> + .setPositiveButton(R.string.nc_yes) { _, _ -> magicTrustManager.addCertInTrustStore(cert) sslErrorHandler?.proceed() } - .setNegativeButton(R.string.nc_no) { view1 -> + .setNegativeButton(R.string.nc_no) { _, _ -> sslErrorHandler?.cancel() } - .show() + + viewThemeUtils.colorMaterialAlertDialogBackground(context, dialogBuilder) + + val dialog = dialogBuilder.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } catch (e: CertificateParsingException) { Log.d(TAG, "Failed to parse the certificate") } diff --git a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java index e1ae1a25e..eca9367db 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/CallActivity.java @@ -880,12 +880,13 @@ public class CallActivity extends CallBaseActivity { if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) { if (!appPreferences.getPushToTalkIntroShown()) { + int primary = viewThemeUtils.getScheme(binding.audioOutputButton.getContext()).getPrimary(); spotlightView = new SpotlightView.Builder(this) .introAnimationDuration(300) .enableRevealAnimation(true) .performClick(false) .fadeinTextDuration(400) - .headingTvColor(getResources().getColor(R.color.colorPrimary)) + .headingTvColor(primary) .headingTvSize(20) .headingTvText(getResources().getString(R.string.nc_push_to_talk)) .subHeadingTvColor(getResources().getColor(R.color.bg_default)) @@ -894,7 +895,7 @@ public class CallActivity extends CallBaseActivity { .maskColor(Color.parseColor("#dc000000")) .target(binding.microphoneButton) .lineAnimDuration(400) - .lineAndArcColor(getResources().getColor(R.color.colorPrimary)) + .lineAndArcColor(primary) .enableDismissAfterShown(true) .dismissOnBackPress(true) .usageId("pushToTalk") diff --git a/app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt b/app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt index ccd30f3b9..4b5baa820 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/activities/FullScreenTextViewerActivity.kt @@ -34,15 +34,20 @@ import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.ActivityFullScreenTextBinding +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.Mimetype.TEXT_PREFIX_GENERIC import io.noties.markwon.Markwon import java.io.File +import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class FullScreenTextViewerActivity : AppCompatActivity() { lateinit var binding: ActivityFullScreenTextBinding + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var path: String override fun onCreateOptionsMenu(menu: Menu?): Boolean { @@ -77,6 +82,7 @@ class FullScreenTextViewerActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this) binding = ActivityFullScreenTextBinding.inflate(layoutInflater) setContentView(binding.root) @@ -98,12 +104,9 @@ class FullScreenTextViewerActivity : AppCompatActivity() { supportActionBar?.title = fileName supportActionBar?.setDisplayHomeAsUpEnabled(true) - if (resources != null) { - DisplayUtils.applyColorToStatusBar( - this, - ResourcesCompat.getColor(resources, R.color.appbar, null) - ) + viewThemeUtils.themeStatusBar(this, binding.textviewToolbar) + if (resources != null) { DisplayUtils.applyColorToNavigationBar( this.window, ResourcesCompat.getColor(resources, R.color.bg_default, null) diff --git a/app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java b/app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java index 08b972545..27d9487bb 100644 --- a/app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java +++ b/app/src/main/java/com/nextcloud/talk/activities/TakePhotoActivity.java @@ -106,7 +106,7 @@ public class TakePhotoActivity extends AppCompatActivity { setContentView(binding.getRoot()); viewThemeUtils.themeFAB(binding.takePhoto); - viewThemeUtils.colorMaterialButtonBackground(binding.send); + viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.send); cameraProviderFuture = ProcessCameraProvider.getInstance(this); cameraProviderFuture.addListener(() -> { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java index a7b49be04..ad4179e88 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/AdvancedUserItem.java @@ -30,10 +30,10 @@ import android.view.View; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.interfaces.DraweeController; import com.nextcloud.talk.R; -import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.databinding.AccountItemBinding; import com.nextcloud.talk.models.json.participants.Participant; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.DisplayUtils; @@ -54,11 +54,16 @@ public class AdvancedUserItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + roundPlaceholderDrawable))); + } else { + holder.binding.avatarDraweeView.setImageResource(fallbackImageResource); } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java index 0b3cddd86..cf42f44fe 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/ConversationItem.java @@ -61,7 +61,6 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem; import eu.davidea.flexibleadapter.items.IFilterable; import eu.davidea.flexibleadapter.items.IFlexible; import eu.davidea.flexibleadapter.items.ISectionable; -import eu.davidea.flexibleadapter.utils.FlexibleUtils; import eu.davidea.viewholders.FlexibleViewHolder; public class ConversationItem extends AbstractFlexibleItem implements @@ -144,9 +143,9 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_document))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_document)); + } break; default: break; @@ -275,6 +280,7 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + Drawable[] layers = new Drawable[2]; layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background); layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground); @@ -307,14 +313,26 @@ public class ConversationItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_group))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_group)); + } break; case ROOM_PUBLIC_CALL: - holder.binding.dialogAvatar.setImageDrawable( - ContextCompat.getDrawable(context, - R.drawable.ic_circular_link)); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.dialogAvatar.setImageDrawable( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.dialogAvatar, + R.drawable.ic_avatar_link))); + } else { + holder.binding.dialogAvatar.setImageDrawable( + ContextCompat.getDrawable(context, R.drawable.ic_circular_link)); + } break; default: holder.binding.dialogAvatar.setVisibility(View.GONE); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java b/app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java index 657a605b7..6927b9f39 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/items/GenericTextHeaderItem.java @@ -74,7 +74,7 @@ public class GenericTextHeaderItem extends AbstractHeaderItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_group))); + } else { holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); } } else { @@ -168,9 +171,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_group))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); + } } else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) { - holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView, + R.drawable.ic_avatar_mail))); + } else { + holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); + } } else if (participant.getCalculatedActorType() == Participant.ActorType.GUESTS || Participant.ParticipantType.GUEST.equals(participant.getType()) || Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt index 2e9e723d4..78e59fd35 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingLocationMessageViewHolder.kt @@ -41,7 +41,6 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.appcompat.content.res.AppCompatResources -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.amulyakhare.textdrawable.TextDrawable @@ -50,6 +49,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.UriUtils @@ -69,13 +69,14 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess var locationName: String? = "" var locationGeoLink: String? = "" - @JvmField @Inject - var context: Context? = null + lateinit var context: Context - @JvmField @Inject - var appPreferences: AppPreferences? = null + lateinit var appPreferences: AppPreferences + + @Inject + lateinit var viewThemeUtils: ViewThemeUtils lateinit var reactionsInterface: ReactionsInterface @@ -89,7 +90,6 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess colorizeMessageBubble(message) itemView.isSelected = false - binding.messageTime.setTextColor(context?.resources!!.getColor(R.color.warm_grey_four)) val textSize = context?.resources!!.getDimension(R.dimen.chat_text_size) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) @@ -101,7 +101,13 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess // geo-location setLocationDataOnMessageItem(message) - Reaction().showReactions(message, binding.reactions, binding.messageText.context, false) + Reaction().showReactions( + message, + binding.reactions, + binding.messageText.context, + false, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -155,25 +161,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = itemView.resources - - var bubbleResource = R.drawable.shape_incoming_message - - if (message.isGrouped) { - bubbleResource = R.drawable.shape_grouped_incoming_message - } - - val bgBubbleColor = if (message.isDeleted) { - 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) + viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) } private fun setParentMessageDataOnMessageItem(message: ChatMessage) { @@ -199,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) { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) + viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView) } else { binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt index 6d9fc90da..b92a5d21f 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPollMessageViewHolder.kt @@ -29,7 +29,6 @@ import android.text.TextUtils import android.view.View import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.amulyakhare.textdrawable.TextDrawable @@ -41,6 +40,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA import com.nextcloud.talk.databinding.ItemCustomIncomingPollMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.polls.ui.PollMainDialogFragment +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.preferences.AppPreferences @@ -60,6 +60,9 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH @Inject lateinit var appPreferences: AppPreferences + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + @Inject lateinit var ncApi: NcApi @@ -78,14 +81,19 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH colorizeMessageBubble(message) itemView.isSelected = false - binding.messageTime.setTextColor(ResourcesCompat.getColor(context?.resources!!, R.color.warm_grey_four, null)) // parent message handling setParentMessageDataOnMessageItem(message) setPollPreview(message) - Reaction().showReactions(message, binding.reactions, binding.messageTime.context, false) + Reaction().showReactions( + message, + binding.reactions, + binding.messageTime.context, + false, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -183,26 +191,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = itemView.resources - - var bubbleResource = R.drawable.shape_incoming_message - - if (message.isGrouped) { - bubbleResource = R.drawable.shape_grouped_incoming_message - } - - val bgBubbleColor = if (message.isDeleted) { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null) - } else { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble, null) - } - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - bubbleResource - ) - ViewCompat.setBackground(bubble, bubbleDrawable) + viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) } private fun setParentMessageDataOnMessageItem(message: ChatMessage) { @@ -228,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) { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) + viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView) } else { binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java index 48fc8a041..687fdc750 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingPreviewMessageViewHolder.java @@ -26,9 +26,13 @@ import android.view.View; import android.widget.ProgressBar; import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.material.card.MaterialCardView; +import com.nextcloud.talk.R; import com.nextcloud.talk.databinding.ItemCustomIncomingPreviewMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; +import com.nextcloud.talk.models.json.chat.ChatMessage; +import androidx.core.content.ContextCompat; import androidx.emoji.widget.EmojiTextView; public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder { @@ -39,6 +43,16 @@ public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHol binding = ItemCustomIncomingPreviewMessageBinding.bind(itemView); } + @Override + public void onBind(ChatMessage message) { + super.onBind(message); + + binding.messageText.setTextColor(ContextCompat.getColor(binding.messageText.getContext(), + R.color.no_emphasis_text)); + binding.messageTime.setTextColor(ContextCompat.getColor(binding.messageText.getContext(), + R.color.no_emphasis_text)); + } + @Override public EmojiTextView getMessageText() { return binding.messageText; @@ -60,7 +74,7 @@ public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHol } @Override - public View getPreviewContactContainer() { + public MaterialCardView getPreviewContactContainer() { return binding.contactContainer; } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt index 8546dea0d..75757c896 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/IncomingVoiceMessageViewHolder.kt @@ -37,7 +37,6 @@ import android.view.View import android.widget.SeekBar import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat -import androidx.core.view.ViewCompat import androidx.work.WorkInfo import androidx.work.WorkManager import autodagger.AutoInjector @@ -90,7 +89,6 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message colorizeMessageBubble(message) itemView.isSelected = false - binding.messageTime.setTextColor(ResourcesCompat.getColor(context?.resources!!, R.color.warm_grey_four, null)) // parent message handling setParentMessageDataOnMessageItem(message) @@ -98,6 +96,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message updateDownloadState(message) binding.seekbar.max = message.voiceMessageDuration viewThemeUtils.themeHorizontalSeekBar(binding.seekbar) + viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar) if (message.isPlayingVoiceMessage) { showPlayButton() @@ -146,7 +145,13 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message } }) - Reaction().showReactions(message, binding.reactions, binding.messageTime.context, false) + Reaction().showReactions( + message, + binding.reactions, + binding.messageTime.context, + false, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -261,25 +266,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = itemView.resources - - var bubbleResource = R.drawable.shape_incoming_message - - if (message.isGrouped) { - bubbleResource = R.drawable.shape_grouped_incoming_message - } - - val bgBubbleColor = if (message.isDeleted) { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null) - } else { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble, null) - } - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, bubbleResource - ) - ViewCompat.setBackground(bubble, bubbleDrawable) + viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) } private fun setParentMessageDataOnMessageItem(message: ChatMessage) { @@ -305,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) { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) + viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView) } else { binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt index 95152a920..f5be6eea3 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicIncomingTextMessageViewHolder.kt @@ -26,7 +26,6 @@ package com.nextcloud.talk.adapters.messages import android.content.Context import android.content.Intent -import android.content.res.Resources import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable import android.net.Uri @@ -38,7 +37,6 @@ import android.util.TypedValue import android.view.View import androidx.core.content.ContextCompat import androidx.core.content.res.ResourcesCompat -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.amulyakhare.textdrawable.TextDrawable @@ -48,6 +46,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.TextMatchers @@ -61,13 +60,14 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message private val binding: ItemCustomIncomingTextMessageBinding = ItemCustomIncomingTextMessageBinding.bind(itemView) - @JvmField @Inject - var context: Context? = null + lateinit var context: Context - @JvmField @Inject - var appPreferences: AppPreferences? = null + lateinit var viewThemeUtils: ViewThemeUtils + + @Inject + lateinit var appPreferences: AppPreferences lateinit var reactionsInterface: ReactionsInterface @@ -87,12 +87,9 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message binding.messageAuthor.visibility = View.GONE } - val resources = itemView.resources - - setBubbleOnChatMessage(message, resources) + viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted) itemView.isSelected = false - binding.messageTime.setTextColor(ResourcesCompat.getColor(resources, R.color.warm_grey_four, null)) var messageString: Spannable = SpannableString(message.text) @@ -120,7 +117,13 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.replyable) - Reaction().showReactions(message, binding.reactions, binding.messageText.context, false) + Reaction().showReactions( + message, + binding.reactions, + binding.messageText.context, + false, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -141,30 +144,6 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message } } - private fun setBubbleOnChatMessage( - message: ChatMessage, - resources: Resources - ) { - val bgBubbleColor = if (message.isDeleted) { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble_deleted, null) - } else { - ResourcesCompat.getColor(resources, R.color.bg_message_list_incoming_bubble, null) - } - - var bubbleResource = R.drawable.shape_incoming_message - - if (message.isGrouped) { - bubbleResource = R.drawable.shape_grouped_incoming_message - } - - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, bubbleResource - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } - private fun processParentMessage(message: ChatMessage) { val parentChatMessage = message.parentMessage parentChatMessage!!.activeUser = message.activeUser @@ -183,13 +162,12 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message context!!.getText(R.string.nc_nick_guest) else parentChatMessage.actorDisplayName binding.messageQuote.quotedMessage.text = parentChatMessage.text - binding.messageQuote.quotedMessageAuthor - .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast)) - if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) + viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView) } else { - binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) + binding.messageQuote.quoteColoredView.setBackgroundColor( + ContextCompat.getColor(binding.messageQuote.quoteColoredView.context, R.color.high_emphasis_text) + ) } } @@ -245,7 +223,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message individualHashMap["name"]!!, individualHashMap["type"]!!, message.activeUser!!, - R.xml.chip_you + R.xml.chip_you, + viewThemeUtils ) } else { messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan( @@ -255,7 +234,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message individualHashMap["name"]!!, individualHashMap["type"]!!, message.activeUser!!, - R.xml.chip_others + R.xml.chip_others, + viewThemeUtils ) } } else if (individualHashMap["type"] == "file") { diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt index 6102446e5..158fd2323 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicOutcomingTextMessageViewHolder.kt @@ -25,14 +25,13 @@ package com.nextcloud.talk.adapters.messages import android.content.Context import android.content.Intent +import android.graphics.PorterDuff import android.net.Uri import android.text.Spannable import android.text.SpannableString import android.util.TypedValue import android.view.View import androidx.core.content.res.ResourcesCompat -import androidx.core.graphics.ColorUtils -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.google.android.flexbox.FlexboxLayout @@ -43,15 +42,12 @@ import com.nextcloud.talk.databinding.ItemCustomOutcomingTextMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ReadStatus import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback -import com.nextcloud.talk.ui.theme.ServerTheme import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.DisplayUtils.getMessageSelector import com.nextcloud.talk.utils.DisplayUtils.searchAndReplaceWithMentionSpan import com.nextcloud.talk.utils.TextMatchers import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder import javax.inject.Inject -import kotlin.math.roundToInt @AutoInjector(NextcloudTalkApplication::class) class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewHolder(itemView) { @@ -64,9 +60,6 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage @Inject lateinit var viewThemeUtils: ViewThemeUtils - @Inject - lateinit var serverTheme: ServerTheme - lateinit var reactionsInterface: ReactionsInterface override fun onBind(message: ChatMessage) { @@ -75,18 +68,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage val messageParameters: HashMap>? = message.messageParameters var messageString: Spannable = SpannableString(message.text) realView.isSelected = false - binding.messageTime.setTextColor(ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_60_INT)) val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams layoutParams.isWrapBefore = false var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) + val textColor = viewThemeUtils.getScheme(binding.messageText.context).onSurfaceVariant + binding.messageTime.setTextColor(textColor) if (messageParameters != null && messageParameters.size > 0) { messageString = processMessageParameters(messageParameters, message, messageString) } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() layoutParams.isWrapBefore = true - binding.messageTime.setTextColor( - ResourcesCompat.getColor(context!!.resources, R.color.warm_grey_four, null) - ) realView.isSelected = true } @@ -94,9 +85,8 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageTime.layoutParams = layoutParams + binding.messageText.setTextColor(textColor) binding.messageText.text = messageString - binding.messageText.setTextColor(serverTheme.colorText) - binding.messageText.setLinkTextColor(serverTheme.colorText) // parent message handling if (!message.isDeleted && message.parentMessage != null) { @@ -121,7 +111,9 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage readStatusDrawableInt?.let { drawableInt -> ResourcesCompat.getDrawable(context!!.resources, drawableInt, null)?.let { binding.checkMark.setImageDrawable(it) - viewThemeUtils.colorImageViewText(binding.checkMark) + binding.checkMark.setColorFilter( + viewThemeUtils.getScheme(binding.messageText.context).onSurfaceVariant, PorterDuff.Mode.SRC_ATOP + ) } } @@ -129,7 +121,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage itemView.setTag(MessageSwipeCallback.REPLYABLE_VIEW_TAG, message.replyable) - Reaction().showReactions(message, binding.reactions, context!!, true) + Reaction().showReactions(message, binding.reactions, context, true, viewThemeUtils) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -141,6 +133,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage private fun processParentMessage(message: ChatMessage) { val parentChatMessage = message.parentMessage + val textColor = viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant parentChatMessage!!.activeUser = message.activeUser parentChatMessage.imageUrl?.let { binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE @@ -156,43 +149,14 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName ?: context!!.getText(R.string.nc_nick_guest) binding.messageQuote.quotedMessage.text = parentChatMessage.text - binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) - binding.messageQuote.quotedMessageAuthor.setTextColor( - ColorUtils.setAlphaComponent( - serverTheme.colorText, - ALPHA_80_INT - ) - ) - - binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText) + binding.messageQuote.quotedMessageAuthor.setTextColor(textColor) + binding.messageQuote.quotedMessage.setTextColor(textColor) + binding.messageQuote.quoteColoredView.setBackgroundColor(textColor) } private fun setBubbleOnChatMessage(message: ChatMessage) { - val resources = sharedApplication!!.resources - val elementColor = viewThemeUtils.getElementColor(binding.root.context) - val bgBubbleColor = if (message.isDeleted) { - ColorUtils.setAlphaComponent(elementColor, HALF_ALPHA_INT) - } else { - elementColor - } - if (message.isGrouped) { - val bubbleDrawable = getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_grouped_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } else { - val bubbleDrawable = getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } + viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted) } private fun processMessageParameters( @@ -215,7 +179,8 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage individualHashMap["name"]!!, individualHashMap["type"]!!, message.activeUser, - R.xml.chip_others + R.xml.chip_others, + viewThemeUtils ) } else if (individualHashMap["type"] == "file") { realView.setOnClickListener { v: View? -> @@ -234,8 +199,5 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage companion object { const val TEXT_SIZE_MULTIPLIER = 2.5 - private const val HALF_ALPHA_INT: Int = 255 / 2 - private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt() - private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt() } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java index e6c5a7d23..5b2609540 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/MagicPreviewMessageViewHolder.java @@ -42,6 +42,7 @@ import android.widget.PopupMenu; import android.widget.ProgressBar; import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.material.card.MaterialCardView; import com.nextcloud.talk.R; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.components.filebrowser.models.BrowserFile; @@ -50,7 +51,7 @@ import com.nextcloud.talk.components.filebrowser.webdav.ReadFilesystemOperation; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.models.json.chat.ChatMessage; -import com.nextcloud.talk.ui.theme.ServerTheme; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DrawableUtils; import com.nextcloud.talk.utils.FileViewerUtils; @@ -94,7 +95,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom Context context; @Inject - ServerTheme serverTheme; + ViewThemeUtils viewThemeUtils; @Inject OkHttpClient okHttpClient; @@ -149,6 +150,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom } progressBar = getProgressBar(); + viewThemeUtils.colorCircularProgressBar(getProgressBar()); image = getImage(); clickView = getImage(); getMessageText().setVisibility(View.VISIBLE); @@ -165,6 +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()); } else { getPreviewContainer().setVisibility(View.VISIBLE); getPreviewContactContainer().setVisibility(View.GONE); @@ -184,7 +189,8 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom if (drawable != null && (drawableResourceId == R.drawable.ic_mimetype_folder || drawableResourceId == R.drawable.ic_mimetype_package_x_generic)) { - drawable.setColorFilter(serverTheme.getPrimaryColor(), PorterDuff.Mode.SRC_ATOP); + drawable.setColorFilter(viewThemeUtils.getScheme(image.getContext()).getPrimary(), + PorterDuff.Mode.SRC_ATOP); } image.getHierarchy().setPlaceholderImage(drawable); @@ -239,7 +245,11 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable()); reactionsBinding = getReactionsBinding(); - new Reaction().showReactions(message, reactionsBinding, getMessageText().getContext(), true); + new Reaction().showReactions(message, + reactionsBinding, + getMessageText().getContext(), + true, + viewThemeUtils); reactionsBinding.reactionsEmojiWrapper.setOnClickListener(l -> { reactionsInterface.onClickReactions(message); }); @@ -353,7 +363,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom public abstract View getPreviewContainer(); - public abstract View getPreviewContactContainer(); + public abstract MaterialCardView getPreviewContactContainer(); public abstract SimpleDraweeView getPreviewContactPhoto(); diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt index fecf4af64..37ddc8bb6 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingLocationMessageViewHolder.kt @@ -25,6 +25,7 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context import android.content.Intent +import android.graphics.PorterDuff import android.net.Uri import android.util.Log import android.util.TypedValue @@ -34,9 +35,6 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.appcompat.content.res.AppCompatResources -import androidx.core.content.res.ResourcesCompat -import androidx.core.graphics.ColorUtils -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.google.android.flexbox.FlexboxLayout @@ -46,10 +44,8 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA import com.nextcloud.talk.databinding.ItemCustomOutcomingLocationMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ReadStatus -import com.nextcloud.talk.ui.theme.ServerTheme import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.UriUtils import com.stfalcon.chatkit.messages.MessageHolders import java.net.URLEncoder @@ -68,22 +64,20 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders var locationName: String? = "" var locationGeoLink: String? = "" - @JvmField @Inject - var context: Context? = null + lateinit var context: Context @Inject lateinit var viewThemeUtils: ViewThemeUtils - @Inject - lateinit var serverTheme: ServerTheme - lateinit var reactionsInterface: ReactionsInterface @SuppressLint("SetTextI18n") override fun onBind(message: ChatMessage) { super.onBind(message) sharedApplication!!.componentApplication.inject(this) + val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant + binding.messageTime.setTextColor(textColor) realView.isSelected = false val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams @@ -94,11 +88,8 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders colorizeMessageBubble(message) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageTime.layoutParams = layoutParams - binding.messageTime.setTextColor(ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_60_INT)) binding.messageText.text = message.text - binding.messageText.setTextColor(serverTheme.colorText) - binding.messageText.setLinkTextColor(serverTheme.colorText) // parent message handling setParentMessageDataOnMessageItem(message) @@ -118,7 +109,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context!!, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - viewThemeUtils.colorImageViewText(binding.checkMark) + binding.checkMark.setColorFilter( + viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, PorterDuff.Mode.SRC_ATOP + ) } } @@ -127,7 +120,13 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders // geo-location setLocationDataOnMessageItem(message) - Reaction().showReactions(message, binding.reactions, binding.messageText.context, true) + Reaction().showReactions( + message, + binding.reactions, + binding.messageText.context, + true, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -213,12 +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 - binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) - binding.messageQuote.quotedMessageAuthor.setTextColor( - ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_80_INT) - ) - - binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText) + viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) + viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) + viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView) binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE } else { @@ -227,30 +223,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = sharedApplication!!.resources - val elementColor = viewThemeUtils.getElementColor(binding.root.context) - val bgBubbleColor = if (message.isDeleted) { - ColorUtils.setAlphaComponent(elementColor, HALF_ALPHA_INT) - } else { - elementColor - } - if (message.isGrouped) { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_grouped_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } else { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } + viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted) } private fun openGeoLink() { @@ -277,6 +250,5 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders private const val TAG = "LocOutMessageView" private const val HALF_ALPHA_INT: Int = 255 / 2 private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt() - private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt() } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt index a418ac686..e8da3f5ba 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPollMessageViewHolder.kt @@ -23,12 +23,9 @@ package com.nextcloud.talk.adapters.messages import android.annotation.SuppressLint import android.content.Context -import android.content.res.ColorStateList +import android.graphics.PorterDuff import android.view.View import androidx.appcompat.content.res.AppCompatResources -import androidx.core.content.res.ResourcesCompat -import androidx.core.graphics.ColorUtils -import androidx.core.view.ViewCompat import autodagger.AutoInjector import coil.load import com.nextcloud.talk.R @@ -40,14 +37,11 @@ import com.nextcloud.talk.databinding.ItemCustomOutcomingPollMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ReadStatus import com.nextcloud.talk.polls.ui.PollMainDialogFragment -import com.nextcloud.talk.ui.theme.ServerTheme import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.preferences.AppPreferences import com.stfalcon.chatkit.messages.MessageHolders import javax.inject.Inject -import kotlin.math.roundToInt @AutoInjector(NextcloudTalkApplication::class) class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : MessageHolders @@ -62,9 +56,6 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag @Inject lateinit var viewThemeUtils: ViewThemeUtils - @Inject - lateinit var serverTheme: ServerTheme - @Inject lateinit var appPreferences: AppPreferences @@ -80,16 +71,12 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag super.onBind(message) this.message = message sharedApplication!!.componentApplication.inject(this) + val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant + binding.messageTime.setTextColor(textColor) colorizeMessageBubble(message) itemView.isSelected = false - binding.messageTime.setTextColor( - ColorUtils.setAlphaComponent( - serverTheme.colorText, - ALPHA_60_INT - ) - ) // parent message handling setParentMessageDataOnMessageItem(message) @@ -109,7 +96,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - viewThemeUtils.colorImageViewText(binding.checkMark) + binding.checkMark.setColorFilter( + viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, PorterDuff.Mode.SRC_ATOP + ) } } @@ -117,7 +106,13 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag setPollPreview(message) - Reaction().showReactions(message, binding.reactions, binding.messageTime.context, true) + Reaction().showReactions( + message, + binding.reactions, + binding.messageTime.context, + true, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -142,9 +137,6 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag } if (pollId != null && pollName != null) { - binding.messagePollTitle.setTextColor(serverTheme.colorText) - binding.messagePollSubtitle.setTextColor(serverTheme.colorText) - binding.messagePollIcon.imageTintList = ColorStateList.valueOf(serverTheme.colorText) binding.messagePollTitle.text = pollName val roomToken = (payload as? MessagePayload)!!.roomToken @@ -184,12 +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 - binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) - binding.messageQuote.quotedMessageAuthor.setTextColor( - ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_80_INT) - ) - - binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText) + viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) + viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) + viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView) binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE } else { @@ -198,30 +187,7 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = sharedApplication!!.resources - val elementColor = viewThemeUtils.getElementColor(binding.root.context) - val bgBubbleColor = if (message.isDeleted) { - ColorUtils.setAlphaComponent(elementColor, HALF_ALPHA_INT) - } else { - elementColor - } - if (message.isGrouped) { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_grouped_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } else { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } + viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted) } fun assignReactionInterface(reactionsInterface: ReactionsInterface) { @@ -230,8 +196,5 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag companion object { private val TAG = NextcloudTalkApplication::class.java.simpleName - private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt() - private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt() - private const val HALF_ALPHA_INT: Int = 255 / 2 } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java index 3456b02a7..9426cfab0 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingPreviewMessageViewHolder.java @@ -26,12 +26,17 @@ import android.view.View; import android.widget.ProgressBar; import com.facebook.drawee.view.SimpleDraweeView; +import com.google.android.material.card.MaterialCardView; +import com.nextcloud.talk.R; import com.nextcloud.talk.databinding.ItemCustomOutcomingPreviewMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; +import com.nextcloud.talk.models.json.chat.ChatMessage; +import androidx.core.content.ContextCompat; import androidx.emoji.widget.EmojiTextView; public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder { + private final ItemCustomOutcomingPreviewMessageBinding binding; public OutcomingPreviewMessageViewHolder(View itemView) { @@ -39,6 +44,16 @@ public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHo binding = ItemCustomOutcomingPreviewMessageBinding.bind(itemView); } + @Override + public void onBind(ChatMessage message) { + super.onBind(message); + + binding.messageText.setTextColor(ContextCompat.getColor(binding.messageText.getContext(), + R.color.no_emphasis_text)); + binding.messageTime.setTextColor(ContextCompat.getColor(binding.messageText.getContext(), + R.color.no_emphasis_text)); + } + @Override public EmojiTextView getMessageText() { return binding.messageText; @@ -60,7 +75,7 @@ public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHo } @Override - public View getPreviewContactContainer() { + public MaterialCardView getPreviewContactContainer() { return binding.contactContainer; } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt index 060897ba8..ffd94e1e4 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/OutcomingVoiceMessageViewHolder.kt @@ -31,9 +31,6 @@ import android.view.View import android.widget.SeekBar import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat -import androidx.core.content.res.ResourcesCompat -import androidx.core.graphics.ColorUtils -import androidx.core.view.ViewCompat import androidx.work.WorkInfo import androidx.work.WorkManager import autodagger.AutoInjector @@ -44,15 +41,12 @@ import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedA import com.nextcloud.talk.databinding.ItemCustomOutcomingVoiceMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ReadStatus -import com.nextcloud.talk.ui.theme.ServerTheme import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils -import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.preferences.AppPreferences import com.stfalcon.chatkit.messages.MessageHolders import java.util.concurrent.ExecutionException import javax.inject.Inject -import kotlin.math.roundToInt @AutoInjector(NextcloudTalkApplication::class) class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders @@ -68,9 +62,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders @Inject lateinit var viewThemeUtils: ViewThemeUtils - @Inject - lateinit var serverTheme: ServerTheme - @JvmField @Inject var appPreferences: AppPreferences? = null @@ -87,23 +78,20 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders super.onBind(message) this.message = message sharedApplication!!.componentApplication.inject(this) + val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant + binding.messageTime.setTextColor(textColor) colorizeMessageBubble(message) itemView.isSelected = false - binding.messageTime.setTextColor( - ColorUtils.setAlphaComponent( - serverTheme.colorText, - ALPHA_60_INT - ) - ) // parent message handling setParentMessageDataOnMessageItem(message) updateDownloadState(message) binding.seekbar.max = message.voiceMessageDuration - viewThemeUtils.themeHorizontalSeekBar(binding.seekbar, serverTheme.colorText) + viewThemeUtils.themeHorizontalSeekBar(binding.seekbar) + viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar) handleIsPlayingVoiceMessageState(message) @@ -142,13 +130,21 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders readStatusDrawableInt?.let { drawableInt -> AppCompatResources.getDrawable(context!!, drawableInt)?.let { binding.checkMark.setImageDrawable(it) - viewThemeUtils.colorImageViewText(binding.checkMark) + binding.checkMark.setColorFilter( + viewThemeUtils.getScheme(binding.checkMark.context).onSurfaceVariant, PorterDuff.Mode.SRC_ATOP + ) } } binding.checkMark.setContentDescription(readStatusContentDescriptionString) - Reaction().showReactions(message, binding.reactions, binding.messageTime.context, true) + Reaction().showReactions( + message, + binding.reactions, + binding.messageTime.context, + true, + viewThemeUtils + ) binding.reactions.reactionsEmojiWrapper.setOnClickListener { reactionsInterface.onClickReactions(message) } @@ -165,7 +161,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders context!!, R.drawable.ic_baseline_play_arrow_voice_message_24 ) - binding.playPauseBtn.icon.setColorFilter(serverTheme.colorText, PorterDuff.Mode.SRC_ATOP) binding.seekbar.progress = SEEKBAR_START message.resetVoiceMessage = false } @@ -186,7 +181,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders context!!, R.drawable.ic_baseline_pause_voice_message_24 ) - binding.playPauseBtn.icon.setColorFilter(serverTheme.colorText, PorterDuff.Mode.SRC_ATOP) binding.seekbar.progress = message.voiceMessagePlayedSeconds } else { binding.playPauseBtn.visibility = View.VISIBLE @@ -194,7 +188,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders context!!, R.drawable.ic_baseline_play_arrow_voice_message_24 ) - binding.playPauseBtn.icon.setColorFilter(serverTheme.colorText, PorterDuff.Mode.SRC_ATOP) } } @@ -270,15 +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 - binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) - binding.messageQuote.quotedMessageAuthor.setTextColor( - ColorUtils.setAlphaComponent( - serverTheme.colorText, - ALPHA_80_INT - ) - ) - - binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText) + viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage) + viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor) + viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView) binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE } else { @@ -287,30 +274,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders } private fun colorizeMessageBubble(message: ChatMessage) { - val resources = sharedApplication!!.resources - val elementColor = viewThemeUtils.getElementColor(binding.root.context) - val bgBubbleColor = if (message.isDeleted) { - ColorUtils.setAlphaComponent(elementColor, HALF_ALPHA_INT) - } else { - elementColor - } - if (message.isGrouped) { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_grouped_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } else { - val bubbleDrawable = DisplayUtils.getMessageSelector( - bgBubbleColor, - ResourcesCompat.getColor(resources, R.color.transparent, null), - bgBubbleColor, - R.drawable.shape_outcoming_message - ) - ViewCompat.setBackground(bubble, bubbleDrawable) - } + viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted) } fun assignVoiceMessageInterface(voiceMessageInterface: VoiceMessageInterface) { @@ -324,8 +288,5 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders companion object { private const val TAG = "VoiceOutMessageView" private const val SEEKBAR_START: Int = 0 - private const val HALF_ALPHA_INT: Int = 255 / 2 - private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt() - private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt() } } diff --git a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt index 08ae5d868..1eff0dae0 100644 --- a/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt +++ b/app/src/main/java/com/nextcloud/talk/adapters/messages/Reaction.kt @@ -27,11 +27,11 @@ import android.content.Context import android.view.ViewGroup import android.widget.LinearLayout import android.widget.TextView -import androidx.appcompat.content.res.AppCompatResources import androidx.core.content.ContextCompat import com.nextcloud.talk.R import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.models.json.chat.ChatMessage +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils import com.vanniktech.emoji.EmojiTextView @@ -41,7 +41,8 @@ class Reaction { message: ChatMessage, binding: ReactionsInsideMessageBinding, context: Context, - isOutgoingMessage: Boolean + isOutgoingMessage: Boolean, + viewThemeUtils: ViewThemeUtils ) { binding.reactionsEmojiWrapper.removeAllViews() if (message.reactions != null && message.reactions!!.isNotEmpty()) { @@ -49,7 +50,6 @@ class Reaction { var remainingEmojisToDisplay = MAX_EMOJIS_TO_DISPLAY val showInfoAboutMoreEmojis = message.reactions!!.size > MAX_EMOJIS_TO_DISPLAY - val textColor = getTextColor(context, isOutgoingMessage, binding) val amountParams = getAmountLayoutParams(context) val wrapperParams = getWrapperLayoutParams(context) @@ -58,9 +58,12 @@ class Reaction { val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt() for ((emoji, amount) in message.reactions!!) { + val isSelfReaction = message.reactionsSelf != null && + message.reactionsSelf!!.isNotEmpty() && + message.reactionsSelf!!.contains(emoji) + val textColor = getTextColor(isOutgoingMessage, isSelfReaction, binding, viewThemeUtils) val emojiWithAmountWrapper = getEmojiWithAmountWrapperLayout( - context, - message, + binding.reactionsEmojiWrapper.context, emoji, amount, EmojiWithAmountWrapperLayoutInfo( @@ -69,7 +72,10 @@ class Reaction { wrapperParams, paddingSide, paddingTop, - paddingBottom + paddingBottom, + viewThemeUtils, + isOutgoingMessage, + isSelfReaction ), ) @@ -86,7 +92,6 @@ class Reaction { private fun getEmojiWithAmountWrapperLayout( context: Context, - message: ChatMessage, emoji: String, amount: Int, layoutInfo: EmojiWithAmountWrapperLayoutInfo @@ -98,12 +103,17 @@ class Reaction { emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, layoutInfo.amountParams)) emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams - if (message.reactionsSelf != null && - message.reactionsSelf!!.isNotEmpty() && - message.reactionsSelf!!.contains(emoji) - ) { - emojiWithAmountWrapper.background = - AppCompatResources.getDrawable(context, R.drawable.reaction_self_background) + if (layoutInfo.isSelfReaction) { + val color = if (layoutInfo.isOutgoingMessage) { + ContextCompat.getColor( + emojiWithAmountWrapper.context, + R.color.bg_message_list_incoming_bubble + ) + } else { + layoutInfo.viewThemeUtils.getScheme(emojiWithAmountWrapper.context).primaryContainer + } + layoutInfo.viewThemeUtils.setCheckedBackground(emojiWithAmountWrapper, color) + emojiWithAmountWrapper.setPaddingRelative( layoutInfo.paddingSide, layoutInfo.paddingTop, @@ -166,12 +176,13 @@ class Reaction { } private fun getTextColor( - context: Context, isOutgoingMessage: Boolean, - binding: ReactionsInsideMessageBinding + isSelfReaction: Boolean, + binding: ReactionsInsideMessageBinding, + viewThemeUtils: ViewThemeUtils ): Int { - var textColor = ContextCompat.getColor(context, R.color.white) - if (!isOutgoingMessage) { + var textColor = viewThemeUtils.getScheme(binding.root.context).onSurfaceVariant + if (!isOutgoingMessage || isSelfReaction) { textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) } return textColor @@ -183,7 +194,10 @@ class Reaction { val wrapperParams: LinearLayout.LayoutParams, val paddingSide: Int, val paddingTop: Int, - val paddingBottom: Int + val paddingBottom: Int, + val viewThemeUtils: ViewThemeUtils, + val isOutgoingMessage: Boolean, + val isSelfReaction: Boolean ) companion object { diff --git a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java index 6c4985c48..c121946b1 100644 --- a/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java +++ b/app/src/main/java/com/nextcloud/talk/callbacks/MentionAutocompleteCallback.java @@ -31,6 +31,7 @@ import com.facebook.widget.text.span.BetterImageSpan; import com.nextcloud.talk.R; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.models.json.mention.Mention; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.MagicCharPolicy; import com.nextcloud.talk.utils.text.Spans; @@ -39,15 +40,19 @@ import com.vanniktech.emoji.EmojiRange; import com.vanniktech.emoji.Emojis; public class MentionAutocompleteCallback implements AutocompleteCallback { + private final ViewThemeUtils viewThemeUtils; private Context context; private User conversationUser; private EditText editText; - public MentionAutocompleteCallback(Context context, User conversationUser, - EditText editText) { + public MentionAutocompleteCallback(Context context, + User conversationUser, + EditText editText, + ViewThemeUtils viewThemeUtils) { this.context = context; this.conversationUser = conversationUser; this.editText = editText; + this.viewThemeUtils = viewThemeUtils; } @Override @@ -73,11 +78,14 @@ public class MentionAutocompleteCallback implements AutocompleteCallback context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let { - String.format(it, title) + String.format(it, title.trim()) } else -> context?.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let { - String.format(it, title) + String.format(it, title.trim()) } } - LovelyStandardDialog(activity) - .setPositiveButtonColorRes(R.color.nc_darkGreen) + val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageInputView.context) .setTitle(confirmationQuestion) .setMessage(filenamesWithLinebreaks.toString()) - .setPositiveButton(R.string.nc_yes) { v -> - if (UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) { + .setPositiveButton(R.string.nc_yes) { _, _ -> + if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) { uploadFiles(filesToUpload, false) } else { UploadAndShareFilesWorker.requestStoragePermission(this) } } - .setNegativeButton(R.string.nc_no) { + .setNegativeButton(R.string.nc_no) { _, _ -> // unused atm } - .show() + + viewThemeUtils.colorMaterialAlertDialogBackground( + binding.messageInputView.context, + materialAlertDialogBuilder + ) + + val dialog = materialAlertDialogBuilder.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } catch (e: IllegalStateException) { Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG) .show() @@ -1683,7 +1683,8 @@ class ChatController(args: Bundle) : val callback = MentionAutocompleteCallback( activity, conversationUser!!, - binding.messageInputView.inputEditText + binding.messageInputView.inputEditText, + viewThemeUtils ) if (mentionAutocomplete == null && binding.messageInputView.inputEditText != null) { @@ -1764,6 +1765,8 @@ class ChatController(args: Bundle) : cancelReply() } + viewThemeUtils.themeImageButton(binding.messageInputView.findViewById(R.id.cancelReplyButton)) + cancelNotificationsForCurrentConversation() Log.d(TAG, "onAttach inConversation: " + inConversation.toString()) @@ -2487,6 +2490,16 @@ class ChatController(args: Bundle) : super.onCreateOptionsMenu(menu, inflater) inflater.inflate(R.menu.menu_conversation, menu) + viewThemeUtils.colorToolbarMenuIcon( + binding.messageInputView.context, + menu.findItem(R.id.conversation_voice_call) + ) + + viewThemeUtils.colorToolbarMenuIcon( + binding.messageInputView.context, + menu.findItem(R.id.conversation_video_call) + ) + if (conversationUser?.userId == "?") { menu.removeItem(R.id.conversation_info) } else { @@ -2685,8 +2698,7 @@ class ChatController(args: Bundle) : chatMessage, conversationUser, hasChatPermission, - ncApi!!, - serverTheme + ncApi ).show() } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt index 04398483f..29799f224 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ContactsController.kt @@ -65,7 +65,6 @@ import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.ui.dialog.ContactsBottomDialog import com.nextcloud.talk.users.UserManager -import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ConductorRemapping import com.nextcloud.talk.utils.bundle.BundleKeys @@ -104,9 +103,6 @@ class ContactsController(args: Bundle) : @Inject lateinit var ncApi: NcApi - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - private var credentials: String? = null private var currentUser: User? = null private var contactsQueryDisposable: Disposable? = null @@ -338,6 +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!!) 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 @@ -381,6 +378,14 @@ class ContactsController(args: Bundle) : override fun onPrepareOptionsMenu(menu: Menu) { super.onPrepareOptionsMenu(menu) + + if (searchItem != null) { + viewThemeUtils.colorToolbarMenuIcon( + binding.titleTextView.context, + searchItem!! + ) + } + checkAndHandleDoneMenuItem() if (adapter?.hasFilter() == true) { searchItem!!.expandActionView() @@ -632,6 +637,7 @@ class ContactsController(args: Bundle) : ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null), PorterDuff.Mode.SRC_IN ) + viewThemeUtils.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink) disengageProgressBar() } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt index 6347acbb8..43602e232 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationInfoController.kt @@ -30,6 +30,7 @@ import android.annotation.SuppressLint import android.content.Intent import android.graphics.drawable.Drawable import android.graphics.drawable.LayerDrawable +import android.os.Build import android.os.Bundle import android.os.Parcelable import android.text.TextUtils @@ -73,7 +74,6 @@ import com.nextcloud.talk.models.json.participants.Participant.ActorType.GROUPS import com.nextcloud.talk.models.json.participants.Participant.ActorType.USERS import com.nextcloud.talk.models.json.participants.ParticipantsOverall import com.nextcloud.talk.shareditems.activities.SharedItemsActivity -import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DateConstants import com.nextcloud.talk.utils.DateUtils @@ -113,9 +113,6 @@ class ConversationInfoController(args: Bundle) : @Inject lateinit var eventBus: EventBus - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - private val conversationToken: String? private val conversationUser: User? private val hasAvatarSpacing: Boolean @@ -234,6 +231,8 @@ class ConversationInfoController(args: Bundle) : } binding.addParticipantsAction.visibility = View.GONE + + viewThemeUtils.colorCircularProgressBar(binding.progressBar) } private fun setupWebinaryView() { @@ -437,7 +436,7 @@ class ConversationInfoController(args: Bundle) : for (i in participants.indices) { participant = participants[i] - userItem = ParticipantItem(router.activity, participant, conversationUser) + userItem = ParticipantItem(router.activity, participant, conversationUser, viewThemeUtils) if (participant.sessionId != null) { userItem.isOnline = !participant.sessionId.equals("0") } else { @@ -789,12 +788,32 @@ class ConversationInfoController(args: Bundle) : .build() binding.avatarImage.controller = draweeController } - Conversation.ConversationType.ROOM_GROUP_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( - R.drawable.ic_circular_group - ) - Conversation.ConversationType.ROOM_PUBLIC_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( - R.drawable.ic_circular_link - ) + Conversation.ConversationType.ROOM_GROUP_CALL -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + binding.avatarImage.hierarchy.setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_group) + ) + ) + } else { + binding.avatarImage.hierarchy.setPlaceholderImage( + R.drawable.ic_circular_group + ) + } + } + Conversation.ConversationType.ROOM_PUBLIC_CALL -> { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + binding.avatarImage.hierarchy.setPlaceholderImage( + DisplayUtils.getRoundedDrawable( + viewThemeUtils.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_link) + ) + ) + } else { + binding.avatarImage.hierarchy.setPlaceholderImage( + R.drawable.ic_circular_link + ) + } + } Conversation.ConversationType.ROOM_SYSTEM -> { val layers = arrayOfNulls(2) layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java index 72a953d8b..e002adbee 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/ConversationsListController.java @@ -31,9 +31,7 @@ import android.content.ClipData; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; -import android.content.res.ColorStateList; import android.graphics.Bitmap; -import android.graphics.Color; import android.net.Uri; import android.os.Build; import android.os.Bundle; @@ -341,6 +339,7 @@ public class ConversationsListController extends BaseController implements Flexi credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()); if (getActivity() != null && getActivity() instanceof MainActivity) { loadUserAvatar(((MainActivity) getActivity()).binding.switchAccountButton); + viewThemeUtils.colorMaterialTextButton(((MainActivity) getActivity()).binding.switchAccountButton); } fetchData(); } @@ -359,7 +358,7 @@ public class ConversationsListController extends BaseController implements Flexi SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE); if (searchItem != null) { searchView = (SearchView) MenuItemCompat.getActionView(searchItem); - DisplayUtils.themeSearchView(searchView, context); + viewThemeUtils.themeSearchView(searchView); searchView.setMaxWidth(Integer.MAX_VALUE); searchView.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER); int imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_FULLSCREEN; @@ -421,23 +420,15 @@ public class ConversationsListController extends BaseController implements Flexi activity.binding.searchText.setOnClickListener(v -> { showSearchView(activity, searchView, searchItem); - if (getResources() != null) { - DisplayUtils.applyColorToStatusBar( - activity, - ResourcesCompat.getColor(getResources(), R.color.appbar, null) - ); - } + viewThemeUtils.themeStatusBar(activity, searchView); }); } searchView.setOnCloseListener(() -> { if (TextUtils.isEmpty(searchView.getQuery().toString())) { searchView.onActionViewCollapsed(); - if (activity != null && getResources() != null) { - DisplayUtils.applyColorToStatusBar( - activity, - ResourcesCompat.getColor(getResources(), R.color.bg_default, null) - ); + if (activity != null) { + viewThemeUtils.resetStatusBar(activity, searchView); } } else { searchView.post(() -> searchView.setQuery(TAG, true)); @@ -481,10 +472,7 @@ public class ConversationsListController extends BaseController implements Flexi activity.binding.toolbar.setVisibility(View.GONE); activity.binding.searchToolbar.setVisibility(View.VISIBLE); if (getResources() != null) { - DisplayUtils.applyColorToStatusBar( - activity, - ResourcesCompat.getColor(getResources(), R.color.bg_default, null) - ); + viewThemeUtils.resetStatusBar(activity, activity.binding.searchToolbar); } } SmoothScrollLinearLayoutManager layoutManager = @@ -816,9 +804,7 @@ public class ConversationsListController extends BaseController implements Flexi recyclerView.smoothScrollToPosition(nextUnreadConversationScrollPosition); } }); - - newMentionPopupBubble.setTextColor(Color.WHITE); - newMentionPopupBubble.setIconTint(ColorStateList.valueOf(Color.WHITE)); + viewThemeUtils.colorMaterialButtonPrimaryFilled(newMentionPopupBubble); } private void checkToShowUnreadBubble() { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt index add4ac128..caa597562 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/ProfileController.kt @@ -39,9 +39,7 @@ import android.view.MenuItem import android.view.View import android.view.ViewGroup import android.widget.Toast -import androidx.annotation.ColorInt import androidx.annotation.DrawableRes -import androidx.core.graphics.drawable.DrawableCompat import androidx.core.view.ViewCompat import androidx.recyclerview.widget.RecyclerView import autodagger.AutoInjector @@ -108,9 +106,6 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { @Inject lateinit var permissionUtil: PlatformPermissionUtil - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - private var currentUser: User? = null private var edit = false private var adapter: UserInfoAdapter? = null @@ -197,7 +192,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { override fun onAttach(view: View) { super.onAttach(view) - adapter = UserInfoAdapter(null, viewThemeUtils.getElementColor(activity!!), this) + adapter = UserInfoAdapter(null, viewThemeUtils, this) binding.userinfoList.adapter = adapter binding.userinfoList.setItemViewCacheSize(DEFAULT_CACHE_SIZE) currentUser = userManager.currentUser.blockingGet() @@ -266,8 +261,10 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { } private fun colorIcons() { - viewThemeUtils.colorImageView(binding.avatarChoose) - viewThemeUtils.colorImageView(binding.avatarCamera) + viewThemeUtils.themeFAB(binding.avatarChoose) + viewThemeUtils.themeFAB(binding.avatarCamera) + viewThemeUtils.themeFAB(binding.avatarUpload) + viewThemeUtils.themeFAB(binding.avatarDelete) } private fun isAllEmpty(items: Array): Boolean { @@ -710,18 +707,18 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { class UserInfoAdapter( displayList: List?, - @ColorInt tintColor: Int, - controller: ProfileController + private val viewThemeUtils: ViewThemeUtils, + private val controller: ProfileController ) : RecyclerView.Adapter() { var displayList: List? var filteredDisplayList: MutableList = LinkedList() - @ColorInt - protected var mTintColor: Int - private val controller: ProfileController - class ViewHolder(val binding: UserInfoDetailsTableItemBinding) : RecyclerView.ViewHolder(binding.root) + init { + this.displayList = displayList ?: LinkedList() + } + fun setData(displayList: List) { this.displayList = displayList updateFilteredList() @@ -758,7 +755,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { initUserInfoEditText(holder, item) holder.binding.icon.contentDescription = item.hint - DrawableCompat.setTint(holder.binding.icon.drawable, mTintColor) + viewThemeUtils.colorImageView(holder.binding.icon) if (!TextUtils.isEmpty(item.text) || controller.edit) { holder.binding.userInfoDetailContainer.visibility = View.VISIBLE controller.viewThemeUtils.colorTextInputLayout(holder.binding.userInfoInputLayout) @@ -853,12 +850,6 @@ class ProfileController : NewBaseController(R.layout.controller_profile) { displayList!![position].scope = scope notifyDataSetChanged() } - - init { - this.displayList = displayList ?: LinkedList() - mTintColor = tintColor - this.controller = controller - } } enum class Field(val fieldName: String, val scopeName: String) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt index 3ad36737b..f903aab9c 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/SettingsController.kt @@ -60,6 +60,7 @@ import com.bluelinelabs.conductor.Controller import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.textfield.TextInputLayout import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.R @@ -78,7 +79,6 @@ import com.nextcloud.talk.jobs.ContactAddressBookWorker.Companion.deleteAll import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.userprofile.UserProfileOverall import com.nextcloud.talk.users.UserManager -import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.LoggingUtils.sendMailWithAttachment @@ -92,7 +92,6 @@ import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.preferences.MagicUserInputModule import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder import com.yarolegovich.lovelydialog.LovelySaveStateHandler -import com.yarolegovich.lovelydialog.LovelyStandardDialog import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable @@ -119,10 +118,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { @Inject lateinit var currentUserProvider: CurrentUserProviderNew - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - - private var saveStateHandler: LovelySaveStateHandler? = null private var currentUser: User? = null private var credentials: String? = null private var proxyTypeChangeListener: OnPreferenceValueChangedListener? = null @@ -154,10 +149,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { getCurrentUser() - if (saveStateHandler == null) { - saveStateHandler = LovelySaveStateHandler() - } - registerChangeListeners() setupSettingsScreen() @@ -385,11 +376,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { } } - override fun onSaveViewState(view: View, outState: Bundle) { - saveStateHandler!!.saveInstanceState(outState) - super.onSaveViewState(view, outState) - } - override fun onRestoreViewState(view: View, savedViewState: Bundle) { super.onRestoreViewState(view, savedViewState) if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) { @@ -401,23 +387,27 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { private fun showRemoveAccountWarning(savedInstanceState: Bundle?) { if (activity != null) { - LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL) - .setTopColorRes(R.color.nc_darkRed) - .setIcon( - DisplayUtils.getTintedDrawable( - resources, - R.drawable.ic_delete_black_24dp, - R.color.bg_default - ) - ) - .setPositiveButtonColor(context!!.resources.getColor(R.color.nc_darkRed)) + val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageText.context) .setTitle(R.string.nc_settings_remove_account) .setMessage(R.string.nc_settings_remove_confirmation) - .setPositiveButton(R.string.nc_settings_remove, { removeCurrentAccount() }) - .setNegativeButton(R.string.nc_cancel, null) - .setInstanceStateHandler(ID_REMOVE_ACCOUNT_WARNING_DIALOG, saveStateHandler) - .setSavedInstanceState(savedInstanceState) - .show() + .setPositiveButton(R.string.nc_settings_remove) { _, _ -> + removeCurrentAccount() + } + .setNegativeButton(R.string.nc_cancel) { _, _ -> + // unused atm + } + + viewThemeUtils.colorMaterialAlertDialogBackground( + binding.messageText.context, + materialAlertDialogBuilder + ) + + val dialog = materialAlertDialogBuilder.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } } @@ -566,7 +556,9 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { if (ApplicationWideMessageHolder.getInstance().messageType != null) { when (ApplicationWideMessageHolder.getInstance().messageType) { ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED -> { - binding.messageText.setTextColor(resources!!.getColor(R.color.colorPrimary)) + binding.messageText.setTextColor( + viewThemeUtils.getScheme(binding.messageText.context).primary + ) binding.messageText.text = resources!!.getString(R.string.nc_settings_account_updated) binding.messageView.visibility = View.VISIBLE } @@ -575,13 +567,17 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { binding.messageText.setTextColor(resources!!.getColor(R.color.nc_darkRed)) binding.messageText.text = resources!!.getString(R.string.nc_settings_wrong_account) binding.messageView.visibility = View.VISIBLE - binding.messageText.setTextColor(resources!!.getColor(R.color.colorPrimary)) + binding.messageText.setTextColor( + viewThemeUtils.getScheme(binding.messageText.context).primary + ) binding.messageText.text = resources!!.getString(R.string.nc_Server_account_imported) binding.messageView.visibility = View.VISIBLE } ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED -> { - binding.messageText.setTextColor(resources!!.getColor(R.color.colorPrimary)) + binding.messageText.setTextColor( + viewThemeUtils.getScheme(binding.messageText.context).primary + ) binding.messageText.text = resources!!.getString(R.string.nc_Server_account_imported) binding.messageView.visibility = View.VISIBLE } @@ -961,13 +957,16 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { }) phoneNumberInputLayout.addView(phoneNumberField) phoneNumberLayoutWrapper.addView(phoneNumberInputLayout) - val dialog = AlertDialog.Builder((activity)!!) + val dialogBuilder = MaterialAlertDialogBuilder(phoneNumberInputLayout.context) .setTitle(R.string.nc_settings_phone_book_integration_phone_number_dialog_title) .setMessage(R.string.nc_settings_phone_book_integration_phone_number_dialog_description) .setView(phoneNumberLayoutWrapper) .setPositiveButton(context!!.resources.getString(R.string.nc_common_set), null) .setNegativeButton(context!!.resources.getString(R.string.nc_common_skip), null) - .create() + + viewThemeUtils.colorMaterialAlertDialogBackground(phoneNumberInputLayout.context, dialogBuilder) + + val dialog = dialogBuilder.create() dialog.setOnShowListener(object : OnShowListener { override fun onShow(dialogInterface: DialogInterface) { val button = dialog.getButton(AlertDialog.BUTTON_POSITIVE) @@ -978,7 +977,13 @@ class SettingsController : NewBaseController(R.layout.controller_settings) { }) } }) + dialog.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } private fun setPhoneNumber(textInputLayout: TextInputLayout, dialog: AlertDialog) { diff --git a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt index b4ac8e152..0c16840a0 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/SwitchAccountController.kt @@ -138,7 +138,7 @@ class SwitchAccountController(args: Bundle? = null) : participant.actorType = Participant.ActorType.USERS participant.actorId = userId participant.displayName = user.displayName - userItems.add(AdvancedUserItem(participant, user, null)) + userItems.add(AdvancedUserItem(participant, user, null, viewThemeUtils)) } } adapter!!.addListener(onSwitchItemClickListener) @@ -156,7 +156,7 @@ class SwitchAccountController(args: Bundle? = null) : participant.displayName = importAccount.getUsername() user = User() user.baseUrl = importAccount.getBaseUrl() - userItems.add(AdvancedUserItem(participant, user, account)) + userItems.add(AdvancedUserItem(participant, user, account, viewThemeUtils)) } adapter!!.addListener(onImportItemClickListener) adapter!!.updateDataSet(userItems, false) diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java index 52c77b5ee..d88b143ec 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/BaseController.java @@ -49,6 +49,7 @@ import com.nextcloud.talk.controllers.ServerSelectionController; import com.nextcloud.talk.controllers.SwitchAccountController; import com.nextcloud.talk.controllers.WebViewLoginController; import com.nextcloud.talk.controllers.base.providers.ActionBarProvider; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.preferences.AppPreferences; @@ -70,9 +71,13 @@ public abstract class BaseController extends ButterKnifeController { private static final String TAG = "BaseController"; @Inject AppPreferences appPreferences; + @Inject Context context; + @Inject + ViewThemeUtils viewThemeUtils; + protected BaseController() { cleanTempCertPreference(); } @@ -109,12 +114,19 @@ public abstract class BaseController extends ButterKnifeController { @Override protected void onViewBound(@NonNull View view) { super.onViewBound(view); + MainActivity activity = null; + + if (getActivity() != null && getActivity() instanceof MainActivity) { + activity = (MainActivity) getActivity(); + viewThemeUtils.themeCardView(activity.binding.searchToolbar); + viewThemeUtils.themeToolbar(activity.binding.toolbar); + viewThemeUtils.themeSearchBarText(activity.binding.searchText); + } if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.getIsKeyboardIncognito()) { disableKeyboardPersonalisedLearning((ViewGroup) view); - if (getActivity() != null && getActivity() instanceof MainActivity) { - MainActivity activity = (MainActivity) getActivity(); + if (activity != null) { disableKeyboardPersonalisedLearning(activity.binding.appBar); } } @@ -174,15 +186,9 @@ public abstract class BaseController extends ButterKnifeController { if ((getResources() != null)) { if (showSearchBar) { - DisplayUtils.applyColorToStatusBar( - activity, ResourcesCompat.getColor(getResources(), - R.color.bg_default, null) - ); + viewThemeUtils.resetStatusBar(activity, activity.binding.searchToolbar); } else { - DisplayUtils.applyColorToStatusBar( - activity, ResourcesCompat.getColor(getResources(), - R.color.appbar, null) - ); + viewThemeUtils.themeStatusBar(activity, activity.binding.searchToolbar); } } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/base/NewBaseController.kt b/app/src/main/java/com/nextcloud/talk/controllers/base/NewBaseController.kt index a26f39247..065c3b078 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/base/NewBaseController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/base/NewBaseController.kt @@ -56,6 +56,7 @@ import com.nextcloud.talk.controllers.WebViewLoginController import com.nextcloud.talk.controllers.base.providers.ActionBarProvider import com.nextcloud.talk.controllers.util.ControllerViewBindingDelegate import com.nextcloud.talk.databinding.ActivityMainBinding +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.preferences.AppPreferences import javax.inject.Inject @@ -73,6 +74,9 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? = @Inject lateinit var context: Context + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + protected open val title: String? get() = null @@ -115,11 +119,19 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? = } protected open fun onViewBound(view: View) { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences!!.isKeyboardIncognito) { - disableKeyboardPersonalisedLearning(view as ViewGroup) - if (activity != null && activity is MainActivity) { - val activity = activity as MainActivity? - disableKeyboardPersonalisedLearning(activity!!.binding.appBar) + var activity: MainActivity? = null + + 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) + } + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.isKeyboardIncognito) { + disableKeyboardPersonalisedLearning((view as ViewGroup)) + if (activity != null) { + disableKeyboardPersonalisedLearning(activity.binding.appBar) } } } @@ -176,6 +188,7 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? = val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams binding.searchToolbar.visibility = View.GONE binding.toolbar.visibility = View.VISIBLE + viewThemeUtils.colorToolbarOverflowIcon(binding.toolbar) layoutParams.scrollFlags = 0 binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( binding.appBar.context, @@ -192,19 +205,9 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? = private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) { if (activity != null && resources != null) { if (showSearchBar) { - DisplayUtils.applyColorToStatusBar( - activity, - ResourcesCompat.getColor( - resources, R.color.bg_default, null - ) - ) + view?.let { viewThemeUtils.resetStatusBar(activity, it) } } else { - DisplayUtils.applyColorToStatusBar( - activity, - ResourcesCompat.getColor( - resources, R.color.appbar, null - ) - ) + view?.let { viewThemeUtils.themeStatusBar(activity, it) } } } } diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt index c7e45e489..79b6a15f2 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/EntryMenuController.kt @@ -46,8 +46,6 @@ import com.nextcloud.talk.controllers.base.NewBaseController import com.nextcloud.talk.controllers.util.viewBinding import com.nextcloud.talk.databinding.ControllerEntryMenuBinding import com.nextcloud.talk.models.json.conversations.Conversation -import com.nextcloud.talk.ui.theme.ServerTheme -import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.ShareUtils import com.nextcloud.talk.utils.UriUtils @@ -74,12 +72,6 @@ class EntryMenuController(args: Bundle) : @Inject lateinit var userManager: UserManager - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - - @Inject - lateinit var serverTheme: ServerTheme - private val operation: ConversationOperationEnum private var conversation: Conversation? = null private var shareIntent: Intent? = null diff --git a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt index db94f4074..89f9402af 100644 --- a/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt +++ b/app/src/main/java/com/nextcloud/talk/controllers/bottomsheet/OperationsMenuController.kt @@ -117,6 +117,8 @@ class OperationsMenuController(args: Bundle) : NewBaseController( sharedApplication!!.componentApplication.inject(this) currentUser = userManager.currentUser.blockingGet() + viewThemeUtils.colorCircularProgressBar(binding.progressBar) + if (!TextUtils.isEmpty(callUrl) && callUrl.contains("/call")) { conversationToken = callUrl.substring(callUrl.lastIndexOf("/") + 1) if (callUrl.contains("/index.php")) { diff --git a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java index 24c1a5b31..7bcaef1e6 100644 --- a/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java +++ b/app/src/main/java/com/nextcloud/talk/jobs/NotificationWorker.java @@ -346,6 +346,7 @@ public class NotificationWorker extends Worker { if (Build.VERSION.SDK_INT >= 23) { // This method should exist since API 21, but some phones don't have it // So as a safeguard, we don't use it until 23 + notificationBuilder.setColor(context.getResources().getColor(R.color.colorPrimary)); } diff --git a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt index a9d553b25..0f2a732a0 100644 --- a/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/messagesearch/MessageSearchActivity.kt @@ -41,7 +41,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.ActivityMessageSearchBinding -import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew @@ -65,9 +64,6 @@ class MessageSearchActivity : BaseActivity() { @Inject lateinit var userProvider: CurrentUserProviderNew - @Inject - lateinit var viewThemeUtils: ViewThemeUtils - private lateinit var binding: ActivityMessageSearchBinding private lateinit var searchView: SearchView diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt index 8e3016fb4..f970d0f68 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollCreateOptionViewHolder.kt @@ -50,7 +50,7 @@ class PollCreateOptionViewHolder( } binding.pollOptionTextEdit.setText(pollCreateOptionItem.pollOption) - viewThemeUtils.colorEditText(binding.pollOptionTextEdit) + viewThemeUtils.colorTextInputLayout(binding.pollOptionTextInputLayout) if (focus) { itemsListener.requestFocus(binding.pollOptionTextEdit) diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt index f08cb68cf..3595471ca 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultHeaderViewHolder.kt @@ -41,6 +41,9 @@ class PollResultHeaderViewHolder( binding.pollOptionText.text = item.name binding.pollOptionPercentText.text = "${item.percent}%" + viewThemeUtils.colorDialogSupportingText(binding.pollOptionText) + viewThemeUtils.colorDialogSupportingText(binding.pollOptionPercentText) + if (item.selfVoted) { binding.pollOptionText.setTypeface(null, Typeface.BOLD) binding.pollOptionPercentText.setTypeface(null, Typeface.BOLD) diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt index 543591302..781b10e8c 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultVoterViewHolder.kt @@ -29,12 +29,14 @@ import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.PollResultVoterItemBinding import com.nextcloud.talk.polls.model.PollDetails +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.DisplayUtils class PollResultVoterViewHolder( private val user: User, - override val binding: PollResultVoterItemBinding + override val binding: PollResultVoterItemBinding, + private val viewThemeUtils: ViewThemeUtils ) : PollResultViewHolder(binding) { @SuppressLint("SetTextI18n") @@ -45,6 +47,7 @@ class PollResultVoterViewHolder( binding.pollVoterName.text = item.details.actorDisplayName binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details) + viewThemeUtils.colorDialogSupportingText(binding.pollVoterName) } private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? { diff --git a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultsAdapter.kt b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultsAdapter.kt index df600fd37..cbc71da83 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultsAdapter.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/adapters/PollResultsAdapter.kt @@ -52,7 +52,7 @@ class PollResultsAdapter( LayoutInflater.from(parent.context), parent, false ) - viewHolder = PollResultVoterViewHolder(user, itemBinding) + viewHolder = PollResultVoterViewHolder(user, itemBinding, viewThemeUtils) } PollResultVotersOverviewItem.VIEW_TYPE -> { val itemBinding = PollResultVotersOverviewItemBinding.inflate( diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt index 1167ad128..3b87d924d 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollCreateDialogFragment.kt @@ -31,11 +31,11 @@ import android.view.View import android.view.ViewGroup import android.widget.EditText import android.widget.Toast -import androidx.appcompat.app.AlertDialog import androidx.fragment.app.DialogFragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import autodagger.AutoInjector +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogPollCreateBinding @@ -73,9 +73,11 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { binding = DialogPollCreateBinding.inflate(LayoutInflater.from(context)) - return AlertDialog.Builder(requireContext()) + val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context) .setView(binding.root) - .create() + viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder) + + return dialogBuilder.create() } override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -99,16 +101,15 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener } private fun themeDialog() { - viewThemeUtils.colorTextViewText(binding.pollQuestion) - viewThemeUtils.colorTextViewText(binding.pollOptions) - viewThemeUtils.colorTextViewText(binding.pollSettings) + viewThemeUtils.colorPrimaryTextViewElement(binding.pollQuestion) + viewThemeUtils.colorPrimaryTextViewElement(binding.pollOptions) + viewThemeUtils.colorPrimaryTextViewElement(binding.pollSettings) - viewThemeUtils.colorEditText(binding.pollCreateQuestionTextEdit) + viewThemeUtils.colorTextInputLayout(binding.pollCreateQuestionTextInputLayout) viewThemeUtils.colorMaterialButtonText(binding.pollAddOptionsItem) - // TODO button also needs a disabled state handling for colors viewThemeUtils.colorMaterialButtonText(binding.pollDismiss) - viewThemeUtils.colorMaterialButtonBackground(binding.pollCreateButton) + viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollCreateButton) viewThemeUtils.themeCheckbox(binding.pollPrivatePollCheckbox) viewThemeUtils.themeCheckbox(binding.pollMultipleAnswersCheckbox) diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt index 77b46f8aa..785669cd8 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollLoadingFragment.kt @@ -29,12 +29,17 @@ import androidx.fragment.app.Fragment import autodagger.AutoInjector import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogPollLoadingBinding +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class PollLoadingFragment : Fragment() { private lateinit var binding: DialogPollLoadingBinding + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + var fragmentHeight = 0 override fun onCreate(savedInstanceState: Bundle?) { @@ -50,6 +55,7 @@ class PollLoadingFragment : Fragment() { ): View { binding = DialogPollLoadingBinding.inflate(inflater, container, false) binding.root.layoutParams.height = fragmentHeight + viewThemeUtils.colorCircularProgressBar(binding.pollLoadingProgressbar) return binding.root } diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt index f775746ff..fe5fb3268 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollMainDialogFragment.kt @@ -26,16 +26,17 @@ import android.os.Bundle import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import androidx.appcompat.app.AlertDialog import androidx.core.os.bundleOf import androidx.fragment.app.DialogFragment import androidx.lifecycle.ViewModelProvider import autodagger.AutoInjector +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.DialogPollMainBinding import com.nextcloud.talk.polls.viewmodels.PollMainViewModel +import com.nextcloud.talk.ui.theme.ViewThemeUtils import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) @@ -44,6 +45,9 @@ class PollMainDialogFragment : DialogFragment() { @Inject lateinit var viewModelFactory: ViewModelProvider.Factory + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var binding: DialogPollMainBinding private lateinit var viewModel: PollMainViewModel @@ -66,11 +70,15 @@ class PollMainDialogFragment : DialogFragment() { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { binding = DialogPollMainBinding.inflate(LayoutInflater.from(context)) - val dialog = AlertDialog.Builder(requireContext()) - .setView(binding.root) - .create() + val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root) + + viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder) + + val dialog = dialogBuilder.create() binding.messagePollTitle.text = viewModel.pollTitle + viewThemeUtils.colorDialogHeadline(binding.messagePollTitle) + viewThemeUtils.colorDialogIcon(binding.messagePollIcon) return dialog } @@ -135,6 +143,7 @@ class PollMainDialogFragment : DialogFragment() { private fun initVotersAmount(showVotersAmount: Boolean, numVoters: Int, showResultSubtitle: Boolean) { if (showVotersAmount) { + viewThemeUtils.colorDialogSupportingText(binding.pollVotesAmount) binding.pollVotesAmount.visibility = View.VISIBLE binding.pollVotesAmount.text = resources.getQuantityString( R.plurals.polls_amount_voters, @@ -146,6 +155,7 @@ class PollMainDialogFragment : DialogFragment() { } if (showResultSubtitle) { + viewThemeUtils.colorDialogSupportingText(binding.pollResultsSubtitle) binding.pollResultsSubtitle.visibility = View.VISIBLE binding.pollResultsSubtitleSeperator.visibility = View.VISIBLE } else { diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt index 0a9c3db12..6264aa5ec 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollResultsFragment.kt @@ -31,6 +31,7 @@ import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import androidx.recyclerview.widget.LinearLayoutManager import autodagger.AutoInjector +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogPollResultsBinding @@ -98,8 +99,8 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener { } private fun themeDialog() { - viewThemeUtils.colorMaterialButtonBackground(binding.editVoteButton) - viewThemeUtils.colorMaterialButtonText(binding.pollResultsEndPollButton) + viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.editVoteButton) + viewThemeUtils.colorMaterialButtonPrimaryBorderless(binding.pollResultsEndPollButton) } private fun initAdapter() { @@ -123,14 +124,25 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener { if (showEndPollButton) { binding.pollResultsEndPollButton.visibility = View.VISIBLE binding.pollResultsEndPollButton.setOnClickListener { - AlertDialog.Builder(requireContext()) + val dialogBuilder = MaterialAlertDialogBuilder(binding.pollResultsEndPollButton.context) .setTitle(R.string.polls_end_poll) .setMessage(R.string.polls_end_poll_confirm) .setPositiveButton(R.string.polls_end_poll) { _, _ -> parentViewModel.endPoll() } .setNegativeButton(R.string.nc_cancel, null) - .show() + + viewThemeUtils.colorMaterialAlertDialogBackground( + binding.pollResultsEndPollButton.context, + dialogBuilder + ) + + val dialog = dialogBuilder.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } } else { binding.pollResultsEndPollButton.visibility = View.GONE diff --git a/app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt b/app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt index 5972334db..0dde5d01b 100644 --- a/app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/polls/ui/PollVoteFragment.kt @@ -37,6 +37,7 @@ import androidx.appcompat.app.AlertDialog import androidx.fragment.app.Fragment import androidx.lifecycle.ViewModelProvider import autodagger.AutoInjector +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogPollVoteBinding @@ -126,9 +127,9 @@ class PollVoteFragment : Fragment() { } private fun themeDialog() { - viewThemeUtils.colorMaterialButtonBackground(binding.pollVoteSubmitButton) + viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollVoteSubmitButton) viewThemeUtils.colorMaterialButtonText(binding.pollVoteEndPollButton) - viewThemeUtils.colorMaterialButtonText(binding.pollVoteEditDismiss) + viewThemeUtils.colorMaterialButtonPrimaryOutlined(binding.pollVoteEditDismiss) } private fun updateDismissEditButton(showDismissEditButton: Boolean) { @@ -206,14 +207,25 @@ class PollVoteFragment : Fragment() { if (showEndPollButton) { binding.pollVoteEndPollButton.visibility = View.VISIBLE binding.pollVoteEndPollButton.setOnClickListener { - AlertDialog.Builder(requireContext()) + val dialogBuilder = MaterialAlertDialogBuilder(binding.pollVoteEndPollButton.context) .setTitle(R.string.polls_end_poll) .setMessage(R.string.polls_end_poll_confirm) .setPositiveButton(R.string.polls_end_poll) { _, _ -> parentViewModel.endPoll() } .setNegativeButton(R.string.nc_cancel, null) - .show() + + viewThemeUtils.colorMaterialAlertDialogBackground( + binding.pollVoteEndPollButton.context, + dialogBuilder + ) + + val dialog = dialogBuilder.show() + + viewThemeUtils.colorTextButtons( + dialog.getButton(AlertDialog.BUTTON_POSITIVE), + dialog.getButton(AlertDialog.BUTTON_NEGATIVE) + ) } } else { binding.pollVoteEndPollButton.visibility = View.GONE diff --git a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java index 977e0f51e..ada79fd7c 100644 --- a/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java +++ b/app/src/main/java/com/nextcloud/talk/presenters/MentionAutocompletePresenter.java @@ -36,6 +36,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.models.json.mention.MentionOverall; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.users.UserManager; import com.nextcloud.talk.utils.ApiUtils; import com.otaliastudios.autocomplete.RecyclerViewPresenter; @@ -69,6 +70,9 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter @Inject UserManager userManager; + @Inject + ViewThemeUtils viewThemeUtils; + private User currentUser; private FlexibleAdapter adapter; private Context context; @@ -150,7 +154,8 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter new MentionAutocompleteItem( mention, currentUser, - context)); + context, + viewThemeUtils)); } if (adapter.getItemCount() != 0) { diff --git a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt index da0d78049..6dabd3567 100644 --- a/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/remotefilebrowser/activities/RemoteFileBrowserActivity.kt @@ -24,6 +24,7 @@ package com.nextcloud.talk.remotefilebrowser.activities import android.app.Activity import android.content.Intent +import android.content.res.ColorStateList import android.os.Bundle import android.util.Log import android.view.Menu @@ -74,14 +75,18 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater) setSupportActionBar(binding.remoteFileBrowserItemsToolbar) + viewThemeUtils.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) + binding.pathNavigationBackButton.iconTint = ColorStateList.valueOf(scheme.onSurface) + binding.pathNavigationBackButton.setTextColor(scheme.onSurface) + viewThemeUtils.colorMaterialTextButton(binding.pathNavigationBackButton) + viewThemeUtils.themeStatusBar(this, binding.remoteFileBrowserItemsToolbar) setContentView(binding.root) - DisplayUtils.applyColorToStatusBar( - this, - ResourcesCompat.getColor( - resources, R.color.appbar, null - ) - ) DisplayUtils.applyColorToNavigationBar( this.window, ResourcesCompat.getColor(resources, R.color.bg_default, null) diff --git a/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt b/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt index 48b415c59..309498dc9 100644 --- a/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt +++ b/app/src/main/java/com/nextcloud/talk/shareditems/activities/SharedItemsActivity.kt @@ -73,14 +73,10 @@ class SharedItemsActivity : AppCompatActivity() { setSupportActionBar(binding.sharedItemsToolbar) setContentView(binding.root) - DisplayUtils.applyColorToStatusBar( - this, - ResourcesCompat.getColor( - resources, - R.color.appbar, - null - ) - ) + viewThemeUtils.themeStatusBar(this, binding.sharedItemsToolbar) + viewThemeUtils.themeToolbar(binding.sharedItemsToolbar) + viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs) + DisplayUtils.applyColorToNavigationBar( this.window, ResourcesCompat.getColor(resources, R.color.bg_default, null) @@ -150,7 +146,7 @@ class SharedItemsActivity : AppCompatActivity() { else -> {} } - viewThemeUtils.colorTabLayout(binding.sharedItemsTabs) + viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs) } private fun clearEmptyLoading() { diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt index 13a0564fb..40d291366 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/AttachmentDialog.kt @@ -26,23 +26,34 @@ import android.app.Activity import android.os.Bundle import android.view.View import android.view.ViewGroup +import autodagger.AutoInjector import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.ChatController import com.nextcloud.talk.databinding.DialogAttachmentBinding +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew +import javax.inject.Inject +@AutoInjector(NextcloudTalkApplication::class) class AttachmentDialog(val activity: Activity, var chatController: ChatController) : BottomSheetDialog(activity) { + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var dialogAttachmentBinding: DialogAttachmentBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + dialogAttachmentBinding = DialogAttachmentBinding.inflate(layoutInflater) setContentView(dialogAttachmentBinding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(dialogAttachmentBinding.root) initItemsStrings() initItemsVisibility() initItemsClickListeners() diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt index 5e879e736..f55a30967 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/AudioOutputDialog.kt @@ -31,7 +31,6 @@ import com.nextcloud.talk.R import com.nextcloud.talk.activities.CallActivity import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.databinding.DialogAudioOutputBinding -import com.nextcloud.talk.ui.theme.ServerTheme import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.webrtc.WebRtcAudioManager import javax.inject.Inject @@ -42,21 +41,17 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call @Inject lateinit var viewThemeUtils: ViewThemeUtils - @Inject - lateinit var serverTheme: ServerTheme - private lateinit var dialogAudioOutputBinding: DialogAudioOutputBinding - init { - NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + dialogAudioOutputBinding = DialogAudioOutputBinding.inflate(layoutInflater) setContentView(dialogAudioOutputBinding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialogDark(dialogAudioOutputBinding.root) updateOutputDeviceList() initClickListeners() } @@ -98,22 +93,22 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call when (callActivity.audioManager?.currentAudioDevice) { WebRtcAudioManager.AudioDevice.BLUETOOTH -> { viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputBluetoothIcon) - dialogAudioOutputBinding.audioOutputBluetoothText.setTextColor(serverTheme.primaryColor) + viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputBluetoothText) } WebRtcAudioManager.AudioDevice.SPEAKER_PHONE -> { viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputSpeakerIcon) - dialogAudioOutputBinding.audioOutputSpeakerText.setTextColor(serverTheme.primaryColor) + viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputSpeakerText) } WebRtcAudioManager.AudioDevice.EARPIECE -> { viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputEarspeakerIcon) - dialogAudioOutputBinding.audioOutputEarspeakerText.setTextColor(serverTheme.primaryColor) + viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputEarspeakerText) } WebRtcAudioManager.AudioDevice.WIRED_HEADSET -> { viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputWiredHeadsetIcon) - dialogAudioOutputBinding.audioOutputWiredHeadsetText.setTextColor(serverTheme.primaryColor) + viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputWiredHeadsetText) } else -> Log.d(TAG, "AudioOutputDialog doesn't know this AudioDevice") diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java index 3881bed5c..4642a1503 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ChooseAccountDialogFragment.java @@ -39,7 +39,6 @@ import android.view.ViewGroup; import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.interfaces.DraweeController; import com.google.android.material.dialog.MaterialAlertDialogBuilder; -import com.nextcloud.talk.R; import com.nextcloud.talk.activities.MainActivity; import com.nextcloud.talk.adapters.items.AdvancedUserItem; import com.nextcloud.talk.api.NcApi; @@ -113,12 +112,18 @@ public class ChooseAccountDialogFragment extends DialogFragment { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); + User user = userManager.getCurrentUser().blockingGet(); + themeViews(); + setupCurrentUser(user); + setupListeners(user); + setupAdapter(); + prepareViews(); + } + + private void setupCurrentUser(User user) { // Defining user picture binding.currentAccount.userIcon.setTag(""); - - // Defining user texts, accounts, etc. - User user = userManager.getCurrentUser().blockingGet(); if (user != null) { binding.currentAccount.userName.setText(user.getDisplayName()); binding.currentAccount.ticker.setVisibility(View.GONE); @@ -148,7 +153,39 @@ public class ChooseAccountDialogFragment extends DialogFragment { loadCurrentStatus(user); } + } + private void setupAdapter() { + if (adapter == null) { + adapter = new FlexibleAdapter<>(userItems, getActivity(), false); + + User userEntity; + Participant participant; + + for (Object userItem : userManager.getUsers().blockingGet()) { + userEntity = (User) userItem; + if (!userEntity.getCurrent()) { + String userId; + if (userEntity.getUserId() != null) { + userId = userEntity.getUserId(); + } else { + userId = userEntity.getUsername(); + } + + participant = new Participant(); + participant.setActorType(Participant.ActorType.USERS); + participant.setActorId(userId); + participant.setDisplayName(userEntity.getDisplayName()); + userItems.add(new AdvancedUserItem(participant, userEntity, null, viewThemeUtils)); + } + } + + adapter.addListener(onSwitchItemClickListener); + adapter.updateDataSet(userItems, false); + } + } + + private void setupListeners(User user) { // Creating listeners for quick-actions binding.currentAccount.getRoot().setOnClickListener(v -> dismiss()); @@ -173,36 +210,18 @@ public class ChooseAccountDialogFragment extends DialogFragment { Log.w(TAG, "status was null"); } }); + } - if (adapter == null) { - adapter = new FlexibleAdapter<>(userItems, getActivity(), false); + private void themeViews() { + viewThemeUtils.themeDialog(binding.getRoot()); + viewThemeUtils.themeDialogDivider(binding.divider); - User userEntity; - Participant participant; - - for (Object userItem : userManager.getUsers().blockingGet()) { - userEntity = (User) userItem; - if (!userEntity.getCurrent()) { - String userId; - if (userEntity.getUserId() != null) { - userId = userEntity.getUserId(); - } else { - userId = userEntity.getUsername(); - } - - participant = new Participant(); - participant.setActorType(Participant.ActorType.USERS); - participant.setActorId(userId); - participant.setDisplayName(userEntity.getDisplayName()); - userItems.add(new AdvancedUserItem(participant, userEntity, null)); - } - } - - adapter.addListener(onSwitchItemClickListener); - adapter.updateDataSet(userItems, false); - } - - prepareViews(); + viewThemeUtils.colorMaterialTextButton(binding.setStatus); + viewThemeUtils.colorDialogMenuText(binding.setStatus); + viewThemeUtils.colorMaterialTextButton(binding.addAccount); + viewThemeUtils.colorDialogMenuText(binding.addAccount); + viewThemeUtils.colorMaterialTextButton(binding.manageSettings); + viewThemeUtils.colorDialogMenuText(binding.manageSettings); } private void loadCurrentStatus(User user) { @@ -305,7 +324,7 @@ public class ChooseAccountDialogFragment extends DialogFragment { status.getStatus(), status.getIcon(), size, - getContext().getResources().getColor(R.color.dialog_background), + viewThemeUtils.getScheme(binding.currentAccount.ticker.getContext()).getSurface(), getContext())); binding.currentAccount.ticker.setVisibility(View.VISIBLE); diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt index d1decfc0d..b4bc81478 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ContactsBottomDialog.kt @@ -35,6 +35,8 @@ import com.nextcloud.talk.R import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController import com.nextcloud.talk.databinding.DialogBottomContactsBinding +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class ContactsBottomDialog( @@ -42,20 +44,22 @@ class ContactsBottomDialog( val bundle: Bundle ) : BottomSheetDialog(activity) { + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private var dialogRouter: Router? = null private lateinit var binding: DialogBottomContactsBinding - init { - NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) - } - override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + binding = DialogBottomContactsBinding.inflate(layoutInflater) setContentView(binding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(binding.root) executeEntryMenuController(bundle) } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt index b23ec1b6b..a3387912a 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ConversationsListBottomDialog.kt @@ -56,6 +56,7 @@ import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.DialogConversationOperationsBinding import com.nextcloud.talk.jobs.LeaveConversationWorker import com.nextcloud.talk.models.json.conversations.Conversation +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.utils.Mimetype.TEXT_PLAIN import com.nextcloud.talk.utils.ShareUtils @@ -83,18 +84,20 @@ class ConversationsListBottomDialog( lateinit var ncApi: NcApi @Inject - lateinit var userManager: UserManager + lateinit var viewThemeUtils: ViewThemeUtils - init { - NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) - } + @Inject + lateinit var userManager: UserManager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + binding = DialogConversationOperationsBinding.inflate(layoutInflater) setContentView(binding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(binding.root) initHeaderDescription() initItemsVisibility() initClickListeners() diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt index 8da1a0c5d..173fee7db 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/MessageActionsDialog.kt @@ -31,18 +31,20 @@ import android.view.View import android.view.ViewGroup import android.view.inputmethod.InputMethodManager import androidx.annotation.NonNull -import androidx.appcompat.content.res.AppCompatResources +import autodagger.AutoInjector import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.R import com.nextcloud.talk.api.NcApi +import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.ChatController import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.databinding.DialogMessageActionsBinding import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.generic.GenericOverall +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew import com.vanniktech.emoji.EmojiPopup @@ -53,7 +55,9 @@ import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers +import javax.inject.Inject +@AutoInjector(NextcloudTalkApplication::class) class MessageActionsDialog( private val chatController: ChatController, private val message: ChatMessage, @@ -64,16 +68,22 @@ class MessageActionsDialog( private val ncApi: NcApi ) : BottomSheetDialog(chatController.activity!!) { + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var dialogMessageActionsBinding: DialogMessageActionsBinding private lateinit var popup: EmojiPopup override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + dialogMessageActionsBinding = DialogMessageActionsBinding.inflate(layoutInflater) setContentView(dialogMessageActionsBinding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(dialogMessageActionsBinding.root) initEmojiBar(hasChatPermission) initMenuItemCopy(!message.isDeleted) initMenuReplyToMessage(message.replyable && hasChatPermission) @@ -215,7 +225,7 @@ class MessageActionsDialog( private fun checkAndSetEmojiSelfReaction(emoji: EmojiTextView) { if (emoji.text?.toString() != null && message.reactionsSelf?.contains(emoji.text?.toString()) == true) { - emoji.background = AppCompatResources.getDrawable(context, R.drawable.reaction_self_bottom_sheet_background) + viewThemeUtils.setCheckedBackground(emoji) } } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt index 4a18828df..0f2914139 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ScopeDialog.kt @@ -26,13 +26,18 @@ import android.content.Context import android.os.Bundle import android.view.View import android.view.ViewGroup +import autodagger.AutoInjector import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetDialog import com.nextcloud.talk.R +import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.controllers.ProfileController import com.nextcloud.talk.databinding.DialogScopeBinding import com.nextcloud.talk.models.json.userprofile.Scope +import com.nextcloud.talk.ui.theme.ViewThemeUtils +import javax.inject.Inject +@AutoInjector(NextcloudTalkApplication::class) class ScopeDialog( con: Context, private val userInfoAdapter: ProfileController.UserInfoAdapter, @@ -40,15 +45,22 @@ class ScopeDialog( private val position: Int ) : BottomSheetDialog(con) { + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var dialogScopeBinding: DialogScopeBinding override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + dialogScopeBinding = DialogScopeBinding.inflate(layoutInflater) setContentView(dialogScopeBinding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(dialogScopeBinding.root) + if (field == ProfileController.Field.DISPLAYNAME || field == ProfileController.Field.EMAIL) { dialogScopeBinding.scopePrivate.visibility = View.GONE } diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt index 6c6dfb9d6..65e016d33 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/SetStatusDialogFragment.kt @@ -36,13 +36,13 @@ import android.widget.AdapterView.OnItemSelectedListener import android.widget.ArrayAdapter import android.widget.ImageView import android.widget.TextView -import androidx.appcompat.app.AlertDialog import androidx.core.widget.doAfterTextChanged import androidx.fragment.app.DialogFragment import androidx.recyclerview.widget.LinearLayoutManager import autodagger.AutoInjector import com.bluelinelabs.logansquare.LoganSquare import com.google.android.material.card.MaterialCardView +import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.nextcloud.talk.R import com.nextcloud.talk.adapters.PredefinedStatusClickListener import com.nextcloud.talk.adapters.PredefinedStatusListAdapter @@ -166,9 +166,10 @@ class SetStatusDialogFragment : override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { binding = DialogSetStatusBinding.inflate(LayoutInflater.from(context)) - return AlertDialog.Builder(requireContext()) - .setView(binding.root) - .create() + val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root) + viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder) + + return dialogBuilder.create() } @SuppressLint("DefaultLocale") @@ -241,10 +242,12 @@ class SetStatusDialogFragment : } } - viewThemeUtils.colorMaterialButtonText(binding.clearStatus) - viewThemeUtils.colorMaterialButtonBackground(binding.setStatus) + viewThemeUtils.themeDialog(binding.root) - binding.customStatusInput.highlightColor = resources.getColor(R.color.colorPrimary) + viewThemeUtils.colorMaterialButtonText(binding.clearStatus) + viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.setStatus) + + viewThemeUtils.colorTextInputLayout(binding.customStatusInputContainer) binding.customStatusInput.doAfterTextChanged { text -> binding.setStatus.isEnabled = !text.isNullOrEmpty() @@ -416,7 +419,7 @@ class SetStatusDialogFragment : } } viewThemeUtils.colorCardViewBackground(views.first) - viewThemeUtils.colorTextViewText(views.second) + viewThemeUtils.colorPrimaryTextViewElement(views.second) } private fun clearTopStatus() { diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt b/app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt index 554fc27b7..9b496c338 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/ShowReactionsDialog.kt @@ -51,13 +51,14 @@ import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.reactions.ReactionsOverall -import com.nextcloud.talk.ui.theme.ServerTheme +import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.utils.ApiUtils import io.reactivex.Observer import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.disposables.Disposable import io.reactivex.schedulers.Schedulers import java.util.Collections +import javax.inject.Inject @AutoInjector(NextcloudTalkApplication::class) class ShowReactionsDialog( @@ -66,10 +67,12 @@ class ShowReactionsDialog( private val chatMessage: ChatMessage, private val user: User?, private val hasChatPermission: Boolean, - private val ncApi: NcApi, - private val serverTheme: ServerTheme + private val ncApi: NcApi ) : BottomSheetDialog(activity), ReactionItemClickListener { + @Inject + lateinit var viewThemeUtils: ViewThemeUtils + private lateinit var binding: DialogMessageReactionsBinding private var adapter: ReactionsAdapter? = null @@ -78,9 +81,12 @@ class ShowReactionsDialog( override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) + NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) + binding = DialogMessageReactionsBinding.inflate(layoutInflater) setContentView(binding.root) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) + viewThemeUtils.themeDialog(binding.root) adapter = ReactionsAdapter(this, user) binding.reactionsList.adapter = adapter binding.reactionsList.layoutManager = LinearLayoutManager(context) @@ -98,7 +104,6 @@ class ShowReactionsDialog( adapter?.list?.clear() if (chatMessage.reactions != null && chatMessage.reactions!!.isNotEmpty()) { var reactionsTotal = 0 - binding.emojiReactionsTabs.setSelectedTabIndicatorColor(serverTheme.primaryColor) for ((emoji, amount) in chatMessage.reactions!!) { reactionsTotal = reactionsTotal.plus(amount as Int) val tab: TabLayout.Tab = binding.emojiReactionsTabs.newTab() // Create a new Tab names "First Tab" @@ -139,6 +144,8 @@ class ShowReactionsDialog( } }) + viewThemeUtils.themeTabLayoutOnSurface(binding.emojiReactionsTabs) + updateParticipantsForEmoji(chatMessage, tagAll) } adapter?.notifyDataSetChanged() diff --git a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java index e348504cd..b2ba7bcaa 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java +++ b/app/src/main/java/com/nextcloud/talk/ui/dialog/SortingOrderDialogFragment.java @@ -120,7 +120,8 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O * find all relevant UI elements and set their values. */ private void setupDialogElements() { - viewThemeUtils.colorMaterialButtonText(binding.cancel); + viewThemeUtils.themeDialog(binding.root); + viewThemeUtils.colorMaterialButtonPrimaryBorderless(binding.cancel); taggedViews = new View[12]; taggedViews[0] = binding.sortByNameAscending; @@ -165,7 +166,7 @@ public class SortingOrderDialogFragment extends DialogFragment implements View.O viewThemeUtils.colorMaterialButtonText((MaterialButton) view); } if (view instanceof TextView) { - viewThemeUtils.colorTextViewElement((TextView) view); + viewThemeUtils.colorPrimaryTextViewElement((TextView) view); ((TextView) view).setTypeface(Typeface.DEFAULT_BOLD); } } diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemes.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemes.kt new file mode 100644 index 000000000..9ed1a3d11 --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemes.kt @@ -0,0 +1,35 @@ +/* + * Nextcloud Talk application + * + * @author Andy Scherzinger + * Copyright (C) 2022 Andy Scherzinger + * + * 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 . + */ + +package com.nextcloud.talk.ui.theme + +import scheme.Scheme + +interface MaterialSchemes { + /** + * Schema for light theme + */ + val lightScheme: Scheme + + /** + * Schema for light theme + */ + val darkScheme: Scheme +} diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesImpl.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesImpl.kt new file mode 100644 index 000000000..713266a5b --- /dev/null +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesImpl.kt @@ -0,0 +1,33 @@ +/* + * Nextcloud Talk application + * + * @author Andy Scherzinger + * Copyright (C) 2022 Andy Scherzinger + * + * 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 . + */ + +package com.nextcloud.talk.ui.theme + +import scheme.Scheme + +class MaterialSchemesImpl(serverTheme: ServerTheme) : MaterialSchemes { + override val lightScheme: Scheme + override val darkScheme: Scheme + + init { + lightScheme = Scheme.light(serverTheme.primaryColor) + darkScheme = Scheme.dark(serverTheme.primaryColor) + } +} diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProvider.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProvider.kt similarity index 79% rename from app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProvider.kt rename to app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProvider.kt index 3011956e6..10a0f8cdf 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProvider.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProvider.kt @@ -24,8 +24,8 @@ package com.nextcloud.talk.ui.theme import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.models.json.capabilities.Capabilities -interface ServerThemeProvider { - fun getServerThemeForUser(user: User?): ServerTheme - fun getServerThemeForCapabilities(capabilities: Capabilities?): ServerTheme - fun getServerThemeForCurrentUser(): ServerTheme +interface MaterialSchemesProvider { + fun getMaterialSchemesForUser(user: User?): MaterialSchemes + fun getMaterialSchemesForCapabilities(capabilities: Capabilities?): MaterialSchemes + fun getMaterialSchemesForCurrentUser(): MaterialSchemes } diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProviderImpl.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProviderImpl.kt similarity index 70% rename from app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProviderImpl.kt rename to app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProviderImpl.kt index ada276a40..bcd1e534b 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeProviderImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/MaterialSchemesProviderImpl.kt @@ -30,14 +30,14 @@ import com.nextcloud.talk.utils.ui.ColorUtil import java.util.concurrent.ConcurrentHashMap import javax.inject.Inject -internal class ServerThemeProviderImpl @Inject constructor( +internal class MaterialSchemesProviderImpl @Inject constructor( private val userProvider: CurrentUserProviderNew, private val colorUtil: ColorUtil -) : ServerThemeProvider { +) : MaterialSchemesProvider { - private val themeCache: ConcurrentHashMap = ConcurrentHashMap() + private val themeCache: ConcurrentHashMap = ConcurrentHashMap() - override fun getServerThemeForUser(user: User?): ServerTheme { + override fun getMaterialSchemesForUser(user: User?): MaterialSchemes { val url: String = if (user?.baseUrl != null) { user.baseUrl!! } else { @@ -45,18 +45,18 @@ internal class ServerThemeProviderImpl @Inject constructor( } if (!themeCache.containsKey(url)) { - themeCache[url] = getServerThemeForCapabilities(user?.capabilities) + themeCache[url] = getMaterialSchemesForCapabilities(user?.capabilities) } return themeCache[url]!! } - override fun getServerThemeForCurrentUser(): ServerTheme { - return getServerThemeForUser(userProvider.currentUser.blockingGet()) + override fun getMaterialSchemesForCurrentUser(): MaterialSchemes { + return getMaterialSchemesForUser(userProvider.currentUser.blockingGet()) } - override fun getServerThemeForCapabilities(capabilities: Capabilities?): ServerTheme { - return ServerThemeImpl(capabilities?.themingCapability, colorUtil) + override fun getMaterialSchemesForCapabilities(capabilities: Capabilities?): MaterialSchemes { + return MaterialSchemesImpl(ServerThemeImpl(capabilities?.themingCapability, colorUtil)) } companion object { diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeImpl.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeImpl.kt index d87aae795..1020a0727 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeImpl.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/ServerThemeImpl.kt @@ -27,8 +27,7 @@ import com.nextcloud.talk.R import com.nextcloud.talk.models.json.capabilities.ThemingCapability import com.nextcloud.talk.utils.ui.ColorUtil -internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil: ColorUtil) : - ServerTheme { +internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil: ColorUtil) : ServerTheme { override val primaryColor: Int override val colorElement: Int @@ -38,11 +37,9 @@ internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil: init { primaryColor = colorUtil.getNullSafeColorWithFallbackRes(themingCapability?.color, R.color.colorPrimary) - colorElement = colorUtil.getNullSafeColor(themingCapability?.colorElement, primaryColor) colorElementBright = colorUtil.getNullSafeColor(themingCapability?.colorElementBright, primaryColor) colorElementDark = colorUtil.getNullSafeColor(themingCapability?.colorElementDark, primaryColor) - colorText = colorUtil.getTextColor(themingCapability?.colorText, primaryColor) } } diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ThemeModule.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/ThemeModule.kt index 54410e609..ac9405b0d 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ThemeModule.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/ThemeModule.kt @@ -33,12 +33,12 @@ internal abstract class ThemeModule { @Binds @Reusable - abstract fun bindServerThemeProvider(provider: ServerThemeProviderImpl): ServerThemeProvider + abstract fun bindMaterialSchemesProvider(provider: MaterialSchemesProviderImpl): MaterialSchemesProvider companion object { @Provides - fun provideCurrentServerTheme(themeProvider: ServerThemeProvider): ServerTheme { - return themeProvider.getServerThemeForCurrentUser() + fun provideCurrentMaterialSchemes(themeProvider: MaterialSchemesProvider): MaterialSchemes { + return themeProvider.getMaterialSchemesForCurrentUser() } } } diff --git a/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt b/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt index 1cc9adaa5..7fa45980f 100644 --- a/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt +++ b/app/src/main/java/com/nextcloud/talk/ui/theme/ViewThemeUtils.kt @@ -21,74 +21,193 @@ 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.talk.R +import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DrawableUtils import com.nextcloud.talk.utils.ui.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 javax.inject.Inject +import kotlin.math.roundToInt @Suppress("TooManyFunctions") -class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private val colorUtil: ColorUtil) { +class ViewThemeUtils @Inject constructor(private val schemes: MaterialSchemes, private val colorUtil: ColorUtil) { /** - * Color for painting elements + * Scheme for painting elements */ - fun getElementColor(context: Context): Int = when { - isDarkMode(context) -> theme.colorElementDark - else -> theme.colorElementBright + fun getScheme(context: Context): Scheme = when { + isDarkMode(context) -> schemes.darkScheme + else -> schemes.lightScheme } - private fun withElementColor(view: View, block: (Int) -> Unit) { - block(getElementColor(view.context)) + 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(R.id.search_src_text) + val searchPlate = searchView.findViewById(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) { - withElementColor(fab) { color -> - fab.backgroundTintList = ColorStateList.valueOf(color) - fab.imageTintList = ColorStateList.valueOf(theme.colorText) + 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) { - withElementColor(seekBar) { color -> - themeHorizontalSeekBar(seekBar, color) + withScheme(seekBar) { scheme -> + themeHorizontalProgressBar(seekBar, scheme.primary) + seekBar.thumb.setColorFilter(scheme.primary, PorterDuff.Mode.SRC_IN) } } - fun themeHorizontalSeekBar(seekBar: SeekBar, @ColorInt color: Int) { - themeHorizontalProgressBar(seekBar, color) - seekBar.thumb.setColorFilter(color, PorterDuff.Mode.SRC_IN) - } - fun themeHorizontalProgressBar(progressBar: ProgressBar?, @ColorInt color: Int) { if (progressBar != null) { progressBar.indeterminateDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN) @@ -96,23 +215,50 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } } - fun colorTextViewElement(textView: TextView) { - withElementColor(textView) { color -> - textView.setTextColor(color) + fun colorPrimaryTextViewElement(textView: TextView) { + withScheme(textView) { scheme -> + textView.setTextColor(scheme.primary) } } - fun colorTextViewText(textView: TextView) { - textView.setTextColor(theme.colorText) + 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) { - withElementColor(imageView) { color -> - imageView.imageTintList = ColorStateList.valueOf(theme.colorText) - imageView.backgroundTintList = ColorStateList.valueOf(color) + 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) + ) + ) } } @@ -120,61 +266,256 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private * Tints the image with element color */ fun colorImageView(imageView: ImageView) { - withElementColor(imageView) { color -> - imageView.imageTintList = ColorStateList.valueOf(color) + withScheme(imageView) { scheme -> + imageView.imageTintList = ColorStateList.valueOf(scheme.primary) } } - /** - * Tints the image with text color - */ - fun colorImageViewText(imageView: ImageView) { - imageView.imageTintList = ColorStateList.valueOf(theme.colorText) + 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) { - withElementColor(button) { color -> + 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(color, disabledColor) + intArrayOf(scheme.primary, disabledColor) ) button.setTextColor(colorStateList) button.iconTint = colorStateList } } - fun colorMaterialButtonBackground(button: MaterialButton) { - withElementColor(button) { color -> - button.setBackgroundColor(color) + 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) + ) + ) + ) + } + } + } - val disabledColor = ContextCompat.getColor(button.context, R.color.disabled_text) - val colorStateList = ColorStateList( + 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(theme.colorText, disabledColor) + intArrayOf( + scheme.onPrimary, + colorUtil.adjustOpacity(scheme.onSurface, ON_SURFACE_OPACITY_BUTTON_DISABLED) + ) ) + } + } - button.setTextColor(colorStateList) - button.iconTint = colorStateList + 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) { - withElementColor(card) { color -> - card.setCardBackgroundColor(color) + 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) { - withElementColor(category) { color -> - category.setTitleColor(color) + withScheme(category) { scheme -> + category.setTitleColor(scheme.primary) } } @@ -188,7 +529,7 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } fun colorSwitchCompat(switchCompat: SwitchCompat) { - withElementColor(switchCompat) { color -> + withScheme(switchCompat) { scheme -> val context = switchCompat.context @@ -203,11 +544,16 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private context.theme ) - val trackColor = - Color.argb(SWITCHCOMPAT_TRACK_ALPHA, Color.red(color), Color.green(color), Color.blue(color)) + 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(color, thumbUncheckedColor) + intArrayOf(scheme.primary, thumbUncheckedColor) ) switchCompat.trackTintList = ColorStateList( @@ -218,58 +564,49 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } fun colorDrawable(context: Context, drawable: Drawable) { - val color = getElementColor(context) - drawable.setTint(color) + val scheme = getScheme(context) + drawable.setTint(scheme.primary) } fun themeCheckbox(checkbox: CheckBox) { - withElementColor(checkbox) { color -> + withScheme(checkbox) { scheme -> checkbox.buttonTintList = ColorStateList( arrayOf( intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked) ), - intArrayOf(Color.GRAY, color) + intArrayOf(Color.GRAY, scheme.primary) ) } } fun themeRadioButton(radioButton: RadioButton) { - withElementColor(radioButton) { color -> + withScheme(radioButton) { scheme -> radioButton.buttonTintList = ColorStateList( arrayOf( intArrayOf(-android.R.attr.state_checked), intArrayOf(android.R.attr.state_checked) ), - intArrayOf(Color.GRAY, color) + intArrayOf(Color.GRAY, scheme.primary) ) } } fun themeSwipeRefreshLayout(swipeRefreshLayout: SwipeRefreshLayout) { - withElementColor(swipeRefreshLayout) { color -> - swipeRefreshLayout.setColorSchemeColors(color) + withScheme(swipeRefreshLayout) { scheme -> + swipeRefreshLayout.setColorSchemeColors(scheme.primary) swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background) } } fun colorProgressBar(progressIndicator: LinearProgressIndicator) { - withElementColor(progressIndicator) { color -> - progressIndicator.setIndicatorColor(progressColor(progressIndicator.context, color)) + withScheme(progressIndicator) { scheme -> + progressIndicator.setIndicatorColor(scheme.primary) } } - private fun progressColor(context: Context, color: Int): Int { - val lightness = when (isDarkMode(context)) { - true -> PROGRESS_LIGHTNESS_DARK_THEME - false -> PROGRESS_LIGHTNESS_LIGHT_THEME - } - return colorUtil.setLightness(color, lightness) - } - fun colorEditText(editText: EditText) { - withElementColor(editText) { color -> - editText.setTextColor(color) + withScheme(editText) { scheme -> // TODO check API-level compatibility // editText.background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) editText.backgroundTintList = ColorStateList( @@ -278,16 +615,18 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private intArrayOf(android.R.attr.state_focused) ), intArrayOf( - Color.GRAY, - color + scheme.outline, + scheme.primary ) ) + editText.setHintTextColor(scheme.onSurfaceVariant) + editText.setTextColor(scheme.onSurface) } } fun colorTextInputLayout(textInputLayout: TextInputLayout) { - withElementColor(textInputLayout) { color -> - val errorColor = Color.GRAY + withScheme(textInputLayout) { scheme -> + val errorColor = scheme.onSurfaceVariant val errorColorStateList = ColorStateList( arrayOf( @@ -305,8 +644,8 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private intArrayOf(android.R.attr.state_focused) ), intArrayOf( - Color.GRAY, - color + scheme.outline, + scheme.primary ) ) @@ -318,12 +657,32 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } } - fun colorTabLayout(tabLayout: TabLayout) { - withElementColor(tabLayout) { color -> - tabLayout.setSelectedTabIndicatorColor(color) + 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( @@ -337,28 +696,149 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private } fun colorChipBackground(chip: Chip) { - withElementColor(chip) { color -> - chip.chipBackgroundColor = ColorStateList.valueOf(color) - chip.setTextColor(theme.colorText) + withScheme(chip) { scheme -> + chip.chipBackgroundColor = ColorStateList.valueOf(scheme.primary) + chip.setTextColor(scheme.onPrimary) } } fun colorChipOutlined(chip: Chip, strokeWidth: Float) { - withElementColor(chip) { color -> + withScheme(chip) { scheme -> chip.chipBackgroundColor = ColorStateList.valueOf(Color.TRANSPARENT) chip.chipStrokeWidth = strokeWidth - chip.chipStrokeColor = ColorStateList.valueOf(color) - chip.setTextColor(color) + 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(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 const val SWITCHCOMPAT_TRACK_ALPHA: Int = 77 - private const val PROGRESS_LIGHTNESS_LIGHT_THEME: Float = 0.76f - private const val PROGRESS_LIGHTNESS_DARK_THEME: Float = 0.28f + + 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 } } diff --git a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java index b1cf49354..4ce8b73ab 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java +++ b/app/src/main/java/com/nextcloud/talk/utils/DisplayUtils.java @@ -81,6 +81,7 @@ import com.nextcloud.talk.R; import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.events.UserMentionClickEvent; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.nextcloud.talk.utils.text.Spans; import org.greenrobot.eventbus.EventBus; @@ -103,7 +104,6 @@ import androidx.annotation.Nullable; import androidx.annotation.StringRes; import androidx.annotation.XmlRes; import androidx.appcompat.widget.AppCompatDrawableManager; -import androidx.appcompat.widget.SearchView; import androidx.core.content.ContextCompat; import androidx.core.content.res.ResourcesCompat; import androidx.core.graphics.ColorUtils; @@ -297,11 +297,16 @@ public class DisplayUtils { User conversationUser, String type, @XmlRes int chipResource, - @Nullable EditText emojiEditText) { + @Nullable EditText emojiEditText, + ViewThemeUtils viewThemeUtils) { ChipDrawable chip = ChipDrawable.createFromResource(context, chipResource); chip.setText(EmojiCompat.get().process(label)); chip.setEllipsize(TextUtils.TruncateAt.MIDDLE); + if (chipResource == R.xml.chip_you) { + viewThemeUtils.themePrimaryMentionChip(context, chip); + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { Configuration config = context.getResources().getConfiguration(); chip.setLayoutDirection(config.getLayoutDirection()); @@ -367,7 +372,8 @@ public class DisplayUtils { public static Spannable searchAndReplaceWithMentionSpan(Context context, Spannable text, String id, String label, String type, User conversationUser, - @XmlRes int chipXmlRes) { + @XmlRes int chipXmlRes, + ViewThemeUtils viewThemeUtils) { Spannable spannableString = new SpannableString(text); String stringText = text.toString(); @@ -395,10 +401,18 @@ public class DisplayUtils { conversationUser, type, chipXmlRes, - null), + null, + viewThemeUtils), BetterImageSpan.ALIGN_CENTER, id, label); spannableString.setSpan(mentionChipSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + if (chipXmlRes == R.xml.chip_you) { + spannableString.setSpan( + new ForegroundColorSpan(viewThemeUtils.getScheme(context).getOnPrimary()), + start, + end, + Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); + } if ("user".equals(type) && !conversationUser.getUserId().equals(id)) { spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } @@ -517,19 +531,6 @@ public class DisplayUtils { window.setNavigationBarColor(color); } - /** - * Theme search view - * - * @param searchView searchView to be changed - * @param context the app's context - */ - public static void themeSearchView(SearchView searchView, Context context) { - // hacky as no default way is provided - SearchView.SearchAutoComplete editText = searchView.findViewById(R.id.search_src_text); - editText.setTextSize(16); - editText.setHintTextColor(context.getResources().getColor(R.color.fontSecondaryAppbar)); - } - /** * beautifies a given URL by removing any http/https protocol prefix. * diff --git a/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java b/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java index d33dd52c5..3fa5fc4ca 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java +++ b/app/src/main/java/com/nextcloud/talk/utils/preferences/MagicUserInputModule.java @@ -28,22 +28,30 @@ import android.view.LayoutInflater; import android.view.View; import android.view.inputmethod.EditorInfo; import android.widget.EditText; -import androidx.appcompat.app.AlertDialog; -import autodagger.AutoInjector; +import android.widget.TextView; + +import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.nextcloud.talk.R; import com.nextcloud.talk.application.NextcloudTalkApplication; +import com.nextcloud.talk.ui.theme.ViewThemeUtils; import com.yarolegovich.mp.io.StandardUserInputModule; -import javax.inject.Inject; import java.util.ArrayList; import java.util.List; +import javax.inject.Inject; + +import autodagger.AutoInjector; + @AutoInjector(NextcloudTalkApplication.class) public class MagicUserInputModule extends StandardUserInputModule { @Inject AppPreferences appPreferences; + @Inject + ViewThemeUtils viewThemeUtils; + private List keysWithIntegerInput = new ArrayList<>(); public MagicUserInputModule(Context context) { @@ -65,6 +73,11 @@ public class MagicUserInputModule extends StandardUserInputModule { final Listener 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); + + int paddingStartEnd = Math.round(view.getResources().getDimension(R.dimen.standard_padding)); + int paddingTopBottom = Math.round(view.getResources().getDimension(R.dimen.dialog_padding_top_bottom)); + view.setPadding(paddingStartEnd, paddingTopBottom, paddingStartEnd, paddingTopBottom); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.getIsKeyboardIncognito()) { inputField.setImeOptions(inputField.getImeOptions() | EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING); @@ -79,11 +92,17 @@ public class MagicUserInputModule extends StandardUserInputModule { inputField.setInputType(InputType.TYPE_CLASS_NUMBER); } - final Dialog dialog = new AlertDialog.Builder(context) - .setTitle(title) - .setView(view) - .show(); - view.findViewById(R.id.mp_btn_confirm).setOnClickListener(new View.OnClickListener() { + final MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(view.getContext()) + .setTitle(title) + .setView(view); + + viewThemeUtils.colorMaterialAlertDialogBackground(view.getContext(), dialogBuilder); + + final Dialog dialog = dialogBuilder.show(); + + TextView button = view.findViewById(R.id.mp_btn_confirm); + viewThemeUtils.colorPrimaryTextViewElement(button); + button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { listener.onInput(inputField.getText().toString()); diff --git a/app/src/main/java/com/nextcloud/talk/utils/ui/ColorUtil.kt b/app/src/main/java/com/nextcloud/talk/utils/ui/ColorUtil.kt index 97d90ab49..3f4a8a558 100644 --- a/app/src/main/java/com/nextcloud/talk/utils/ui/ColorUtil.kt +++ b/app/src/main/java/com/nextcloud/talk/utils/ui/ColorUtil.kt @@ -28,6 +28,7 @@ import androidx.core.content.ContextCompat import androidx.core.graphics.ColorUtils import com.nextcloud.talk.R import javax.inject.Inject +import kotlin.math.roundToInt class ColorUtil @Inject constructor(private val context: Context) { @@ -73,6 +74,16 @@ class ColorUtil @Inject constructor(private val context: Context) { return this?.let { Color.parseColor(this) } ?: fallback() } + @ColorInt + fun adjustOpacity(color: Int, opacity: Float): Int { + return Color.argb( + (Color.alpha(color) * opacity).roundToInt(), + Color.red(color), + Color.green(color), + Color.blue(color) + ) + } + companion object { private const val HSL_SIZE: Int = 3 private const val INDEX_LIGHTNESS: Int = 2 diff --git a/app/src/main/res/drawable-v24/ic_avatar_background.xml b/app/src/main/res/drawable-v24/ic_avatar_background.xml new file mode 100644 index 000000000..84b02c9cb --- /dev/null +++ b/app/src/main/res/drawable-v24/ic_avatar_background.xml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_document.xml b/app/src/main/res/drawable/ic_avatar_document.xml new file mode 100644 index 000000000..5488941ab --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_document.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_group.xml b/app/src/main/res/drawable/ic_avatar_group.xml new file mode 100644 index 000000000..3dcdb9e9b --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_group.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_link.xml b/app/src/main/res/drawable/ic_avatar_link.xml new file mode 100644 index 000000000..c4890f82a --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_link.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/ic_avatar_mail.xml b/app/src/main/res/drawable/ic_avatar_mail.xml new file mode 100644 index 000000000..cbbfce6bf --- /dev/null +++ b/app/src/main/res/drawable/ic_avatar_mail.xml @@ -0,0 +1,31 @@ + + + + + diff --git a/app/src/main/res/drawable/reaction_self_background.xml b/app/src/main/res/drawable/reaction_self_background.xml index 3310cf25a..deaea7a6f 100644 --- a/app/src/main/res/drawable/reaction_self_background.xml +++ b/app/src/main/res/drawable/reaction_self_background.xml @@ -21,10 +21,10 @@ + android:color="@color/high_emphasis_text" /> + android:color="#FFFFFF" /> + app:cardElevation="0dp" + app:strokeWidth="@dimen/zero"> - - @@ -144,16 +133,6 @@ app:titleTextColor="@color/fontAppbar" tools:title="@string/nc_app_product_name"> - - diff --git a/app/src/main/res/layout/controller_chat.xml b/app/src/main/res/layout/controller_chat.xml index 60be4c6d4..1e42b0657 100644 --- a/app/src/main/res/layout/controller_chat.xml +++ b/app/src/main/res/layout/controller_chat.xml @@ -74,6 +74,7 @@ app:incomingImageTimeTextSize="12sp" app:incomingTextColor="@color/nc_incoming_text_default" app:incomingTextLinkColor="@color/nc_incoming_text_default" + app:incomingTimeTextColor="@color/no_emphasis_text" app:incomingTextSize="@dimen/chat_text_size" app:incomingTimeTextSize="12sp" app:outcomingBubblePaddingBottom="@dimen/message_bubble_corners_padding" @@ -84,8 +85,8 @@ app:outcomingDefaultBubblePressedColor="@color/colorPrimary" app:outcomingDefaultBubbleSelectedColor="@color/transparent" app:outcomingImageTimeTextSize="12sp" - app:outcomingTextColor="@color/nc_outcoming_text_default" - app:outcomingTextLinkColor="@color/nc_outcoming_text_default" + app:outcomingTextColor="@color/high_emphasis_text" + app:outcomingTextLinkColor="@color/high_emphasis_text" app:outcomingTextSize="@dimen/chat_text_size" app:outcomingTimeTextSize="12sp" app:textAutoLink="all" /> diff --git a/app/src/main/res/layout/controller_profile.xml b/app/src/main/res/layout/controller_profile.xml index 4d850c72c..d09b65b7d 100644 --- a/app/src/main/res/layout/controller_profile.xml +++ b/app/src/main/res/layout/controller_profile.xml @@ -29,8 +29,7 @@ + android:layout_height="wrap_content"> - + android:tint="@android:color/white" + app:elevation="0dp" + app:fabSize="mini" + app:srcCompat="@drawable/upload" /> - + android:tint="@android:color/white" + app:elevation="0dp" + app:fabSize="mini" + app:srcCompat="@drawable/ic_mimetype_folder" /> - + android:tint="@android:color/white" + app:elevation="0dp" + app:fabSize="mini" + app:srcCompat="@drawable/ic_baseline_photo_camera_24" /> - + android:tint="@android:color/white" + app:elevation="0dp" + app:fabSize="mini" + app:srcCompat="@drawable/trashbin" /> + diff --git a/app/src/main/res/layout/current_account_item.xml b/app/src/main/res/layout/current_account_item.xml index d1972e62a..928dbbe5f 100644 --- a/app/src/main/res/layout/current_account_item.xml +++ b/app/src/main/res/layout/current_account_item.xml @@ -21,14 +21,15 @@ --> + app:cardElevation="0dp" + app:strokeWidth="@dimen/zero"> - - + app:iconTint="@color/high_emphasis_text" /> @@ -127,11 +121,11 @@ android:text="@string/nc_settings" android:textAlignment="textStart" android:textAllCaps="false" - android:textColor="@color/fontAppbar" + android:textColor="@color/high_emphasis_text" app:icon="@drawable/ic_settings" app:iconGravity="start" app:iconPadding="22dp" - app:iconTint="@color/fontAppbar" + app:iconTint="@color/high_emphasis_text" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" /> diff --git a/app/src/main/res/layout/dialog_poll_loading.xml b/app/src/main/res/layout/dialog_poll_loading.xml index 07e00ecd0..d98309513 100644 --- a/app/src/main/res/layout/dialog_poll_loading.xml +++ b/app/src/main/res/layout/dialog_poll_loading.xml @@ -26,6 +26,7 @@ tools:background="@color/white"> diff --git a/app/src/main/res/layout/item_custom_incoming_location_message.xml b/app/src/main/res/layout/item_custom_incoming_location_message.xml index ac3f4199b..5916d1b53 100644 --- a/app/src/main/res/layout/item_custom_incoming_location_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_location_message.xml @@ -87,6 +87,8 @@ android:layout_height="wrap_content" android:layout_below="@id/messageText" android:layout_marginStart="8dp" + android:alpha="0.6" + android:textColor="@color/no_emphasis_text" app:layout_alignSelf="center" /> diff --git a/app/src/main/res/layout/item_custom_incoming_preview_message.xml b/app/src/main/res/layout/item_custom_incoming_preview_message.xml index aa640544f..7cef2baf2 100644 --- a/app/src/main/res/layout/item_custom_incoming_preview_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_preview_message.xml @@ -87,7 +87,7 @@ android:layout_height="wrap_content" android:layout_margin="2dp" android:layout_marginBottom="1dp" - app:cardCornerRadius="8dp" + app:cardCornerRadius="@dimen/dialogBorderRadius" app:cardElevation="2dp" app:layout_alignSelf="flex_start" app:layout_flexGrow="1" @@ -152,10 +152,11 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="2dp" + android:alpha="0.6" android:autoLink="none" android:textAlignment="viewStart" - android:textColor="@color/warm_grey_four" - android:textColorLink="@color/warm_grey_four" + android:textColor="@color/no_emphasis_text" + android:textColorLink="@color/no_emphasis_text" android:textIsSelectable="true" android:textSize="12sp" app:layout_alignSelf="flex_start" @@ -170,7 +171,8 @@ android:layout_alignParentEnd="true" android:layout_marginStart="8dp" android:layout_marginEnd="2dp" - android:textColor="@color/warm_grey_four" + android:alpha="0.6" + android:textColor="@color/no_emphasis_text" app:layout_alignSelf="center" tools:text="12:38" /> diff --git a/app/src/main/res/layout/item_custom_incoming_text_message.xml b/app/src/main/res/layout/item_custom_incoming_text_message.xml index c3cf411e1..defaf021c 100644 --- a/app/src/main/res/layout/item_custom_incoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_text_message.xml @@ -59,8 +59,9 @@ android:layout_width="match_parent" android:layout_height="wrap_content" android:layout_marginBottom="4dp" + android:alpha="0.6" android:textAlignment="viewStart" - android:textColor="@color/textColorMaxContrast" + android:textColor="@color/no_emphasis_text" android:textIsSelectable="false" android:textSize="12sp" tools:text="Jane Doe" /> @@ -83,6 +84,8 @@ android:layout_height="wrap_content" android:layout_below="@id/messageText" android:layout_marginStart="8dp" + android:alpha="0.6" + android:textColor="@color/no_emphasis_text" android:textIsSelectable="false" app:layout_alignSelf="center" /> diff --git a/app/src/main/res/layout/item_custom_incoming_voice_message.xml b/app/src/main/res/layout/item_custom_incoming_voice_message.xml index 3002c1eba..5a9330bed 100644 --- a/app/src/main/res/layout/item_custom_incoming_voice_message.xml +++ b/app/src/main/res/layout/item_custom_incoming_voice_message.xml @@ -40,77 +40,79 @@ android:layout_marginEnd="8dp" app:roundAsCircle="true" /> - + + + + + android:layout_height="wrap_content" + android:layout_marginBottom="4dp" + android:textAlignment="viewStart" + android:textColor="@color/textColorMaxContrast" + android:textSize="12sp" /> - + - + - + - + - + - + - + - - - - - + diff --git a/app/src/main/res/layout/item_custom_outcoming_location_message.xml b/app/src/main/res/layout/item_custom_outcoming_location_message.xml index 5af1bab92..bd5a0aa62 100644 --- a/app/src/main/res/layout/item_custom_outcoming_location_message.xml +++ b/app/src/main/res/layout/item_custom_outcoming_location_message.xml @@ -58,6 +58,7 @@ android:layout_alignWithParentIfMissing="true" android:lineSpacingMultiplier="1.2" android:textAlignment="viewStart" + android:textColor="@color/high_emphasis_text" android:textColorHighlight="@color/nc_grey" android:textIsSelectable="false" tools:text="Talk to you later!" /> @@ -68,6 +69,8 @@ android:layout_height="wrap_content" android:layout_below="@id/messageText" android:layout_marginStart="8dp" + android:alpha="0.6" + android:textColor="@color/no_emphasis_text" app:layout_alignSelf="center" tools:text="10:35" /> @@ -78,7 +81,8 @@ android:layout_below="@id/messageTime" android:layout_marginStart="8dp" android:contentDescription="@null" - app:layout_alignSelf="center" /> + app:layout_alignSelf="center" + app:tint="@color/high_emphasis_text" /> + app:tint="@color/high_emphasis_text" /> @@ -75,7 +74,7 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/double_margin_between_elements" android:text="@string/message_poll_tap_to_open" - android:textColor="@color/nc_outcoming_text_default" /> + android:textColor="@color/high_emphasis_text" /> @@ -94,8 +94,8 @@ android:layout_below="@id/messageTime" android:layout_marginStart="8dp" android:contentDescription="@null" - android:textColor="@color/nc_outcoming_text_default" - app:layout_alignSelf="center" /> + app:layout_alignSelf="center" + app:tint="@color/high_emphasis_text" /> diff --git a/app/src/main/res/layout/item_custom_outcoming_text_message.xml b/app/src/main/res/layout/item_custom_outcoming_text_message.xml index 31ebd5342..fc10826d5 100644 --- a/app/src/main/res/layout/item_custom_outcoming_text_message.xml +++ b/app/src/main/res/layout/item_custom_outcoming_text_message.xml @@ -63,6 +63,8 @@ android:layout_height="wrap_content" android:layout_below="@id/messageText" android:layout_marginStart="8dp" + android:alpha="0.6" + android:textColor="@color/no_emphasis_text" android:textIsSelectable="false" app:layout_alignSelf="center" tools:text="10:35" /> @@ -74,7 +76,8 @@ android:layout_below="@id/messageTime" android:layout_marginStart="8dp" android:contentDescription="@null" - app:layout_alignSelf="center" /> + app:layout_alignSelf="center" + app:tint="@color/high_emphasis_text" /> + android:gravity="center_vertical" + android:orientation="horizontal"> + android:visibility="gone" /> + app:iconTint="@color/high_emphasis_text" + app:rippleColor="#1FFFFFFF" /> @@ -101,8 +103,9 @@ android:layout_height="wrap_content" android:layout_below="@id/messageTime" android:layout_marginStart="8dp" + android:contentDescription="@null" app:layout_alignSelf="center" - android:contentDescription="@null" /> + app:tint="@color/high_emphasis_text" /> + #ffffff #deffffff #99ffffff #61ffffff @@ -71,7 +72,7 @@ #4B4B4B #282828 - #222222 + #1FFFFFFF #818181 #353535 diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml index 0c547cd91..1de3f5fb0 100644 --- a/app/src/main/res/values/colors.xml +++ b/app/src/main/res/values/colors.xml @@ -36,6 +36,7 @@ #ffffff + #000000 #de000000 #99000000 #61000000 @@ -99,7 +100,7 @@ #99121212 - #eeeeee + #1F121212 #EEEEEE - - - - - - @@ -134,7 +137,7 @@ @null - - - - - - @@ -263,7 +266,7 @@ 0dp -