Merge pull request #2084 from nextcloud/feature/2076/Material3

🎨 Material 3️⃣
This commit is contained in:
Andy Scherzinger 2022-08-11 23:00:01 +02:00 committed by GitHub
commit 2bd7688f9c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
127 changed files with 5872 additions and 1088 deletions

View File

@ -335,6 +335,7 @@ dependencies {
gplayImplementation "com.google.firebase:firebase-messaging:23.0.7" gplayImplementation "com.google.firebase:firebase-messaging:23.0.7"
// implementation 'androidx.activity:activity-ktx:1.4.0' // implementation 'androidx.activity:activity-ktx:1.4.0'
implementation project(':material-color-utilities')
} }
task installGitHooks(type: Copy, group: "development") { task installGitHooks(type: Copy, group: "development") {

View File

@ -27,15 +27,17 @@ import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.WindowManager import android.view.WindowManager
import android.webkit.SslErrorHandler import android.webkit.SslErrorHandler
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.events.CertificateEvent import com.nextcloud.talk.events.CertificateEvent
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.SecurityUtils import com.nextcloud.talk.utils.SecurityUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import com.nextcloud.talk.utils.ssl.MagicTrustManager import com.nextcloud.talk.utils.ssl.MagicTrustManager
import com.yarolegovich.lovelydialog.LovelyStandardDialog
import org.greenrobot.eventbus.EventBus import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode import org.greenrobot.eventbus.ThreadMode
@ -53,6 +55,9 @@ open class BaseActivity : AppCompatActivity() {
@Inject @Inject
lateinit var appPreferences: AppPreferences lateinit var appPreferences: AppPreferences
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject @Inject
lateinit var context: Context lateinit var context: Context
@ -110,21 +115,26 @@ open class BaseActivity : AppCompatActivity() {
issuedBy, issuedFor, validFrom, validUntil issuedBy, issuedFor, validFrom, validUntil
) )
LovelyStandardDialog(this) val dialogBuilder = MaterialAlertDialogBuilder(this)
.setTopColorRes(R.color.nc_darkRed) .setIcon(viewThemeUtils.colorMaterialAlertDialogIcon(context, R.drawable.ic_security_white_24dp))
.setNegativeButtonColorRes(R.color.nc_darkRed)
.setPositiveButtonColorRes(R.color.colorPrimary)
.setIcon(R.drawable.ic_security_white_24dp)
.setTitle(R.string.nc_certificate_dialog_title) .setTitle(R.string.nc_certificate_dialog_title)
.setMessage(dialogText) .setMessage(dialogText)
.setPositiveButton(R.string.nc_yes) { v -> .setPositiveButton(R.string.nc_yes) { _, _ ->
magicTrustManager.addCertInTrustStore(cert) magicTrustManager.addCertInTrustStore(cert)
sslErrorHandler?.proceed() sslErrorHandler?.proceed()
} }
.setNegativeButton(R.string.nc_no) { view1 -> .setNegativeButton(R.string.nc_no) { _, _ ->
sslErrorHandler?.cancel() 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) { } catch (e: CertificateParsingException) {
Log.d(TAG, "Failed to parse the certificate") Log.d(TAG, "Failed to parse the certificate")
} }

View File

@ -880,12 +880,13 @@ public class CallActivity extends CallBaseActivity {
if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) { if (EffortlessPermissions.hasPermissions(this, PERMISSIONS_MICROPHONE)) {
if (!appPreferences.getPushToTalkIntroShown()) { if (!appPreferences.getPushToTalkIntroShown()) {
int primary = viewThemeUtils.getScheme(binding.audioOutputButton.getContext()).getPrimary();
spotlightView = new SpotlightView.Builder(this) spotlightView = new SpotlightView.Builder(this)
.introAnimationDuration(300) .introAnimationDuration(300)
.enableRevealAnimation(true) .enableRevealAnimation(true)
.performClick(false) .performClick(false)
.fadeinTextDuration(400) .fadeinTextDuration(400)
.headingTvColor(getResources().getColor(R.color.colorPrimary)) .headingTvColor(primary)
.headingTvSize(20) .headingTvSize(20)
.headingTvText(getResources().getString(R.string.nc_push_to_talk)) .headingTvText(getResources().getString(R.string.nc_push_to_talk))
.subHeadingTvColor(getResources().getColor(R.color.bg_default)) .subHeadingTvColor(getResources().getColor(R.color.bg_default))
@ -894,7 +895,7 @@ public class CallActivity extends CallBaseActivity {
.maskColor(Color.parseColor("#dc000000")) .maskColor(Color.parseColor("#dc000000"))
.target(binding.microphoneButton) .target(binding.microphoneButton)
.lineAnimDuration(400) .lineAnimDuration(400)
.lineAndArcColor(getResources().getColor(R.color.colorPrimary)) .lineAndArcColor(primary)
.enableDismissAfterShown(true) .enableDismissAfterShown(true)
.dismissOnBackPress(true) .dismissOnBackPress(true)
.usageId("pushToTalk") .usageId("pushToTalk")

View File

@ -34,15 +34,20 @@ import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.ActivityFullScreenTextBinding import com.nextcloud.talk.databinding.ActivityFullScreenTextBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.Mimetype.TEXT_PREFIX_GENERIC import com.nextcloud.talk.utils.Mimetype.TEXT_PREFIX_GENERIC
import io.noties.markwon.Markwon import io.noties.markwon.Markwon
import java.io.File import java.io.File
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class FullScreenTextViewerActivity : AppCompatActivity() { class FullScreenTextViewerActivity : AppCompatActivity() {
lateinit var binding: ActivityFullScreenTextBinding lateinit var binding: ActivityFullScreenTextBinding
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var path: String private lateinit var path: String
override fun onCreateOptionsMenu(menu: Menu?): Boolean { override fun onCreateOptionsMenu(menu: Menu?): Boolean {
@ -77,6 +82,7 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
binding = ActivityFullScreenTextBinding.inflate(layoutInflater) binding = ActivityFullScreenTextBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
@ -98,12 +104,9 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
supportActionBar?.title = fileName supportActionBar?.title = fileName
supportActionBar?.setDisplayHomeAsUpEnabled(true) supportActionBar?.setDisplayHomeAsUpEnabled(true)
if (resources != null) { viewThemeUtils.themeStatusBar(this, binding.textviewToolbar)
DisplayUtils.applyColorToStatusBar(
this,
ResourcesCompat.getColor(resources, R.color.appbar, null)
)
if (resources != null) {
DisplayUtils.applyColorToNavigationBar( DisplayUtils.applyColorToNavigationBar(
this.window, this.window,
ResourcesCompat.getColor(resources, R.color.bg_default, null) ResourcesCompat.getColor(resources, R.color.bg_default, null)

View File

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

View File

@ -30,10 +30,10 @@ import android.view.View;
import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.interfaces.DraweeController;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.databinding.AccountItemBinding; import com.nextcloud.talk.databinding.AccountItemBinding;
import com.nextcloud.talk.models.json.participants.Participant; 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.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DisplayUtils;
@ -54,11 +54,16 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
private final User user; private final User user;
@Nullable @Nullable
private final Account account; private final Account account;
private final ViewThemeUtils viewThemeUtils;
public AdvancedUserItem(Participant participant, User user, @Nullable Account account) { public AdvancedUserItem(Participant participant,
User user,
@Nullable Account account,
ViewThemeUtils viewThemeUtils) {
this.participant = participant; this.participant = participant;
this.user = user; this.user = user;
this.account = account; this.account = account;
this.viewThemeUtils = viewThemeUtils;
} }
@Override @Override
@ -110,9 +115,7 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
holder.binding.userName, holder.binding.userName,
participant.getDisplayName(), participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication() viewThemeUtils.getScheme(holder.binding.userName.getContext()).getPrimary());
.getResources()
.getColor(R.color.colorPrimary));
} else { } else {
holder.binding.userName.setText(participant.getDisplayName()); holder.binding.userName.setText(participant.getDisplayName());
} }

View File

@ -25,6 +25,7 @@
package com.nextcloud.talk.adapters.items; package com.nextcloud.talk.adapters.items;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
@ -134,19 +135,15 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
holder.binding.avatarDraweeView.setAlpha(1.0f); holder.binding.avatarDraweeView.setAlpha(1.0f);
} }
holder.binding.nameText.setText(participant.getDisplayName());
if (adapter.hasFilter()) { if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.binding.nameText, FlexibleUtils.highlightText(holder.binding.nameText,
participant.getDisplayName(), participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication viewThemeUtils.getScheme(holder.binding.nameText.getContext()).getPrimary());
.Companion
.getSharedApplication()
.getResources()
.getColor(R.color.colorPrimary));
} }
holder.binding.nameText.setText(participant.getDisplayName());
if (TextUtils.isEmpty(participant.getDisplayName()) && if (TextUtils.isEmpty(participant.getDisplayName()) &&
(participant.getType().equals(Participant.ParticipantType.GUEST) || (participant.getType().equals(Participant.ParticipantType.GUEST) ||
participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) { participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
@ -162,45 +159,57 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
participant.getCalculatedActorType() == Participant.ActorType.CIRCLES || participant.getCalculatedActorType() == Participant.ActorType.CIRCLES ||
PARTICIPANT_SOURCE_CIRCLES.equals(participant.getSource())) { PARTICIPANT_SOURCE_CIRCLES.equals(participant.getSource())) {
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); setGenericAvatar(holder, R.drawable.ic_avatar_group, R.drawable.ic_circular_group);
} else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) { } else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) {
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail); setGenericAvatar(holder, R.drawable.ic_avatar_mail, R.drawable.ic_circular_mail);
} else if ( } else if (
participant.getCalculatedActorType() == Participant.ActorType.GUESTS || participant.getCalculatedActorType() == Participant.ActorType.GUESTS ||
Participant.ParticipantType.GUEST.equals(participant.getType()) || Participant.ParticipantType.GUEST.equals(participant.getType()) ||
Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) {
String displayName = NextcloudTalkApplication.Companion.getSharedApplication() String displayName;
.getResources().getString(R.string.nc_guest);
if (!TextUtils.isEmpty(participant.getDisplayName())) { if (!TextUtils.isEmpty(participant.getDisplayName())) {
displayName = participant.getDisplayName(); displayName = participant.getDisplayName();
} else {
displayName = NextcloudTalkApplication.Companion.getSharedApplication()
.getResources().getString(R.string.nc_guest);
} }
DraweeController draweeController = Fresco.newDraweeControllerBuilder() setUserStyleAvatar(holder,
.setOldController(holder.binding.avatarDraweeView.getController()) ApiUtils.getUrlForGuestAvatar(user.getBaseUrl(), displayName, false));
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForGuestAvatar(user.getBaseUrl(),
displayName,
false)))
.build();
holder.binding.avatarDraweeView.setController(draweeController);
} else if (participant.getCalculatedActorType() == Participant.ActorType.USERS || } else if (participant.getCalculatedActorType() == Participant.ActorType.USERS ||
PARTICIPANT_SOURCE_USERS.equals(participant.getSource())) { PARTICIPANT_SOURCE_USERS.equals(participant.getSource())) {
DraweeController draweeController = Fresco.newDraweeControllerBuilder() setUserStyleAvatar(holder,
.setOldController(holder.binding.avatarDraweeView.getController()) ApiUtils.getUrlForAvatar(user.getBaseUrl(),
.setAutoPlayAnimations(true) participant.getCalculatedActorId(),
.setImageRequest(DisplayUtils.getImageRequestForUrl( false));
ApiUtils.getUrlForAvatar(user.getBaseUrl(), }
participant.getCalculatedActorId(), }
false)))
.build(); private void setUserStyleAvatar(ContactItemViewHolder holder, String avatarUrl) {
holder.binding.avatarDraweeView.setController(draweeController); DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.binding.avatarDraweeView.getController())
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarUrl))
.build();
holder.binding.avatarDraweeView.setController(draweeController);
}
private void setGenericAvatar(
ContactItemViewHolder holder,
int roundPlaceholderDrawable,
int fallbackImageResource) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
DisplayUtils.getRoundedDrawable(
viewThemeUtils.themePlaceholderAvatar(holder.binding.avatarDraweeView,
roundPlaceholderDrawable)));
} else {
holder.binding.avatarDraweeView.setImageResource(fallbackImageResource);
} }
} }

View File

@ -61,7 +61,6 @@ import eu.davidea.flexibleadapter.items.AbstractFlexibleItem;
import eu.davidea.flexibleadapter.items.IFilterable; import eu.davidea.flexibleadapter.items.IFilterable;
import eu.davidea.flexibleadapter.items.IFlexible; import eu.davidea.flexibleadapter.items.IFlexible;
import eu.davidea.flexibleadapter.items.ISectionable; import eu.davidea.flexibleadapter.items.ISectionable;
import eu.davidea.flexibleadapter.utils.FlexibleUtils;
import eu.davidea.viewholders.FlexibleViewHolder; import eu.davidea.viewholders.FlexibleViewHolder;
public class ConversationItem extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements public class ConversationItem extends AbstractFlexibleItem<ConversationItem.ConversationItemViewHolder> implements
@ -144,9 +143,9 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
null)); null));
if (adapter.hasFilter()) { if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.binding.dialogName, conversation.getDisplayName(), viewThemeUtils.highlightText(holder.binding.dialogName,
String.valueOf(adapter.getFilter(String.class)), conversation.getDisplayName(),
viewThemeUtils.getElementColor(holder.binding.dialogName.getContext())); String.valueOf(adapter.getFilter(String.class)));
} else { } else {
holder.binding.dialogName.setText(conversation.getDisplayName()); holder.binding.dialogName.setText(conversation.getDisplayName());
} }
@ -264,9 +263,15 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
break; break;
case "file": case "file":
shouldLoadAvatar = false; shouldLoadAvatar = false;
holder.binding.dialogAvatar.setImageDrawable( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.getDrawable(context, holder.binding.dialogAvatar.setImageDrawable(
R.drawable.ic_circular_document)); 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; break;
default: default:
break; break;
@ -275,6 +280,7 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) { if (Conversation.ConversationType.ROOM_SYSTEM.equals(conversation.getType())) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
Drawable[] layers = new Drawable[2]; Drawable[] layers = new Drawable[2];
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background); layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background);
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground); layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground);
@ -307,14 +313,26 @@ public class ConversationItem extends AbstractFlexibleItem<ConversationItem.Conv
} }
break; break;
case ROOM_GROUP_CALL: case ROOM_GROUP_CALL:
holder.binding.dialogAvatar.setImageDrawable( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.getDrawable(context, holder.binding.dialogAvatar.setImageDrawable(
R.drawable.ic_circular_group)); 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; break;
case ROOM_PUBLIC_CALL: case ROOM_PUBLIC_CALL:
holder.binding.dialogAvatar.setImageDrawable( if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
ContextCompat.getDrawable(context, holder.binding.dialogAvatar.setImageDrawable(
R.drawable.ic_circular_link)); 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; break;
default: default:
holder.binding.dialogAvatar.setVisibility(View.GONE); holder.binding.dialogAvatar.setVisibility(View.GONE);

View File

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

View File

@ -26,21 +26,21 @@ package com.nextcloud.talk.adapters.items;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.view.View; import android.view.View;
import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.interfaces.DraweeController;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.models.json.mention.Mention;
import com.nextcloud.talk.models.json.status.StatusType; import com.nextcloud.talk.models.json.status.StatusType;
import com.nextcloud.talk.ui.StatusDrawable; import com.nextcloud.talk.ui.StatusDrawable;
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DisplayUtils;
import java.util.List; import java.util.List;
import java.util.Objects;
import java.util.regex.Pattern; import java.util.regex.Pattern;
import androidx.constraintlayout.widget.ConstraintLayout; import androidx.constraintlayout.widget.ConstraintLayout;
@ -67,11 +67,12 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
private final String statusMessage; private final String statusMessage;
private final User currentUser; private final User currentUser;
private final Context context; private final Context context;
private final ViewThemeUtils viewThemeUtils;
public MentionAutocompleteItem( public MentionAutocompleteItem(
Mention mention, Mention mention,
User currentUser, User currentUser,
Context activityContext) { Context activityContext, ViewThemeUtils viewThemeUtils) {
this.objectId = mention.getId(); this.objectId = mention.getId();
this.displayName = mention.getLabel(); this.displayName = mention.getLabel();
this.source = mention.getSource(); this.source = mention.getSource();
@ -80,6 +81,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
this.statusMessage = mention.getStatusMessage(); this.statusMessage = mention.getStatusMessage();
this.currentUser = currentUser; this.currentUser = currentUser;
this.context = activityContext; this.context = activityContext;
this.viewThemeUtils = viewThemeUtils;
} }
public String getSource() { public String getSource() {
@ -133,26 +135,27 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
FlexibleUtils.highlightText(holder.binding.nameText, FlexibleUtils.highlightText(holder.binding.nameText,
displayName, displayName,
String.valueOf(adapter.getFilter(String.class)), String.valueOf(adapter.getFilter(String.class)),
Objects.requireNonNull(NextcloudTalkApplication viewThemeUtils
.Companion .getScheme(holder.binding.secondaryText.getContext())
.getSharedApplication()) .getPrimary());
.getResources().getColor(R.color.colorPrimary)); FlexibleUtils.highlightText(holder.binding.secondaryText,
if (holder.binding.secondaryText != null) { "@" + objectId,
FlexibleUtils.highlightText(holder.binding.secondaryText, String.valueOf(adapter.getFilter(String.class)),
"@" + objectId, viewThemeUtils
String.valueOf(adapter.getFilter(String.class)), .getScheme(holder.binding.secondaryText.getContext())
NextcloudTalkApplication.Companion.getSharedApplication() .getPrimary());
.getResources().getColor(R.color.colorPrimary));
}
} else { } else {
holder.binding.nameText.setText(displayName); holder.binding.nameText.setText(displayName);
if (holder.binding.secondaryText != null) { holder.binding.secondaryText.setText("@" + objectId);
holder.binding.secondaryText.setText("@" + objectId);
}
} }
if (SOURCE_CALLS.equals(source)) { if (SOURCE_CALLS.equals(source)) {
if (holder.binding.avatarDraweeView != null) { 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_group)));
} else {
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);
} }
} else { } else {
@ -168,9 +171,7 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
false); false);
} }
if (holder.binding.avatarDraweeView != null) { holder.binding.avatarDraweeView.setController(null);
holder.binding.avatarDraweeView.setController(null);
}
DraweeController draweeController = Fresco.newDraweeControllerBuilder() DraweeController draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(holder.binding.avatarDraweeView.getController()) .setOldController(holder.binding.avatarDraweeView.getController())
@ -184,39 +185,35 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
} }
private void drawStatus(ParticipantItem.ParticipantItemViewHolder holder) { private void drawStatus(ParticipantItem.ParticipantItemViewHolder holder) {
if (holder.binding.conversationInfoStatusMessage != null && float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context);
holder.binding.participantStatusEmoji != null && holder.binding.userStatusImage.setImageDrawable(new StatusDrawable(
holder.binding.userStatusImage != null) { status,
float size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, context); NO_ICON,
holder.binding.userStatusImage.setImageDrawable(new StatusDrawable( size,
status, context.getResources().getColor(R.color.bg_default),
NO_ICON, context));
size,
context.getResources().getColor(R.color.bg_default),
context));
if (statusMessage != null) { if (statusMessage != null) {
holder.binding.conversationInfoStatusMessage.setText(statusMessage); holder.binding.conversationInfoStatusMessage.setText(statusMessage);
alignUsernameVertical(holder, 0); alignUsernameVertical(holder, 0);
} else { } else {
holder.binding.conversationInfoStatusMessage.setText(""); holder.binding.conversationInfoStatusMessage.setText("");
alignUsernameVertical(holder, 10); alignUsernameVertical(holder, 10);
}
if (statusIcon != null && !statusIcon.isEmpty()) {
holder.binding.participantStatusEmoji.setText(statusIcon);
} else {
holder.binding.participantStatusEmoji.setVisibility(View.GONE);
}
if (status != null && status.equals(StatusType.DND.getString())) {
if (statusMessage == null || statusMessage.isEmpty()) {
holder.binding.conversationInfoStatusMessage.setText(R.string.dnd);
} }
} else if (status != null && status.equals(StatusType.AWAY.getString())) {
if (statusIcon != null && !statusIcon.isEmpty()) { if (statusMessage == null || statusMessage.isEmpty()) {
holder.binding.participantStatusEmoji.setText(statusIcon); holder.binding.conversationInfoStatusMessage.setText(R.string.away);
} else {
holder.binding.participantStatusEmoji.setVisibility(View.GONE);
}
if (status != null && status.equals(StatusType.DND.getString())) {
if (statusMessage == null || statusMessage.isEmpty()) {
holder.binding.conversationInfoStatusMessage.setText(R.string.dnd);
}
} else if (status != null && status.equals(StatusType.AWAY.getString())) {
if (statusMessage == null || statusMessage.isEmpty()) {
holder.binding.conversationInfoStatusMessage.setText(R.string.away);
}
} }
} }
} }

View File

@ -77,9 +77,11 @@ data class MessageResultItem constructor(
} }
private fun bindMessageExcerpt(holder: ViewHolder) { private fun bindMessageExcerpt(holder: ViewHolder) {
val messageSpannable = SpannableString(messageEntry.messageExcerpt) val highlightedSpan = viewThemeUtils.createHighlightedSpan(
val highlightColor = viewThemeUtils.getElementColor(holder.binding.messageExcerpt.context) holder.binding.messageExcerpt.context,
val highlightedSpan = DisplayUtils.searchAndColor(messageSpannable, messageEntry.searchTerm, highlightColor) SpannableString(messageEntry.messageExcerpt),
messageEntry.searchTerm
)
holder.binding.messageExcerpt.text = highlightedSpan holder.binding.messageExcerpt.text = highlightedSpan
} }

View File

@ -27,6 +27,7 @@ package com.nextcloud.talk.adapters.items;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Context; import android.content.Context;
import android.content.res.Resources; import android.content.res.Resources;
import android.os.Build;
import android.text.TextUtils; import android.text.TextUtils;
import android.view.View; import android.view.View;
@ -41,6 +42,7 @@ import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.participants.Participant.InCallFlags; import com.nextcloud.talk.models.json.participants.Participant.InCallFlags;
import com.nextcloud.talk.models.json.status.StatusType; import com.nextcloud.talk.models.json.status.StatusType;
import com.nextcloud.talk.ui.StatusDrawable; import com.nextcloud.talk.ui.StatusDrawable;
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.ApiUtils;
import com.nextcloud.talk.utils.DisplayUtils; import com.nextcloud.talk.utils.DisplayUtils;
@ -64,14 +66,16 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
private final Context context; private final Context context;
private final Participant participant; private final Participant participant;
private final User user; private final User user;
private final ViewThemeUtils viewThemeUtils;
public boolean isOnline = true; public boolean isOnline = true;
public ParticipantItem(Context activityContext, public ParticipantItem(Context activityContext,
Participant participant, Participant participant,
User user) { User user, ViewThemeUtils viewThemeUtils) {
this.context = activityContext; this.context = activityContext;
this.participant = participant; this.participant = participant;
this.user = user; this.user = user;
this.viewThemeUtils = viewThemeUtils;
} }
public Participant getModel() { public Participant getModel() {
@ -127,16 +131,14 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
holder.binding.avatarDraweeView.setAlpha(1.0f); holder.binding.avatarDraweeView.setAlpha(1.0f);
} }
holder.binding.nameText.setText(participant.getDisplayName());
if (adapter.hasFilter()) { if (adapter.hasFilter()) {
FlexibleUtils.highlightText(holder.binding.nameText, participant.getDisplayName(), FlexibleUtils.highlightText(holder.binding.nameText, participant.getDisplayName(),
String.valueOf(adapter.getFilter(String.class)), String.valueOf(adapter.getFilter(String.class)),
NextcloudTalkApplication.Companion.getSharedApplication() viewThemeUtils.getScheme(holder.binding.nameText.getContext()).getPrimary());
.getResources()
.getColor(R.color.colorPrimary));
} }
holder.binding.nameText.setText(participant.getDisplayName());
if (TextUtils.isEmpty(participant.getDisplayName()) && if (TextUtils.isEmpty(participant.getDisplayName()) &&
(participant.getType().equals(Participant.ParticipantType.GUEST) || (participant.getType().equals(Participant.ParticipantType.GUEST) ||
participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) { participant.getType().equals(Participant.ParticipantType.USER_FOLLOWING_LINK))) {
@ -150,9 +152,23 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
"groups".equals(participant.getSource()) || "groups".equals(participant.getSource()) ||
participant.getCalculatedActorType() == Participant.ActorType.CIRCLES || participant.getCalculatedActorType() == Participant.ActorType.CIRCLES ||
"circles".equals(participant.getSource())) { "circles".equals(participant.getSource())) {
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group); 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_group)));
} else {
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);
}
} else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) { } 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 || } else if (participant.getCalculatedActorType() == Participant.ActorType.GUESTS ||
Participant.ParticipantType.GUEST.equals(participant.getType()) || Participant.ParticipantType.GUEST.equals(participant.getType()) ||
Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) { Participant.ParticipantType.GUEST_MODERATOR.equals(participant.getType())) {

View File

@ -41,7 +41,6 @@ import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.view.ViewCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.amulyakhare.textdrawable.TextDrawable 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.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage 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.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.UriUtils import com.nextcloud.talk.utils.UriUtils
@ -69,13 +69,14 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
var locationName: String? = "" var locationName: String? = ""
var locationGeoLink: String? = "" var locationGeoLink: String? = ""
@JvmField
@Inject @Inject
var context: Context? = null lateinit var context: Context
@JvmField
@Inject @Inject
var appPreferences: AppPreferences? = null lateinit var appPreferences: AppPreferences
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
lateinit var reactionsInterface: ReactionsInterface lateinit var reactionsInterface: ReactionsInterface
@ -89,7 +90,6 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
colorizeMessageBubble(message) colorizeMessageBubble(message)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(context?.resources!!.getColor(R.color.warm_grey_four))
val textSize = context?.resources!!.getDimension(R.dimen.chat_text_size) val textSize = context?.resources!!.getDimension(R.dimen.chat_text_size)
binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
@ -101,7 +101,13 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
// geo-location // geo-location
setLocationDataOnMessageItem(message) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -155,25 +161,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = itemView.resources viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
} }
private fun setParentMessageDataOnMessageItem(message: ChatMessage) { private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@ -199,7 +187,7 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
.setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast)) .setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
} else { } else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
} }

View File

@ -29,7 +29,6 @@ import android.text.TextUtils
import android.view.View import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.amulyakhare.textdrawable.TextDrawable 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.databinding.ItemCustomIncomingPollMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.polls.ui.PollMainDialogFragment 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.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
@ -60,6 +60,9 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
@Inject @Inject
lateinit var appPreferences: AppPreferences lateinit var appPreferences: AppPreferences
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject @Inject
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@ -78,14 +81,19 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
colorizeMessageBubble(message) colorizeMessageBubble(message)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(ResourcesCompat.getColor(context?.resources!!, R.color.warm_grey_four, null))
// parent message handling // parent message handling
setParentMessageDataOnMessageItem(message) setParentMessageDataOnMessageItem(message)
setPollPreview(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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -183,26 +191,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = itemView.resources viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
} }
private fun setParentMessageDataOnMessageItem(message: ChatMessage) { private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@ -228,7 +217,7 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
.setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
} else { } else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
} }

View File

@ -26,9 +26,13 @@ import android.view.View;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.facebook.drawee.view.SimpleDraweeView; 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.ItemCustomIncomingPreviewMessageBinding;
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding;
import com.nextcloud.talk.models.json.chat.ChatMessage;
import androidx.core.content.ContextCompat;
import androidx.emoji.widget.EmojiTextView; import androidx.emoji.widget.EmojiTextView;
public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder { public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder {
@ -39,6 +43,16 @@ public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHol
binding = ItemCustomIncomingPreviewMessageBinding.bind(itemView); 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 @Override
public EmojiTextView getMessageText() { public EmojiTextView getMessageText() {
return binding.messageText; return binding.messageText;
@ -60,7 +74,7 @@ public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHol
} }
@Override @Override
public View getPreviewContactContainer() { public MaterialCardView getPreviewContactContainer() {
return binding.contactContainer; return binding.contactContainer;
} }

View File

@ -37,7 +37,6 @@ import android.view.View
import android.widget.SeekBar import android.widget.SeekBar
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import androidx.work.WorkInfo import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import autodagger.AutoInjector import autodagger.AutoInjector
@ -90,7 +89,6 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
colorizeMessageBubble(message) colorizeMessageBubble(message)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(ResourcesCompat.getColor(context?.resources!!, R.color.warm_grey_four, null))
// parent message handling // parent message handling
setParentMessageDataOnMessageItem(message) setParentMessageDataOnMessageItem(message)
@ -98,6 +96,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
updateDownloadState(message) updateDownloadState(message)
binding.seekbar.max = message.voiceMessageDuration binding.seekbar.max = message.voiceMessageDuration
viewThemeUtils.themeHorizontalSeekBar(binding.seekbar) viewThemeUtils.themeHorizontalSeekBar(binding.seekbar)
viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
if (message.isPlayingVoiceMessage) { if (message.isPlayingVoiceMessage) {
showPlayButton() 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -261,25 +266,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = itemView.resources viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
} }
private fun setParentMessageDataOnMessageItem(message: ChatMessage) { private fun setParentMessageDataOnMessageItem(message: ChatMessage) {
@ -305,7 +292,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
.setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast)) .setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
} else { } else {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast) binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.textColorMaxContrast)
} }

View File

@ -26,7 +26,6 @@ package com.nextcloud.talk.adapters.messages
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.res.Resources
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.net.Uri import android.net.Uri
@ -38,7 +37,6 @@ import android.util.TypedValue
import android.view.View import android.view.View
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.view.ViewCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.amulyakhare.textdrawable.TextDrawable 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.databinding.ItemCustomIncomingTextMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback 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.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.TextMatchers import com.nextcloud.talk.utils.TextMatchers
@ -61,13 +60,14 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
private val binding: ItemCustomIncomingTextMessageBinding = ItemCustomIncomingTextMessageBinding.bind(itemView) private val binding: ItemCustomIncomingTextMessageBinding = ItemCustomIncomingTextMessageBinding.bind(itemView)
@JvmField
@Inject @Inject
var context: Context? = null lateinit var context: Context
@JvmField
@Inject @Inject
var appPreferences: AppPreferences? = null lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var appPreferences: AppPreferences
lateinit var reactionsInterface: ReactionsInterface lateinit var reactionsInterface: ReactionsInterface
@ -87,12 +87,9 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
binding.messageAuthor.visibility = View.GONE binding.messageAuthor.visibility = View.GONE
} }
val resources = itemView.resources viewThemeUtils.themeIncomingMessageBubble(bubble, message.isGrouped, message.isDeleted)
setBubbleOnChatMessage(message, resources)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(ResourcesCompat.getColor(resources, R.color.warm_grey_four, null))
var messageString: Spannable = SpannableString(message.text) 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) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) 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) { private fun processParentMessage(message: ChatMessage) {
val parentChatMessage = message.parentMessage val parentChatMessage = message.parentMessage
parentChatMessage!!.activeUser = message.activeUser 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 context!!.getText(R.string.nc_nick_guest) else parentChatMessage.actorDisplayName
binding.messageQuote.quotedMessage.text = parentChatMessage.text binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessageAuthor
.setTextColor(ContextCompat.getColor(context!!, R.color.textColorMaxContrast))
if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) { if (parentChatMessage.actorId?.equals(message.activeUser!!.userId) == true) {
binding.messageQuote.quoteColoredView.setBackgroundResource(R.color.colorPrimary) viewThemeUtils.colorPrimaryView(binding.messageQuote.quoteColoredView)
} else { } 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["name"]!!,
individualHashMap["type"]!!, individualHashMap["type"]!!,
message.activeUser!!, message.activeUser!!,
R.xml.chip_you R.xml.chip_you,
viewThemeUtils
) )
} else { } else {
messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan( messageStringInternal = DisplayUtils.searchAndReplaceWithMentionSpan(
@ -255,7 +234,8 @@ class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : Message
individualHashMap["name"]!!, individualHashMap["name"]!!,
individualHashMap["type"]!!, individualHashMap["type"]!!,
message.activeUser!!, message.activeUser!!,
R.xml.chip_others R.xml.chip_others,
viewThemeUtils
) )
} }
} else if (individualHashMap["type"] == "file") { } else if (individualHashMap["type"] == "file") {

View File

@ -25,14 +25,13 @@ package com.nextcloud.talk.adapters.messages
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.PorterDuff
import android.net.Uri import android.net.Uri
import android.text.Spannable import android.text.Spannable
import android.text.SpannableString import android.text.SpannableString
import android.util.TypedValue import android.util.TypedValue
import android.view.View import android.view.View
import androidx.core.content.res.ResourcesCompat import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.ColorUtils
import androidx.core.view.ViewCompat
import autodagger.AutoInjector import autodagger.AutoInjector
import coil.load import coil.load
import com.google.android.flexbox.FlexboxLayout 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.ChatMessage
import com.nextcloud.talk.models.json.chat.ReadStatus import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback 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.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils 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.DisplayUtils.searchAndReplaceWithMentionSpan
import com.nextcloud.talk.utils.TextMatchers import com.nextcloud.talk.utils.TextMatchers
import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewHolder<ChatMessage>(itemView) { class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessageViewHolder<ChatMessage>(itemView) {
@ -64,9 +60,6 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
lateinit var reactionsInterface: ReactionsInterface lateinit var reactionsInterface: ReactionsInterface
override fun onBind(message: ChatMessage) { override fun onBind(message: ChatMessage) {
@ -75,18 +68,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
val messageParameters: HashMap<String?, HashMap<String?, String?>>? = message.messageParameters val messageParameters: HashMap<String?, HashMap<String?, String?>>? = message.messageParameters
var messageString: Spannable = SpannableString(message.text) var messageString: Spannable = SpannableString(message.text)
realView.isSelected = false realView.isSelected = false
binding.messageTime.setTextColor(ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_60_INT))
val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams
layoutParams.isWrapBefore = false layoutParams.isWrapBefore = false
var textSize = context!!.resources.getDimension(R.dimen.chat_text_size) 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) { if (messageParameters != null && messageParameters.size > 0) {
messageString = processMessageParameters(messageParameters, message, messageString) messageString = processMessageParameters(messageParameters, message, messageString)
} else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) { } else if (TextMatchers.isMessageWithSingleEmoticonOnly(message.text)) {
textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat() textSize = (textSize * TEXT_SIZE_MULTIPLIER).toFloat()
layoutParams.isWrapBefore = true layoutParams.isWrapBefore = true
binding.messageTime.setTextColor(
ResourcesCompat.getColor(context!!.resources, R.color.warm_grey_four, null)
)
realView.isSelected = true realView.isSelected = true
} }
@ -94,9 +85,8 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
binding.messageTime.layoutParams = layoutParams binding.messageTime.layoutParams = layoutParams
binding.messageText.setTextColor(textColor)
binding.messageText.text = messageString binding.messageText.text = messageString
binding.messageText.setTextColor(serverTheme.colorText)
binding.messageText.setLinkTextColor(serverTheme.colorText)
// parent message handling // parent message handling
if (!message.isDeleted && message.parentMessage != null) { if (!message.isDeleted && message.parentMessage != null) {
@ -121,7 +111,9 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
readStatusDrawableInt?.let { drawableInt -> readStatusDrawableInt?.let { drawableInt ->
ResourcesCompat.getDrawable(context!!.resources, drawableInt, null)?.let { ResourcesCompat.getDrawable(context!!.resources, drawableInt, null)?.let {
binding.checkMark.setImageDrawable(it) 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) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -141,6 +133,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
private fun processParentMessage(message: ChatMessage) { private fun processParentMessage(message: ChatMessage) {
val parentChatMessage = message.parentMessage val parentChatMessage = message.parentMessage
val textColor = viewThemeUtils.getScheme(binding.messageQuote.quotedMessage.context).onSurfaceVariant
parentChatMessage!!.activeUser = message.activeUser parentChatMessage!!.activeUser = message.activeUser
parentChatMessage.imageUrl?.let { parentChatMessage.imageUrl?.let {
binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE binding.messageQuote.quotedMessageImage.visibility = View.VISIBLE
@ -156,43 +149,14 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest) ?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText)
binding.messageQuote.quotedMessageAuthor.setTextColor( binding.messageQuote.quotedMessageAuthor.setTextColor(textColor)
ColorUtils.setAlphaComponent( binding.messageQuote.quotedMessage.setTextColor(textColor)
serverTheme.colorText, binding.messageQuote.quoteColoredView.setBackgroundColor(textColor)
ALPHA_80_INT
)
)
binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText)
} }
private fun setBubbleOnChatMessage(message: ChatMessage) { private fun setBubbleOnChatMessage(message: ChatMessage) {
val resources = sharedApplication!!.resources viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
}
} }
private fun processMessageParameters( private fun processMessageParameters(
@ -215,7 +179,8 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
individualHashMap["name"]!!, individualHashMap["name"]!!,
individualHashMap["type"]!!, individualHashMap["type"]!!,
message.activeUser, message.activeUser,
R.xml.chip_others R.xml.chip_others,
viewThemeUtils
) )
} else if (individualHashMap["type"] == "file") { } else if (individualHashMap["type"] == "file") {
realView.setOnClickListener { v: View? -> realView.setOnClickListener { v: View? ->
@ -234,8 +199,5 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
companion object { companion object {
const val TEXT_SIZE_MULTIPLIER = 2.5 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()
} }
} }

View File

@ -42,6 +42,7 @@ import android.widget.PopupMenu;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.facebook.drawee.view.SimpleDraweeView; import com.facebook.drawee.view.SimpleDraweeView;
import com.google.android.material.card.MaterialCardView;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.components.filebrowser.models.BrowserFile; 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.data.user.model.User;
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding;
import com.nextcloud.talk.models.json.chat.ChatMessage; 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.DisplayUtils;
import com.nextcloud.talk.utils.DrawableUtils; import com.nextcloud.talk.utils.DrawableUtils;
import com.nextcloud.talk.utils.FileViewerUtils; import com.nextcloud.talk.utils.FileViewerUtils;
@ -94,7 +95,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
Context context; Context context;
@Inject @Inject
ServerTheme serverTheme; ViewThemeUtils viewThemeUtils;
@Inject @Inject
OkHttpClient okHttpClient; OkHttpClient okHttpClient;
@ -149,6 +150,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
} }
progressBar = getProgressBar(); progressBar = getProgressBar();
viewThemeUtils.colorCircularProgressBar(getProgressBar());
image = getImage(); image = getImage();
clickView = getImage(); clickView = getImage();
getMessageText().setVisibility(View.VISIBLE); getMessageText().setVisibility(View.VISIBLE);
@ -165,6 +167,9 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
progressBar = getPreviewContactProgressBar(); progressBar = getPreviewContactProgressBar();
getMessageText().setVisibility(View.INVISIBLE); getMessageText().setVisibility(View.INVISIBLE);
clickView = getPreviewContactContainer(); clickView = getPreviewContactContainer();
viewThemeUtils.colorContactChatItemBackground(getPreviewContactContainer());
viewThemeUtils.colorContactChatItemName(getPreviewContactName());
viewThemeUtils.colorCircularProgressBarOnPrimaryContainer(getPreviewContactProgressBar());
} else { } else {
getPreviewContainer().setVisibility(View.VISIBLE); getPreviewContainer().setVisibility(View.VISIBLE);
getPreviewContactContainer().setVisibility(View.GONE); getPreviewContactContainer().setVisibility(View.GONE);
@ -184,7 +189,8 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
if (drawable != null && if (drawable != null &&
(drawableResourceId == R.drawable.ic_mimetype_folder || (drawableResourceId == R.drawable.ic_mimetype_folder ||
drawableResourceId == R.drawable.ic_mimetype_package_x_generic)) { 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); image.getHierarchy().setPlaceholderImage(drawable);
@ -239,7 +245,11 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable()); itemView.setTag(REPLYABLE_VIEW_TAG, message.getReplyable());
reactionsBinding = getReactionsBinding(); reactionsBinding = getReactionsBinding();
new Reaction().showReactions(message, reactionsBinding, getMessageText().getContext(), true); new Reaction().showReactions(message,
reactionsBinding,
getMessageText().getContext(),
true,
viewThemeUtils);
reactionsBinding.reactionsEmojiWrapper.setOnClickListener(l -> { reactionsBinding.reactionsEmojiWrapper.setOnClickListener(l -> {
reactionsInterface.onClickReactions(message); reactionsInterface.onClickReactions(message);
}); });
@ -353,7 +363,7 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
public abstract View getPreviewContainer(); public abstract View getPreviewContainer();
public abstract View getPreviewContactContainer(); public abstract MaterialCardView getPreviewContactContainer();
public abstract SimpleDraweeView getPreviewContactPhoto(); public abstract SimpleDraweeView getPreviewContactPhoto();

View File

@ -25,6 +25,7 @@ package com.nextcloud.talk.adapters.messages
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.graphics.PorterDuff
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
import android.util.TypedValue import android.util.TypedValue
@ -34,9 +35,6 @@ import android.webkit.WebView
import android.webkit.WebViewClient import android.webkit.WebViewClient
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.content.res.AppCompatResources 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 autodagger.AutoInjector
import coil.load import coil.load
import com.google.android.flexbox.FlexboxLayout 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.databinding.ItemCustomOutcomingLocationMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.chat.ReadStatus 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.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.UriUtils import com.nextcloud.talk.utils.UriUtils
import com.stfalcon.chatkit.messages.MessageHolders import com.stfalcon.chatkit.messages.MessageHolders
import java.net.URLEncoder import java.net.URLEncoder
@ -68,22 +64,20 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
var locationName: String? = "" var locationName: String? = ""
var locationGeoLink: String? = "" var locationGeoLink: String? = ""
@JvmField
@Inject @Inject
var context: Context? = null lateinit var context: Context
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
lateinit var reactionsInterface: ReactionsInterface lateinit var reactionsInterface: ReactionsInterface
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBind(message: ChatMessage) { override fun onBind(message: ChatMessage) {
super.onBind(message) super.onBind(message)
sharedApplication!!.componentApplication.inject(this) sharedApplication!!.componentApplication.inject(this)
val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
binding.messageTime.setTextColor(textColor)
realView.isSelected = false realView.isSelected = false
val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams val layoutParams = binding.messageTime.layoutParams as FlexboxLayout.LayoutParams
@ -94,11 +88,8 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
colorizeMessageBubble(message) colorizeMessageBubble(message)
binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize) binding.messageText.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
binding.messageTime.layoutParams = layoutParams binding.messageTime.layoutParams = layoutParams
binding.messageTime.setTextColor(ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_60_INT))
binding.messageText.text = message.text binding.messageText.text = message.text
binding.messageText.setTextColor(serverTheme.colorText)
binding.messageText.setLinkTextColor(serverTheme.colorText)
// parent message handling // parent message handling
setParentMessageDataOnMessageItem(message) setParentMessageDataOnMessageItem(message)
@ -118,7 +109,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
readStatusDrawableInt?.let { drawableInt -> readStatusDrawableInt?.let { drawableInt ->
AppCompatResources.getDrawable(context!!, drawableInt)?.let { AppCompatResources.getDrawable(context!!, drawableInt)?.let {
binding.checkMark.setImageDrawable(it) 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 // geo-location
setLocationDataOnMessageItem(message) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -213,12 +212,9 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest) ?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
binding.messageQuote.quotedMessageAuthor.setTextColor( viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_80_INT) viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
)
binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText)
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} else { } else {
@ -227,30 +223,7 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = sharedApplication!!.resources viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
}
} }
private fun openGeoLink() { private fun openGeoLink() {
@ -277,6 +250,5 @@ class OutcomingLocationMessageViewHolder(incomingView: View) : MessageHolders
private const val TAG = "LocOutMessageView" private const val TAG = "LocOutMessageView"
private const val HALF_ALPHA_INT: Int = 255 / 2 private const val HALF_ALPHA_INT: Int = 255 / 2
private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt() private val ALPHA_60_INT: Int = (255 * 0.6).roundToInt()
private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt()
} }
} }

View File

@ -23,12 +23,9 @@ package com.nextcloud.talk.adapters.messages
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.res.ColorStateList import android.graphics.PorterDuff
import android.view.View import android.view.View
import androidx.appcompat.content.res.AppCompatResources 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 autodagger.AutoInjector
import coil.load import coil.load
import com.nextcloud.talk.R 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.ChatMessage
import com.nextcloud.talk.models.json.chat.ReadStatus import com.nextcloud.talk.models.json.chat.ReadStatus
import com.nextcloud.talk.polls.ui.PollMainDialogFragment 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.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders import com.stfalcon.chatkit.messages.MessageHolders
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : MessageHolders class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : MessageHolders
@ -62,9 +56,6 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
@Inject @Inject
lateinit var appPreferences: AppPreferences lateinit var appPreferences: AppPreferences
@ -80,16 +71,12 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
super.onBind(message) super.onBind(message)
this.message = message this.message = message
sharedApplication!!.componentApplication.inject(this) sharedApplication!!.componentApplication.inject(this)
val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
binding.messageTime.setTextColor(textColor)
colorizeMessageBubble(message) colorizeMessageBubble(message)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(
ColorUtils.setAlphaComponent(
serverTheme.colorText,
ALPHA_60_INT
)
)
// parent message handling // parent message handling
setParentMessageDataOnMessageItem(message) setParentMessageDataOnMessageItem(message)
@ -109,7 +96,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
readStatusDrawableInt?.let { drawableInt -> readStatusDrawableInt?.let { drawableInt ->
AppCompatResources.getDrawable(context, drawableInt)?.let { AppCompatResources.getDrawable(context, drawableInt)?.let {
binding.checkMark.setImageDrawable(it) 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) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -142,9 +137,6 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
} }
if (pollId != null && pollName != null) { 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 binding.messagePollTitle.text = pollName
val roomToken = (payload as? MessagePayload)!!.roomToken val roomToken = (payload as? MessagePayload)!!.roomToken
@ -184,12 +176,9 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context.getText(R.string.nc_nick_guest) ?: context.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
binding.messageQuote.quotedMessageAuthor.setTextColor( viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
ColorUtils.setAlphaComponent(serverTheme.colorText, ALPHA_80_INT) viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
)
binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText)
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} else { } else {
@ -198,30 +187,7 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = sharedApplication!!.resources viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
}
} }
fun assignReactionInterface(reactionsInterface: ReactionsInterface) { fun assignReactionInterface(reactionsInterface: ReactionsInterface) {
@ -230,8 +196,5 @@ class OutcomingPollMessageViewHolder(outcomingView: View, payload: Any) : Messag
companion object { companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName 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
} }
} }

View File

@ -26,12 +26,17 @@ import android.view.View;
import android.widget.ProgressBar; import android.widget.ProgressBar;
import com.facebook.drawee.view.SimpleDraweeView; 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.ItemCustomOutcomingPreviewMessageBinding;
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding; import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding;
import com.nextcloud.talk.models.json.chat.ChatMessage;
import androidx.core.content.ContextCompat;
import androidx.emoji.widget.EmojiTextView; import androidx.emoji.widget.EmojiTextView;
public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder { public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder {
private final ItemCustomOutcomingPreviewMessageBinding binding; private final ItemCustomOutcomingPreviewMessageBinding binding;
public OutcomingPreviewMessageViewHolder(View itemView) { public OutcomingPreviewMessageViewHolder(View itemView) {
@ -39,6 +44,16 @@ public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHo
binding = ItemCustomOutcomingPreviewMessageBinding.bind(itemView); 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 @Override
public EmojiTextView getMessageText() { public EmojiTextView getMessageText() {
return binding.messageText; return binding.messageText;
@ -60,7 +75,7 @@ public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHo
} }
@Override @Override
public View getPreviewContactContainer() { public MaterialCardView getPreviewContactContainer() {
return binding.contactContainer; return binding.contactContainer;
} }

View File

@ -31,9 +31,6 @@ import android.view.View
import android.widget.SeekBar import android.widget.SeekBar
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat 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.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import autodagger.AutoInjector 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.databinding.ItemCustomOutcomingVoiceMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.chat.ReadStatus 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.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders import com.stfalcon.chatkit.messages.MessageHolders
import java.util.concurrent.ExecutionException import java.util.concurrent.ExecutionException
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
@ -68,9 +62,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
@JvmField @JvmField
@Inject @Inject
var appPreferences: AppPreferences? = null var appPreferences: AppPreferences? = null
@ -87,23 +78,20 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
super.onBind(message) super.onBind(message)
this.message = message this.message = message
sharedApplication!!.componentApplication.inject(this) sharedApplication!!.componentApplication.inject(this)
val textColor = viewThemeUtils.getScheme(binding.messageTime.context).onSurfaceVariant
binding.messageTime.setTextColor(textColor)
colorizeMessageBubble(message) colorizeMessageBubble(message)
itemView.isSelected = false itemView.isSelected = false
binding.messageTime.setTextColor(
ColorUtils.setAlphaComponent(
serverTheme.colorText,
ALPHA_60_INT
)
)
// parent message handling // parent message handling
setParentMessageDataOnMessageItem(message) setParentMessageDataOnMessageItem(message)
updateDownloadState(message) updateDownloadState(message)
binding.seekbar.max = message.voiceMessageDuration binding.seekbar.max = message.voiceMessageDuration
viewThemeUtils.themeHorizontalSeekBar(binding.seekbar, serverTheme.colorText) viewThemeUtils.themeHorizontalSeekBar(binding.seekbar)
viewThemeUtils.colorCircularProgressBarOnSurfaceVariant(binding.progressBar)
handleIsPlayingVoiceMessageState(message) handleIsPlayingVoiceMessageState(message)
@ -142,13 +130,21 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
readStatusDrawableInt?.let { drawableInt -> readStatusDrawableInt?.let { drawableInt ->
AppCompatResources.getDrawable(context!!, drawableInt)?.let { AppCompatResources.getDrawable(context!!, drawableInt)?.let {
binding.checkMark.setImageDrawable(it) 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) 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 { binding.reactions.reactionsEmojiWrapper.setOnClickListener {
reactionsInterface.onClickReactions(message) reactionsInterface.onClickReactions(message)
} }
@ -165,7 +161,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
context!!, context!!,
R.drawable.ic_baseline_play_arrow_voice_message_24 R.drawable.ic_baseline_play_arrow_voice_message_24
) )
binding.playPauseBtn.icon.setColorFilter(serverTheme.colorText, PorterDuff.Mode.SRC_ATOP)
binding.seekbar.progress = SEEKBAR_START binding.seekbar.progress = SEEKBAR_START
message.resetVoiceMessage = false message.resetVoiceMessage = false
} }
@ -186,7 +181,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
context!!, context!!,
R.drawable.ic_baseline_pause_voice_message_24 R.drawable.ic_baseline_pause_voice_message_24
) )
binding.playPauseBtn.icon.setColorFilter(serverTheme.colorText, PorterDuff.Mode.SRC_ATOP)
binding.seekbar.progress = message.voiceMessagePlayedSeconds binding.seekbar.progress = message.voiceMessagePlayedSeconds
} else { } else {
binding.playPauseBtn.visibility = View.VISIBLE binding.playPauseBtn.visibility = View.VISIBLE
@ -194,7 +188,6 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
context!!, context!!,
R.drawable.ic_baseline_play_arrow_voice_message_24 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 binding.messageQuote.quotedMessageAuthor.text = parentChatMessage.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest) ?: context!!.getText(R.string.nc_nick_guest)
binding.messageQuote.quotedMessage.text = parentChatMessage.text binding.messageQuote.quotedMessage.text = parentChatMessage.text
binding.messageQuote.quotedMessage.setTextColor(serverTheme.colorText) viewThemeUtils.colorOutgoingQuoteText(binding.messageQuote.quotedMessage)
binding.messageQuote.quotedMessageAuthor.setTextColor( viewThemeUtils.colorOutgoingQuoteAuthorText(binding.messageQuote.quotedMessageAuthor)
ColorUtils.setAlphaComponent( viewThemeUtils.colorOutgoingQuoteBackground(binding.messageQuote.quoteColoredView)
serverTheme.colorText,
ALPHA_80_INT
)
)
binding.messageQuote.quoteColoredView.setBackgroundColor(serverTheme.colorText)
binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE binding.messageQuote.quotedChatMessageView.visibility = View.VISIBLE
} else { } else {
@ -287,30 +274,7 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
} }
private fun colorizeMessageBubble(message: ChatMessage) { private fun colorizeMessageBubble(message: ChatMessage) {
val resources = sharedApplication!!.resources viewThemeUtils.themeOutgoingMessageBubble(bubble, message.isGrouped, message.isDeleted)
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)
}
} }
fun assignVoiceMessageInterface(voiceMessageInterface: VoiceMessageInterface) { fun assignVoiceMessageInterface(voiceMessageInterface: VoiceMessageInterface) {
@ -324,8 +288,5 @@ class OutcomingVoiceMessageViewHolder(outcomingView: View) : MessageHolders
companion object { companion object {
private const val TAG = "VoiceOutMessageView" private const val TAG = "VoiceOutMessageView"
private const val SEEKBAR_START: Int = 0 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()
} }
} }

View File

@ -27,11 +27,11 @@ import android.content.Context
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.LinearLayout import android.widget.LinearLayout
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.content.res.AppCompatResources
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.vanniktech.emoji.EmojiTextView import com.vanniktech.emoji.EmojiTextView
@ -41,7 +41,8 @@ class Reaction {
message: ChatMessage, message: ChatMessage,
binding: ReactionsInsideMessageBinding, binding: ReactionsInsideMessageBinding,
context: Context, context: Context,
isOutgoingMessage: Boolean isOutgoingMessage: Boolean,
viewThemeUtils: ViewThemeUtils
) { ) {
binding.reactionsEmojiWrapper.removeAllViews() binding.reactionsEmojiWrapper.removeAllViews()
if (message.reactions != null && message.reactions!!.isNotEmpty()) { if (message.reactions != null && message.reactions!!.isNotEmpty()) {
@ -49,7 +50,6 @@ class Reaction {
var remainingEmojisToDisplay = MAX_EMOJIS_TO_DISPLAY var remainingEmojisToDisplay = MAX_EMOJIS_TO_DISPLAY
val showInfoAboutMoreEmojis = message.reactions!!.size > MAX_EMOJIS_TO_DISPLAY val showInfoAboutMoreEmojis = message.reactions!!.size > MAX_EMOJIS_TO_DISPLAY
val textColor = getTextColor(context, isOutgoingMessage, binding)
val amountParams = getAmountLayoutParams(context) val amountParams = getAmountLayoutParams(context)
val wrapperParams = getWrapperLayoutParams(context) val wrapperParams = getWrapperLayoutParams(context)
@ -58,9 +58,12 @@ class Reaction {
val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt() val paddingBottom = DisplayUtils.convertDpToPixel(WRAPPER_PADDING_BOTTOM, context).toInt()
for ((emoji, amount) in message.reactions!!) { 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( val emojiWithAmountWrapper = getEmojiWithAmountWrapperLayout(
context, binding.reactionsEmojiWrapper.context,
message,
emoji, emoji,
amount, amount,
EmojiWithAmountWrapperLayoutInfo( EmojiWithAmountWrapperLayoutInfo(
@ -69,7 +72,10 @@ class Reaction {
wrapperParams, wrapperParams,
paddingSide, paddingSide,
paddingTop, paddingTop,
paddingBottom paddingBottom,
viewThemeUtils,
isOutgoingMessage,
isSelfReaction
), ),
) )
@ -86,7 +92,6 @@ class Reaction {
private fun getEmojiWithAmountWrapperLayout( private fun getEmojiWithAmountWrapperLayout(
context: Context, context: Context,
message: ChatMessage,
emoji: String, emoji: String,
amount: Int, amount: Int,
layoutInfo: EmojiWithAmountWrapperLayoutInfo layoutInfo: EmojiWithAmountWrapperLayoutInfo
@ -98,12 +103,17 @@ class Reaction {
emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, layoutInfo.amountParams)) emojiWithAmountWrapper.addView(getReactionCount(context, layoutInfo.textColor, amount, layoutInfo.amountParams))
emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams emojiWithAmountWrapper.layoutParams = layoutInfo.wrapperParams
if (message.reactionsSelf != null && if (layoutInfo.isSelfReaction) {
message.reactionsSelf!!.isNotEmpty() && val color = if (layoutInfo.isOutgoingMessage) {
message.reactionsSelf!!.contains(emoji) ContextCompat.getColor(
) { emojiWithAmountWrapper.context,
emojiWithAmountWrapper.background = R.color.bg_message_list_incoming_bubble
AppCompatResources.getDrawable(context, R.drawable.reaction_self_background) )
} else {
layoutInfo.viewThemeUtils.getScheme(emojiWithAmountWrapper.context).primaryContainer
}
layoutInfo.viewThemeUtils.setCheckedBackground(emojiWithAmountWrapper, color)
emojiWithAmountWrapper.setPaddingRelative( emojiWithAmountWrapper.setPaddingRelative(
layoutInfo.paddingSide, layoutInfo.paddingSide,
layoutInfo.paddingTop, layoutInfo.paddingTop,
@ -166,12 +176,13 @@ class Reaction {
} }
private fun getTextColor( private fun getTextColor(
context: Context,
isOutgoingMessage: Boolean, isOutgoingMessage: Boolean,
binding: ReactionsInsideMessageBinding isSelfReaction: Boolean,
binding: ReactionsInsideMessageBinding,
viewThemeUtils: ViewThemeUtils
): Int { ): Int {
var textColor = ContextCompat.getColor(context, R.color.white) var textColor = viewThemeUtils.getScheme(binding.root.context).onSurfaceVariant
if (!isOutgoingMessage) { if (!isOutgoingMessage || isSelfReaction) {
textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text) textColor = ContextCompat.getColor(binding.root.context, R.color.high_emphasis_text)
} }
return textColor return textColor
@ -183,7 +194,10 @@ class Reaction {
val wrapperParams: LinearLayout.LayoutParams, val wrapperParams: LinearLayout.LayoutParams,
val paddingSide: Int, val paddingSide: Int,
val paddingTop: Int, val paddingTop: Int,
val paddingBottom: Int val paddingBottom: Int,
val viewThemeUtils: ViewThemeUtils,
val isOutgoingMessage: Boolean,
val isSelfReaction: Boolean
) )
companion object { companion object {

View File

@ -31,6 +31,7 @@ import com.facebook.widget.text.span.BetterImageSpan;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.models.json.mention.Mention; 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.DisplayUtils;
import com.nextcloud.talk.utils.MagicCharPolicy; import com.nextcloud.talk.utils.MagicCharPolicy;
import com.nextcloud.talk.utils.text.Spans; import com.nextcloud.talk.utils.text.Spans;
@ -39,15 +40,19 @@ import com.vanniktech.emoji.EmojiRange;
import com.vanniktech.emoji.Emojis; import com.vanniktech.emoji.Emojis;
public class MentionAutocompleteCallback implements AutocompleteCallback<Mention> { public class MentionAutocompleteCallback implements AutocompleteCallback<Mention> {
private final ViewThemeUtils viewThemeUtils;
private Context context; private Context context;
private User conversationUser; private User conversationUser;
private EditText editText; private EditText editText;
public MentionAutocompleteCallback(Context context, User conversationUser, public MentionAutocompleteCallback(Context context,
EditText editText) { User conversationUser,
EditText editText,
ViewThemeUtils viewThemeUtils) {
this.context = context; this.context = context;
this.conversationUser = conversationUser; this.conversationUser = conversationUser;
this.editText = editText; this.editText = editText;
this.viewThemeUtils = viewThemeUtils;
} }
@Override @Override
@ -73,11 +78,14 @@ public class MentionAutocompleteCallback implements AutocompleteCallback<Mention
conversationUser, conversationUser,
item.getSource(), item.getSource(),
R.xml.chip_you, R.xml.chip_you,
editText), editText,
viewThemeUtils),
BetterImageSpan.ALIGN_CENTER, BetterImageSpan.ALIGN_CENTER,
item.getId(), item.getLabel()); item.getId(), item.getLabel());
editable.setSpan(mentionChipSpan, start, start + replacementStringBuilder.toString().length(), editable.setSpan(mentionChipSpan, start, start + replacementStringBuilder.toString().length(),
Spanned.SPAN_INCLUSIVE_INCLUSIVE); Spanned.SPAN_INCLUSIVE_INCLUSIVE);
return true; return true;
} }

View File

@ -35,11 +35,9 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.content.res.AssetFileDescriptor import android.content.res.AssetFileDescriptor
import android.content.res.ColorStateList
import android.content.res.Resources import android.content.res.Resources
import android.database.Cursor import android.database.Cursor
import android.graphics.Bitmap import android.graphics.Bitmap
import android.graphics.Color
import android.graphics.drawable.ColorDrawable import android.graphics.drawable.ColorDrawable
import android.media.MediaPlayer import android.media.MediaPlayer
import android.media.MediaRecorder import android.media.MediaRecorder
@ -74,6 +72,7 @@ import android.widget.ImageView
import android.widget.PopupMenu import android.widget.PopupMenu
import android.widget.RelativeLayout import android.widget.RelativeLayout
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.view.ContextThemeWrapper import androidx.appcompat.view.ContextThemeWrapper
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider import androidx.core.content.FileProvider
@ -100,6 +99,7 @@ import com.facebook.drawee.backends.pipeline.Fresco
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
import com.facebook.imagepipeline.image.CloseableImage import com.facebook.imagepipeline.image.CloseableImage
import com.google.android.flexbox.FlexboxLayout import com.google.android.flexbox.FlexboxLayout
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.activities.CallActivity import com.nextcloud.talk.activities.CallActivity
@ -154,8 +154,6 @@ import com.nextcloud.talk.ui.dialog.MessageActionsDialog
import com.nextcloud.talk.ui.dialog.ShowReactionsDialog import com.nextcloud.talk.ui.dialog.ShowReactionsDialog
import com.nextcloud.talk.ui.recyclerview.MessageSwipeActions import com.nextcloud.talk.ui.recyclerview.MessageSwipeActions
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback 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.ApiUtils
import com.nextcloud.talk.utils.AttendeePermissionsUtil import com.nextcloud.talk.utils.AttendeePermissionsUtil
import com.nextcloud.talk.utils.ConductorRemapping import com.nextcloud.talk.utils.ConductorRemapping
@ -190,7 +188,6 @@ import com.stfalcon.chatkit.messages.MessageHolders.ContentChecker
import com.stfalcon.chatkit.messages.MessagesListAdapter import com.stfalcon.chatkit.messages.MessagesListAdapter
import com.stfalcon.chatkit.utils.DateFormatter import com.stfalcon.chatkit.utils.DateFormatter
import com.vanniktech.emoji.EmojiPopup import com.vanniktech.emoji.EmojiPopup
import com.yarolegovich.lovelydialog.LovelyStandardDialog
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
@ -237,12 +234,6 @@ class ChatController(args: Bundle) :
@Inject @Inject
lateinit var permissionUtil: PlatformPermissionUtil lateinit var permissionUtil: PlatformPermissionUtil
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
val disposables = DisposableSet() val disposables = DisposableSet()
var roomToken: String? = null var roomToken: String? = null
@ -655,8 +646,7 @@ class ChatController(args: Bundle) :
} }
} }
binding.popupBubbleView.setTextColor(Color.WHITE) viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.popupBubbleView)
binding.popupBubbleView.setIconTint(ColorStateList.valueOf(Color.WHITE))
binding.messageInputView.setPadding(0, 0, 0, 0) binding.messageInputView.setPadding(0, 0, 0, 0)
@ -1415,28 +1405,38 @@ class ChatController(args: Bundle) :
val confirmationQuestion = when (filesToUpload.size) { val confirmationQuestion = when (filesToUpload.size) {
1 -> context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let { 1 -> 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 { else -> context?.resources?.getString(R.string.nc_upload_confirm_send_multiple)?.let {
String.format(it, title) String.format(it, title.trim())
} }
} }
LovelyStandardDialog(activity) val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageInputView.context)
.setPositiveButtonColorRes(R.color.nc_darkGreen)
.setTitle(confirmationQuestion) .setTitle(confirmationQuestion)
.setMessage(filenamesWithLinebreaks.toString()) .setMessage(filenamesWithLinebreaks.toString())
.setPositiveButton(R.string.nc_yes) { v -> .setPositiveButton(R.string.nc_yes) { _, _ ->
if (UploadAndShareFilesWorker.isStoragePermissionGranted(context!!)) { if (UploadAndShareFilesWorker.isStoragePermissionGranted(context)) {
uploadFiles(filesToUpload, false) uploadFiles(filesToUpload, false)
} else { } else {
UploadAndShareFilesWorker.requestStoragePermission(this) UploadAndShareFilesWorker.requestStoragePermission(this)
} }
} }
.setNegativeButton(R.string.nc_no) { .setNegativeButton(R.string.nc_no) { _, _ ->
// unused atm // 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) { } catch (e: IllegalStateException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG) Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
.show() .show()
@ -1683,7 +1683,8 @@ class ChatController(args: Bundle) :
val callback = MentionAutocompleteCallback( val callback = MentionAutocompleteCallback(
activity, activity,
conversationUser!!, conversationUser!!,
binding.messageInputView.inputEditText binding.messageInputView.inputEditText,
viewThemeUtils
) )
if (mentionAutocomplete == null && binding.messageInputView.inputEditText != null) { if (mentionAutocomplete == null && binding.messageInputView.inputEditText != null) {
@ -1764,6 +1765,8 @@ class ChatController(args: Bundle) :
cancelReply() cancelReply()
} }
viewThemeUtils.themeImageButton(binding.messageInputView.findViewById<ImageButton>(R.id.cancelReplyButton))
cancelNotificationsForCurrentConversation() cancelNotificationsForCurrentConversation()
Log.d(TAG, "onAttach inConversation: " + inConversation.toString()) Log.d(TAG, "onAttach inConversation: " + inConversation.toString())
@ -2487,6 +2490,16 @@ class ChatController(args: Bundle) :
super.onCreateOptionsMenu(menu, inflater) super.onCreateOptionsMenu(menu, inflater)
inflater.inflate(R.menu.menu_conversation, menu) 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 == "?") { if (conversationUser?.userId == "?") {
menu.removeItem(R.id.conversation_info) menu.removeItem(R.id.conversation_info)
} else { } else {
@ -2685,8 +2698,7 @@ class ChatController(args: Bundle) :
chatMessage, chatMessage,
conversationUser, conversationUser,
hasChatPermission, hasChatPermission,
ncApi!!, ncApi
serverTheme
).show() ).show()
} }
} }

View File

@ -65,7 +65,6 @@ import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter
import com.nextcloud.talk.models.json.participants.Participant import com.nextcloud.talk.models.json.participants.Participant
import com.nextcloud.talk.ui.dialog.ContactsBottomDialog import com.nextcloud.talk.ui.dialog.ContactsBottomDialog
import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ConductorRemapping import com.nextcloud.talk.utils.ConductorRemapping
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
@ -104,9 +103,6 @@ class ContactsController(args: Bundle) :
@Inject @Inject
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private var credentials: String? = null private var credentials: String? = null
private var currentUser: User? = null private var currentUser: User? = null
private var contactsQueryDisposable: Disposable? = null private var contactsQueryDisposable: Disposable? = null
@ -338,6 +334,7 @@ class ContactsController(args: Bundle) :
val searchManager: SearchManager? = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager? val searchManager: SearchManager? = activity?.getSystemService(Context.SEARCH_SERVICE) as SearchManager?
if (searchItem != null) { if (searchItem != null) {
searchView = MenuItemCompat.getActionView(searchItem) as SearchView searchView = MenuItemCompat.getActionView(searchItem) as SearchView
viewThemeUtils.themeSearchView(searchView!!)
searchView!!.maxWidth = Int.MAX_VALUE searchView!!.maxWidth = Int.MAX_VALUE
searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER searchView!!.inputType = InputType.TYPE_TEXT_VARIATION_FILTER
var imeOptions: Int = EditorInfo.IME_ACTION_DONE or EditorInfo.IME_FLAG_NO_FULLSCREEN 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) { override fun onPrepareOptionsMenu(menu: Menu) {
super.onPrepareOptionsMenu(menu) super.onPrepareOptionsMenu(menu)
if (searchItem != null) {
viewThemeUtils.colorToolbarMenuIcon(
binding.titleTextView.context,
searchItem!!
)
}
checkAndHandleDoneMenuItem() checkAndHandleDoneMenuItem()
if (adapter?.hasFilter() == true) { if (adapter?.hasFilter() == true) {
searchItem!!.expandActionView() searchItem!!.expandActionView()
@ -632,6 +637,7 @@ class ContactsController(args: Bundle) :
ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null), ResourcesCompat.getColor(resources!!, R.color.colorBackgroundDarker, null),
PorterDuff.Mode.SRC_IN PorterDuff.Mode.SRC_IN
) )
viewThemeUtils.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink) viewThemeUtils.colorImageViewButton(binding.conversationPrivacyToggle.publicCallLink)
disengageProgressBar() disengageProgressBar()
} }

View File

@ -30,6 +30,7 @@ import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.graphics.drawable.LayerDrawable import android.graphics.drawable.LayerDrawable
import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.os.Parcelable import android.os.Parcelable
import android.text.TextUtils 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.Participant.ActorType.USERS
import com.nextcloud.talk.models.json.participants.ParticipantsOverall import com.nextcloud.talk.models.json.participants.ParticipantsOverall
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity 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.ApiUtils
import com.nextcloud.talk.utils.DateConstants import com.nextcloud.talk.utils.DateConstants
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
@ -113,9 +113,6 @@ class ConversationInfoController(args: Bundle) :
@Inject @Inject
lateinit var eventBus: EventBus lateinit var eventBus: EventBus
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private val conversationToken: String? private val conversationToken: String?
private val conversationUser: User? private val conversationUser: User?
private val hasAvatarSpacing: Boolean private val hasAvatarSpacing: Boolean
@ -234,6 +231,8 @@ class ConversationInfoController(args: Bundle) :
} }
binding.addParticipantsAction.visibility = View.GONE binding.addParticipantsAction.visibility = View.GONE
viewThemeUtils.colorCircularProgressBar(binding.progressBar)
} }
private fun setupWebinaryView() { private fun setupWebinaryView() {
@ -437,7 +436,7 @@ class ConversationInfoController(args: Bundle) :
for (i in participants.indices) { for (i in participants.indices) {
participant = participants[i] participant = participants[i]
userItem = ParticipantItem(router.activity, participant, conversationUser) userItem = ParticipantItem(router.activity, participant, conversationUser, viewThemeUtils)
if (participant.sessionId != null) { if (participant.sessionId != null) {
userItem.isOnline = !participant.sessionId.equals("0") userItem.isOnline = !participant.sessionId.equals("0")
} else { } else {
@ -789,12 +788,32 @@ class ConversationInfoController(args: Bundle) :
.build() .build()
binding.avatarImage.controller = draweeController binding.avatarImage.controller = draweeController
} }
Conversation.ConversationType.ROOM_GROUP_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( Conversation.ConversationType.ROOM_GROUP_CALL -> {
R.drawable.ic_circular_group if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
) binding.avatarImage.hierarchy.setPlaceholderImage(
Conversation.ConversationType.ROOM_PUBLIC_CALL -> binding.avatarImage.hierarchy.setPlaceholderImage( DisplayUtils.getRoundedDrawable(
R.drawable.ic_circular_link 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 -> { Conversation.ConversationType.ROOM_SYSTEM -> {
val layers = arrayOfNulls<Drawable>(2) val layers = arrayOfNulls<Drawable>(2)
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background) layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)

View File

@ -31,9 +31,7 @@ import android.content.ClipData;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.content.res.ColorStateList;
import android.graphics.Bitmap; import android.graphics.Bitmap;
import android.graphics.Color;
import android.net.Uri; import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
@ -341,6 +339,7 @@ public class ConversationsListController extends BaseController implements Flexi
credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken()); credentials = ApiUtils.getCredentials(currentUser.getUsername(), currentUser.getToken());
if (getActivity() != null && getActivity() instanceof MainActivity) { if (getActivity() != null && getActivity() instanceof MainActivity) {
loadUserAvatar(((MainActivity) getActivity()).binding.switchAccountButton); loadUserAvatar(((MainActivity) getActivity()).binding.switchAccountButton);
viewThemeUtils.colorMaterialTextButton(((MainActivity) getActivity()).binding.switchAccountButton);
} }
fetchData(); fetchData();
} }
@ -359,7 +358,7 @@ public class ConversationsListController extends BaseController implements Flexi
SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE); SearchManager searchManager = (SearchManager) getActivity().getSystemService(Context.SEARCH_SERVICE);
if (searchItem != null) { if (searchItem != null) {
searchView = (SearchView) MenuItemCompat.getActionView(searchItem); searchView = (SearchView) MenuItemCompat.getActionView(searchItem);
DisplayUtils.themeSearchView(searchView, context); viewThemeUtils.themeSearchView(searchView);
searchView.setMaxWidth(Integer.MAX_VALUE); searchView.setMaxWidth(Integer.MAX_VALUE);
searchView.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER); searchView.setInputType(InputType.TYPE_TEXT_VARIATION_FILTER);
int imeOptions = EditorInfo.IME_ACTION_DONE | EditorInfo.IME_FLAG_NO_FULLSCREEN; 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 -> { activity.binding.searchText.setOnClickListener(v -> {
showSearchView(activity, searchView, searchItem); showSearchView(activity, searchView, searchItem);
if (getResources() != null) { viewThemeUtils.themeStatusBar(activity, searchView);
DisplayUtils.applyColorToStatusBar(
activity,
ResourcesCompat.getColor(getResources(), R.color.appbar, null)
);
}
}); });
} }
searchView.setOnCloseListener(() -> { searchView.setOnCloseListener(() -> {
if (TextUtils.isEmpty(searchView.getQuery().toString())) { if (TextUtils.isEmpty(searchView.getQuery().toString())) {
searchView.onActionViewCollapsed(); searchView.onActionViewCollapsed();
if (activity != null && getResources() != null) { if (activity != null) {
DisplayUtils.applyColorToStatusBar( viewThemeUtils.resetStatusBar(activity, searchView);
activity,
ResourcesCompat.getColor(getResources(), R.color.bg_default, null)
);
} }
} else { } else {
searchView.post(() -> searchView.setQuery(TAG, true)); 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.toolbar.setVisibility(View.GONE);
activity.binding.searchToolbar.setVisibility(View.VISIBLE); activity.binding.searchToolbar.setVisibility(View.VISIBLE);
if (getResources() != null) { if (getResources() != null) {
DisplayUtils.applyColorToStatusBar( viewThemeUtils.resetStatusBar(activity, activity.binding.searchToolbar);
activity,
ResourcesCompat.getColor(getResources(), R.color.bg_default, null)
);
} }
} }
SmoothScrollLinearLayoutManager layoutManager = SmoothScrollLinearLayoutManager layoutManager =
@ -816,9 +804,7 @@ public class ConversationsListController extends BaseController implements Flexi
recyclerView.smoothScrollToPosition(nextUnreadConversationScrollPosition); recyclerView.smoothScrollToPosition(nextUnreadConversationScrollPosition);
} }
}); });
viewThemeUtils.colorMaterialButtonPrimaryFilled(newMentionPopupBubble);
newMentionPopupBubble.setTextColor(Color.WHITE);
newMentionPopupBubble.setIconTint(ColorStateList.valueOf(Color.WHITE));
} }
private void checkToShowUnreadBubble() { private void checkToShowUnreadBubble() {

View File

@ -39,9 +39,7 @@ import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.Toast import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes import androidx.annotation.DrawableRes
import androidx.core.graphics.drawable.DrawableCompat
import androidx.core.view.ViewCompat import androidx.core.view.ViewCompat
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import autodagger.AutoInjector import autodagger.AutoInjector
@ -108,9 +106,6 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
@Inject @Inject
lateinit var permissionUtil: PlatformPermissionUtil lateinit var permissionUtil: PlatformPermissionUtil
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private var currentUser: User? = null private var currentUser: User? = null
private var edit = false private var edit = false
private var adapter: UserInfoAdapter? = null private var adapter: UserInfoAdapter? = null
@ -197,7 +192,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
override fun onAttach(view: View) { override fun onAttach(view: View) {
super.onAttach(view) super.onAttach(view)
adapter = UserInfoAdapter(null, viewThemeUtils.getElementColor(activity!!), this) adapter = UserInfoAdapter(null, viewThemeUtils, this)
binding.userinfoList.adapter = adapter binding.userinfoList.adapter = adapter
binding.userinfoList.setItemViewCacheSize(DEFAULT_CACHE_SIZE) binding.userinfoList.setItemViewCacheSize(DEFAULT_CACHE_SIZE)
currentUser = userManager.currentUser.blockingGet() currentUser = userManager.currentUser.blockingGet()
@ -266,8 +261,10 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
} }
private fun colorIcons() { private fun colorIcons() {
viewThemeUtils.colorImageView(binding.avatarChoose) viewThemeUtils.themeFAB(binding.avatarChoose)
viewThemeUtils.colorImageView(binding.avatarCamera) viewThemeUtils.themeFAB(binding.avatarCamera)
viewThemeUtils.themeFAB(binding.avatarUpload)
viewThemeUtils.themeFAB(binding.avatarDelete)
} }
private fun isAllEmpty(items: Array<String?>): Boolean { private fun isAllEmpty(items: Array<String?>): Boolean {
@ -710,18 +707,18 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
class UserInfoAdapter( class UserInfoAdapter(
displayList: List<UserInfoDetailsItem>?, displayList: List<UserInfoDetailsItem>?,
@ColorInt tintColor: Int, private val viewThemeUtils: ViewThemeUtils,
controller: ProfileController private val controller: ProfileController
) : RecyclerView.Adapter<UserInfoAdapter.ViewHolder>() { ) : RecyclerView.Adapter<UserInfoAdapter.ViewHolder>() {
var displayList: List<UserInfoDetailsItem>? var displayList: List<UserInfoDetailsItem>?
var filteredDisplayList: MutableList<UserInfoDetailsItem> = LinkedList() var filteredDisplayList: MutableList<UserInfoDetailsItem> = LinkedList()
@ColorInt
protected var mTintColor: Int
private val controller: ProfileController
class ViewHolder(val binding: UserInfoDetailsTableItemBinding) : RecyclerView.ViewHolder(binding.root) class ViewHolder(val binding: UserInfoDetailsTableItemBinding) : RecyclerView.ViewHolder(binding.root)
init {
this.displayList = displayList ?: LinkedList()
}
fun setData(displayList: List<UserInfoDetailsItem>) { fun setData(displayList: List<UserInfoDetailsItem>) {
this.displayList = displayList this.displayList = displayList
updateFilteredList() updateFilteredList()
@ -758,7 +755,7 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
initUserInfoEditText(holder, item) initUserInfoEditText(holder, item)
holder.binding.icon.contentDescription = item.hint 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) { if (!TextUtils.isEmpty(item.text) || controller.edit) {
holder.binding.userInfoDetailContainer.visibility = View.VISIBLE holder.binding.userInfoDetailContainer.visibility = View.VISIBLE
controller.viewThemeUtils.colorTextInputLayout(holder.binding.userInfoInputLayout) controller.viewThemeUtils.colorTextInputLayout(holder.binding.userInfoInputLayout)
@ -853,12 +850,6 @@ class ProfileController : NewBaseController(R.layout.controller_profile) {
displayList!![position].scope = scope displayList!![position].scope = scope
notifyDataSetChanged() notifyDataSetChanged()
} }
init {
this.displayList = displayList ?: LinkedList()
mTintColor = tintColor
this.controller = controller
}
} }
enum class Field(val fieldName: String, val scopeName: String) { enum class Field(val fieldName: String, val scopeName: String) {

View File

@ -60,6 +60,7 @@ import com.bluelinelabs.conductor.Controller
import com.bluelinelabs.conductor.RouterTransaction import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R 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.generic.GenericOverall
import com.nextcloud.talk.models.json.userprofile.UserProfileOverall import com.nextcloud.talk.models.json.userprofile.UserProfileOverall
import com.nextcloud.talk.users.UserManager import com.nextcloud.talk.users.UserManager
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.LoggingUtils.sendMailWithAttachment 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.preferences.MagicUserInputModule
import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder import com.nextcloud.talk.utils.singletons.ApplicationWideMessageHolder
import com.yarolegovich.lovelydialog.LovelySaveStateHandler import com.yarolegovich.lovelydialog.LovelySaveStateHandler
import com.yarolegovich.lovelydialog.LovelyStandardDialog
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
@ -119,10 +118,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
@Inject @Inject
lateinit var currentUserProvider: CurrentUserProviderNew lateinit var currentUserProvider: CurrentUserProviderNew
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private var saveStateHandler: LovelySaveStateHandler? = null
private var currentUser: User? = null private var currentUser: User? = null
private var credentials: String? = null private var credentials: String? = null
private var proxyTypeChangeListener: OnPreferenceValueChangedListener<String>? = null private var proxyTypeChangeListener: OnPreferenceValueChangedListener<String>? = null
@ -154,10 +149,6 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
getCurrentUser() getCurrentUser()
if (saveStateHandler == null) {
saveStateHandler = LovelySaveStateHandler()
}
registerChangeListeners() registerChangeListeners()
setupSettingsScreen() 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) { override fun onRestoreViewState(view: View, savedViewState: Bundle) {
super.onRestoreViewState(view, savedViewState) super.onRestoreViewState(view, savedViewState)
if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) { if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
@ -401,23 +387,27 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
private fun showRemoveAccountWarning(savedInstanceState: Bundle?) { private fun showRemoveAccountWarning(savedInstanceState: Bundle?) {
if (activity != null) { if (activity != null) {
LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL) val materialAlertDialogBuilder = MaterialAlertDialogBuilder(binding.messageText.context)
.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))
.setTitle(R.string.nc_settings_remove_account) .setTitle(R.string.nc_settings_remove_account)
.setMessage(R.string.nc_settings_remove_confirmation) .setMessage(R.string.nc_settings_remove_confirmation)
.setPositiveButton(R.string.nc_settings_remove, { removeCurrentAccount() }) .setPositiveButton(R.string.nc_settings_remove) { _, _ ->
.setNegativeButton(R.string.nc_cancel, null) removeCurrentAccount()
.setInstanceStateHandler(ID_REMOVE_ACCOUNT_WARNING_DIALOG, saveStateHandler) }
.setSavedInstanceState(savedInstanceState) .setNegativeButton(R.string.nc_cancel) { _, _ ->
.show() // 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) { if (ApplicationWideMessageHolder.getInstance().messageType != null) {
when (ApplicationWideMessageHolder.getInstance().messageType) { when (ApplicationWideMessageHolder.getInstance().messageType) {
ApplicationWideMessageHolder.MessageType.ACCOUNT_UPDATED_NOT_ADDED -> { 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.messageText.text = resources!!.getString(R.string.nc_settings_account_updated)
binding.messageView.visibility = View.VISIBLE 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.setTextColor(resources!!.getColor(R.color.nc_darkRed))
binding.messageText.text = resources!!.getString(R.string.nc_settings_wrong_account) binding.messageText.text = resources!!.getString(R.string.nc_settings_wrong_account)
binding.messageView.visibility = View.VISIBLE 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.messageText.text = resources!!.getString(R.string.nc_Server_account_imported)
binding.messageView.visibility = View.VISIBLE binding.messageView.visibility = View.VISIBLE
} }
ApplicationWideMessageHolder.MessageType.ACCOUNT_WAS_IMPORTED -> { 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.messageText.text = resources!!.getString(R.string.nc_Server_account_imported)
binding.messageView.visibility = View.VISIBLE binding.messageView.visibility = View.VISIBLE
} }
@ -961,13 +957,16 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
}) })
phoneNumberInputLayout.addView(phoneNumberField) phoneNumberInputLayout.addView(phoneNumberField)
phoneNumberLayoutWrapper.addView(phoneNumberInputLayout) 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) .setTitle(R.string.nc_settings_phone_book_integration_phone_number_dialog_title)
.setMessage(R.string.nc_settings_phone_book_integration_phone_number_dialog_description) .setMessage(R.string.nc_settings_phone_book_integration_phone_number_dialog_description)
.setView(phoneNumberLayoutWrapper) .setView(phoneNumberLayoutWrapper)
.setPositiveButton(context!!.resources.getString(R.string.nc_common_set), null) .setPositiveButton(context!!.resources.getString(R.string.nc_common_set), null)
.setNegativeButton(context!!.resources.getString(R.string.nc_common_skip), 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 { dialog.setOnShowListener(object : OnShowListener {
override fun onShow(dialogInterface: DialogInterface) { override fun onShow(dialogInterface: DialogInterface) {
val button = dialog.getButton(AlertDialog.BUTTON_POSITIVE) val button = dialog.getButton(AlertDialog.BUTTON_POSITIVE)
@ -978,7 +977,13 @@ class SettingsController : NewBaseController(R.layout.controller_settings) {
}) })
} }
}) })
dialog.show() dialog.show()
viewThemeUtils.colorTextButtons(
dialog.getButton(AlertDialog.BUTTON_POSITIVE),
dialog.getButton(AlertDialog.BUTTON_NEGATIVE)
)
} }
private fun setPhoneNumber(textInputLayout: TextInputLayout, dialog: AlertDialog) { private fun setPhoneNumber(textInputLayout: TextInputLayout, dialog: AlertDialog) {

View File

@ -138,7 +138,7 @@ class SwitchAccountController(args: Bundle? = null) :
participant.actorType = Participant.ActorType.USERS participant.actorType = Participant.ActorType.USERS
participant.actorId = userId participant.actorId = userId
participant.displayName = user.displayName participant.displayName = user.displayName
userItems.add(AdvancedUserItem(participant, user, null)) userItems.add(AdvancedUserItem(participant, user, null, viewThemeUtils))
} }
} }
adapter!!.addListener(onSwitchItemClickListener) adapter!!.addListener(onSwitchItemClickListener)
@ -156,7 +156,7 @@ class SwitchAccountController(args: Bundle? = null) :
participant.displayName = importAccount.getUsername() participant.displayName = importAccount.getUsername()
user = User() user = User()
user.baseUrl = importAccount.getBaseUrl() user.baseUrl = importAccount.getBaseUrl()
userItems.add(AdvancedUserItem(participant, user, account)) userItems.add(AdvancedUserItem(participant, user, account, viewThemeUtils))
} }
adapter!!.addListener(onImportItemClickListener) adapter!!.addListener(onImportItemClickListener)
adapter!!.updateDataSet(userItems, false) adapter!!.updateDataSet(userItems, false)

View File

@ -49,6 +49,7 @@ import com.nextcloud.talk.controllers.ServerSelectionController;
import com.nextcloud.talk.controllers.SwitchAccountController; import com.nextcloud.talk.controllers.SwitchAccountController;
import com.nextcloud.talk.controllers.WebViewLoginController; import com.nextcloud.talk.controllers.WebViewLoginController;
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider; 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.DisplayUtils;
import com.nextcloud.talk.utils.preferences.AppPreferences; import com.nextcloud.talk.utils.preferences.AppPreferences;
@ -70,9 +71,13 @@ public abstract class BaseController extends ButterKnifeController {
private static final String TAG = "BaseController"; private static final String TAG = "BaseController";
@Inject @Inject
AppPreferences appPreferences; AppPreferences appPreferences;
@Inject @Inject
Context context; Context context;
@Inject
ViewThemeUtils viewThemeUtils;
protected BaseController() { protected BaseController() {
cleanTempCertPreference(); cleanTempCertPreference();
} }
@ -109,12 +114,19 @@ public abstract class BaseController extends ButterKnifeController {
@Override @Override
protected void onViewBound(@NonNull View view) { protected void onViewBound(@NonNull View view) {
super.onViewBound(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()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.getIsKeyboardIncognito()) {
disableKeyboardPersonalisedLearning((ViewGroup) view); disableKeyboardPersonalisedLearning((ViewGroup) view);
if (getActivity() != null && getActivity() instanceof MainActivity) { if (activity != null) {
MainActivity activity = (MainActivity) getActivity();
disableKeyboardPersonalisedLearning(activity.binding.appBar); disableKeyboardPersonalisedLearning(activity.binding.appBar);
} }
} }
@ -174,15 +186,9 @@ public abstract class BaseController extends ButterKnifeController {
if ((getResources() != null)) { if ((getResources() != null)) {
if (showSearchBar) { if (showSearchBar) {
DisplayUtils.applyColorToStatusBar( viewThemeUtils.resetStatusBar(activity, activity.binding.searchToolbar);
activity, ResourcesCompat.getColor(getResources(),
R.color.bg_default, null)
);
} else { } else {
DisplayUtils.applyColorToStatusBar( viewThemeUtils.themeStatusBar(activity, activity.binding.searchToolbar);
activity, ResourcesCompat.getColor(getResources(),
R.color.appbar, null)
);
} }
} }
} }

View File

@ -56,6 +56,7 @@ import com.nextcloud.talk.controllers.WebViewLoginController
import com.nextcloud.talk.controllers.base.providers.ActionBarProvider import com.nextcloud.talk.controllers.base.providers.ActionBarProvider
import com.nextcloud.talk.controllers.util.ControllerViewBindingDelegate import com.nextcloud.talk.controllers.util.ControllerViewBindingDelegate
import com.nextcloud.talk.databinding.ActivityMainBinding import com.nextcloud.talk.databinding.ActivityMainBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.preferences.AppPreferences import com.nextcloud.talk.utils.preferences.AppPreferences
import javax.inject.Inject import javax.inject.Inject
@ -73,6 +74,9 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? =
@Inject @Inject
lateinit var context: Context lateinit var context: Context
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
protected open val title: String? protected open val title: String?
get() = null get() = null
@ -115,11 +119,19 @@ abstract class NewBaseController(@LayoutRes var layoutRes: Int, args: Bundle? =
} }
protected open fun onViewBound(view: View) { protected open fun onViewBound(view: View) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences!!.isKeyboardIncognito) { var activity: MainActivity? = null
disableKeyboardPersonalisedLearning(view as ViewGroup)
if (activity != null && activity is MainActivity) { if (getActivity() != null && getActivity() is MainActivity) {
val activity = activity as MainActivity? activity = getActivity() as MainActivity?
disableKeyboardPersonalisedLearning(activity!!.binding.appBar) 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 val layoutParams = binding.searchToolbar.layoutParams as AppBarLayout.LayoutParams
binding.searchToolbar.visibility = View.GONE binding.searchToolbar.visibility = View.GONE
binding.toolbar.visibility = View.VISIBLE binding.toolbar.visibility = View.VISIBLE
viewThemeUtils.colorToolbarOverflowIcon(binding.toolbar)
layoutParams.scrollFlags = 0 layoutParams.scrollFlags = 0
binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator( binding.appBar.stateListAnimator = AnimatorInflater.loadStateListAnimator(
binding.appBar.context, 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?) { private fun colorizeStatusBar(showSearchBar: Boolean, activity: Activity?, resources: Resources?) {
if (activity != null && resources != null) { if (activity != null && resources != null) {
if (showSearchBar) { if (showSearchBar) {
DisplayUtils.applyColorToStatusBar( view?.let { viewThemeUtils.resetStatusBar(activity, it) }
activity,
ResourcesCompat.getColor(
resources, R.color.bg_default, null
)
)
} else { } else {
DisplayUtils.applyColorToStatusBar( view?.let { viewThemeUtils.themeStatusBar(activity, it) }
activity,
ResourcesCompat.getColor(
resources, R.color.appbar, null
)
)
} }
} }
} }

View File

@ -46,8 +46,6 @@ import com.nextcloud.talk.controllers.base.NewBaseController
import com.nextcloud.talk.controllers.util.viewBinding import com.nextcloud.talk.controllers.util.viewBinding
import com.nextcloud.talk.databinding.ControllerEntryMenuBinding import com.nextcloud.talk.databinding.ControllerEntryMenuBinding
import com.nextcloud.talk.models.json.conversations.Conversation 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.users.UserManager
import com.nextcloud.talk.utils.ShareUtils import com.nextcloud.talk.utils.ShareUtils
import com.nextcloud.talk.utils.UriUtils import com.nextcloud.talk.utils.UriUtils
@ -74,12 +72,6 @@ class EntryMenuController(args: Bundle) :
@Inject @Inject
lateinit var userManager: UserManager lateinit var userManager: UserManager
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
private val operation: ConversationOperationEnum private val operation: ConversationOperationEnum
private var conversation: Conversation? = null private var conversation: Conversation? = null
private var shareIntent: Intent? = null private var shareIntent: Intent? = null

View File

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

View File

@ -346,6 +346,7 @@ public class NotificationWorker extends Worker {
if (Build.VERSION.SDK_INT >= 23) { if (Build.VERSION.SDK_INT >= 23) {
// This method should exist since API 21, but some phones don't have it // 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 // So as a safeguard, we don't use it until 23
notificationBuilder.setColor(context.getResources().getColor(R.color.colorPrimary)); notificationBuilder.setColor(context.getResources().getColor(R.color.colorPrimary));
} }

View File

@ -41,7 +41,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.ConversationsListController import com.nextcloud.talk.controllers.ConversationsListController
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.ActivityMessageSearchBinding import com.nextcloud.talk.databinding.ActivityMessageSearchBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.bundle.BundleKeys import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew import com.nextcloud.talk.utils.database.user.CurrentUserProviderNew
@ -65,9 +64,6 @@ class MessageSearchActivity : BaseActivity() {
@Inject @Inject
lateinit var userProvider: CurrentUserProviderNew lateinit var userProvider: CurrentUserProviderNew
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var binding: ActivityMessageSearchBinding private lateinit var binding: ActivityMessageSearchBinding
private lateinit var searchView: SearchView private lateinit var searchView: SearchView

View File

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

View File

@ -41,6 +41,9 @@ class PollResultHeaderViewHolder(
binding.pollOptionText.text = item.name binding.pollOptionText.text = item.name
binding.pollOptionPercentText.text = "${item.percent}%" binding.pollOptionPercentText.text = "${item.percent}%"
viewThemeUtils.colorDialogSupportingText(binding.pollOptionText)
viewThemeUtils.colorDialogSupportingText(binding.pollOptionPercentText)
if (item.selfVoted) { if (item.selfVoted) {
binding.pollOptionText.setTypeface(null, Typeface.BOLD) binding.pollOptionText.setTypeface(null, Typeface.BOLD)
binding.pollOptionPercentText.setTypeface(null, Typeface.BOLD) binding.pollOptionPercentText.setTypeface(null, Typeface.BOLD)

View File

@ -29,12 +29,14 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.PollResultVoterItemBinding import com.nextcloud.talk.databinding.PollResultVoterItemBinding
import com.nextcloud.talk.polls.model.PollDetails 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.ApiUtils
import com.nextcloud.talk.utils.DisplayUtils import com.nextcloud.talk.utils.DisplayUtils
class PollResultVoterViewHolder( class PollResultVoterViewHolder(
private val user: User, private val user: User,
override val binding: PollResultVoterItemBinding override val binding: PollResultVoterItemBinding,
private val viewThemeUtils: ViewThemeUtils
) : PollResultViewHolder(binding) { ) : PollResultViewHolder(binding) {
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
@ -45,6 +47,7 @@ class PollResultVoterViewHolder(
binding.pollVoterName.text = item.details.actorDisplayName binding.pollVoterName.text = item.details.actorDisplayName
binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details) binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details)
viewThemeUtils.colorDialogSupportingText(binding.pollVoterName)
} }
private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? { private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? {

View File

@ -52,7 +52,7 @@ class PollResultsAdapter(
LayoutInflater.from(parent.context), parent, LayoutInflater.from(parent.context), parent,
false false
) )
viewHolder = PollResultVoterViewHolder(user, itemBinding) viewHolder = PollResultVoterViewHolder(user, itemBinding, viewThemeUtils)
} }
PollResultVotersOverviewItem.VIEW_TYPE -> { PollResultVotersOverviewItem.VIEW_TYPE -> {
val itemBinding = PollResultVotersOverviewItemBinding.inflate( val itemBinding = PollResultVotersOverviewItemBinding.inflate(

View File

@ -31,11 +31,11 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.EditText import android.widget.EditText
import android.widget.Toast import android.widget.Toast
import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogPollCreateBinding import com.nextcloud.talk.databinding.DialogPollCreateBinding
@ -73,9 +73,11 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
binding = DialogPollCreateBinding.inflate(LayoutInflater.from(context)) binding = DialogPollCreateBinding.inflate(LayoutInflater.from(context))
return AlertDialog.Builder(requireContext()) val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context)
.setView(binding.root) .setView(binding.root)
.create() viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
return dialogBuilder.create()
} }
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@ -99,16 +101,15 @@ class PollCreateDialogFragment : DialogFragment(), PollCreateOptionsItemListener
} }
private fun themeDialog() { private fun themeDialog() {
viewThemeUtils.colorTextViewText(binding.pollQuestion) viewThemeUtils.colorPrimaryTextViewElement(binding.pollQuestion)
viewThemeUtils.colorTextViewText(binding.pollOptions) viewThemeUtils.colorPrimaryTextViewElement(binding.pollOptions)
viewThemeUtils.colorTextViewText(binding.pollSettings) viewThemeUtils.colorPrimaryTextViewElement(binding.pollSettings)
viewThemeUtils.colorEditText(binding.pollCreateQuestionTextEdit) viewThemeUtils.colorTextInputLayout(binding.pollCreateQuestionTextInputLayout)
viewThemeUtils.colorMaterialButtonText(binding.pollAddOptionsItem) viewThemeUtils.colorMaterialButtonText(binding.pollAddOptionsItem)
// TODO button also needs a disabled state handling for colors
viewThemeUtils.colorMaterialButtonText(binding.pollDismiss) viewThemeUtils.colorMaterialButtonText(binding.pollDismiss)
viewThemeUtils.colorMaterialButtonBackground(binding.pollCreateButton) viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollCreateButton)
viewThemeUtils.themeCheckbox(binding.pollPrivatePollCheckbox) viewThemeUtils.themeCheckbox(binding.pollPrivatePollCheckbox)
viewThemeUtils.themeCheckbox(binding.pollMultipleAnswersCheckbox) viewThemeUtils.themeCheckbox(binding.pollMultipleAnswersCheckbox)

View File

@ -29,12 +29,17 @@ import androidx.fragment.app.Fragment
import autodagger.AutoInjector import autodagger.AutoInjector
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogPollLoadingBinding import com.nextcloud.talk.databinding.DialogPollLoadingBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class PollLoadingFragment : Fragment() { class PollLoadingFragment : Fragment() {
private lateinit var binding: DialogPollLoadingBinding private lateinit var binding: DialogPollLoadingBinding
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
var fragmentHeight = 0 var fragmentHeight = 0
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
@ -50,6 +55,7 @@ class PollLoadingFragment : Fragment() {
): View { ): View {
binding = DialogPollLoadingBinding.inflate(inflater, container, false) binding = DialogPollLoadingBinding.inflate(inflater, container, false)
binding.root.layoutParams.height = fragmentHeight binding.root.layoutParams.height = fragmentHeight
viewThemeUtils.colorCircularProgressBar(binding.pollLoadingProgressbar)
return binding.root return binding.root
} }

View File

@ -26,16 +26,17 @@ import android.os.Bundle
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf import androidx.core.os.bundleOf
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.DialogPollMainBinding import com.nextcloud.talk.databinding.DialogPollMainBinding
import com.nextcloud.talk.polls.viewmodels.PollMainViewModel import com.nextcloud.talk.polls.viewmodels.PollMainViewModel
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import javax.inject.Inject import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
@ -44,6 +45,9 @@ class PollMainDialogFragment : DialogFragment() {
@Inject @Inject
lateinit var viewModelFactory: ViewModelProvider.Factory lateinit var viewModelFactory: ViewModelProvider.Factory
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var binding: DialogPollMainBinding private lateinit var binding: DialogPollMainBinding
private lateinit var viewModel: PollMainViewModel private lateinit var viewModel: PollMainViewModel
@ -66,11 +70,15 @@ class PollMainDialogFragment : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
binding = DialogPollMainBinding.inflate(LayoutInflater.from(context)) binding = DialogPollMainBinding.inflate(LayoutInflater.from(context))
val dialog = AlertDialog.Builder(requireContext()) val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root)
.setView(binding.root)
.create() viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
val dialog = dialogBuilder.create()
binding.messagePollTitle.text = viewModel.pollTitle binding.messagePollTitle.text = viewModel.pollTitle
viewThemeUtils.colorDialogHeadline(binding.messagePollTitle)
viewThemeUtils.colorDialogIcon(binding.messagePollIcon)
return dialog return dialog
} }
@ -135,6 +143,7 @@ class PollMainDialogFragment : DialogFragment() {
private fun initVotersAmount(showVotersAmount: Boolean, numVoters: Int, showResultSubtitle: Boolean) { private fun initVotersAmount(showVotersAmount: Boolean, numVoters: Int, showResultSubtitle: Boolean) {
if (showVotersAmount) { if (showVotersAmount) {
viewThemeUtils.colorDialogSupportingText(binding.pollVotesAmount)
binding.pollVotesAmount.visibility = View.VISIBLE binding.pollVotesAmount.visibility = View.VISIBLE
binding.pollVotesAmount.text = resources.getQuantityString( binding.pollVotesAmount.text = resources.getQuantityString(
R.plurals.polls_amount_voters, R.plurals.polls_amount_voters,
@ -146,6 +155,7 @@ class PollMainDialogFragment : DialogFragment() {
} }
if (showResultSubtitle) { if (showResultSubtitle) {
viewThemeUtils.colorDialogSupportingText(binding.pollResultsSubtitle)
binding.pollResultsSubtitle.visibility = View.VISIBLE binding.pollResultsSubtitle.visibility = View.VISIBLE
binding.pollResultsSubtitleSeperator.visibility = View.VISIBLE binding.pollResultsSubtitleSeperator.visibility = View.VISIBLE
} else { } else {

View File

@ -31,6 +31,7 @@ import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogPollResultsBinding import com.nextcloud.talk.databinding.DialogPollResultsBinding
@ -98,8 +99,8 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener {
} }
private fun themeDialog() { private fun themeDialog() {
viewThemeUtils.colorMaterialButtonBackground(binding.editVoteButton) viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.editVoteButton)
viewThemeUtils.colorMaterialButtonText(binding.pollResultsEndPollButton) viewThemeUtils.colorMaterialButtonPrimaryBorderless(binding.pollResultsEndPollButton)
} }
private fun initAdapter() { private fun initAdapter() {
@ -123,14 +124,25 @@ class PollResultsFragment : Fragment(), PollResultItemClickListener {
if (showEndPollButton) { if (showEndPollButton) {
binding.pollResultsEndPollButton.visibility = View.VISIBLE binding.pollResultsEndPollButton.visibility = View.VISIBLE
binding.pollResultsEndPollButton.setOnClickListener { binding.pollResultsEndPollButton.setOnClickListener {
AlertDialog.Builder(requireContext()) val dialogBuilder = MaterialAlertDialogBuilder(binding.pollResultsEndPollButton.context)
.setTitle(R.string.polls_end_poll) .setTitle(R.string.polls_end_poll)
.setMessage(R.string.polls_end_poll_confirm) .setMessage(R.string.polls_end_poll_confirm)
.setPositiveButton(R.string.polls_end_poll) { _, _ -> .setPositiveButton(R.string.polls_end_poll) { _, _ ->
parentViewModel.endPoll() parentViewModel.endPoll()
} }
.setNegativeButton(R.string.nc_cancel, null) .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 { } else {
binding.pollResultsEndPollButton.visibility = View.GONE binding.pollResultsEndPollButton.visibility = View.GONE

View File

@ -37,6 +37,7 @@ import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.ViewModelProvider import androidx.lifecycle.ViewModelProvider
import autodagger.AutoInjector import autodagger.AutoInjector
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogPollVoteBinding import com.nextcloud.talk.databinding.DialogPollVoteBinding
@ -126,9 +127,9 @@ class PollVoteFragment : Fragment() {
} }
private fun themeDialog() { private fun themeDialog() {
viewThemeUtils.colorMaterialButtonBackground(binding.pollVoteSubmitButton) viewThemeUtils.colorMaterialButtonPrimaryFilled(binding.pollVoteSubmitButton)
viewThemeUtils.colorMaterialButtonText(binding.pollVoteEndPollButton) viewThemeUtils.colorMaterialButtonText(binding.pollVoteEndPollButton)
viewThemeUtils.colorMaterialButtonText(binding.pollVoteEditDismiss) viewThemeUtils.colorMaterialButtonPrimaryOutlined(binding.pollVoteEditDismiss)
} }
private fun updateDismissEditButton(showDismissEditButton: Boolean) { private fun updateDismissEditButton(showDismissEditButton: Boolean) {
@ -206,14 +207,25 @@ class PollVoteFragment : Fragment() {
if (showEndPollButton) { if (showEndPollButton) {
binding.pollVoteEndPollButton.visibility = View.VISIBLE binding.pollVoteEndPollButton.visibility = View.VISIBLE
binding.pollVoteEndPollButton.setOnClickListener { binding.pollVoteEndPollButton.setOnClickListener {
AlertDialog.Builder(requireContext()) val dialogBuilder = MaterialAlertDialogBuilder(binding.pollVoteEndPollButton.context)
.setTitle(R.string.polls_end_poll) .setTitle(R.string.polls_end_poll)
.setMessage(R.string.polls_end_poll_confirm) .setMessage(R.string.polls_end_poll_confirm)
.setPositiveButton(R.string.polls_end_poll) { _, _ -> .setPositiveButton(R.string.polls_end_poll) { _, _ ->
parentViewModel.endPoll() parentViewModel.endPoll()
} }
.setNegativeButton(R.string.nc_cancel, null) .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 { } else {
binding.pollVoteEndPollButton.visibility = View.GONE binding.pollVoteEndPollButton.visibility = View.GONE

View File

@ -36,6 +36,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.models.json.mention.Mention; import com.nextcloud.talk.models.json.mention.Mention;
import com.nextcloud.talk.models.json.mention.MentionOverall; 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.users.UserManager;
import com.nextcloud.talk.utils.ApiUtils; import com.nextcloud.talk.utils.ApiUtils;
import com.otaliastudios.autocomplete.RecyclerViewPresenter; import com.otaliastudios.autocomplete.RecyclerViewPresenter;
@ -69,6 +70,9 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter<Mention>
@Inject @Inject
UserManager userManager; UserManager userManager;
@Inject
ViewThemeUtils viewThemeUtils;
private User currentUser; private User currentUser;
private FlexibleAdapter<AbstractFlexibleItem> adapter; private FlexibleAdapter<AbstractFlexibleItem> adapter;
private Context context; private Context context;
@ -150,7 +154,8 @@ public class MentionAutocompletePresenter extends RecyclerViewPresenter<Mention>
new MentionAutocompleteItem( new MentionAutocompleteItem(
mention, mention,
currentUser, currentUser,
context)); context,
viewThemeUtils));
} }
if (adapter.getItemCount() != 0) { if (adapter.getItemCount() != 0) {

View File

@ -24,6 +24,7 @@ package com.nextcloud.talk.remotefilebrowser.activities
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.res.ColorStateList
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.Menu import android.view.Menu
@ -74,14 +75,18 @@ class RemoteFileBrowserActivity : AppCompatActivity(), SelectionInterface, Swipe
binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater) binding = ActivityRemoteFileBrowserBinding.inflate(layoutInflater)
setSupportActionBar(binding.remoteFileBrowserItemsToolbar) 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) setContentView(binding.root)
DisplayUtils.applyColorToStatusBar(
this,
ResourcesCompat.getColor(
resources, R.color.appbar, null
)
)
DisplayUtils.applyColorToNavigationBar( DisplayUtils.applyColorToNavigationBar(
this.window, this.window,
ResourcesCompat.getColor(resources, R.color.bg_default, null) ResourcesCompat.getColor(resources, R.color.bg_default, null)

View File

@ -73,14 +73,10 @@ class SharedItemsActivity : AppCompatActivity() {
setSupportActionBar(binding.sharedItemsToolbar) setSupportActionBar(binding.sharedItemsToolbar)
setContentView(binding.root) setContentView(binding.root)
DisplayUtils.applyColorToStatusBar( viewThemeUtils.themeStatusBar(this, binding.sharedItemsToolbar)
this, viewThemeUtils.themeToolbar(binding.sharedItemsToolbar)
ResourcesCompat.getColor( viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs)
resources,
R.color.appbar,
null
)
)
DisplayUtils.applyColorToNavigationBar( DisplayUtils.applyColorToNavigationBar(
this.window, this.window,
ResourcesCompat.getColor(resources, R.color.bg_default, null) ResourcesCompat.getColor(resources, R.color.bg_default, null)
@ -150,7 +146,7 @@ class SharedItemsActivity : AppCompatActivity() {
else -> {} else -> {}
} }
viewThemeUtils.colorTabLayout(binding.sharedItemsTabs) viewThemeUtils.themeTabLayoutOnSurface(binding.sharedItemsTabs)
} }
private fun clearEmptyLoading() { private fun clearEmptyLoading() {

View File

@ -26,23 +26,34 @@ import android.app.Activity
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import autodagger.AutoInjector
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.ChatController import com.nextcloud.talk.controllers.ChatController
import com.nextcloud.talk.databinding.DialogAttachmentBinding import com.nextcloud.talk.databinding.DialogAttachmentBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew 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) { class AttachmentDialog(val activity: Activity, var chatController: ChatController) : BottomSheetDialog(activity) {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var dialogAttachmentBinding: DialogAttachmentBinding private lateinit var dialogAttachmentBinding: DialogAttachmentBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
dialogAttachmentBinding = DialogAttachmentBinding.inflate(layoutInflater) dialogAttachmentBinding = DialogAttachmentBinding.inflate(layoutInflater)
setContentView(dialogAttachmentBinding.root) setContentView(dialogAttachmentBinding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(dialogAttachmentBinding.root)
initItemsStrings() initItemsStrings()
initItemsVisibility() initItemsVisibility()
initItemsClickListeners() initItemsClickListeners()

View File

@ -31,7 +31,6 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.activities.CallActivity import com.nextcloud.talk.activities.CallActivity
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.databinding.DialogAudioOutputBinding import com.nextcloud.talk.databinding.DialogAudioOutputBinding
import com.nextcloud.talk.ui.theme.ServerTheme
import com.nextcloud.talk.ui.theme.ViewThemeUtils import com.nextcloud.talk.ui.theme.ViewThemeUtils
import com.nextcloud.talk.webrtc.WebRtcAudioManager import com.nextcloud.talk.webrtc.WebRtcAudioManager
import javax.inject.Inject import javax.inject.Inject
@ -42,21 +41,17 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call
@Inject @Inject
lateinit var viewThemeUtils: ViewThemeUtils lateinit var viewThemeUtils: ViewThemeUtils
@Inject
lateinit var serverTheme: ServerTheme
private lateinit var dialogAudioOutputBinding: DialogAudioOutputBinding private lateinit var dialogAudioOutputBinding: DialogAudioOutputBinding
init {
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
dialogAudioOutputBinding = DialogAudioOutputBinding.inflate(layoutInflater) dialogAudioOutputBinding = DialogAudioOutputBinding.inflate(layoutInflater)
setContentView(dialogAudioOutputBinding.root) setContentView(dialogAudioOutputBinding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialogDark(dialogAudioOutputBinding.root)
updateOutputDeviceList() updateOutputDeviceList()
initClickListeners() initClickListeners()
} }
@ -98,22 +93,22 @@ class AudioOutputDialog(val callActivity: CallActivity) : BottomSheetDialog(call
when (callActivity.audioManager?.currentAudioDevice) { when (callActivity.audioManager?.currentAudioDevice) {
WebRtcAudioManager.AudioDevice.BLUETOOTH -> { WebRtcAudioManager.AudioDevice.BLUETOOTH -> {
viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputBluetoothIcon) viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputBluetoothIcon)
dialogAudioOutputBinding.audioOutputBluetoothText.setTextColor(serverTheme.primaryColor) viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputBluetoothText)
} }
WebRtcAudioManager.AudioDevice.SPEAKER_PHONE -> { WebRtcAudioManager.AudioDevice.SPEAKER_PHONE -> {
viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputSpeakerIcon) viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputSpeakerIcon)
dialogAudioOutputBinding.audioOutputSpeakerText.setTextColor(serverTheme.primaryColor) viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputSpeakerText)
} }
WebRtcAudioManager.AudioDevice.EARPIECE -> { WebRtcAudioManager.AudioDevice.EARPIECE -> {
viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputEarspeakerIcon) viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputEarspeakerIcon)
dialogAudioOutputBinding.audioOutputEarspeakerText.setTextColor(serverTheme.primaryColor) viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputEarspeakerText)
} }
WebRtcAudioManager.AudioDevice.WIRED_HEADSET -> { WebRtcAudioManager.AudioDevice.WIRED_HEADSET -> {
viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputWiredHeadsetIcon) viewThemeUtils.colorImageView(dialogAudioOutputBinding.audioOutputWiredHeadsetIcon)
dialogAudioOutputBinding.audioOutputWiredHeadsetText.setTextColor(serverTheme.primaryColor) viewThemeUtils.colorPrimaryTextViewElementDarkMode(dialogAudioOutputBinding.audioOutputWiredHeadsetText)
} }
else -> Log.d(TAG, "AudioOutputDialog doesn't know this AudioDevice") else -> Log.d(TAG, "AudioOutputDialog doesn't know this AudioDevice")

View File

@ -39,7 +39,6 @@ import android.view.ViewGroup;
import com.facebook.drawee.backends.pipeline.Fresco; import com.facebook.drawee.backends.pipeline.Fresco;
import com.facebook.drawee.interfaces.DraweeController; import com.facebook.drawee.interfaces.DraweeController;
import com.google.android.material.dialog.MaterialAlertDialogBuilder; import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.nextcloud.talk.R;
import com.nextcloud.talk.activities.MainActivity; import com.nextcloud.talk.activities.MainActivity;
import com.nextcloud.talk.adapters.items.AdvancedUserItem; import com.nextcloud.talk.adapters.items.AdvancedUserItem;
import com.nextcloud.talk.api.NcApi; import com.nextcloud.talk.api.NcApi;
@ -113,12 +112,18 @@ public class ChooseAccountDialogFragment extends DialogFragment {
public void onViewCreated(@NonNull View view, Bundle savedInstanceState) { public void onViewCreated(@NonNull View view, Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState); super.onViewCreated(view, savedInstanceState);
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this); 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 // Defining user picture
binding.currentAccount.userIcon.setTag(""); binding.currentAccount.userIcon.setTag("");
// Defining user texts, accounts, etc.
User user = userManager.getCurrentUser().blockingGet();
if (user != null) { if (user != null) {
binding.currentAccount.userName.setText(user.getDisplayName()); binding.currentAccount.userName.setText(user.getDisplayName());
binding.currentAccount.ticker.setVisibility(View.GONE); binding.currentAccount.ticker.setVisibility(View.GONE);
@ -148,7 +153,39 @@ public class ChooseAccountDialogFragment extends DialogFragment {
loadCurrentStatus(user); 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 // Creating listeners for quick-actions
binding.currentAccount.getRoot().setOnClickListener(v -> dismiss()); binding.currentAccount.getRoot().setOnClickListener(v -> dismiss());
@ -173,36 +210,18 @@ public class ChooseAccountDialogFragment extends DialogFragment {
Log.w(TAG, "status was null"); Log.w(TAG, "status was null");
} }
}); });
}
if (adapter == null) { private void themeViews() {
adapter = new FlexibleAdapter<>(userItems, getActivity(), false); viewThemeUtils.themeDialog(binding.getRoot());
viewThemeUtils.themeDialogDivider(binding.divider);
User userEntity; viewThemeUtils.colorMaterialTextButton(binding.setStatus);
Participant participant; viewThemeUtils.colorDialogMenuText(binding.setStatus);
viewThemeUtils.colorMaterialTextButton(binding.addAccount);
for (Object userItem : userManager.getUsers().blockingGet()) { viewThemeUtils.colorDialogMenuText(binding.addAccount);
userEntity = (User) userItem; viewThemeUtils.colorMaterialTextButton(binding.manageSettings);
if (!userEntity.getCurrent()) { viewThemeUtils.colorDialogMenuText(binding.manageSettings);
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();
} }
private void loadCurrentStatus(User user) { private void loadCurrentStatus(User user) {
@ -305,7 +324,7 @@ public class ChooseAccountDialogFragment extends DialogFragment {
status.getStatus(), status.getStatus(),
status.getIcon(), status.getIcon(),
size, size,
getContext().getResources().getColor(R.color.dialog_background), viewThemeUtils.getScheme(binding.currentAccount.ticker.getContext()).getSurface(),
getContext())); getContext()));
binding.currentAccount.ticker.setVisibility(View.VISIBLE); binding.currentAccount.ticker.setVisibility(View.VISIBLE);

View File

@ -35,6 +35,8 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController import com.nextcloud.talk.controllers.bottomsheet.EntryMenuController
import com.nextcloud.talk.databinding.DialogBottomContactsBinding import com.nextcloud.talk.databinding.DialogBottomContactsBinding
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class ContactsBottomDialog( class ContactsBottomDialog(
@ -42,20 +44,22 @@ class ContactsBottomDialog(
val bundle: Bundle val bundle: Bundle
) : BottomSheetDialog(activity) { ) : BottomSheetDialog(activity) {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private var dialogRouter: Router? = null private var dialogRouter: Router? = null
private lateinit var binding: DialogBottomContactsBinding private lateinit var binding: DialogBottomContactsBinding
init {
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
binding = DialogBottomContactsBinding.inflate(layoutInflater) binding = DialogBottomContactsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(binding.root)
executeEntryMenuController(bundle) executeEntryMenuController(bundle)
} }

View File

@ -56,6 +56,7 @@ import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.DialogConversationOperationsBinding import com.nextcloud.talk.databinding.DialogConversationOperationsBinding
import com.nextcloud.talk.jobs.LeaveConversationWorker import com.nextcloud.talk.jobs.LeaveConversationWorker
import com.nextcloud.talk.models.json.conversations.Conversation 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.users.UserManager
import com.nextcloud.talk.utils.Mimetype.TEXT_PLAIN import com.nextcloud.talk.utils.Mimetype.TEXT_PLAIN
import com.nextcloud.talk.utils.ShareUtils import com.nextcloud.talk.utils.ShareUtils
@ -83,18 +84,20 @@ class ConversationsListBottomDialog(
lateinit var ncApi: NcApi lateinit var ncApi: NcApi
@Inject @Inject
lateinit var userManager: UserManager lateinit var viewThemeUtils: ViewThemeUtils
init { @Inject
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this) lateinit var userManager: UserManager
}
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
binding = DialogConversationOperationsBinding.inflate(layoutInflater) binding = DialogConversationOperationsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(binding.root)
initHeaderDescription() initHeaderDescription()
initItemsVisibility() initItemsVisibility()
initClickListeners() initClickListeners()

View File

@ -31,18 +31,20 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import androidx.annotation.NonNull 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.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.BuildConfig import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.ChatController import com.nextcloud.talk.controllers.ChatController
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.DialogMessageActionsBinding import com.nextcloud.talk.databinding.DialogMessageActionsBinding
import com.nextcloud.talk.models.json.chat.ChatMessage import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.conversations.Conversation import com.nextcloud.talk.models.json.conversations.Conversation
import com.nextcloud.talk.models.json.generic.GenericOverall 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.ApiUtils
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
import com.vanniktech.emoji.EmojiPopup import com.vanniktech.emoji.EmojiPopup
@ -53,7 +55,9 @@ import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class MessageActionsDialog( class MessageActionsDialog(
private val chatController: ChatController, private val chatController: ChatController,
private val message: ChatMessage, private val message: ChatMessage,
@ -64,16 +68,22 @@ class MessageActionsDialog(
private val ncApi: NcApi private val ncApi: NcApi
) : BottomSheetDialog(chatController.activity!!) { ) : BottomSheetDialog(chatController.activity!!) {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var dialogMessageActionsBinding: DialogMessageActionsBinding private lateinit var dialogMessageActionsBinding: DialogMessageActionsBinding
private lateinit var popup: EmojiPopup private lateinit var popup: EmojiPopup
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
dialogMessageActionsBinding = DialogMessageActionsBinding.inflate(layoutInflater) dialogMessageActionsBinding = DialogMessageActionsBinding.inflate(layoutInflater)
setContentView(dialogMessageActionsBinding.root) setContentView(dialogMessageActionsBinding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(dialogMessageActionsBinding.root)
initEmojiBar(hasChatPermission) initEmojiBar(hasChatPermission)
initMenuItemCopy(!message.isDeleted) initMenuItemCopy(!message.isDeleted)
initMenuReplyToMessage(message.replyable && hasChatPermission) initMenuReplyToMessage(message.replyable && hasChatPermission)
@ -215,7 +225,7 @@ class MessageActionsDialog(
private fun checkAndSetEmojiSelfReaction(emoji: EmojiTextView) { private fun checkAndSetEmojiSelfReaction(emoji: EmojiTextView) {
if (emoji.text?.toString() != null && message.reactionsSelf?.contains(emoji.text?.toString()) == true) { 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)
} }
} }

View File

@ -26,13 +26,18 @@ import android.content.Context
import android.os.Bundle import android.os.Bundle
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import autodagger.AutoInjector
import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.bottomsheet.BottomSheetBehavior
import com.google.android.material.bottomsheet.BottomSheetDialog import com.google.android.material.bottomsheet.BottomSheetDialog
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.controllers.ProfileController import com.nextcloud.talk.controllers.ProfileController
import com.nextcloud.talk.databinding.DialogScopeBinding import com.nextcloud.talk.databinding.DialogScopeBinding
import com.nextcloud.talk.models.json.userprofile.Scope import com.nextcloud.talk.models.json.userprofile.Scope
import com.nextcloud.talk.ui.theme.ViewThemeUtils
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class ScopeDialog( class ScopeDialog(
con: Context, con: Context,
private val userInfoAdapter: ProfileController.UserInfoAdapter, private val userInfoAdapter: ProfileController.UserInfoAdapter,
@ -40,15 +45,22 @@ class ScopeDialog(
private val position: Int private val position: Int
) : BottomSheetDialog(con) { ) : BottomSheetDialog(con) {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var dialogScopeBinding: DialogScopeBinding private lateinit var dialogScopeBinding: DialogScopeBinding
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
dialogScopeBinding = DialogScopeBinding.inflate(layoutInflater) dialogScopeBinding = DialogScopeBinding.inflate(layoutInflater)
setContentView(dialogScopeBinding.root) setContentView(dialogScopeBinding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(dialogScopeBinding.root)
if (field == ProfileController.Field.DISPLAYNAME || field == ProfileController.Field.EMAIL) { if (field == ProfileController.Field.DISPLAYNAME || field == ProfileController.Field.EMAIL) {
dialogScopeBinding.scopePrivate.visibility = View.GONE dialogScopeBinding.scopePrivate.visibility = View.GONE
} }

View File

@ -36,13 +36,13 @@ import android.widget.AdapterView.OnItemSelectedListener
import android.widget.ArrayAdapter import android.widget.ArrayAdapter
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.appcompat.app.AlertDialog
import androidx.core.widget.doAfterTextChanged import androidx.core.widget.doAfterTextChanged
import androidx.fragment.app.DialogFragment import androidx.fragment.app.DialogFragment
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import autodagger.AutoInjector import autodagger.AutoInjector
import com.bluelinelabs.logansquare.LoganSquare import com.bluelinelabs.logansquare.LoganSquare
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.adapters.PredefinedStatusClickListener import com.nextcloud.talk.adapters.PredefinedStatusClickListener
import com.nextcloud.talk.adapters.PredefinedStatusListAdapter import com.nextcloud.talk.adapters.PredefinedStatusListAdapter
@ -166,9 +166,10 @@ class SetStatusDialogFragment :
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
binding = DialogSetStatusBinding.inflate(LayoutInflater.from(context)) binding = DialogSetStatusBinding.inflate(LayoutInflater.from(context))
return AlertDialog.Builder(requireContext()) val dialogBuilder = MaterialAlertDialogBuilder(binding.root.context).setView(binding.root)
.setView(binding.root) viewThemeUtils.colorMaterialAlertDialogBackground(binding.root.context, dialogBuilder)
.create()
return dialogBuilder.create()
} }
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
@ -241,10 +242,12 @@ class SetStatusDialogFragment :
} }
} }
viewThemeUtils.colorMaterialButtonText(binding.clearStatus) viewThemeUtils.themeDialog(binding.root)
viewThemeUtils.colorMaterialButtonBackground(binding.setStatus)
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.customStatusInput.doAfterTextChanged { text ->
binding.setStatus.isEnabled = !text.isNullOrEmpty() binding.setStatus.isEnabled = !text.isNullOrEmpty()
@ -416,7 +419,7 @@ class SetStatusDialogFragment :
} }
} }
viewThemeUtils.colorCardViewBackground(views.first) viewThemeUtils.colorCardViewBackground(views.first)
viewThemeUtils.colorTextViewText(views.second) viewThemeUtils.colorPrimaryTextViewElement(views.second)
} }
private fun clearTopStatus() { private fun clearTopStatus() {

View File

@ -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.conversations.Conversation
import com.nextcloud.talk.models.json.generic.GenericOverall import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.reactions.ReactionsOverall 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 com.nextcloud.talk.utils.ApiUtils
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
import io.reactivex.disposables.Disposable import io.reactivex.disposables.Disposable
import io.reactivex.schedulers.Schedulers import io.reactivex.schedulers.Schedulers
import java.util.Collections import java.util.Collections
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class) @AutoInjector(NextcloudTalkApplication::class)
class ShowReactionsDialog( class ShowReactionsDialog(
@ -66,10 +67,12 @@ class ShowReactionsDialog(
private val chatMessage: ChatMessage, private val chatMessage: ChatMessage,
private val user: User?, private val user: User?,
private val hasChatPermission: Boolean, private val hasChatPermission: Boolean,
private val ncApi: NcApi, private val ncApi: NcApi
private val serverTheme: ServerTheme
) : BottomSheetDialog(activity), ReactionItemClickListener { ) : BottomSheetDialog(activity), ReactionItemClickListener {
@Inject
lateinit var viewThemeUtils: ViewThemeUtils
private lateinit var binding: DialogMessageReactionsBinding private lateinit var binding: DialogMessageReactionsBinding
private var adapter: ReactionsAdapter? = null private var adapter: ReactionsAdapter? = null
@ -78,9 +81,12 @@ class ShowReactionsDialog(
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
binding = DialogMessageReactionsBinding.inflate(layoutInflater) binding = DialogMessageReactionsBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT) window?.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.WRAP_CONTENT)
viewThemeUtils.themeDialog(binding.root)
adapter = ReactionsAdapter(this, user) adapter = ReactionsAdapter(this, user)
binding.reactionsList.adapter = adapter binding.reactionsList.adapter = adapter
binding.reactionsList.layoutManager = LinearLayoutManager(context) binding.reactionsList.layoutManager = LinearLayoutManager(context)
@ -98,7 +104,6 @@ class ShowReactionsDialog(
adapter?.list?.clear() adapter?.list?.clear()
if (chatMessage.reactions != null && chatMessage.reactions!!.isNotEmpty()) { if (chatMessage.reactions != null && chatMessage.reactions!!.isNotEmpty()) {
var reactionsTotal = 0 var reactionsTotal = 0
binding.emojiReactionsTabs.setSelectedTabIndicatorColor(serverTheme.primaryColor)
for ((emoji, amount) in chatMessage.reactions!!) { for ((emoji, amount) in chatMessage.reactions!!) {
reactionsTotal = reactionsTotal.plus(amount as Int) reactionsTotal = reactionsTotal.plus(amount as Int)
val tab: TabLayout.Tab = binding.emojiReactionsTabs.newTab() // Create a new Tab names "First Tab" 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) updateParticipantsForEmoji(chatMessage, tagAll)
} }
adapter?.notifyDataSetChanged() adapter?.notifyDataSetChanged()

View File

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

View File

@ -0,0 +1,35 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.ui.theme
import scheme.Scheme
interface MaterialSchemes {
/**
* Schema for light theme
*/
val lightScheme: Scheme
/**
* Schema for light theme
*/
val darkScheme: Scheme
}

View File

@ -0,0 +1,33 @@
/*
* Nextcloud Talk application
*
* @author Andy Scherzinger
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.ui.theme
import 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)
}
}

View File

@ -24,8 +24,8 @@ package com.nextcloud.talk.ui.theme
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.models.json.capabilities.Capabilities import com.nextcloud.talk.models.json.capabilities.Capabilities
interface ServerThemeProvider { interface MaterialSchemesProvider {
fun getServerThemeForUser(user: User?): ServerTheme fun getMaterialSchemesForUser(user: User?): MaterialSchemes
fun getServerThemeForCapabilities(capabilities: Capabilities?): ServerTheme fun getMaterialSchemesForCapabilities(capabilities: Capabilities?): MaterialSchemes
fun getServerThemeForCurrentUser(): ServerTheme fun getMaterialSchemesForCurrentUser(): MaterialSchemes
} }

View File

@ -30,14 +30,14 @@ import com.nextcloud.talk.utils.ui.ColorUtil
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import javax.inject.Inject import javax.inject.Inject
internal class ServerThemeProviderImpl @Inject constructor( internal class MaterialSchemesProviderImpl @Inject constructor(
private val userProvider: CurrentUserProviderNew, private val userProvider: CurrentUserProviderNew,
private val colorUtil: ColorUtil private val colorUtil: ColorUtil
) : ServerThemeProvider { ) : MaterialSchemesProvider {
private val themeCache: ConcurrentHashMap<String, ServerTheme> = ConcurrentHashMap() private val themeCache: ConcurrentHashMap<String, MaterialSchemes> = ConcurrentHashMap()
override fun getServerThemeForUser(user: User?): ServerTheme { override fun getMaterialSchemesForUser(user: User?): MaterialSchemes {
val url: String = if (user?.baseUrl != null) { val url: String = if (user?.baseUrl != null) {
user.baseUrl!! user.baseUrl!!
} else { } else {
@ -45,18 +45,18 @@ internal class ServerThemeProviderImpl @Inject constructor(
} }
if (!themeCache.containsKey(url)) { if (!themeCache.containsKey(url)) {
themeCache[url] = getServerThemeForCapabilities(user?.capabilities) themeCache[url] = getMaterialSchemesForCapabilities(user?.capabilities)
} }
return themeCache[url]!! return themeCache[url]!!
} }
override fun getServerThemeForCurrentUser(): ServerTheme { override fun getMaterialSchemesForCurrentUser(): MaterialSchemes {
return getServerThemeForUser(userProvider.currentUser.blockingGet()) return getMaterialSchemesForUser(userProvider.currentUser.blockingGet())
} }
override fun getServerThemeForCapabilities(capabilities: Capabilities?): ServerTheme { override fun getMaterialSchemesForCapabilities(capabilities: Capabilities?): MaterialSchemes {
return ServerThemeImpl(capabilities?.themingCapability, colorUtil) return MaterialSchemesImpl(ServerThemeImpl(capabilities?.themingCapability, colorUtil))
} }
companion object { companion object {

View File

@ -27,8 +27,7 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.models.json.capabilities.ThemingCapability import com.nextcloud.talk.models.json.capabilities.ThemingCapability
import com.nextcloud.talk.utils.ui.ColorUtil import com.nextcloud.talk.utils.ui.ColorUtil
internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil: ColorUtil) : internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil: ColorUtil) : ServerTheme {
ServerTheme {
override val primaryColor: Int override val primaryColor: Int
override val colorElement: Int override val colorElement: Int
@ -38,11 +37,9 @@ internal class ServerThemeImpl(themingCapability: ThemingCapability?, colorUtil:
init { init {
primaryColor = colorUtil.getNullSafeColorWithFallbackRes(themingCapability?.color, R.color.colorPrimary) primaryColor = colorUtil.getNullSafeColorWithFallbackRes(themingCapability?.color, R.color.colorPrimary)
colorElement = colorUtil.getNullSafeColor(themingCapability?.colorElement, primaryColor) colorElement = colorUtil.getNullSafeColor(themingCapability?.colorElement, primaryColor)
colorElementBright = colorUtil.getNullSafeColor(themingCapability?.colorElementBright, primaryColor) colorElementBright = colorUtil.getNullSafeColor(themingCapability?.colorElementBright, primaryColor)
colorElementDark = colorUtil.getNullSafeColor(themingCapability?.colorElementDark, primaryColor) colorElementDark = colorUtil.getNullSafeColor(themingCapability?.colorElementDark, primaryColor)
colorText = colorUtil.getTextColor(themingCapability?.colorText, primaryColor) colorText = colorUtil.getTextColor(themingCapability?.colorText, primaryColor)
} }
} }

View File

@ -33,12 +33,12 @@ internal abstract class ThemeModule {
@Binds @Binds
@Reusable @Reusable
abstract fun bindServerThemeProvider(provider: ServerThemeProviderImpl): ServerThemeProvider abstract fun bindMaterialSchemesProvider(provider: MaterialSchemesProviderImpl): MaterialSchemesProvider
companion object { companion object {
@Provides @Provides
fun provideCurrentServerTheme(themeProvider: ServerThemeProvider): ServerTheme { fun provideCurrentMaterialSchemes(themeProvider: MaterialSchemesProvider): MaterialSchemes {
return themeProvider.getServerThemeForCurrentUser() return themeProvider.getMaterialSchemesForCurrentUser()
} }
} }
} }

View File

@ -21,74 +21,193 @@
package com.nextcloud.talk.ui.theme package com.nextcloud.talk.ui.theme
import android.annotation.TargetApi
import android.app.Activity
import android.content.Context import android.content.Context
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.graphics.Color import android.graphics.Color
import android.graphics.PorterDuff import android.graphics.PorterDuff
import android.graphics.drawable.Drawable 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.View
import android.view.ViewGroup
import android.widget.Button
import android.widget.CheckBox import android.widget.CheckBox
import android.widget.EditText import android.widget.EditText
import android.widget.ImageButton
import android.widget.ImageView import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.RadioButton import android.widget.RadioButton
import android.widget.SeekBar import android.widget.SeekBar
import android.widget.TextView import android.widget.TextView
import androidx.annotation.ColorInt import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import androidx.appcompat.content.res.AppCompatResources import androidx.appcompat.content.res.AppCompatResources
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.SearchView.SearchAutoComplete
import androidx.appcompat.widget.SwitchCompat import androidx.appcompat.widget.SwitchCompat
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import androidx.core.content.res.ResourcesCompat 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.core.view.children
import androidx.swiperefreshlayout.widget.SwipeRefreshLayout import androidx.swiperefreshlayout.widget.SwipeRefreshLayout
import com.google.android.material.appbar.MaterialToolbar
import com.google.android.material.button.MaterialButton import com.google.android.material.button.MaterialButton
import com.google.android.material.card.MaterialCardView import com.google.android.material.card.MaterialCardView
import com.google.android.material.chip.Chip 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.floatingactionbutton.FloatingActionButton
import com.google.android.material.progressindicator.LinearProgressIndicator 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.tabs.TabLayout
import com.google.android.material.textfield.TextInputLayout import com.google.android.material.textfield.TextInputLayout
import com.google.android.material.textview.MaterialTextView
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.DrawableUtils import com.nextcloud.talk.utils.DrawableUtils
import com.nextcloud.talk.utils.ui.ColorUtil import com.nextcloud.talk.utils.ui.ColorUtil
import com.nextcloud.talk.utils.ui.PlatformThemeUtil.isDarkMode import com.nextcloud.talk.utils.ui.PlatformThemeUtil.isDarkMode
import com.vanniktech.emoji.EmojiTextView
import com.yarolegovich.mp.MaterialPreferenceCategory import com.yarolegovich.mp.MaterialPreferenceCategory
import com.yarolegovich.mp.MaterialSwitchPreference import com.yarolegovich.mp.MaterialSwitchPreference
import eu.davidea.flexibleadapter.utils.FlexibleUtils
import scheme.Scheme
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt
@Suppress("TooManyFunctions") @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 { fun getScheme(context: Context): Scheme = when {
isDarkMode(context) -> theme.colorElementDark isDarkMode(context) -> schemes.darkScheme
else -> theme.colorElementBright else -> schemes.lightScheme
} }
private fun withElementColor(view: View, block: (Int) -> Unit) { private fun getSchemeDark(): Scheme = schemes.darkScheme
block(getElementColor(view.context))
private fun withScheme(view: View, block: (Scheme) -> Unit) {
block(getScheme(view.context))
}
private fun withScheme(context: Context, block: (Scheme) -> Unit) {
block(getScheme(context))
}
private fun withSchemeDark(block: (Scheme) -> Unit) {
block(getSchemeDark())
}
fun themeToolbar(toolbar: MaterialToolbar) {
withScheme(toolbar) { scheme ->
toolbar.setBackgroundColor(scheme.surface)
toolbar.setNavigationIconTint(scheme.onSurface)
toolbar.setTitleTextColor(scheme.onSurface)
}
}
fun colorViewBackground(view: View) {
withScheme(view) { scheme ->
view.setBackgroundColor(scheme.surface)
}
}
fun colorToolbarMenuIcon(context: Context, item: MenuItem) {
withScheme(context) { scheme ->
item.icon.setColorFilter(scheme.onSurface, PorterDuff.Mode.SRC_ATOP)
}
}
fun colorToolbarOverflowIcon(toolbar: MaterialToolbar) {
withScheme(toolbar) { scheme ->
toolbar.overflowIcon?.setColorFilter(scheme.onSurface, PorterDuff.Mode.SRC_ATOP)
}
}
fun themeSearchView(searchView: SearchView) {
withScheme(searchView) { scheme ->
// hacky as no default way is provided
val editText = searchView.findViewById<SearchAutoComplete>(R.id.search_src_text)
val searchPlate = searchView.findViewById<LinearLayout>(R.id.search_plate)
editText.textSize = SEARCH_TEXT_SIZE
editText.setHintTextColor(scheme.onSurfaceVariant)
editText.setTextColor(scheme.onSurface)
editText.setBackgroundColor(scheme.surface)
searchPlate.setBackgroundColor(scheme.surface)
}
}
fun themeSearchBarText(searchText: MaterialTextView) {
withScheme(searchText) { scheme ->
searchText.setHintTextColor(scheme.onSurfaceVariant)
}
}
fun themeStatusBar(activity: Activity, view: View) {
withScheme(view) { scheme ->
DisplayUtils.applyColorToStatusBar(activity, scheme.surface)
}
}
fun resetStatusBar(activity: Activity, view: View) {
DisplayUtils.applyColorToStatusBar(
activity,
ResourcesCompat.getColor(
activity.resources,
R.color.bg_default,
activity.theme
)
)
}
fun themeDialog(view: View) {
withScheme(view) { scheme ->
view.setBackgroundColor(scheme.surface)
}
}
fun themeDialogDark(view: View) {
withSchemeDark { scheme ->
view.setBackgroundColor(scheme.surface)
}
}
fun themeDialogDivider(view: View) {
withScheme(view) { scheme ->
view.setBackgroundColor(scheme.surfaceVariant)
}
} }
fun themeFAB(fab: FloatingActionButton) { fun themeFAB(fab: FloatingActionButton) {
withElementColor(fab) { color -> withScheme(fab) { scheme ->
fab.backgroundTintList = ColorStateList.valueOf(color) fab.backgroundTintList = ColorStateList.valueOf(scheme.primaryContainer)
fab.imageTintList = ColorStateList.valueOf(theme.colorText) fab.imageTintList = ColorStateList.valueOf(scheme.onPrimaryContainer)
}
}
fun themeCardView(cardView: MaterialCardView) {
withScheme(cardView) { scheme ->
cardView.backgroundTintList = ColorStateList.valueOf(scheme.surface)
} }
} }
fun themeHorizontalSeekBar(seekBar: SeekBar) { fun themeHorizontalSeekBar(seekBar: SeekBar) {
withElementColor(seekBar) { color -> withScheme(seekBar) { scheme ->
themeHorizontalSeekBar(seekBar, color) 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) { fun themeHorizontalProgressBar(progressBar: ProgressBar?, @ColorInt color: Int) {
if (progressBar != null) { if (progressBar != null) {
progressBar.indeterminateDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN) 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) { fun colorPrimaryTextViewElement(textView: TextView) {
withElementColor(textView) { color -> withScheme(textView) { scheme ->
textView.setTextColor(color) textView.setTextColor(scheme.primary)
} }
} }
fun colorTextViewText(textView: TextView) { fun colorPrimaryTextViewElementDarkMode(textView: TextView) {
textView.setTextColor(theme.colorText) 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. * Colors the background as element color and the foreground as text color.
*/ */
fun colorImageViewButton(imageView: ImageView) { fun colorImageViewButton(imageView: ImageView) {
withElementColor(imageView) { color -> withScheme(imageView) { scheme ->
imageView.imageTintList = ColorStateList.valueOf(theme.colorText) imageView.imageTintList = ColorStateList.valueOf(scheme.onPrimaryContainer)
imageView.backgroundTintList = ColorStateList.valueOf(color) 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 * Tints the image with element color
*/ */
fun colorImageView(imageView: ImageView) { fun colorImageView(imageView: ImageView) {
withElementColor(imageView) { color -> withScheme(imageView) { scheme ->
imageView.imageTintList = ColorStateList.valueOf(color) imageView.imageTintList = ColorStateList.valueOf(scheme.primary)
} }
} }
/** fun colorOutgoingQuoteText(textView: TextView) {
* Tints the image with text color withScheme(textView) { scheme ->
*/ textView.setTextColor(scheme.onSurfaceVariant)
fun colorImageViewText(imageView: ImageView) { }
imageView.imageTintList = ColorStateList.valueOf(theme.colorText) }
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) { fun colorMaterialButtonText(button: MaterialButton) {
withElementColor(button) { color -> withScheme(button) { scheme ->
val disabledColor = ContextCompat.getColor(button.context, R.color.disabled_text) val disabledColor = ContextCompat.getColor(button.context, R.color.disabled_text)
val colorStateList = ColorStateList( val colorStateList = ColorStateList(
arrayOf( arrayOf(
intArrayOf(android.R.attr.state_enabled), intArrayOf(android.R.attr.state_enabled),
intArrayOf(-android.R.attr.state_enabled) intArrayOf(-android.R.attr.state_enabled)
), ),
intArrayOf(color, disabledColor) intArrayOf(scheme.primary, disabledColor)
) )
button.setTextColor(colorStateList) button.setTextColor(colorStateList)
button.iconTint = colorStateList button.iconTint = colorStateList
} }
} }
fun colorMaterialButtonBackground(button: MaterialButton) { fun colorTextButtons(vararg buttons: Button) {
withElementColor(button) { color -> withScheme(buttons[0]) { scheme ->
button.setBackgroundColor(color) 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) fun colorMaterialButtonPrimaryFilled(button: MaterialButton) {
val colorStateList = ColorStateList( 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( arrayOf(
intArrayOf(android.R.attr.state_enabled), intArrayOf(android.R.attr.state_enabled),
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) fun colorMaterialButtonPrimaryOutlined(button: MaterialButton) {
button.iconTint = colorStateList 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) { fun colorCardViewBackground(card: MaterialCardView) {
withElementColor(card) { color -> withScheme(card) { scheme ->
card.setCardBackgroundColor(color) 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 // TODO split this util into classes depending on framework views vs library views
fun colorPreferenceCategory(category: MaterialPreferenceCategory) { fun colorPreferenceCategory(category: MaterialPreferenceCategory) {
withElementColor(category) { color -> withScheme(category) { scheme ->
category.setTitleColor(color) category.setTitleColor(scheme.primary)
} }
} }
@ -188,7 +529,7 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
} }
fun colorSwitchCompat(switchCompat: SwitchCompat) { fun colorSwitchCompat(switchCompat: SwitchCompat) {
withElementColor(switchCompat) { color -> withScheme(switchCompat) { scheme ->
val context = switchCompat.context val context = switchCompat.context
@ -203,11 +544,16 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
context.theme context.theme
) )
val trackColor = val trackColor = Color.argb(
Color.argb(SWITCHCOMPAT_TRACK_ALPHA, Color.red(color), Color.green(color), Color.blue(color)) SWITCH_COMPAT_TRACK_ALPHA,
Color.red(scheme.primary),
Color.green(scheme.primary),
Color.blue(scheme.primary)
)
switchCompat.thumbTintList = ColorStateList( switchCompat.thumbTintList = ColorStateList(
arrayOf(intArrayOf(android.R.attr.state_checked), intArrayOf()), arrayOf(intArrayOf(android.R.attr.state_checked), intArrayOf()),
intArrayOf(color, thumbUncheckedColor) intArrayOf(scheme.primary, thumbUncheckedColor)
) )
switchCompat.trackTintList = ColorStateList( switchCompat.trackTintList = ColorStateList(
@ -218,58 +564,49 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
} }
fun colorDrawable(context: Context, drawable: Drawable) { fun colorDrawable(context: Context, drawable: Drawable) {
val color = getElementColor(context) val scheme = getScheme(context)
drawable.setTint(color) drawable.setTint(scheme.primary)
} }
fun themeCheckbox(checkbox: CheckBox) { fun themeCheckbox(checkbox: CheckBox) {
withElementColor(checkbox) { color -> withScheme(checkbox) { scheme ->
checkbox.buttonTintList = ColorStateList( checkbox.buttonTintList = ColorStateList(
arrayOf( arrayOf(
intArrayOf(-android.R.attr.state_checked), intArrayOf(-android.R.attr.state_checked),
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) { fun themeRadioButton(radioButton: RadioButton) {
withElementColor(radioButton) { color -> withScheme(radioButton) { scheme ->
radioButton.buttonTintList = ColorStateList( radioButton.buttonTintList = ColorStateList(
arrayOf( arrayOf(
intArrayOf(-android.R.attr.state_checked), intArrayOf(-android.R.attr.state_checked),
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) { fun themeSwipeRefreshLayout(swipeRefreshLayout: SwipeRefreshLayout) {
withElementColor(swipeRefreshLayout) { color -> withScheme(swipeRefreshLayout) { scheme ->
swipeRefreshLayout.setColorSchemeColors(color) swipeRefreshLayout.setColorSchemeColors(scheme.primary)
swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background) swipeRefreshLayout.setProgressBackgroundColorSchemeResource(R.color.refresh_spinner_background)
} }
} }
fun colorProgressBar(progressIndicator: LinearProgressIndicator) { fun colorProgressBar(progressIndicator: LinearProgressIndicator) {
withElementColor(progressIndicator) { color -> withScheme(progressIndicator) { scheme ->
progressIndicator.setIndicatorColor(progressColor(progressIndicator.context, color)) 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) { fun colorEditText(editText: EditText) {
withElementColor(editText) { color -> withScheme(editText) { scheme ->
editText.setTextColor(color)
// TODO check API-level compatibility // TODO check API-level compatibility
// editText.background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP) // editText.background.setColorFilter(color, PorterDuff.Mode.SRC_ATOP)
editText.backgroundTintList = ColorStateList( editText.backgroundTintList = ColorStateList(
@ -278,16 +615,18 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
intArrayOf(android.R.attr.state_focused) intArrayOf(android.R.attr.state_focused)
), ),
intArrayOf( intArrayOf(
Color.GRAY, scheme.outline,
color scheme.primary
) )
) )
editText.setHintTextColor(scheme.onSurfaceVariant)
editText.setTextColor(scheme.onSurface)
} }
} }
fun colorTextInputLayout(textInputLayout: TextInputLayout) { fun colorTextInputLayout(textInputLayout: TextInputLayout) {
withElementColor(textInputLayout) { color -> withScheme(textInputLayout) { scheme ->
val errorColor = Color.GRAY val errorColor = scheme.onSurfaceVariant
val errorColorStateList = ColorStateList( val errorColorStateList = ColorStateList(
arrayOf( arrayOf(
@ -305,8 +644,8 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
intArrayOf(android.R.attr.state_focused) intArrayOf(android.R.attr.state_focused)
), ),
intArrayOf( intArrayOf(
Color.GRAY, scheme.outline,
color scheme.primary
) )
) )
@ -318,12 +657,32 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
} }
} }
fun colorTabLayout(tabLayout: TabLayout) { fun themeTabLayoutOnSurface(tabLayout: TabLayout) {
withElementColor(tabLayout) { color -> withScheme(tabLayout) { scheme ->
tabLayout.setSelectedTabIndicatorColor(color) 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? { fun getPlaceholderImage(context: Context, mimetype: String?): Drawable? {
val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype) val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimetype)
val drawable = AppCompatResources.getDrawable( val drawable = AppCompatResources.getDrawable(
@ -337,28 +696,149 @@ class ViewThemeUtils @Inject constructor(private val theme: ServerTheme, private
} }
fun colorChipBackground(chip: Chip) { fun colorChipBackground(chip: Chip) {
withElementColor(chip) { color -> withScheme(chip) { scheme ->
chip.chipBackgroundColor = ColorStateList.valueOf(color) chip.chipBackgroundColor = ColorStateList.valueOf(scheme.primary)
chip.setTextColor(theme.colorText) chip.setTextColor(scheme.onPrimary)
} }
} }
fun colorChipOutlined(chip: Chip, strokeWidth: Float) { fun colorChipOutlined(chip: Chip, strokeWidth: Float) {
withElementColor(chip) { color -> withScheme(chip) { scheme ->
chip.chipBackgroundColor = ColorStateList.valueOf(Color.TRANSPARENT) chip.chipBackgroundColor = ColorStateList.valueOf(Color.TRANSPARENT)
chip.chipStrokeWidth = strokeWidth chip.chipStrokeWidth = strokeWidth
chip.chipStrokeColor = ColorStateList.valueOf(color) chip.chipStrokeColor = ColorStateList.valueOf(scheme.primary)
chip.setTextColor(color) chip.setTextColor(scheme.primary)
} }
} }
@TargetApi(Build.VERSION_CODES.O)
fun themePlaceholderAvatar(avatar: View, @DrawableRes foreground: Int): Drawable? {
var drawable: LayerDrawable? = null
withScheme(avatar) { scheme ->
val layers = arrayOfNulls<Drawable>(2)
layers[0] = ContextCompat.getDrawable(avatar.context, R.drawable.ic_avatar_background)
layers[0]?.setTint(scheme.surfaceVariant)
layers[1] = ContextCompat.getDrawable(avatar.context, foreground)
layers[1]?.setTint(scheme.onSurfaceVariant)
drawable = LayerDrawable(layers)
}
return drawable
}
fun themePrimaryMentionChip(context: Context, chip: ChipDrawable) {
withScheme(context) { scheme ->
chip.chipBackgroundColor = ColorStateList.valueOf(scheme.primary)
chip.setTextColor(scheme.onPrimary)
}
}
fun setCheckedBackground(emoji: EmojiTextView) {
withScheme(emoji) { scheme ->
val drawable = AppCompatResources
.getDrawable(emoji.context, R.drawable.reaction_self_bottom_sheet_background)!!
.mutate()
DrawableCompat.setTintList(
drawable,
ColorStateList.valueOf(scheme.primary)
)
emoji.background = drawable
}
}
fun setCheckedBackground(linearLayout: LinearLayout, @ColorInt backgroundColor: Int) {
withScheme(linearLayout) { scheme ->
val drawable = AppCompatResources
.getDrawable(linearLayout.context, R.drawable.reaction_self_background)!!
.mutate()
DrawableCompat.setTintList(
drawable,
ColorStateList.valueOf(backgroundColor)
)
linearLayout.background = drawable
}
}
fun colorDialogMenuText(button: MaterialButton) {
withScheme(button) { scheme ->
button.setTextColor(scheme.onSurface)
button.iconTint = ColorStateList.valueOf(scheme.onSurface)
}
}
fun colorMaterialAlertDialogBackground(context: Context, dialogBuilder: MaterialAlertDialogBuilder) {
withScheme(dialogBuilder.context) { scheme ->
val materialShapeDrawable = MaterialShapeDrawable(
context,
null,
com.google.android.material.R.attr.alertDialogStyle,
com.google.android.material.R.style.MaterialAlertDialog_MaterialComponents
)
materialShapeDrawable.initializeElevationOverlay(context)
materialShapeDrawable.fillColor = ColorStateList.valueOf(scheme.surface)
// dialogCornerRadius first appeared in Android Pie
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
val radius = context.resources.getDimension(R.dimen.dialogBorderRadius)
materialShapeDrawable.setCornerSize(radius)
}
dialogBuilder.background = materialShapeDrawable
}
}
fun colorDialogHeadline(textView: TextView) {
withScheme(textView) { scheme ->
textView.setTextColor(scheme.onSurface)
}
}
fun colorDialogSupportingText(textView: TextView) {
withScheme(textView) { scheme ->
textView.setTextColor(scheme.onSurfaceVariant)
}
}
fun colorDialogIcon(icon: ImageView) {
withScheme(icon) { scheme ->
icon.setColorFilter(scheme.secondary)
}
}
fun highlightText(textView: TextView, originalText: String, constraint: String) {
withScheme(textView) { scheme ->
FlexibleUtils.highlightText(textView, originalText, constraint, scheme.primary)
}
}
fun createHighlightedSpan(context: Context, messageSpannable: SpannableString, searchTerm: String): Spannable {
var spannable: Spannable = messageSpannable
withScheme(context) { scheme ->
spannable = DisplayUtils.searchAndColor(messageSpannable, searchTerm, scheme.primary)
}
return spannable
}
fun colorMaterialAlertDialogIcon(context: Context, drawableId: Int): Drawable {
val drawable = AppCompatResources.getDrawable(context, drawableId)!!
withScheme(context) { scheme ->
DrawableCompat.setTint(drawable, scheme.secondary)
}
return drawable
}
companion object { companion object {
private val THEMEABLE_PLACEHOLDER_IDS = listOf( private val THEMEABLE_PLACEHOLDER_IDS = listOf(
R.drawable.ic_mimetype_package_x_generic, R.drawable.ic_mimetype_package_x_generic,
R.drawable.ic_mimetype_folder R.drawable.ic_mimetype_folder
) )
private const val SWITCHCOMPAT_TRACK_ALPHA: Int = 77
private const val PROGRESS_LIGHTNESS_LIGHT_THEME: Float = 0.76f private val ALPHA_80_INT: Int = (255 * 0.8).roundToInt()
private const val PROGRESS_LIGHTNESS_DARK_THEME: Float = 0.28f
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
} }
} }

View File

@ -81,6 +81,7 @@ import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.data.user.model.User; import com.nextcloud.talk.data.user.model.User;
import com.nextcloud.talk.events.UserMentionClickEvent; import com.nextcloud.talk.events.UserMentionClickEvent;
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
import com.nextcloud.talk.utils.text.Spans; import com.nextcloud.talk.utils.text.Spans;
import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.EventBus;
@ -103,7 +104,6 @@ import androidx.annotation.Nullable;
import androidx.annotation.StringRes; import androidx.annotation.StringRes;
import androidx.annotation.XmlRes; import androidx.annotation.XmlRes;
import androidx.appcompat.widget.AppCompatDrawableManager; import androidx.appcompat.widget.AppCompatDrawableManager;
import androidx.appcompat.widget.SearchView;
import androidx.core.content.ContextCompat; import androidx.core.content.ContextCompat;
import androidx.core.content.res.ResourcesCompat; import androidx.core.content.res.ResourcesCompat;
import androidx.core.graphics.ColorUtils; import androidx.core.graphics.ColorUtils;
@ -297,11 +297,16 @@ public class DisplayUtils {
User conversationUser, User conversationUser,
String type, String type,
@XmlRes int chipResource, @XmlRes int chipResource,
@Nullable EditText emojiEditText) { @Nullable EditText emojiEditText,
ViewThemeUtils viewThemeUtils) {
ChipDrawable chip = ChipDrawable.createFromResource(context, chipResource); ChipDrawable chip = ChipDrawable.createFromResource(context, chipResource);
chip.setText(EmojiCompat.get().process(label)); chip.setText(EmojiCompat.get().process(label));
chip.setEllipsize(TextUtils.TruncateAt.MIDDLE); chip.setEllipsize(TextUtils.TruncateAt.MIDDLE);
if (chipResource == R.xml.chip_you) {
viewThemeUtils.themePrimaryMentionChip(context, chip);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
Configuration config = context.getResources().getConfiguration(); Configuration config = context.getResources().getConfiguration();
chip.setLayoutDirection(config.getLayoutDirection()); chip.setLayoutDirection(config.getLayoutDirection());
@ -367,7 +372,8 @@ public class DisplayUtils {
public static Spannable searchAndReplaceWithMentionSpan(Context context, Spannable text, public static Spannable searchAndReplaceWithMentionSpan(Context context, Spannable text,
String id, String label, String type, String id, String label, String type,
User conversationUser, User conversationUser,
@XmlRes int chipXmlRes) { @XmlRes int chipXmlRes,
ViewThemeUtils viewThemeUtils) {
Spannable spannableString = new SpannableString(text); Spannable spannableString = new SpannableString(text);
String stringText = text.toString(); String stringText = text.toString();
@ -395,10 +401,18 @@ public class DisplayUtils {
conversationUser, conversationUser,
type, type,
chipXmlRes, chipXmlRes,
null), null,
viewThemeUtils),
BetterImageSpan.ALIGN_CENTER, id, BetterImageSpan.ALIGN_CENTER, id,
label); label);
spannableString.setSpan(mentionChipSpan, start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 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)) { if ("user".equals(type) && !conversationUser.getUserId().equals(id)) {
spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); spannableString.setSpan(clickableSpan, start, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
} }
@ -517,19 +531,6 @@ public class DisplayUtils {
window.setNavigationBarColor(color); 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. * beautifies a given URL by removing any http/https protocol prefix.
* *

View File

@ -28,22 +28,30 @@ import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.inputmethod.EditorInfo; import android.view.inputmethod.EditorInfo;
import android.widget.EditText; import android.widget.EditText;
import androidx.appcompat.app.AlertDialog; import android.widget.TextView;
import autodagger.AutoInjector;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.nextcloud.talk.R; import com.nextcloud.talk.R;
import com.nextcloud.talk.application.NextcloudTalkApplication; import com.nextcloud.talk.application.NextcloudTalkApplication;
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
import com.yarolegovich.mp.io.StandardUserInputModule; import com.yarolegovich.mp.io.StandardUserInputModule;
import javax.inject.Inject;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import javax.inject.Inject;
import autodagger.AutoInjector;
@AutoInjector(NextcloudTalkApplication.class) @AutoInjector(NextcloudTalkApplication.class)
public class MagicUserInputModule extends StandardUserInputModule { public class MagicUserInputModule extends StandardUserInputModule {
@Inject @Inject
AppPreferences appPreferences; AppPreferences appPreferences;
@Inject
ViewThemeUtils viewThemeUtils;
private List<String> keysWithIntegerInput = new ArrayList<>(); private List<String> keysWithIntegerInput = new ArrayList<>();
public MagicUserInputModule(Context context) { public MagicUserInputModule(Context context) {
@ -65,6 +73,11 @@ public class MagicUserInputModule extends StandardUserInputModule {
final Listener<String> listener) { final Listener<String> listener) {
final View view = LayoutInflater.from(context).inflate(R.layout.dialog_edittext, null); final View view = LayoutInflater.from(context).inflate(R.layout.dialog_edittext, null);
final EditText inputField = view.findViewById(R.id.mp_text_input); 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()) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && appPreferences.getIsKeyboardIncognito()) {
inputField.setImeOptions(inputField.getImeOptions() | EditorInfo.IME_FLAG_NO_PERSONALIZED_LEARNING); 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); inputField.setInputType(InputType.TYPE_CLASS_NUMBER);
} }
final Dialog dialog = new AlertDialog.Builder(context) final MaterialAlertDialogBuilder dialogBuilder = new MaterialAlertDialogBuilder(view.getContext())
.setTitle(title) .setTitle(title)
.setView(view) .setView(view);
.show();
view.findViewById(R.id.mp_btn_confirm).setOnClickListener(new View.OnClickListener() { 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 @Override
public void onClick(View v) { public void onClick(View v) {
listener.onInput(inputField.getText().toString()); listener.onInput(inputField.getText().toString());

View File

@ -28,6 +28,7 @@ import androidx.core.content.ContextCompat
import androidx.core.graphics.ColorUtils import androidx.core.graphics.ColorUtils
import com.nextcloud.talk.R import com.nextcloud.talk.R
import javax.inject.Inject import javax.inject.Inject
import kotlin.math.roundToInt
class ColorUtil @Inject constructor(private val context: Context) { 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() 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 { companion object {
private const val HSL_SIZE: Int = 3 private const val HSL_SIZE: Int = 3
private const val INDEX_LIGHTNESS: Int = 2 private const val INDEX_LIGHTNESS: Int = 2

View File

@ -0,0 +1,43 @@
<!--
~ /*
~ * Nextcloud Talk application
~ *
~ * @author Mario Danic
~ * Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
~ *
~ * 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 <http://www.gnu.org/licenses/>.
~ */
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108"
android:autoMirrored="true">
<group android:scaleX="0.08035714"
android:scaleY="0.08035714">
<path android:fillType="evenOdd"
android:pathData="M0,0h1344v1344h-1344z" android:strokeLineJoin="round">
<aapt:attr name="android:fillColor">
<gradient android:endX="1343.9999"
android:endY="1.2959057E-4" android:startX="163.34073"
android:startY="1344.0002" android:type="linear">
<item android:color="#FF0082C9" android:offset="0"/>
<item android:color="#FF1CAFFF" android:offset="1"/>
</gradient>
</aapt:attr>
</path>
</group>
</vector>

View File

@ -0,0 +1,31 @@
<!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:fillType="nonZero"
android:pathData="M7.4167,6C7.1833,6 7,6.1833 7,6.4167L7,17.25C7,17.4833 7.1833,17.6667 7.4167,17.6667L16.5833,17.6667C16.8167,17.6667 17,17.4833 17,17.25L17,8.5L14.5,6L7.4167,6ZM8.6667,7.6667L13.6667,7.6667L13.6667,8.5L8.6667,8.5L8.6667,7.6667ZM8.6667,10.1667L12.8333,10.1667L12.8333,11L8.6667,11L8.6667,10.1667ZM8.6667,12.6667L15.3333,12.6667L15.3333,13.5L8.6667,13.5L8.6667,12.6667ZM8.6667,15.1667L12,15.1667L12,16L8.6667,16L8.6667,15.1667Z" />
</vector>

View File

@ -0,0 +1,31 @@
<!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:fillType="nonZero"
android:pathData="M12.729,5C11.044,5 9.833,6.38 9.833,7.702C9.833,9.054 9.93,10.019 10.605,11.08C10.822,11.36 11.074,11.418 11.281,11.659C11.411,12.142 11.513,12.625 11.378,13.107C10.957,13.255 10.557,13.428 10.152,13.59C9.66,13.326 9.09,13.107 8.598,12.914C8.53,12.644 8.579,12.444 8.646,12.19C8.762,12.07 8.868,12.016 8.994,11.901C9.351,11.466 9.37,10.733 9.37,10.212C9.37,9.44 8.675,8.861 7.922,8.861C7.082,8.861 6.474,9.555 6.474,10.212L6.455,10.212C6.455,10.887 6.503,11.37 6.841,11.901C6.938,12.045 7.075,12.07 7.179,12.19C7.244,12.431 7.296,12.673 7.227,12.914C6.61,13.129 6.027,13.397 5.49,13.686C5.085,13.976 5.265,13.862 5.007,14.796C4.888,15.279 6.262,15.501 7.247,15.578C7.198,15.843 7.131,16.196 6.938,16.871C6.629,18.078 11.139,18.512 12.729,18.512C15.074,18.512 18.822,18.072 18.501,16.871C17.999,14.999 18.3,15.221 17.555,14.651C16.503,14.02 15.188,13.525 14.08,13.107C13.935,12.57 14.041,12.171 14.177,11.659C14.403,11.418 14.659,11.312 14.872,11.08C15.537,10.227 15.624,8.741 15.624,7.702C15.624,6.172 14.244,5 12.729,5Z" />
</vector>

View File

@ -0,0 +1,31 @@
<!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:fillType="nonZero"
android:pathData="M13,5.921L9.818,9.105C9.111,9.812 8.781,10.723 8.83,11.562C8.88,12.401 9.263,13.146 9.818,13.701L11.23,12.285C10.663,11.717 10.686,11.065 11.232,10.519L14.414,7.337C14.939,6.812 15.664,6.814 16.186,7.335C16.668,7.891 16.713,8.574 16.182,9.105L15.362,9.925C15.917,10.71 16.007,11.291 15.955,12.16L17.596,10.519C18.833,9.282 18.833,7.154 17.596,5.917C16.36,4.681 14.254,4.706 13,5.921ZM13.707,9.806L12.293,11.224L12.297,11.224C12.847,11.774 12.804,12.482 12.293,12.994L9.111,16.175C8.415,16.767 7.813,16.646 7.342,16.175C6.715,15.549 6.842,14.907 7.342,14.407L8.192,13.56C7.636,12.777 7.543,12.195 7.594,11.328L5.928,12.994C4.689,14.233 4.692,16.354 5.928,17.589C7.163,18.825 9.29,18.825 10.526,17.589L13.707,14.407C14.416,13.699 14.747,12.789 14.698,11.949C14.65,11.109 14.266,10.362 13.709,9.808L13.707,9.806Z" />
</vector>

View File

@ -0,0 +1,31 @@
<!--
~ Nextcloud Talk application
~
~ @author Andy Scherzinger
~ Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
~
~ 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 <http://www.gnu.org/licenses/>.
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="#ffffff"
android:fillType="nonZero"
android:pathData="M6.6675,8.25C6.2985,8.25 6,8.55 6,8.9175L6,15.0825C6,15.4522 6.3,15.75 6.6675,15.75L17.3325,15.75C17.7015,15.75 18,15.45 18,15.0825L18,8.9175C18,8.5485 17.7,8.25 17.3325,8.25L6.6675,8.25ZM7.23,9.021L11.7922,13.5825L12.1875,13.5825L16.7708,9.021L17.229,9.4792L14.4998,12.249L16.5623,14.3527L16.104,14.811L14.0002,12.7072L12.48,14.2485L11.5215,14.2485L10.0013,12.7072L7.8975,14.8312L7.4385,14.352L9.522,12.2483L6.7725,9.4785L7.23,9.021Z" />
</vector>

View File

@ -21,10 +21,10 @@
<stroke <stroke
android:width="1dp" android:width="1dp"
android:color="@color/colorPrimary" /> android:color="@color/high_emphasis_text" />
<solid <solid
android:color="@color/bg_message_own_reaction" /> android:color="#FFFFFF" />
<padding <padding
android:left="1dp" android:left="1dp"

View File

@ -21,14 +21,15 @@
--> -->
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:fresco="http://schemas.android.com/apk/res-auto" xmlns:fresco="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="72dp" android:layout_height="72dp"
android:layout_margin="4dp" android:layout_margin="4dp"
android:orientation="horizontal" android:orientation="horizontal"
app:cardBackgroundColor="@color/transparent" app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp"> app:cardElevation="0dp"
app:strokeWidth="@dimen/zero">
<RelativeLayout <RelativeLayout
android:layout_width="match_parent" android:layout_width="match_parent"

View File

@ -115,17 +115,6 @@
app:iconSize="@dimen/avatar_size_app_bar" app:iconSize="@dimen/avatar_size_app_bar"
tools:visibility="gone" /> tools:visibility="gone" />
<ProgressBar
android:id="@+id/searchProgressBar"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="4dp"
android:layout_gravity="center"
android:indeterminate="true"
android:indeterminateTint="@color/colorPrimary"
android:scaleType="fitCenter"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
@ -144,16 +133,6 @@
app:titleTextColor="@color/fontAppbar" app:titleTextColor="@color/fontAppbar"
tools:title="@string/nc_app_product_name"> tools:title="@string/nc_app_product_name">
<ProgressBar
android:id="@+id/toolbarProgressBar"
android:layout_width="32dp"
android:layout_height="32dp"
android:layout_gravity="center_vertical|end"
android:layout_marginEnd="8dp"
android:visibility="gone"
android:indeterminateTint="@color/white"
android:scaleType="fitCenter" />
</com.google.android.material.appbar.MaterialToolbar> </com.google.android.material.appbar.MaterialToolbar>
</com.google.android.material.appbar.AppBarLayout> </com.google.android.material.appbar.AppBarLayout>

View File

@ -74,6 +74,7 @@
app:incomingImageTimeTextSize="12sp" app:incomingImageTimeTextSize="12sp"
app:incomingTextColor="@color/nc_incoming_text_default" app:incomingTextColor="@color/nc_incoming_text_default"
app:incomingTextLinkColor="@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:incomingTextSize="@dimen/chat_text_size"
app:incomingTimeTextSize="12sp" app:incomingTimeTextSize="12sp"
app:outcomingBubblePaddingBottom="@dimen/message_bubble_corners_padding" app:outcomingBubblePaddingBottom="@dimen/message_bubble_corners_padding"
@ -84,8 +85,8 @@
app:outcomingDefaultBubblePressedColor="@color/colorPrimary" app:outcomingDefaultBubblePressedColor="@color/colorPrimary"
app:outcomingDefaultBubbleSelectedColor="@color/transparent" app:outcomingDefaultBubbleSelectedColor="@color/transparent"
app:outcomingImageTimeTextSize="12sp" app:outcomingImageTimeTextSize="12sp"
app:outcomingTextColor="@color/nc_outcoming_text_default" app:outcomingTextColor="@color/high_emphasis_text"
app:outcomingTextLinkColor="@color/nc_outcoming_text_default" app:outcomingTextLinkColor="@color/high_emphasis_text"
app:outcomingTextSize="@dimen/chat_text_size" app:outcomingTextSize="@dimen/chat_text_size"
app:outcomingTimeTextSize="12sp" app:outcomingTimeTextSize="12sp"
app:textAutoLink="all" /> app:textAutoLink="all" />

View File

@ -29,8 +29,7 @@
<RelativeLayout <RelativeLayout
android:id="@+id/avatarContainer" android:id="@+id/avatarContainer"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content">
android:paddingBottom="@dimen/standard_padding">
<com.facebook.drawee.view.SimpleDraweeView <com.facebook.drawee.view.SimpleDraweeView
android:id="@+id/avatar_image" android:id="@+id/avatar_image"
@ -60,7 +59,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/userinfo_fullName" android:layout_below="@id/userinfo_fullName"
android:layout_centerHorizontal="true" android:layout_centerHorizontal="true"
android:layout_margin="4dp" android:layout_margin="@dimen/standard_quarter_margin"
android:ellipsize="end" android:ellipsize="end"
android:lines="2" android:lines="2"
android:textColor="@color/medium_emphasis_text" android:textColor="@color/medium_emphasis_text"
@ -72,54 +71,62 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/userinfo_baseurl" android:layout_below="@id/userinfo_baseurl"
android:layout_centerInParent="true" android:layout_centerInParent="true"
android:layout_centerHorizontal="true"
android:orientation="horizontal" android:orientation="horizontal"
android:visibility="invisible" android:visibility="invisible"
tools:visibility="visible"> tools:visibility="visible">
<ImageButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/avatar_upload" android:id="@+id/avatar_upload"
android:layout_width="@dimen/min_size_clickable_area" android:layout_width="wrap_content"
android:layout_height="@dimen/min_size_clickable_area" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/standard_half_margin" android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_half_margin" android:layout_marginRight="@dimen/standard_quarter_margin"
android:background="@drawable/round_corner" android:layout_marginBottom="@dimen/standard_margin"
android:contentDescription="@string/upload_new_avatar_from_device" android:contentDescription="@string/upload_new_avatar_from_device"
android:src="@drawable/upload" android:tint="@android:color/white"
app:tint="@color/black" /> app:elevation="0dp"
app:fabSize="mini"
app:srcCompat="@drawable/upload" />
<ImageButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/avatar_choose" android:id="@+id/avatar_choose"
android:layout_width="@dimen/min_size_clickable_area" android:layout_width="wrap_content"
android:layout_height="@dimen/min_size_clickable_area" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/standard_half_margin" android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_half_margin" android:layout_marginRight="@dimen/standard_quarter_margin"
android:background="@drawable/round_corner" android:layout_marginBottom="@dimen/standard_margin"
android:contentDescription="@string/choose_avatar_from_cloud" android:contentDescription="@string/choose_avatar_from_cloud"
android:src="@drawable/ic_mimetype_folder" android:tint="@android:color/white"
app:tint="@color/colorPrimary" /> app:elevation="0dp"
app:fabSize="mini"
app:srcCompat="@drawable/ic_mimetype_folder" />
<ImageButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/avatar_camera" android:id="@+id/avatar_camera"
android:layout_width="@dimen/min_size_clickable_area" android:layout_width="wrap_content"
android:layout_height="@dimen/min_size_clickable_area" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/standard_half_margin" android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_half_margin" android:layout_marginRight="@dimen/standard_quarter_margin"
android:background="@drawable/round_corner" android:layout_marginBottom="@dimen/standard_margin"
android:contentDescription="@string/set_avatar_from_camera" android:contentDescription="@string/set_avatar_from_camera"
android:src="@drawable/ic_baseline_photo_camera_24" android:tint="@android:color/white"
app:tint="@color/colorPrimary" /> app:elevation="0dp"
app:fabSize="mini"
app:srcCompat="@drawable/ic_baseline_photo_camera_24" />
<ImageButton <com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/avatar_delete" android:id="@+id/avatar_delete"
android:layout_width="@dimen/min_size_clickable_area" android:layout_width="wrap_content"
android:layout_height="@dimen/min_size_clickable_area" android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/standard_half_margin" android:layout_marginLeft="@dimen/standard_quarter_margin"
android:layout_marginRight="@dimen/standard_half_margin" android:layout_marginRight="@dimen/standard_quarter_margin"
android:background="@drawable/round_corner" android:layout_marginBottom="@dimen/standard_margin"
android:contentDescription="@string/delete_avatar" android:contentDescription="@string/delete_avatar"
android:src="@drawable/trashbin" android:tint="@android:color/white"
app:tint="@color/black" /> app:elevation="0dp"
app:fabSize="mini"
app:srcCompat="@drawable/trashbin" />
</LinearLayout> </LinearLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -21,14 +21,15 @@
--> -->
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android" <com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
xmlns:fresco="http://schemas.android.com/apk/res-auto" xmlns:fresco="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="72dp" android:layout_height="72dp"
android:layout_margin="4dp" android:layout_margin="4dp"
android:orientation="horizontal" android:orientation="horizontal"
app:cardBackgroundColor="@color/transparent" app:cardBackgroundColor="@color/transparent"
app:cardElevation="0dp"> app:cardElevation="0dp"
app:strokeWidth="@dimen/zero">
<RelativeLayout <RelativeLayout
tools:background="@color/white" tools:background="@color/white"

View File

@ -44,12 +44,6 @@
app:layout_constraintTop_toBottomOf="@id/current_account" app:layout_constraintTop_toBottomOf="@id/current_account"
tools:visibility="visible"> tools:visibility="visible">
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:layout_marginTop="4dp"
android:background="@color/list_divider_background" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/set_status" android:id="@+id/set_status"
style="@style/Nextcloud.Material.TextButton" style="@style/Nextcloud.Material.TextButton"
@ -62,16 +56,16 @@
android:text="@string/set_status" android:text="@string/set_status"
android:textAlignment="textStart" android:textAlignment="textStart"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="@color/fontAppbar" android:textColor="@color/high_emphasis_text"
android:enabled="false" android:enabled="false"
app:icon="@drawable/ic_edit" app:icon="@drawable/ic_edit"
app:iconGravity="start" app:iconGravity="start"
app:iconPadding="22dp" app:iconPadding="22dp"
app:iconTint="@color/fontAppbar" /> app:iconTint="@color/high_emphasis_text" />
</LinearLayout> </LinearLayout>
<View <View
android:id="@+id/separator_line" android:id="@+id/divider"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="1dp" android:layout_height="1dp"
android:layout_marginTop="4dp" android:layout_marginTop="4dp"
@ -90,7 +84,7 @@
app:layout_constraintBottom_toTopOf="@+id/add_account" app:layout_constraintBottom_toTopOf="@+id/add_account"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/separator_line" app:layout_constraintTop_toBottomOf="@+id/divider"
tools:listitem="@layout/account_item" /> tools:listitem="@layout/account_item" />
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
@ -105,11 +99,11 @@
android:text="@string/nc_account_chooser_add_account" android:text="@string/nc_account_chooser_add_account"
android:textAlignment="textStart" android:textAlignment="textStart"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="@color/fontAppbar" android:textColor="@color/high_emphasis_text"
app:icon="@drawable/ic_account_plus" app:icon="@drawable/ic_account_plus"
app:iconGravity="start" app:iconGravity="start"
app:iconPadding="22dp" app:iconPadding="22dp"
app:iconTint="@color/fontAppbar" app:iconTint="@color/high_emphasis_text"
app:layout_constraintBottom_toTopOf="@+id/manage_settings" app:layout_constraintBottom_toTopOf="@+id/manage_settings"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />
@ -127,11 +121,11 @@
android:text="@string/nc_settings" android:text="@string/nc_settings"
android:textAlignment="textStart" android:textAlignment="textStart"
android:textAllCaps="false" android:textAllCaps="false"
android:textColor="@color/fontAppbar" android:textColor="@color/high_emphasis_text"
app:icon="@drawable/ic_settings" app:icon="@drawable/ic_settings"
app:iconGravity="start" app:iconGravity="start"
app:iconPadding="22dp" app:iconPadding="22dp"
app:iconTint="@color/fontAppbar" app:iconTint="@color/high_emphasis_text"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" /> app:layout_constraintStart_toStartOf="parent" />

View File

@ -26,6 +26,7 @@
tools:background="@color/white"> tools:background="@color/white">
<ProgressBar <ProgressBar
android:id="@+id/poll_loading_progressbar"
android:layout_width="25dp" android:layout_width="25dp"
android:layout_height="25dp"> android:layout_height="25dp">
</ProgressBar> </ProgressBar>

View File

@ -87,6 +87,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" /> app:layout_alignSelf="center" />
<include <include

View File

@ -99,6 +99,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="12:38" /> tools:text="12:38" />

View File

@ -87,7 +87,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="2dp" android:layout_margin="2dp"
android:layout_marginBottom="1dp" android:layout_marginBottom="1dp"
app:cardCornerRadius="8dp" app:cardCornerRadius="@dimen/dialogBorderRadius"
app:cardElevation="2dp" app:cardElevation="2dp"
app:layout_alignSelf="flex_start" app:layout_alignSelf="flex_start"
app:layout_flexGrow="1" app:layout_flexGrow="1"
@ -152,10 +152,11 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="2dp" android:layout_marginStart="2dp"
android:alpha="0.6"
android:autoLink="none" android:autoLink="none"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/warm_grey_four" android:textColor="@color/no_emphasis_text"
android:textColorLink="@color/warm_grey_four" android:textColorLink="@color/no_emphasis_text"
android:textIsSelectable="true" android:textIsSelectable="true"
android:textSize="12sp" android:textSize="12sp"
app:layout_alignSelf="flex_start" app:layout_alignSelf="flex_start"
@ -170,7 +171,8 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginEnd="2dp" android:layout_marginEnd="2dp"
android:textColor="@color/warm_grey_four" android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="12:38" /> tools:text="12:38" />

View File

@ -59,8 +59,9 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_marginBottom="4dp"
android:alpha="0.6"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/textColorMaxContrast" android:textColor="@color/no_emphasis_text"
android:textIsSelectable="false" android:textIsSelectable="false"
android:textSize="12sp" android:textSize="12sp"
tools:text="Jane Doe" /> tools:text="Jane Doe" />
@ -83,6 +84,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_alignSelf="center" /> app:layout_alignSelf="center" />

View File

@ -40,77 +40,79 @@
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
app:roundAsCircle="true" /> app:roundAsCircle="true" />
<com.google.android.flexbox.FlexboxLayout <com.google.android.flexbox.FlexboxLayout
android:id="@id/bubble" android:id="@id/bubble"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginEnd="@dimen/message_incoming_bubble_margin_right"
android:layout_toEndOf="@id/messageUserAvatar"
android:orientation="vertical"
app:alignContent="stretch"
app:alignItems="stretch"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<include
android:id="@+id/message_quote"
layout="@layout/item_message_quote"
android:visibility="gone" />
<androidx.emoji.widget.EmojiTextView
android:id="@+id/messageAuthor"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="wrap_content"
android:layout_marginEnd="@dimen/message_incoming_bubble_margin_right" android:layout_marginBottom="4dp"
android:layout_toEndOf="@id/messageUserAvatar" android:textAlignment="viewStart"
android:orientation="vertical" android:textColor="@color/textColorMaxContrast"
app:alignContent="stretch" android:textSize="12sp" />
app:alignItems="stretch"
app:flexWrap="wrap"
app:justifyContent="flex_end">
<include <LinearLayout
android:id="@+id/message_quote" android:layout_width="match_parent"
layout="@layout/item_message_quote" android:layout_height="wrap_content"
android:visibility="gone" /> android:gravity="center_vertical"
android:orientation="horizontal">
<androidx.emoji.widget.EmojiTextView <ProgressBar
android:id="@+id/messageAuthor" android:id="@+id/progressBar"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginBottom="4dp" android:layout_gravity="center"
android:textAlignment="viewStart" android:visibility="gone" />
android:textColor="@color/textColorMaxContrast"
android:textSize="12sp" />
<LinearLayout <com.google.android.material.button.MaterialButton
android:layout_width="match_parent" android:id="@+id/playPauseBtn"
android:layout_height="wrap_content" style="@style/Widget.AppTheme.Button.IconButton"
android:orientation="horizontal" android:layout_width="48dp"
android:gravity="center_vertical"> android:layout_height="48dp"
android:contentDescription="@string/play_pause_voice_message"
android:visibility="visible"
app:cornerRadius="@dimen/button_corner_radius"
app:icon="@drawable/ic_baseline_play_arrow_voice_message_24"
app:iconSize="40dp"
app:iconTint="@color/nc_incoming_text_default" />
<ProgressBar <SeekBar
android:id="@+id/progressBar" android:id="@+id/seekbar"
android:layout_width="wrap_content" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" tools:progress="50" />
android:visibility="gone"/>
<com.google.android.material.button.MaterialButton </LinearLayout>
android:id="@+id/playPauseBtn"
style="@style/Widget.AppTheme.Button.IconButton"
android:layout_width="48dp"
android:layout_height="48dp"
android:contentDescription="@string/play_pause_voice_message"
android:visibility="visible"
app:cornerRadius="@dimen/button_corner_radius"
app:icon="@drawable/ic_baseline_play_arrow_voice_message_24"
app:iconSize="40dp"
app:iconTint="@color/nc_incoming_text_default" />
<SeekBar <TextView
android:id="@+id/seekbar" android:id="@id/messageTime"
android:layout_width="match_parent" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
tools:progress="50" /> 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="12:38" />
</LinearLayout> <include
android:id="@+id/reactions"
layout="@layout/reactions_inside_message" />
<TextView </com.google.android.flexbox.FlexboxLayout>
android:id="@id/messageTime"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/messageText"
android:layout_marginStart="8dp"
app:layout_alignSelf="center"
tools:text="12:38"/>
<include
android:id="@+id/reactions"
layout="@layout/reactions_inside_message" />
</com.google.android.flexbox.FlexboxLayout>
</RelativeLayout> </RelativeLayout>

View File

@ -58,6 +58,7 @@
android:layout_alignWithParentIfMissing="true" android:layout_alignWithParentIfMissing="true"
android:lineSpacingMultiplier="1.2" android:lineSpacingMultiplier="1.2"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textColorHighlight="@color/nc_grey" android:textColorHighlight="@color/nc_grey"
android:textIsSelectable="false" android:textIsSelectable="false"
tools:text="Talk to you later!" /> tools:text="Talk to you later!" />
@ -68,6 +69,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="10:35" /> tools:text="10:35" />
@ -78,7 +81,8 @@
android:layout_below="@id/messageTime" android:layout_below="@id/messageTime"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:contentDescription="@null" android:contentDescription="@null"
app:layout_alignSelf="center" /> app:layout_alignSelf="center"
app:tint="@color/high_emphasis_text" />
<include <include
android:id="@+id/reactions" android:id="@+id/reactions"

View File

@ -56,14 +56,13 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:contentDescription="@null" android:contentDescription="@null"
android:src="@drawable/ic_baseline_bar_chart_24" android:src="@drawable/ic_baseline_bar_chart_24"
app:tint="@color/nc_outcoming_text_default" /> app:tint="@color/high_emphasis_text" />
<androidx.emoji.widget.EmojiTextView <androidx.emoji.widget.EmojiTextView
android:id="@+id/message_poll_title" android:id="@+id/message_poll_title"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/nc_outcoming_text_default"
android:textStyle="bold" android:textStyle="bold"
tools:text="This is the poll title?" /> tools:text="This is the poll title?" />
@ -75,7 +74,7 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/double_margin_between_elements" android:layout_marginTop="@dimen/double_margin_between_elements"
android:text="@string/message_poll_tap_to_open" android:text="@string/message_poll_tap_to_open"
android:textColor="@color/nc_outcoming_text_default" /> android:textColor="@color/high_emphasis_text" />
<TextView <TextView
android:id="@id/messageTime" android:id="@id/messageTime"
@ -83,7 +82,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:textColor="@color/nc_outcoming_text_default" android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="10:35" /> tools:text="10:35" />
@ -94,8 +94,8 @@
android:layout_below="@id/messageTime" android:layout_below="@id/messageTime"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:contentDescription="@null" android:contentDescription="@null"
android:textColor="@color/nc_outcoming_text_default" app:layout_alignSelf="center"
app:layout_alignSelf="center" /> app:tint="@color/high_emphasis_text" />
<include <include
android:id="@+id/reactions" android:id="@+id/reactions"

View File

@ -77,7 +77,7 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_margin="2dp" android:layout_margin="2dp"
app:cardCornerRadius="8dp" app:cardCornerRadius="@dimen/dialogBorderRadius"
app:cardElevation="2dp" app:cardElevation="2dp"
app:layout_alignSelf="flex_start" app:layout_alignSelf="flex_start"
app:layout_flexGrow="1" app:layout_flexGrow="1"
@ -142,9 +142,10 @@
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="2dp" android:layout_marginStart="2dp"
android:alpha="0.6"
android:autoLink="none" android:autoLink="none"
android:textColor="@color/warm_grey_four" android:textColor="@color/no_emphasis_text"
android:textColorLink="@color/warm_grey_four" android:textColorLink="@color/no_emphasis_text"
android:textIsSelectable="true" android:textIsSelectable="true"
android:textSize="12sp" android:textSize="12sp"
android:visibility="invisible" android:visibility="invisible"
@ -160,7 +161,8 @@
android:layout_alignParentEnd="true" android:layout_alignParentEnd="true"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginEnd="2dp" android:layout_marginEnd="2dp"
android:textColor="@color/warm_grey_four" android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="12:34" /> tools:text="12:34" />

View File

@ -63,6 +63,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="10:35" /> tools:text="10:35" />
@ -74,7 +76,8 @@
android:layout_below="@id/messageTime" android:layout_below="@id/messageTime"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:contentDescription="@null" android:contentDescription="@null"
app:layout_alignSelf="center" /> app:layout_alignSelf="center"
app:tint="@color/high_emphasis_text" />
<include <include
android:id="@+id/reactions" android:id="@+id/reactions"

View File

@ -51,17 +51,17 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal" android:gravity="center_vertical"
android:gravity="center_vertical"> android:orientation="horizontal">
<ProgressBar <ProgressBar
android:id="@+id/progressBar" android:id="@+id/progressBar"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_gravity="center" android:layout_gravity="center"
android:indeterminateTint="@color/nc_outcoming_text_default"
android:progressTint="@color/fontAppbar" android:progressTint="@color/fontAppbar"
android:visibility="gone" android:visibility="gone" />
android:indeterminateTint="@color/nc_outcoming_text_default"/>
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/playPauseBtn" android:id="@+id/playPauseBtn"
@ -70,11 +70,11 @@
android:layout_height="48dp" android:layout_height="48dp"
android:contentDescription="@string/play_pause_voice_message" android:contentDescription="@string/play_pause_voice_message"
android:visibility="visible" android:visibility="visible"
app:rippleColor="#1FFFFFFF"
app:cornerRadius="@dimen/button_corner_radius" app:cornerRadius="@dimen/button_corner_radius"
app:icon="@drawable/ic_baseline_play_arrow_voice_message_24" app:icon="@drawable/ic_baseline_play_arrow_voice_message_24"
app:iconSize="40dp" app:iconSize="40dp"
app:iconTint="@color/nc_outcoming_text_default" /> app:iconTint="@color/high_emphasis_text"
app:rippleColor="#1FFFFFFF" />
<SeekBar <SeekBar
android:id="@+id/seekbar" android:id="@+id/seekbar"
@ -92,6 +92,8 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageText" android:layout_below="@id/messageText"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:alpha="0.6"
android:textColor="@color/no_emphasis_text"
app:layout_alignSelf="center" app:layout_alignSelf="center"
tools:text="10:35" /> tools:text="10:35" />
@ -101,8 +103,9 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_below="@id/messageTime" android:layout_below="@id/messageTime"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:contentDescription="@null"
app:layout_alignSelf="center" app:layout_alignSelf="center"
android:contentDescription="@null" /> app:tint="@color/high_emphasis_text" />
<include <include
android:id="@+id/reactions" android:id="@+id/reactions"

View File

@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?><!-- <?xml version="1.0" encoding="utf-8"?>
<!--
~ Nextcloud Talk application ~ Nextcloud Talk application
~ ~
~ @author Mario Danic ~ @author Mario Danic
@ -34,8 +35,8 @@
android:layout_height="match_parent" android:layout_height="match_parent"
android:layout_alignBottom="@id/flexboxQuoted" android:layout_alignBottom="@id/flexboxQuoted"
android:layout_alignParentStart="true" android:layout_alignParentStart="true"
android:layout_marginEnd="4dp" android:layout_marginEnd="8dp"
android:background="@color/colorPrimary" /> android:background="@color/high_emphasis_text" />
<androidx.emoji.widget.EmojiTextView <androidx.emoji.widget.EmojiTextView
android:id="@+id/quotedMessageAuthor" android:id="@+id/quotedMessageAuthor"
@ -44,9 +45,10 @@
android:layout_alignParentTop="true" android:layout_alignParentTop="true"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:layout_toEndOf="@id/quoteColoredView" android:layout_toEndOf="@id/quoteColoredView"
android:alpha="0.6"
android:ellipsize="end" android:ellipsize="end"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/textColorMaxContrast" android:textColor="@color/no_emphasis_text"
android:textIsSelectable="false" android:textIsSelectable="false"
android:textSize="12sp" android:textSize="12sp"
tools:text="Jane Doe" /> tools:text="Jane Doe" />
@ -85,6 +87,7 @@
android:layout_alignStart="@id/quotedMessageAuthor" android:layout_alignStart="@id/quotedMessageAuthor"
android:lineSpacingMultiplier="1.2" android:lineSpacingMultiplier="1.2"
android:textAlignment="viewStart" android:textAlignment="viewStart"
android:textColor="@color/high_emphasis_text"
android:textIsSelectable="false" android:textIsSelectable="false"
android:textSize="14sp" android:textSize="14sp"
app:layout_alignSelf="flex_start" app:layout_alignSelf="flex_start"
@ -102,9 +105,9 @@
android:layout_centerVertical="true" android:layout_centerVertical="true"
android:layout_marginStart="8dp" android:layout_marginStart="8dp"
android:layout_marginEnd="8dp" android:layout_marginEnd="8dp"
android:background="@drawable/ic_cancel_black_24dp" android:background="@color/transparent"
android:backgroundTint="@color/grey_600"
android:contentDescription="@string/nc_message_quote_cancel_reply" android:contentDescription="@string/nc_message_quote_cancel_reply"
android:src="@drawable/ic_cancel_black_24dp"
android:visibility="gone" android:visibility="gone"
tools:visibility="visible" /> tools:visibility="visible" />

View File

@ -104,17 +104,6 @@
app:iconSize="@dimen/avatar_size_app_bar" app:iconSize="@dimen/avatar_size_app_bar"
tools:visibility="visible" /> tools:visibility="visible" />
<ProgressBar
android:id="@+id/searchProgressBar"
android:layout_width="32dp"
android:layout_height="32dp"
android:padding="4dp"
android:layout_gravity="center"
android:indeterminate="true"
android:indeterminateTint="@color/colorPrimary"
android:scaleType="fitCenter"
android:visibility="gone" />
</FrameLayout> </FrameLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -293,9 +293,12 @@
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="end"> android:gravity="end"
android:paddingStart="@dimen/dialog_padding"
android:paddingEnd="@dimen/dialog_padding"
android:paddingBottom="@dimen/dialog_padding_top_bottom">
<com.google.android.material.button.MaterialButton <com.google.android.material.button.MaterialButton
android:id="@+id/cancel" android:id="@+id/cancel"
style="@style/Button.Borderless" style="@style/Button.Borderless"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -35,6 +35,7 @@
<color name="refresh_spinner_background">#222222</color> <color name="refresh_spinner_background">#222222</color>
<!-- general text colors --> <!-- general text colors -->
<color name="no_emphasis_text">#ffffff</color>
<color name="high_emphasis_text">#deffffff</color> <color name="high_emphasis_text">#deffffff</color>
<color name="medium_emphasis_text">#99ffffff</color> <color name="medium_emphasis_text">#99ffffff</color>
<color name="low_emphasis_text">#61ffffff</color> <color name="low_emphasis_text">#61ffffff</color>
@ -71,7 +72,7 @@
<color name="nc_shimmer_default_color">#4B4B4B</color> <color name="nc_shimmer_default_color">#4B4B4B</color>
<color name="nc_shimmer_darker_color">#282828</color> <color name="nc_shimmer_darker_color">#282828</color>
<color name="list_divider_background">#222222</color> <color name="list_divider_background">#1FFFFFFF</color>
<color name="grey_200">#818181</color> <color name="grey_200">#818181</color>
<color name="dialog_background">#353535</color> <color name="dialog_background">#353535</color>

View File

@ -36,6 +36,7 @@
<color name="refresh_spinner_background">#ffffff</color> <color name="refresh_spinner_background">#ffffff</color>
<!-- general text colors --> <!-- general text colors -->
<color name="no_emphasis_text">#000000</color>
<color name="high_emphasis_text">#de000000</color> <color name="high_emphasis_text">#de000000</color>
<color name="medium_emphasis_text">#99000000</color> <color name="medium_emphasis_text">#99000000</color>
<color name="low_emphasis_text">#61000000</color> <color name="low_emphasis_text">#61000000</color>
@ -99,7 +100,7 @@
<color name="camera_bg_tint">#99121212</color> <color name="camera_bg_tint">#99121212</color>
<color name="list_divider_background">#eeeeee</color> <color name="list_divider_background">#1F121212</color>
<color name="grey_200">#EEEEEE</color> <color name="grey_200">#EEEEEE</color>
<!-- this is just a helper for status icon background because getting the background color of a dialog is not <!-- this is just a helper for status icon background because getting the background color of a dialog is not

View File

@ -37,8 +37,8 @@
<dimen name="avatar_size_big">96dp</dimen> <dimen name="avatar_size_big">96dp</dimen>
<dimen name="chat_text_size">14sp</dimen> <dimen name="chat_text_size">14sp</dimen>
<dimen name="message_bubble_corners_radius">6dp</dimen> <dimen name="message_bubble_corners_radius">@dimen/dialogBorderRadius</dimen>
<dimen name="message_bubble_corners_padding">8dp</dimen> <dimen name="message_bubble_corners_padding">16dp</dimen>
<dimen name="geocoding_result_text_size">18sp</dimen> <dimen name="geocoding_result_text_size">18sp</dimen>
@ -74,6 +74,8 @@
<dimen name="standard_eighth_margin">2dp</dimen> <dimen name="standard_eighth_margin">2dp</dimen>
<dimen name="scope_padding">12dp</dimen> <dimen name="scope_padding">12dp</dimen>
<dimen name="dialogBorderRadius">28dp</dimen>
<dimen name="default_checkbox_dialog_start_margin">18dp</dimen> <dimen name="default_checkbox_dialog_start_margin">18dp</dimen>
<dimen name="mediatab_file_icon_size">50dp</dimen> <dimen name="mediatab_file_icon_size">50dp</dimen>

View File

@ -23,7 +23,7 @@
<resources> <resources>
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="AppTheme" parent="Theme.MaterialComponents.DayNight.NoActionBar.Bridge"> <style name="AppTheme" parent="Theme.Material3.DayNight.NoActionBar">
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="colorPrimary">@color/colorPrimary</item> <item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item> <item name="colorPrimaryDark">@color/colorPrimaryDark</item>
@ -42,10 +42,12 @@
<item name="seekBarStyle">@style/Nextcloud.Material.Incoming.SeekBar</item> <item name="seekBarStyle">@style/Nextcloud.Material.Incoming.SeekBar</item>
<item name="bottomSheetDialogTheme">@style/ThemeOverlay.App.BottomSheetDialog</item> <item name="bottomSheetDialogTheme">@style/ThemeOverlay.App.BottomSheetDialog</item>
<item name="popupMenuStyle">@style/ChatSendButtonMenu</item> <item name="popupMenuStyle">@style/ChatSendButtonMenu</item>
<item name="dialogCornerRadius">@dimen/dialogBorderRadius</item>
</style> </style>
<style name="ThemeOverlay.AppTheme.PopupMenu" parent="ThemeOverlay.MaterialComponents.Dark"> <style name="ThemeOverlay.AppTheme.PopupMenu" parent="ThemeOverlay.Material3.Dark">
<item name="android:colorBackground">@color/bg_default</item> <item name="android:colorBackground">@color/bg_default</item>
<item name="colorSurface">@color/bg_default</item>
<item name="android:textColorPrimary">@color/high_emphasis_text</item> <item name="android:textColorPrimary">@color/high_emphasis_text</item>
<item name="android:textColor">@color/high_emphasis_text</item> <item name="android:textColor">@color/high_emphasis_text</item>
<item name="android:textColorSecondary">@color/fontAppbar</item> <item name="android:textColorSecondary">@color/fontAppbar</item>
@ -53,7 +55,7 @@
<item name="iconTint">@color/fontAppbar</item> <item name="iconTint">@color/fontAppbar</item>
</style> </style>
<style name="ChatSendButtonMenu" parent="@style/Widget.AppCompat.PopupMenu"> <style name="ChatSendButtonMenu" parent="@style/Widget.Material3.PopupMenu">
<item name="android:dropDownVerticalOffset">-90dp</item> <item name="android:dropDownVerticalOffset">-90dp</item>
<item name="android:colorPrimary">@color/fg_inverse</item> <item name="android:colorPrimary">@color/fg_inverse</item>
<item name="android:textColorSecondary">@color/fontAppbar</item> <item name="android:textColorSecondary">@color/fontAppbar</item>
@ -65,16 +67,16 @@
<style name="CallButtonMenu" parent="@style/ChatSendButtonMenu" /> <style name="CallButtonMenu" parent="@style/ChatSendButtonMenu" />
<style name="ThemeOverlay.App.BottomSheetDialog" parent="ThemeOverlay.MaterialComponents.DayNight.BottomSheetDialog"> <style name="ThemeOverlay.App.BottomSheetDialog" parent="ThemeOverlay.Material3.DayNight.BottomSheetDialog">
<item name="bottomSheetStyle">@style/Talk.BottomSheetDialog</item> <item name="bottomSheetStyle">@style/Talk.BottomSheetDialog</item>
</style> </style>
<style name="Talk.BottomSheetDialog" parent="Widget.MaterialComponents.BottomSheet.Modal"> <style name="Talk.BottomSheetDialog" parent="Widget.Material3.BottomSheet.Modal">
<item name="backgroundTint">@color/bg_bottom_sheet</item> <item name="backgroundTint">@color/bg_bottom_sheet</item>
<item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item> <item name="shapeAppearanceOverlay">@style/CustomShapeAppearanceBottomSheetDialog</item>
</style> </style>
<style name="TransparentTheme" parent="Theme.MaterialComponents.NoActionBar.Bridge"> <style name="TransparentTheme" parent="Theme.MaterialComponents.NoActionBar">
<item name="android:windowNoTitle">true</item> <item name="android:windowNoTitle">true</item>
<item name="android:windowBackground">@android:color/background_dark</item> <item name="android:windowBackground">@android:color/background_dark</item>
<item name="android:colorBackgroundCacheHint">@null</item> <item name="android:colorBackgroundCacheHint">@null</item>
@ -109,11 +111,12 @@
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
</style> </style>
<style name="appActionBarPopupMenu" parent="@style/Widget.AppCompat.PopupMenu.Overflow"> <style name="appActionBarPopupMenu" parent="@style/Widget.Material3.PopupMenu.Overflow">
<item name="android:colorPrimary">@color/fg_inverse</item> <item name="android:colorPrimary">@color/fg_inverse</item>
<item name="android:textColorSecondary">@color/fontAppbar</item> <item name="android:textColorSecondary">@color/fontAppbar</item>
<item name="android:itemBackground">@color/appbar</item> <item name="android:itemBackground">@color/appbar</item>
<item name="android:background">@color/appbar</item> <item name="android:background">@color/appbar</item>
<item name="android:backgroundTint">@color/appbar</item>
<item name="android:textColor">@color/high_emphasis_text</item> <item name="android:textColor">@color/high_emphasis_text</item>
<item name="iconTint">@color/fontAppbar</item> <item name="iconTint">@color/fontAppbar</item>
</style> </style>
@ -134,7 +137,7 @@
<item name="searchHintIcon">@null</item> <item name="searchHintIcon">@null</item>
</style> </style>
<style name="Button" parent="Widget.MaterialComponents.Button.UnelevatedButton"> <style name="Button" parent="Widget.Material3.Button.UnelevatedButton">
<item name="colorButtonNormal">@color/colorPrimary</item> <item name="colorButtonNormal">@color/colorPrimary</item>
<item name="android:textColor">@color/white</item> <item name="android:textColor">@color/white</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
@ -150,7 +153,7 @@
<item name="android:layout_gravity">center_vertical</item> <item name="android:layout_gravity">center_vertical</item>
</style> </style>
<style name="Widget.AppTheme.Button.IconButton" parent="Widget.MaterialComponents.Button.TextButton"> <style name="Widget.AppTheme.Button.IconButton" parent="Widget.Material3.Button.TextButton">
<item name="android:minWidth">0dp</item> <item name="android:minWidth">0dp</item>
<item name="android:insetLeft">0dp</item> <item name="android:insetLeft">0dp</item>
<item name="android:insetTop">0dp</item> <item name="android:insetTop">0dp</item>
@ -160,14 +163,14 @@
<item name="iconPadding">0dp</item> <item name="iconPadding">0dp</item>
</style> </style>
<style name="Button.Borderless" parent="Widget.MaterialComponents.Button.TextButton"> <style name="Button.Borderless" parent="Widget.Material3.Button.TextButton">
<item name="android:textColor">@drawable/borderless_btn</item> <item name="android:textColor">@drawable/borderless_btn</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>
<item name="android:typeface">sans</item> <item name="android:typeface">sans</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
</style> </style>
<style name="Widget.App.Login.TextInputLayout" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox"> <style name="Widget.App.Login.TextInputLayout" parent="Widget.Material3.TextInputLayout.OutlinedBox">
<item name="colorControlActivated">@color/white</item> <item name="colorControlActivated">@color/white</item>
<item name="colorControlHighlight">@color/white</item> <item name="colorControlHighlight">@color/white</item>
<item name="materialThemeOverlay">@style/ThemeOverlay.App.Login.TextInputLayout</item> <item name="materialThemeOverlay">@style/ThemeOverlay.App.Login.TextInputLayout</item>
@ -185,7 +188,7 @@
<item name="editTextStyle">@style/Widget.MaterialComponents.TextInputEditText.OutlinedBox</item> <item name="editTextStyle">@style/Widget.MaterialComponents.TextInputEditText.OutlinedBox</item>
</style> </style>
<style name="TextInputLayoutLogin" parent="Widget.MaterialComponents.TextInputLayout.OutlinedBox"> <style name="TextInputLayoutLogin" parent="Widget.Material3.TextInputLayout.OutlinedBox">
<item name="boxStrokeColor">@color/white</item> <item name="boxStrokeColor">@color/white</item>
<item name="boxStrokeErrorColor">@color/white</item> <item name="boxStrokeErrorColor">@color/white</item>
<item name="hintTextAppearance">@style/HintTextLogin</item> <item name="hintTextAppearance">@style/HintTextLogin</item>
@ -237,7 +240,7 @@
<item name="android:navigationBarColor">@color/grey950</item> <item name="android:navigationBarColor">@color/grey950</item>
</style> </style>
<style name="Nextcloud.Material.TextButton" parent="Widget.MaterialComponents.Button.TextButton.Icon"> <style name="Nextcloud.Material.TextButton" parent="Widget.Material3.Button.TextButton.Icon">
<item name="android:typeface">sans</item> <item name="android:typeface">sans</item>
<item name="android:textStyle">bold</item> <item name="android:textStyle">bold</item>
</style> </style>
@ -263,7 +266,7 @@
<item name="cornerSizeBottomLeft">0dp</item> <item name="cornerSizeBottomLeft">0dp</item>
</style> </style>
<style name="OutlinedButton" parent="Widget.MaterialComponents.Button.OutlinedButton"> <style name="OutlinedButton" parent="Widget.Material3.Button.OutlinedButton">
<item name="colorAccent">@color/transparent</item> <item name="colorAccent">@color/transparent</item>
<item name="android:textColor">@color/colorPrimaryDark</item> <item name="android:textColor">@color/colorPrimaryDark</item>
<item name="android:textAllCaps">false</item> <item name="android:textAllCaps">false</item>

Some files were not shown because too many files have changed in this diff Show More