diff --git a/app/build.gradle b/app/build.gradle
index 3e85345768..3659bea02e 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -27,7 +27,7 @@ configurations.all {
}
dependencies {
- implementation 'androidx.appcompat:appcompat:1.2.0'
+ implementation 'androidx.appcompat:appcompat:1.3.1'
implementation 'androidx.recyclerview:recyclerview:1.1.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'com.google.android:flexbox:2.0.1'
@@ -157,8 +157,8 @@ dependencies {
testImplementation 'org.robolectric:shadows-multidex:4.4'
}
-def canonicalVersionCode = 303
-def canonicalVersionName = "1.15.4"
+def canonicalVersionCode = 307
+def canonicalVersionName = "1.16.0"
def postFixSize = 10
def abiPostFix = ['armeabi-v7a' : 1,
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index eddee7e844..681fc00c17 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -140,6 +140,12 @@
android:name="org.thoughtcrime.securesms.preferences.QRCodeActivity"
android:screenOrientation="portrait"
android:theme="@style/Theme.Session.DayNight.FlatActionBar" />
+
+
+
+ android:theme="@style/Theme.Session.DayNight">
+ android:theme="@style/Theme.Session.DayNight" />
+
diff --git a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
index dad5b09288..01bc1f38ae 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/ApplicationContext.java
@@ -85,7 +85,6 @@ import org.thoughtcrime.securesms.sskenvironment.ProfileManager;
import org.thoughtcrime.securesms.sskenvironment.ReadReceiptManager;
import org.thoughtcrime.securesms.sskenvironment.TypingStatusRepository;
import org.thoughtcrime.securesms.util.Broadcaster;
-import org.thoughtcrime.securesms.util.UiModeUtilities;
import org.thoughtcrime.securesms.util.dynamiclanguage.LocaleParseHelper;
import org.thoughtcrime.securesms.webrtc.CallMessageProcessor;
import org.webrtc.PeerConnectionFactory;
@@ -165,6 +164,10 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
return (ApplicationContext) context.getApplicationContext();
}
+ public TextSecurePreferences getPrefs() {
+ return textSecurePreferences;
+ }
+
public DatabaseComponent getDatabaseComponent() {
return EntryPoints.get(getApplicationContext(), DatabaseComponent.class);
}
@@ -220,7 +223,6 @@ public class ApplicationContext extends Application implements DefaultLifecycleO
if (userPublicKey != null) {
registerForFCMIfNeeded(false);
}
- UiModeUtilities.setupUiModeToUserSelected(this);
initializeExpiringMessageManager();
initializeTypingStatusRepository();
initializeTypingStatusSender();
diff --git a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
index d969dcb704..4280607ea2 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/BaseActionBarActivity.java
@@ -1,44 +1,103 @@
package org.thoughtcrime.securesms;
+import static org.session.libsession.utilities.TextSecurePreferences.SELECTED_ACCENT_COLOR;
+
import android.app.ActivityManager;
import android.content.Context;
+import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.WindowManager;
+import androidx.annotation.Nullable;
+import androidx.annotation.StyleRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import org.session.libsession.utilities.TextSecurePreferences;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageActivityHelper;
import org.session.libsession.utilities.dynamiclanguage.DynamicLanguageContextWrapper;
+import org.thoughtcrime.securesms.util.ActivityUtilitiesKt;
+import org.thoughtcrime.securesms.util.ThemeState;
+import org.thoughtcrime.securesms.util.UiModeUtilities;
import network.loki.messenger.R;
public abstract class BaseActionBarActivity extends AppCompatActivity {
private static final String TAG = BaseActionBarActivity.class.getSimpleName();
+ private ThemeState currentThemeState;
+
+ private TextSecurePreferences getPreferences() {
+ ApplicationContext appContext = (ApplicationContext) getApplicationContext();
+ return appContext.textSecurePreferences;
+ }
+
+ @StyleRes
+ public int getDesiredTheme() {
+ ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences());
+ int userSelectedTheme = themeState.getTheme();
+ if (themeState.getFollowSystem()) {
+ // do light or dark based on the selected theme
+ boolean isDayUi = UiModeUtilities.isDayUiMode(this);
+ if (userSelectedTheme == R.style.Ocean_Dark || userSelectedTheme == R.style.Ocean_Light) {
+ return isDayUi ? R.style.Ocean_Light : R.style.Ocean_Dark;
+ } else {
+ return isDayUi ? R.style.Classic_Light : R.style.Classic_Dark;
+ }
+ } else {
+ return userSelectedTheme;
+ }
+ }
+
+ @StyleRes @Nullable
+ public Integer getAccentTheme() {
+ if (!getPreferences().hasPreference(SELECTED_ACCENT_COLOR)) return null;
+ ThemeState themeState = ActivityUtilitiesKt.themeState(getPreferences());
+ return themeState.getAccentStyle();
+ }
+
+ @Override
+ public Resources.Theme getTheme() {
+ // New themes
+ Resources.Theme modifiedTheme = super.getTheme();
+ modifiedTheme.applyStyle(getDesiredTheme(), true);
+ Integer accentTheme = getAccentTheme();
+ if (accentTheme != null) {
+ modifiedTheme.applyStyle(accentTheme, true);
+ }
+ currentThemeState = ActivityUtilitiesKt.themeState(getPreferences());
+ return modifiedTheme;
+ }
@Override
protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeButtonEnabled(true);
}
-
- super.onCreate(savedInstanceState);
}
@Override
protected void onResume() {
super.onResume();
- initializeScreenshotSecurity();
+ initializeScreenshotSecurity(true);
DynamicLanguageActivityHelper.recreateIfNotInCorrectLanguage(this, TextSecurePreferences.getLanguage(this));
String name = getResources().getString(R.string.app_name);
Bitmap icon = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground);
int color = getResources().getColor(R.color.app_icon_background);
setTaskDescription(new ActivityManager.TaskDescription(name, icon, color));
+ if (!currentThemeState.equals(ActivityUtilitiesKt.themeState(getPreferences()))) {
+ recreate();
+ }
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ initializeScreenshotSecurity(false);
}
@Override
@@ -49,11 +108,15 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
return true;
}
- private void initializeScreenshotSecurity() {
- if (TextSecurePreferences.isScreenSecurityEnabled(this)) {
+ private void initializeScreenshotSecurity(boolean isResume) {
+ if (!isResume) {
getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
} else {
- getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ if (TextSecurePreferences.isScreenSecurityEnabled(this)) {
+ getWindow().addFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ } else {
+ getWindow().clearFlags(WindowManager.LayoutParams.FLAG_SECURE);
+ }
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt
new file mode 100644
index 0000000000..94c7517eb0
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/attachments/ScreenshotObserver.kt
@@ -0,0 +1,78 @@
+package org.thoughtcrime.securesms.attachments
+
+import android.content.Context
+import android.database.ContentObserver
+import android.net.Uri
+import android.os.Build
+import android.os.Handler
+import android.provider.MediaStore
+import androidx.annotation.RequiresApi
+
+class ScreenshotObserver(private val context: Context, handler: Handler, private val screenshotTriggered: ()->Unit): ContentObserver(handler) {
+
+ override fun onChange(selfChange: Boolean, uri: Uri?) {
+ super.onChange(selfChange, uri)
+ uri ?: return
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
+ queryRelativeDataColumn(uri)
+ } else {
+ queryDataColumn(uri)
+ }
+ }
+
+ private val cache = mutableSetOf()
+
+ private fun queryDataColumn(uri: Uri) {
+ val projection = arrayOf(
+ MediaStore.Images.Media.DATA
+ )
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val dataColumn = cursor.getColumnIndex(MediaStore.Images.Media.DATA)
+ while (cursor.moveToNext()) {
+ val path = cursor.getString(dataColumn)
+ if (path.contains("screenshot", true)) {
+ if (cache.add(uri.hashCode())) {
+ screenshotTriggered()
+ }
+ }
+ }
+ }
+ }
+
+ @RequiresApi(Build.VERSION_CODES.Q)
+ private fun queryRelativeDataColumn(uri: Uri) {
+ val projection = arrayOf(
+ MediaStore.Images.Media.DISPLAY_NAME,
+ MediaStore.Images.Media.RELATIVE_PATH
+ )
+ context.contentResolver.query(
+ uri,
+ projection,
+ null,
+ null,
+ null
+ )?.use { cursor ->
+ val relativePathColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.RELATIVE_PATH)
+ val displayNameColumn =
+ cursor.getColumnIndex(MediaStore.Images.Media.DISPLAY_NAME)
+ while (cursor.moveToNext()) {
+ val name = cursor.getString(displayNameColumn)
+ val relativePath = cursor.getString(relativePathColumn)
+ if (name.contains("screenshot", true) or
+ relativePath.contains("screenshot", true)) {
+ if (cache.add(uri.hashCode())) {
+ screenshotTriggered()
+ }
+ }
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt
index 4797bb3edd..0ded9f346e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/ProfilePictureView.kt
@@ -107,7 +107,7 @@ class ProfilePictureView @JvmOverloads constructor(
if (profilePicturesCache.containsKey(publicKey) && profilePicturesCache[publicKey] == recipient.profileAvatar) return
val signalProfilePicture = recipient.contactPhoto
val avatar = (signalProfilePicture as? ProfileContactPhoto)?.avatarObject
- val placeholder = PlaceholderAvatarPhoto(publicKey, displayName ?: "${publicKey.take(4)}...${publicKey.takeLast(4)}")
+ val placeholder = PlaceholderAvatarPhoto(context, publicKey, displayName ?: "${publicKey.take(4)}...${publicKey.takeLast(4)}")
if (signalProfilePicture != null && avatar != "0" && avatar != "") {
glide.clear(imageView)
glide.load(signalProfilePicture)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/QuoteView.java b/app/src/main/java/org/thoughtcrime/securesms/components/QuoteView.java
deleted file mode 100644
index 6ffb3dde97..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/components/QuoteView.java
+++ /dev/null
@@ -1,304 +0,0 @@
-package org.thoughtcrime.securesms.components;
-
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.os.Build;
-import android.text.TextUtils;
-import android.util.AttributeSet;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.FrameLayout;
-import android.widget.ImageView;
-import android.widget.TextView;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.annotation.RequiresApi;
-
-import com.annimon.stream.Stream;
-import com.bumptech.glide.load.engine.DiskCacheStrategy;
-
-import org.session.libsession.messaging.contacts.Contact;
-import org.session.libsession.messaging.sending_receiving.attachments.Attachment;
-import org.session.libsession.utilities.TextSecurePreferences;
-import org.session.libsession.utilities.ThemeUtil;
-import org.session.libsession.utilities.Util;
-import org.session.libsession.utilities.recipients.Recipient;
-import org.session.libsession.utilities.recipients.RecipientModifiedListener;
-import org.thoughtcrime.securesms.database.SessionContactDatabase;
-import org.thoughtcrime.securesms.dependencies.DatabaseComponent;
-import org.thoughtcrime.securesms.mms.DecryptableStreamUriLoader.DecryptableUri;
-import org.thoughtcrime.securesms.mms.GlideRequests;
-import org.thoughtcrime.securesms.mms.Slide;
-import org.thoughtcrime.securesms.mms.SlideDeck;
-import org.thoughtcrime.securesms.util.UiModeUtilities;
-
-import java.util.List;
-
-import network.loki.messenger.R;
-
-public class QuoteView extends FrameLayout implements RecipientModifiedListener {
-
- private static final String TAG = QuoteView.class.getSimpleName();
-
- private static final int MESSAGE_TYPE_PREVIEW = 0;
- private static final int MESSAGE_TYPE_OUTGOING = 1;
- private static final int MESSAGE_TYPE_INCOMING = 2;
-
- private ViewGroup mainView;
- private ViewGroup footerView;
- private TextView authorView;
- private TextView bodyView;
- private ImageView quoteBarView;
- private ImageView thumbnailView;
- private View attachmentVideoOverlayView;
- private ViewGroup attachmentContainerView;
- private TextView attachmentNameView;
- private ImageView dismissView;
-
- private long id;
- private Recipient author;
- private String body;
- private Recipient conversationRecipient;
- private TextView mediaDescriptionText;
- private TextView missingLinkText;
- private SlideDeck attachments;
- private int messageType;
- private int largeCornerRadius;
- private int smallCornerRadius;
- private CornerMask cornerMask;
-
-
- public QuoteView(Context context) {
- super(context);
- initialize(null);
- }
-
- public QuoteView(Context context, AttributeSet attrs) {
- super(context, attrs);
- initialize(attrs);
- }
-
- public QuoteView(Context context, AttributeSet attrs, int defStyleAttr) {
- super(context, attrs, defStyleAttr);
- initialize(attrs);
- }
-
- @RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
- public QuoteView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
- super(context, attrs, defStyleAttr, defStyleRes);
- initialize(attrs);
- }
-
- private void initialize(@Nullable AttributeSet attrs) {
- inflate(getContext(), R.layout.quote_view, this);
-
- this.mainView = findViewById(R.id.quote_main);
- this.footerView = findViewById(R.id.quote_missing_footer);
- this.authorView = findViewById(R.id.quote_author);
- this.bodyView = findViewById(R.id.quote_text);
- this.quoteBarView = findViewById(R.id.quote_bar);
- this.thumbnailView = findViewById(R.id.quote_thumbnail);
- this.attachmentVideoOverlayView = findViewById(R.id.quote_video_overlay);
- this.attachmentContainerView = findViewById(R.id.quote_attachment_container);
- this.attachmentNameView = findViewById(R.id.quote_attachment_name);
- this.dismissView = findViewById(R.id.quote_dismiss);
- this.mediaDescriptionText = findViewById(R.id.media_type);
- this.missingLinkText = findViewById(R.id.quote_missing_text);
- this.largeCornerRadius = getResources().getDimensionPixelSize(R.dimen.quote_corner_radius_bottom);
- this.smallCornerRadius = getResources().getDimensionPixelSize(R.dimen.quote_corner_radius_bottom);
-
- cornerMask = new CornerMask(this);
- cornerMask.setRadii(largeCornerRadius, largeCornerRadius, smallCornerRadius, smallCornerRadius);
-
- if (attrs != null) {
- TypedArray typedArray = getContext().getTheme().obtainStyledAttributes(attrs, R.styleable.QuoteView, 0, 0);
- int primaryColor = typedArray.getColor(R.styleable.QuoteView_quote_colorPrimary, Color.BLACK);
- int secondaryColor = typedArray.getColor(R.styleable.QuoteView_quote_colorSecondary, Color.BLACK);
- messageType = typedArray.getInt(R.styleable.QuoteView_message_type, 0);
- typedArray.recycle();
-
- dismissView.setVisibility(messageType == MESSAGE_TYPE_PREVIEW ? VISIBLE : GONE);
-
- authorView.setTextColor(primaryColor);
- bodyView.setTextColor(primaryColor);
- attachmentNameView.setTextColor(primaryColor);
- mediaDescriptionText.setTextColor(secondaryColor);
- missingLinkText.setTextColor(primaryColor);
-
- if (messageType == MESSAGE_TYPE_PREVIEW) {
- int radius = getResources().getDimensionPixelOffset(R.dimen.quote_corner_radius_preview);
- cornerMask.setTopLeftRadius(radius);
- cornerMask.setTopRightRadius(radius);
- }
- }
-
- dismissView.setOnClickListener(view -> setVisibility(GONE));
- }
-
- @Override
- protected void dispatchDraw(Canvas canvas) {
- super.dispatchDraw(canvas);
- cornerMask.mask(canvas);
- }
-
- public void setQuote(GlideRequests glideRequests,
- long id,
- @NonNull Recipient author,
- @Nullable String body,
- boolean originalMissing,
- @NonNull SlideDeck attachments,
- @NonNull Recipient conversationRecipient)
- {
- if (this.author != null) this.author.removeListener(this);
-
- this.id = id;
- this.author = author;
- this.body = body;
- this.attachments = attachments;
- this.conversationRecipient = conversationRecipient;
-
- author.addListener(this);
- setQuoteAuthor(author);
- setQuoteText(body, attachments);
- setQuoteAttachment(glideRequests, attachments);
- setQuoteMissingFooter(originalMissing);
- }
-
- public void setTopCornerSizes(boolean topLeftLarge, boolean topRightLarge) {
- cornerMask.setTopLeftRadius(topLeftLarge ? largeCornerRadius : smallCornerRadius);
- cornerMask.setTopRightRadius(topRightLarge ? largeCornerRadius : smallCornerRadius);
- }
-
- public void dismiss() {
- if (this.author != null) this.author.removeListener(this);
-
- this.id = 0;
- this.author = null;
- this.body = null;
-
- setVisibility(GONE);
- }
-
- @Override
- public void onModified(Recipient recipient) {
- Util.runOnMain(() -> {
- if (recipient == author) {
- setQuoteAuthor(recipient);
- }
- });
- }
-
- private void setQuoteAuthor(@NonNull Recipient author) {
- boolean outgoing = messageType != MESSAGE_TYPE_INCOMING;
- boolean isOwnNumber = Util.isOwnNumber(getContext(), author.getAddress().serialize());
-
- String quoteeDisplayName;
-
- String senderHexEncodedPublicKey = author.getAddress().serialize();
- if (senderHexEncodedPublicKey.equalsIgnoreCase(TextSecurePreferences.getLocalNumber(getContext()))) {
- quoteeDisplayName = TextSecurePreferences.getProfileName(getContext());
- } else {
- SessionContactDatabase contactDB = DatabaseComponent.get(getContext()).sessionContactDatabase();
- Contact contact = contactDB.getContactWithSessionID(senderHexEncodedPublicKey);
- if (contact != null) {
- Contact.ContactContext context = (this.conversationRecipient.isOpenGroupRecipient()) ? Contact.ContactContext.OPEN_GROUP : Contact.ContactContext.REGULAR;
- quoteeDisplayName = contact.displayName(context);
- } else {
- quoteeDisplayName = senderHexEncodedPublicKey;
- }
- }
-
- authorView.setText(isOwnNumber ? getContext().getString(R.string.QuoteView_you) : quoteeDisplayName);
-
- // We use the raw color resource because Android 4.x was struggling with tints here
- int colorID = UiModeUtilities.isDayUiMode(getContext()) ? R.color.black : R.color.accent;
- quoteBarView.setImageResource(colorID);
- mainView.setBackgroundColor(ThemeUtil.getThemedColor(getContext(),
- outgoing ? R.attr.message_received_background_color : R.attr.message_sent_background_color));
- }
-
- private void setQuoteText(@Nullable String body, @NonNull SlideDeck attachments) {
- if (!TextUtils.isEmpty(body) || !attachments.containsMediaSlide()) {
- bodyView.setVisibility(VISIBLE);
- bodyView.setText(body == null ? "" : body);
- mediaDescriptionText.setVisibility(GONE);
- return;
- }
-
- bodyView.setVisibility(GONE);
- mediaDescriptionText.setVisibility(VISIBLE);
-
- List audioSlides = Stream.of(attachments.getSlides()).filter(Slide::hasAudio).limit(1).toList();
- List documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList();
- List imageSlides = Stream.of(attachments.getSlides()).filter(Slide::hasImage).limit(1).toList();
- List videoSlides = Stream.of(attachments.getSlides()).filter(Slide::hasVideo).limit(1).toList();
-
- // Given that most types have images, we specifically check images last
- if (!audioSlides.isEmpty()) {
- mediaDescriptionText.setText(R.string.QuoteView_audio);
- } else if (!documentSlides.isEmpty()) {
- mediaDescriptionText.setVisibility(GONE);
- } else if (!videoSlides.isEmpty()) {
- mediaDescriptionText.setText(R.string.QuoteView_video);
- } else if (!imageSlides.isEmpty()) {
- mediaDescriptionText.setText(R.string.QuoteView_photo);
- }
- }
-
- private void setQuoteAttachment(@NonNull GlideRequests glideRequests, @NonNull SlideDeck slideDeck) {
- List imageVideoSlides = Stream.of(slideDeck.getSlides()).filter(s -> s.hasImage() || s.hasVideo()).limit(1).toList();
- List documentSlides = Stream.of(attachments.getSlides()).filter(Slide::hasDocument).limit(1).toList();
-
- attachmentVideoOverlayView.setVisibility(GONE);
-
- if (!imageVideoSlides.isEmpty() && imageVideoSlides.get(0).getThumbnailUri() != null) {
- thumbnailView.setVisibility(VISIBLE);
- attachmentContainerView.setVisibility(GONE);
- dismissView.setBackgroundResource(R.drawable.dismiss_background);
- if (imageVideoSlides.get(0).hasVideo()) {
- attachmentVideoOverlayView.setVisibility(VISIBLE);
- }
- glideRequests.load(new DecryptableUri(imageVideoSlides.get(0).getThumbnailUri()))
- .centerCrop()
- .diskCacheStrategy(DiskCacheStrategy.NONE)
- .into(thumbnailView);
- } else if (!documentSlides.isEmpty()){
- thumbnailView.setVisibility(GONE);
- attachmentContainerView.setVisibility(VISIBLE);
- attachmentNameView.setText(documentSlides.get(0).getFileName().or(""));
- } else {
- thumbnailView.setVisibility(GONE);
- attachmentContainerView.setVisibility(GONE);
- dismissView.setBackgroundDrawable(null);
- }
-
- if (ThemeUtil.isDarkTheme(getContext())) {
- dismissView.setBackgroundResource(R.drawable.circle_alpha);
- }
- }
-
- private void setQuoteMissingFooter(boolean missing) {
- footerView.setVisibility(missing ? VISIBLE : GONE);
- footerView.setBackgroundColor(getResources().getColor(R.color.quote_not_found_background));
- }
-
- public long getQuoteId() {
- return id;
- }
-
- public Recipient getAuthor() {
- return author;
- }
-
- public String getBody() {
- return body;
- }
-
- public List getAttachments() {
- return attachments.asAttachments();
- }
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java b/app/src/main/java/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java
index bdfad8c63a..6e7993a575 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/components/SwitchPreferenceCompat.java
@@ -1,11 +1,10 @@
package org.thoughtcrime.securesms.components;
-import android.annotation.TargetApi;
import android.content.Context;
-import android.os.Build;
+import android.util.AttributeSet;
+
import androidx.preference.CheckBoxPreference;
import androidx.preference.Preference;
-import android.util.AttributeSet;
import network.loki.messenger.R;
@@ -18,7 +17,6 @@ public class SwitchPreferenceCompat extends CheckBoxPreference {
setLayoutRes();
}
- @TargetApi(Build.VERSION_CODES.LOLLIPOP)
public SwitchPreferenceCompat(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
super(context, attrs, defStyleAttr, defStyleRes);
setLayoutRes();
diff --git a/app/src/main/java/org/thoughtcrime/securesms/contacts/UserView.kt b/app/src/main/java/org/thoughtcrime/securesms/contacts/UserView.kt
index 88d8787e88..e88cf1d08b 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/contacts/UserView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/contacts/UserView.kt
@@ -68,18 +68,22 @@ class UserView : LinearLayout {
}
ActionIndicator.Tick -> {
binding.actionIndicatorImageView.visibility = View.VISIBLE
- binding.actionIndicatorImageView.setImageResource(
- if (isSelected) R.drawable.ic_circle_check else R.drawable.ic_circle
- )
+ if (isSelected) {
+ binding.actionIndicatorImageView.setImageResource(R.drawable.padded_circle_accent)
+ } else {
+ binding.actionIndicatorImageView.setImageDrawable(null)
+ }
}
}
}
fun toggleCheckbox(isSelected: Boolean = false) {
binding.actionIndicatorImageView.visibility = View.VISIBLE
- binding.actionIndicatorImageView.setImageResource(
- if (isSelected) R.drawable.ic_circle_check else R.drawable.ic_circle
- )
+ if (isSelected) {
+ binding.actionIndicatorImageView.setImageResource(R.drawable.padded_circle_accent)
+ } else {
+ binding.actionIndicatorImageView.setImageDrawable(null)
+ }
}
fun unbind() {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt
index ee255a2721..7b666be56f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationFragment.kt
@@ -41,7 +41,7 @@ class NewConversationFragment : BottomSheetDialogFragment(), NewConversationDele
}
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
- val dialog = BottomSheetDialog(requireContext(), theme)
+ val dialog = BottomSheetDialog(requireContext(), R.style.Theme_Session_BottomSheet)
dialog.setOnShowListener {
val bottomSheetDialog = it as BottomSheetDialog
val parentLayout =
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt
index f8936d581f..2e62932ab0 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/start/NewConversationHomeFragment.kt
@@ -4,8 +4,11 @@ import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
+import androidx.core.content.ContextCompat
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
import network.loki.messenger.databinding.FragmentNewConversationHomeBinding
@@ -57,5 +60,11 @@ class NewConversationHomeFragment : Fragment() {
contactGroups.remove(unknownSectionTitle)?.let { contactGroups.put(unknownSectionTitle, it) }
adapter.items = contactGroups.flatMap { entry -> listOf(ContactListItem.Header(entry.key)) + entry.value }
binding.contactsRecyclerView.adapter = adapter
+ val divider = ContextCompat.getDrawable(requireActivity(), R.drawable.conversation_menu_divider)!!.let {
+ DividerItemDecoration(requireActivity(), RecyclerView.VERTICAL).apply {
+ setDrawable(it)
+ }
+ }
+ binding.contactsRecyclerView.addItemDecoration(divider)
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
index e5815d974f..7fe583ddbc 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/ConversationActivityV2.kt
@@ -18,6 +18,7 @@ import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
+import android.provider.MediaStore
import android.text.TextUtils
import android.util.Pair
import android.util.TypedValue
@@ -85,6 +86,7 @@ import org.session.libsignal.utilities.hexEncodedPrivateKey
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.ExpirationDialog
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+import org.thoughtcrime.securesms.attachments.ScreenshotObserver
import org.thoughtcrime.securesms.audio.AudioRecorder
import org.thoughtcrime.securesms.contacts.SelectContactsActivity.Companion.selectedContactsKey
import org.thoughtcrime.securesms.contactshare.SimpleTextWatcher
@@ -191,6 +193,13 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
@Inject lateinit var reactionDb: ReactionDatabase
@Inject lateinit var viewModelFactory: ConversationViewModel.AssistedFactory
+ private val screenshotObserver by lazy {
+ ScreenshotObserver(this, Handler(Looper.getMainLooper())) {
+ // post screenshot message
+ sendScreenshotNotification()
+ }
+ }
+
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
private val linkPreviewViewModel: LinkPreviewViewModel by lazy {
ViewModelProvider(this, LinkPreviewViewModel.Factory(LinkPreviewRepository()))
@@ -380,11 +389,17 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(viewModel.threadId)
val recipient = viewModel.recipient ?: return
threadDb.markAllAsRead(viewModel.threadId, recipient.isOpenGroupRecipient)
+ contentResolver.registerContentObserver(
+ MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
+ true,
+ screenshotObserver
+ )
}
override fun onPause() {
super.onPause()
ApplicationContext.getInstance(this).messageNotifier.setVisibleThread(-1)
+ contentResolver.unregisterContentObserver(screenshotObserver)
}
override fun getSystemService(name: String): Any? {
@@ -923,10 +938,12 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
} else if (recipient.isGroupRecipient) {
viewModel.openGroup?.let { openGroup ->
val userCount = lokiApiDb.getUserCount(openGroup.room, openGroup.server) ?: 0
- actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_member_count, userCount)
+ actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_active_member_count, userCount)
} ?: run {
- actionBarBinding.conversationSubtitleView.isVisible = false
+ val userCount = groupDb.getGroupMemberAddresses(recipient.address.toGroupString(), true).size
+ actionBarBinding.conversationSubtitleView.text = getString(R.string.ConversationActivity_member_count, userCount)
}
+ viewModel
} else {
actionBarBinding.conversationSubtitleView.isVisible = false
}
@@ -1317,6 +1334,8 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
}
override fun playVoiceMessageAtIndexIfPossible(indexInAdapter: Int) {
+ if (!textSecurePreferences.autoplayAudioMessages()) return
+
if (indexInAdapter < 0 || indexInAdapter >= adapter.itemCount) { return }
val viewHolder = binding?.conversationRecyclerView?.findViewHolderForAdapterPosition(indexInAdapter) as? ConversationAdapter.VisibleMessageViewHolder ?: return
val visibleMessageView = ViewVisibleMessageBinding.bind(viewHolder.view).visibleMessageView
@@ -1770,6 +1789,14 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
endActionMode()
}
+ private fun sendScreenshotNotification() {
+ val recipient = viewModel.recipient ?: return
+ if (recipient.isGroupRecipient) return
+ val kind = DataExtractionNotification.Kind.Screenshot()
+ val message = DataExtractionNotification(kind)
+ MessageSender.send(message, recipient.address)
+ }
+
private fun sendMediaSavedNotification() {
val recipient = viewModel.recipient ?: return
if (recipient.isGroupRecipient) { return }
@@ -1819,7 +1846,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
searchViewModel.onSearchOpened()
binding?.searchBottomBar?.visibility = View.VISIBLE
binding?.searchBottomBar?.setData(0, 0)
- binding?.inputBar?.visibility = View.GONE
+ binding?.inputBar?.visibility = View.INVISIBLE
}
fun onSearchClosed() {
@@ -1873,6 +1900,7 @@ class ConversationActivityV2 : PassphraseRequiredActionBarActivity(), InputBarDe
ConversationReactionOverlay.Action.DELETE -> deleteMessages(selectedItems)
ConversationReactionOverlay.Action.BAN_AND_DELETE_ALL -> banAndDeleteAll(selectedItems)
ConversationReactionOverlay.Action.BAN_USER -> banUser(selectedItems)
+ ConversationReactionOverlay.Action.COPY_SESSION_ID -> TODO()
}
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
index affabd3f5a..7ac70b843a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBar.kt
@@ -7,9 +7,12 @@ import android.net.Uri
import android.text.InputType
import android.text.TextWatcher
import android.util.AttributeSet
+import android.view.KeyEvent
import android.view.LayoutInflater
import android.view.MotionEvent
+import android.view.inputmethod.EditorInfo
import android.widget.RelativeLayout
+import android.widget.TextView
import androidx.core.view.isVisible
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewInputBarBinding
@@ -27,7 +30,8 @@ import org.thoughtcrime.securesms.util.contains
import org.thoughtcrime.securesms.util.toDp
import org.thoughtcrime.securesms.util.toPx
-class InputBar : RelativeLayout, InputBarEditTextDelegate, QuoteViewDelegate, LinkPreviewDraftViewDelegate {
+class InputBar : RelativeLayout, InputBarEditTextDelegate, QuoteViewDelegate, LinkPreviewDraftViewDelegate,
+ TextView.OnEditorActionListener {
private lateinit var binding: ViewInputBarBinding
private val screenWidth = Resources.getSystem().displayMetrics.widthPixels
private val vMargin by lazy { toDp(4, resources) }
@@ -85,11 +89,31 @@ class InputBar : RelativeLayout, InputBarEditTextDelegate, QuoteViewDelegate, Li
}
}
// Edit text
+ binding.inputBarEditText.setOnEditorActionListener(this)
+ if (TextSecurePreferences.isEnterSendsEnabled(context)) {
+ binding.inputBarEditText.imeOptions = EditorInfo.IME_ACTION_SEND
+ binding.inputBarEditText.inputType =
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+ } else {
+ binding.inputBarEditText.imeOptions = EditorInfo.IME_ACTION_NONE
+ binding.inputBarEditText.inputType =
+ binding.inputBarEditText.inputType or
+ InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
+ }
val incognitoFlag = if (TextSecurePreferences.isIncognitoKeyboardEnabled(context)) 16777216 else 0
binding.inputBarEditText.imeOptions = binding.inputBarEditText.imeOptions or incognitoFlag // Always use incognito keyboard if setting enabled
- binding.inputBarEditText.inputType = binding.inputBarEditText.inputType or InputType.TYPE_TEXT_FLAG_CAP_SENTENCES
binding.inputBarEditText.delegate = this
}
+
+ override fun onEditorAction(v: TextView?, actionId: Int, event: KeyEvent?): Boolean {
+ if (v === binding.inputBarEditText && actionId == EditorInfo.IME_ACTION_SEND) {
+ // same as pressing send button
+ delegate?.sendMessage()
+ return true
+ }
+ return false
+ }
+
// endregion
// region Updating
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
index abf6720aa0..c88e05dbfb 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/input_bar/InputBarButton.kt
@@ -16,8 +16,13 @@ import android.widget.ImageView
import android.widget.RelativeLayout
import androidx.annotation.DrawableRes
import network.loki.messenger.R
-import org.thoughtcrime.securesms.util.*
-import java.util.*
+import org.session.libsession.utilities.getColorFromAttr
+import org.thoughtcrime.securesms.util.GlowViewUtilities
+import org.thoughtcrime.securesms.util.InputBarButtonImageViewContainer
+import org.thoughtcrime.securesms.util.animateSizeChange
+import org.thoughtcrime.securesms.util.getAccentColor
+import org.thoughtcrime.securesms.util.toPx
+import java.util.Date
class InputBarButton : RelativeLayout {
private val gestureHandler = Handler(Looper.getMainLooper())
@@ -43,11 +48,11 @@ class InputBarButton : RelativeLayout {
private val collapsedImageViewPosition by lazy { PointF((expandedSize - collapsedSize) / 2, (expandedSize - collapsedSize) / 2) }
private val colorID by lazy {
if (hasOpaqueBackground) {
- R.color.input_bar_button_background_opaque
+ R.attr.input_bar_button_background_opaque
} else if (isSendButton) {
- R.color.accent
+ R.attr.colorAccent
} else {
- R.color.input_bar_button_background
+ R.attr.input_bar_button_background
}
}
@@ -59,9 +64,9 @@ class InputBarButton : RelativeLayout {
val size = collapsedSize.toInt()
result.layoutParams = LayoutParams(size, size)
result.setBackgroundResource(R.drawable.input_bar_button_background)
- result.mainColor = resources.getColorWithID(colorID, context.theme)
+ result.mainColor = context.getColorFromAttr(colorID)
if (hasOpaqueBackground) {
- result.strokeColor = resources.getColorWithID(R.color.input_bar_button_background_opaque_border, context.theme)
+ result.strokeColor = context.getColorFromAttr(R.attr.input_bar_button_background_opaque_border)
}
result
}
@@ -72,8 +77,7 @@ class InputBarButton : RelativeLayout {
result.layoutParams = LayoutParams(size, size)
result.scaleType = ImageView.ScaleType.CENTER_INSIDE
result.setImageResource(iconID)
- val colorID = if (isSendButton) R.color.black else R.color.text
- result.imageTintList = ColorStateList.valueOf(resources.getColorWithID(colorID, context.theme))
+ result.imageTintList = ColorStateList.valueOf(context.getColorFromAttr(R.attr.input_bar_button_text_color))
result
}
@@ -104,13 +108,18 @@ class InputBarButton : RelativeLayout {
fun getIconID() = iconID
fun expand() {
- GlowViewUtilities.animateColorChange(context, imageViewContainer, colorID, R.color.accent)
+ val fromColor = context.getColorFromAttr(colorID)
+ val toColor = context.getAccentColor()
+ GlowViewUtilities.animateColorChange(imageViewContainer, fromColor, toColor)
imageViewContainer.animateSizeChange(R.dimen.input_bar_button_collapsed_size, R.dimen.input_bar_button_expanded_size, animationDuration)
animateImageViewContainerPositionChange(collapsedImageViewPosition, expandedImageViewPosition)
}
fun collapse() {
- GlowViewUtilities.animateColorChange(context, imageViewContainer, R.color.accent, colorID)
+ val fromColor = context.getAccentColor()
+ val toColor = context.getColorFromAttr(colorID)
+
+ GlowViewUtilities.animateColorChange(imageViewContainer, fromColor, toColor)
imageViewContainer.animateSizeChange(R.dimen.input_bar_button_expanded_size, R.dimen.input_bar_button_collapsed_size, animationDuration)
animateImageViewContainerPositionChange(expandedImageViewPosition, collapsedImageViewPosition)
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt
index c5f12650f7..663dd2e255 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/menus/ConversationMenuHelper.kt
@@ -16,6 +16,7 @@ import android.widget.Toast
import androidx.annotation.ColorInt
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
+import androidx.appcompat.view.ContextThemeWrapper
import androidx.appcompat.widget.SearchView
import androidx.appcompat.widget.SearchView.OnQueryTextListener
import androidx.core.content.pm.ShortcutInfoCompat
@@ -27,6 +28,7 @@ import org.session.libsession.messaging.sending_receiving.leave
import org.session.libsession.utilities.ExpirationUtil
import org.session.libsession.utilities.GroupUtil.doubleDecodeGroupID
import org.session.libsession.utilities.TextSecurePreferences
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsession.utilities.recipients.Recipient
import org.session.libsignal.utilities.guava.Optional
import org.session.libsignal.utilities.toHexString
@@ -43,7 +45,6 @@ import org.thoughtcrime.securesms.groups.EditClosedGroupActivity.Companion.group
import org.thoughtcrime.securesms.preferences.PrivacySettingsActivity
import org.thoughtcrime.securesms.service.WebRtcCallService
import org.thoughtcrime.securesms.util.BitmapUtil
-import org.thoughtcrime.securesms.util.getColorWithID
import java.io.IOException
object ConversationMenuHelper {
@@ -69,7 +70,7 @@ object ConversationMenuHelper {
val actionView = item.actionView
val iconView = actionView.findViewById(R.id.menu_badge_icon)
val badgeView = actionView.findViewById(R.id.expiration_badge)
- @ColorInt val color = context.resources.getColorWithID(R.color.text, context.theme)
+ @ColorInt val color = context.getColorFromAttr(android.R.attr.textColorPrimary)
iconView.colorFilter = PorterDuffColorFilter(color, PorterDuff.Mode.MULTIPLY)
badgeView.text = ExpirationUtil.getExpirationAbbreviatedDisplayValue(context, thread.expireMessages)
actionView.setOnClickListener { onOptionsItemSelected(item) }
@@ -328,7 +329,7 @@ object ConversationMenuHelper {
}
private fun mute(context: Context, thread: Recipient) {
- MuteDialog.show(context) { until: Long ->
+ MuteDialog.show(ContextThemeWrapper(context, context.theme)) { until: Long ->
DatabaseComponent.get(context).recipientDatabase().setMuted(thread, until)
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.java b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.java
index 54a8e7626c..6d16f1f421 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/EmojiReactionsView.java
@@ -22,6 +22,7 @@ import com.google.android.flexbox.FlexboxLayout;
import com.google.android.flexbox.JustifyContent;
import org.session.libsession.utilities.TextSecurePreferences;
+import org.session.libsession.utilities.ThemeUtil;
import org.thoughtcrime.securesms.components.emoji.EmojiImageView;
import org.thoughtcrime.securesms.components.emoji.EmojiUtil;
import org.thoughtcrime.securesms.conversation.v2.ViewUtil;
@@ -126,14 +127,17 @@ public class EmojiReactionsView extends LinearLayout implements View.OnTouchList
int innerPadding = ViewUtil.dpToPx(4);
overflowContainer.setPaddingRelative(innerPadding,innerPadding,innerPadding,innerPadding);
+ int pixelSize = ViewUtil.dpToPx(1);
+
for (Reaction reaction : reactions) {
if (container.getChildCount() + 1 >= DEFAULT_THRESHOLD && threshold != Integer.MAX_VALUE && reactions.size() > threshold) {
if (overflowContainer.getParent() == null) {
container.addView(overflowContainer);
- ViewGroup.LayoutParams overflowParams = overflowContainer.getLayoutParams();
+ MarginLayoutParams overflowParams = (MarginLayoutParams) overflowContainer.getLayoutParams();
overflowParams.height = ViewUtil.dpToPx(26);
+ overflowParams.setMargins(pixelSize, pixelSize, pixelSize, pixelSize);
overflowContainer.setLayoutParams(overflowParams);
- overflowContainer.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.reaction_pill_dialog_background));
+ overflowContainer.setBackground(ContextCompat.getDrawable(getContext(), R.drawable.reaction_pill_background));
}
View pill = buildPill(getContext(), this, reaction, true);
pill.setOnClickListener(v -> {
@@ -147,11 +151,10 @@ public class EmojiReactionsView extends LinearLayout implements View.OnTouchList
View pill = buildPill(getContext(), this, reaction, false);
pill.setTag(reaction);
pill.setOnTouchListener(this);
- container.addView(pill);
- int pixelSize = ViewUtil.dpToPx(1);
MarginLayoutParams params = (MarginLayoutParams) pill.getLayoutParams();
- params.setMargins(pixelSize, 0, pixelSize, 0);
+ params.setMargins(pixelSize, pixelSize, pixelSize, pixelSize);
pill.setLayoutParams(params);
+ container.addView(pill);
}
}
@@ -246,7 +249,7 @@ public class EmojiReactionsView extends LinearLayout implements View.OnTouchList
if (reaction.userWasSender && !isCompact) {
root.setBackground(ContextCompat.getDrawable(context, R.drawable.reaction_pill_background_selected));
- countView.setTextColor(ContextCompat.getColor(context, R.color.reactions_pill_selected_text_color));
+ countView.setTextColor(ThemeUtil.getThemedColor(context, R.attr.reactionsPillSelectedTextColor));
} else {
if (!isCompact) {
root.setBackground(ContextCompat.getDrawable(context, R.drawable.reaction_pill_background));
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt
index d0b9a78226..cb6bb536ff 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/LinkPreviewView.kt
@@ -12,6 +12,7 @@ import androidx.core.content.res.ResourcesCompat
import androidx.core.view.isVisible
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewLinkPreviewBinding
+import org.session.libsession.utilities.getColorFromAttr
import org.thoughtcrime.securesms.components.CornerMask
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
import org.thoughtcrime.securesms.conversation.v2.utilities.MessageBubbleUtilities
@@ -52,14 +53,13 @@ class LinkPreviewView : LinearLayout {
}
// Title
binding.titleTextView.text = linkPreview.title
- val textColorID = if (message.isOutgoing && UiModeUtilities.isDayUiMode(context)) {
- R.color.white
+ val textColorID = if (message.isOutgoing) {
+ R.attr.message_sent_text_color
} else {
- if (UiModeUtilities.isDayUiMode(context)) R.color.black else R.color.white
+ R.attr.message_received_text_color
}
- binding.titleTextView.setTextColor(ResourcesCompat.getColor(resources, textColorID, context.theme))
+ binding.titleTextView.setTextColor(context.getColorFromAttr(textColorID))
// Body
- binding.titleTextView.setTextColor(ResourcesCompat.getColor(resources, textColorID, context.theme))
// Corner radii
val cornerRadii = MessageBubbleUtilities.calculateRadii(context, isStartOfMessageCluster, isEndOfMessageCluster, message.isOutgoing)
cornerMask.setTopLeftRadius(cornerRadii[0])
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/OpenGroupInvitationView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/OpenGroupInvitationView.kt
index 3fbc1e6ac0..fc9a46228e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/OpenGroupInvitationView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/OpenGroupInvitationView.kt
@@ -1,16 +1,19 @@
package org.thoughtcrime.securesms.conversation.v2.messages
import android.content.Context
+import android.content.res.ColorStateList
import android.util.AttributeSet
import android.widget.LinearLayout
import androidx.annotation.ColorInt
import androidx.appcompat.app.AppCompatActivity
+import androidx.core.content.ContextCompat
import network.loki.messenger.R
import network.loki.messenger.databinding.ViewOpenGroupInvitationBinding
import org.session.libsession.messaging.utilities.UpdateMessageData
import org.session.libsession.utilities.OpenGroupUrlParser
import org.thoughtcrime.securesms.conversation.v2.dialogs.JoinOpenGroupDialog
import org.thoughtcrime.securesms.database.model.MessageRecord
+import org.thoughtcrime.securesms.util.getAccentColor
class OpenGroupInvitationView : LinearLayout {
private val binding: ViewOpenGroupInvitationBinding by lazy { ViewOpenGroupInvitationBinding.bind(this) }
@@ -26,8 +29,11 @@ class OpenGroupInvitationView : LinearLayout {
val data = umd.kind as UpdateMessageData.Kind.OpenGroupInvitation
this.data = data
val iconID = if (message.isOutgoing) R.drawable.ic_globe else R.drawable.ic_plus
+ val backgroundColor = if (!message.isOutgoing) context.getAccentColor()
+ else ContextCompat.getColor(context, R.color.transparent_black_6)
with(binding){
openGroupInvitationIconImageView.setImageResource(iconID)
+ openGroupInvitationIconBackground.backgroundTintList = ColorStateList.valueOf(backgroundColor)
openGroupTitleTextView.text = data.groupName
openGroupURLTextView.text = OpenGroupUrlParser.trimQueryParameter(data.groupUrl)
openGroupTitleTextView.setTextColor(textColor)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt
index a08bef5a55..91ab4c106d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/QuoteView.kt
@@ -14,13 +14,14 @@ import network.loki.messenger.R
import network.loki.messenger.databinding.ViewQuoteBinding
import org.session.libsession.messaging.contacts.Contact
import org.session.libsession.utilities.TextSecurePreferences
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.utilities.MentionUtilities
import org.thoughtcrime.securesms.database.SessionContactDatabase
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.mms.SlideDeck
import org.thoughtcrime.securesms.util.MediaUtil
-import org.thoughtcrime.securesms.util.UiModeUtilities
+import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.toPx
import javax.inject.Inject
@@ -89,8 +90,7 @@ class QuoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
binding.quoteViewAccentLine.setBackgroundColor(getLineColor(isOutgoingMessage))
} else if (attachments != null) {
binding.quoteViewAttachmentPreviewImageView.imageTintList = ColorStateList.valueOf(ResourcesCompat.getColor(resources, R.color.white, context.theme))
- val backgroundColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.black else R.color.accent
- val backgroundColor = ResourcesCompat.getColor(resources, backgroundColorID, context.theme)
+ val backgroundColor = context.getAccentColor()
binding.quoteViewAttachmentPreviewContainer.backgroundTintList = ColorStateList.valueOf(backgroundColor)
binding.quoteViewAttachmentPreviewImageView.isVisible = false
binding.quoteViewAttachmentThumbnailImageView.isVisible = false
@@ -120,31 +120,19 @@ class QuoteView @JvmOverloads constructor(context: Context, attrs: AttributeSet?
// region Convenience
@ColorInt private fun getLineColor(isOutgoingMessage: Boolean): Int {
- val isLightMode = UiModeUtilities.isDayUiMode(context)
return when {
- mode == Mode.Regular && isLightMode || mode == Mode.Draft && isLightMode -> {
- ResourcesCompat.getColor(resources, R.color.black, context.theme)
- }
- mode == Mode.Regular && !isLightMode -> {
- if (isOutgoingMessage) {
- ResourcesCompat.getColor(resources, R.color.black, context.theme)
- } else {
- ResourcesCompat.getColor(resources, R.color.accent, context.theme)
- }
- }
- else -> { // Draft & dark mode
- ResourcesCompat.getColor(resources, R.color.accent, context.theme)
- }
+ mode == Mode.Regular && !isOutgoingMessage -> context.getColorFromAttr(R.attr.colorAccent)
+ mode == Mode.Regular -> context.getColorFromAttr(R.attr.message_sent_text_color)
+ else -> context.getColorFromAttr(R.attr.colorAccent)
}
}
@ColorInt private fun getTextColor(isOutgoingMessage: Boolean): Int {
- if (mode == Mode.Draft) { return ResourcesCompat.getColor(resources, R.color.text, context.theme) }
- val isLightMode = UiModeUtilities.isDayUiMode(context)
- return if (!isOutgoingMessage && !isLightMode) {
- ResourcesCompat.getColor(resources, R.color.white, context.theme)
+ if (mode == Mode.Draft) { return context.getColorFromAttr(android.R.attr.textColorPrimary) }
+ return if (!isOutgoingMessage) {
+ context.getColorFromAttr(R.attr.message_received_text_color)
} else {
- ResourcesCompat.getColor(resources, R.color.black, context.theme)
+ context.getColorFromAttr(R.attr.message_sent_text_color)
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt
index 7a00830ef3..88045f8e47 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageContentView.kt
@@ -15,7 +15,6 @@ import android.view.MotionEvent
import android.view.View
import android.widget.LinearLayout
import androidx.annotation.ColorInt
-import androidx.annotation.DrawableRes
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.res.ResourcesCompat
@@ -32,7 +31,7 @@ import org.session.libsession.messaging.jobs.AttachmentDownloadJob
import org.session.libsession.messaging.jobs.JobQueue
import org.session.libsession.messaging.sending_receiving.attachments.AttachmentTransferProgress
import org.session.libsession.messaging.sending_receiving.attachments.DatabaseAttachment
-import org.session.libsession.utilities.ThemeUtil
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsession.utilities.recipients.Recipient
import org.thoughtcrime.securesms.conversation.v2.ConversationActivityV2
import org.thoughtcrime.securesms.conversation.v2.ModalUrlBottomSheet
@@ -44,8 +43,7 @@ import org.thoughtcrime.securesms.database.model.MmsMessageRecord
import org.thoughtcrime.securesms.database.model.SmsMessageRecord
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.SearchUtil
-import org.thoughtcrime.securesms.util.UiModeUtilities
-import org.thoughtcrime.securesms.util.getColorWithID
+import org.thoughtcrime.securesms.util.getAccentColor
import java.util.Locale
import kotlin.math.roundToInt
@@ -70,9 +68,9 @@ class VisibleMessageContentView : LinearLayout {
fun bind(message: MessageRecord, isStartOfMessageCluster: Boolean, isEndOfMessageCluster: Boolean,
glide: GlideRequests, thread: Recipient, searchQuery: String?, contactIsTrusted: Boolean) {
// Background
- val background = getBackground(message.isOutgoing, isStartOfMessageCluster, isEndOfMessageCluster)
- val colorID = if (message.isOutgoing) R.attr.message_sent_background_color else R.attr.message_received_background_color
- val color = ThemeUtil.getThemedColor(context, colorID)
+ val background = getBackground(message.isOutgoing)
+ val color = if (message.isOutgoing) context.getAccentColor()
+ else context.getColorFromAttr(R.attr.message_received_background_color)
val filter = BlendModeColorFilterCompat.createBlendModeColorFilterCompat(color, BlendModeCompat.SRC_IN)
background.colorFilter = filter
binding.contentParent.background = background
@@ -237,22 +235,8 @@ class VisibleMessageContentView : LinearLayout {
private fun ViewVisibleMessageContentBinding.barrierViewsGone(): Boolean =
listOf(albumThumbnailView, linkPreviewView, voiceMessageView.root, quoteView.root).none { it.isVisible }
- private fun getBackground(isOutgoing: Boolean, isStartOfMessageCluster: Boolean, isEndOfMessageCluster: Boolean): Drawable {
- val isSingleMessage = (isStartOfMessageCluster && isEndOfMessageCluster)
- @DrawableRes val backgroundID = when {
- isSingleMessage -> {
- if (isOutgoing) R.drawable.message_bubble_background_sent_alone else R.drawable.message_bubble_background_received_alone
- }
- isStartOfMessageCluster -> {
- if (isOutgoing) R.drawable.message_bubble_background_sent_start else R.drawable.message_bubble_background_received_start
- }
- isEndOfMessageCluster -> {
- if (isOutgoing) R.drawable.message_bubble_background_sent_end else R.drawable.message_bubble_background_received_end
- }
- else -> {
- if (isOutgoing) R.drawable.message_bubble_background_sent_middle else R.drawable.message_bubble_background_received_middle
- }
- }
+ private fun getBackground(isOutgoing: Boolean): Drawable {
+ val backgroundID = if (isOutgoing) R.drawable.message_bubble_background_sent_alone else R.drawable.message_bubble_background_received_alone
return ResourcesCompat.getDrawable(resources, backgroundID, context.theme)!!
}
@@ -307,13 +291,14 @@ class VisibleMessageContentView : LinearLayout {
@ColorInt
fun getTextColor(context: Context, message: MessageRecord): Int {
- val isDayUiMode = UiModeUtilities.isDayUiMode(context)
- val colorID = if (message.isOutgoing) {
- R.color.black
+ val colorAttribute = if (message.isOutgoing) {
+ // sent
+ R.attr.message_sent_text_color
} else {
- if (isDayUiMode) R.color.black else R.color.white
+ // received
+ R.attr.message_received_text_color
}
- return context.resources.getColorWithID(colorID, context.theme)
+ return context.getColorFromAttr(colorAttribute)
}
}
// endregion
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
index bd68693005..0b4c1455fc 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/messages/VisibleMessageView.kt
@@ -16,7 +16,6 @@ import android.widget.LinearLayout
import androidx.appcompat.app.AppCompatActivity
import androidx.constraintlayout.widget.ConstraintLayout
import androidx.core.content.ContextCompat
-import androidx.core.content.res.ResourcesCompat
import androidx.core.os.bundleOf
import androidx.core.view.isInvisible
import androidx.core.view.isVisible
@@ -29,6 +28,7 @@ import org.session.libsession.messaging.contacts.Contact.ContactContext
import org.session.libsession.messaging.open_groups.OpenGroupApi
import org.session.libsession.utilities.Address
import org.session.libsession.utilities.ViewUtil
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsignal.utilities.IdPrefix
import org.session.libsignal.utilities.ThreadUtils
import org.thoughtcrime.securesms.ApplicationContext
@@ -45,7 +45,6 @@ import org.thoughtcrime.securesms.home.UserDetailsBottomSheet
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.disableClipping
-import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.toDp
import org.thoughtcrime.securesms.util.toPx
import java.util.Date
@@ -280,7 +279,7 @@ class VisibleMessageView : LinearLayout {
containerParams.horizontalBias = if (message.isOutgoing) 1f else 0f
container.layoutParams = containerParams
if (message.expiresIn > 0 && !message.isPending) {
- binding.expirationTimerView.setColorFilter(ResourcesCompat.getColor(resources, R.color.text, context.theme))
+ binding.expirationTimerView.setColorFilter(context.getColorFromAttr(android.R.attr.textColorPrimary))
binding.expirationTimerView.isInvisible = false
binding.expirationTimerView.setPercentComplete(0.0f)
if (message.expireStarted > 0) {
@@ -311,7 +310,7 @@ class VisibleMessageView : LinearLayout {
private fun handleIsSelectedChanged() {
background = if (snIsSelected) {
- ColorDrawable(context.resources.getColorWithID(R.color.message_selected, context.theme))
+ ColorDrawable(context.getColorFromAttr(R.attr.message_selected))
} else {
null
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt
index eccb74b127..1ae2902188 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/KThumbnailView.kt
@@ -2,12 +2,14 @@ package org.thoughtcrime.securesms.conversation.v2.utilities
import android.content.Context
import android.graphics.Bitmap
+import android.graphics.drawable.ColorDrawable
import android.graphics.drawable.Drawable
import android.net.Uri
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.FrameLayout
+import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import com.bumptech.glide.load.engine.DiskCacheStrategy
import com.bumptech.glide.load.resource.bitmap.CenterCrop
@@ -64,6 +66,8 @@ open class KThumbnailView: FrameLayout {
typedArray.recycle()
}
+ val background = ContextCompat.getColor(context, R.color.transparent_black_6)
+ binding.root.background = ColorDrawable(background)
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt
index 11b2c6f6d1..1ba4a0c3e5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/MentionUtilities.kt
@@ -15,6 +15,7 @@ import org.session.libsession.messaging.utilities.SodiumUtilities
import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
import org.thoughtcrime.securesms.util.UiModeUtilities
+import org.thoughtcrime.securesms.util.getAccentColor
import java.util.regex.Pattern
object MentionUtilities {
@@ -58,13 +59,12 @@ object MentionUtilities {
}
val result = SpannableString(text)
val isLightMode = UiModeUtilities.isDayUiMode(context)
+ val color = if (isOutgoingMessage) {
+ ResourcesCompat.getColor(context.resources, if (isLightMode) R.color.white else R.color.black, context.theme)
+ } else {
+ context.getAccentColor()
+ }
for (mention in mentions) {
- val colorID = if (isOutgoingMessage) {
- if (isLightMode) R.color.white else R.color.black
- } else {
- R.color.accent
- }
- val color = ResourcesCompat.getColor(context.resources, colorID, context.theme)
result.setSpan(ForegroundColorSpan(color), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
result.setSpan(StyleSpan(Typeface.BOLD), mention.first.lower, mention.first.upper, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailProgressBar.kt b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailProgressBar.kt
index fd9a7c8404..3abfd235ce 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailProgressBar.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/conversation/v2/utilities/ThumbnailProgressBar.kt
@@ -7,8 +7,7 @@ import android.graphics.Rect
import android.os.SystemClock
import android.util.AttributeSet
import android.view.View
-import androidx.core.content.res.ResourcesCompat
-import network.loki.messenger.R
+import org.thoughtcrime.securesms.util.getAccentColor
import kotlin.math.sin
class ThumbnailProgressBar: View {
@@ -25,7 +24,7 @@ class ThumbnailProgressBar: View {
private val paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
style = Paint.Style.FILL
- color = ResourcesCompat.getColor(resources, R.color.accent, null)
+ color = context.getAccentColor()
}
private val objectRect = Rect()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Database.java b/app/src/main/java/org/thoughtcrime/securesms/database/Database.java
index b984a6e0f2..ce950214f0 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Database.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Database.java
@@ -72,6 +72,11 @@ public abstract class Database {
context.getContentResolver().notifyChange(DatabaseContentProviders.StickerPack.CONTENT_URI, null);
}
+ protected void notifyRecipientListeners() {
+ context.getContentResolver().notifyChange(DatabaseContentProviders.Recipient.CONTENT_URI, null);
+ notifyConversationListListeners();
+ }
+
protected void setNotifyConverationListeners(Cursor cursor, long threadId) {
cursor.setNotificationUri(context.getContentResolver(), DatabaseContentProviders.Conversation.getUriForThread(threadId));
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseContentProviders.java b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseContentProviders.java
index 0570d91503..0f4d7c9f25 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseContentProviders.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/DatabaseContentProviders.java
@@ -38,6 +38,10 @@ public class DatabaseContentProviders {
public static final Uri CONTENT_URI = Uri.parse("content://network.loki.securesms.database.stickerpack");
}
+ public static class Recipient extends NoopContentProvider {
+ public static final Uri CONTENT_URI = Uri.parse("content://network.loki.securesms.database.recipient");
+ }
+
private static abstract class NoopContentProvider extends ContentProvider {
@Override
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java
index 2834eb341d..58693172ed 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/RecipientDatabase.java
@@ -27,6 +27,7 @@ import org.thoughtcrime.securesms.database.helpers.SQLCipherOpenHelper;
import java.io.Closeable;
import java.io.IOException;
+import java.util.ArrayList;
import java.util.List;
public class RecipientDatabase extends Database {
@@ -232,6 +233,7 @@ public class RecipientDatabase extends Database {
values.put(COLOR, color.serialize());
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setColor(color);
+ notifyRecipientListeners();
}
public void setDefaultSubscriptionId(@NonNull Recipient recipient, int defaultSubscriptionId) {
@@ -239,6 +241,7 @@ public class RecipientDatabase extends Database {
values.put(DEFAULT_SUBSCRIPTION_ID, defaultSubscriptionId);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setDefaultSubscriptionId(Optional.of(defaultSubscriptionId));
+ notifyRecipientListeners();
}
public void setForceSmsSelection(@NonNull Recipient recipient, boolean forceSmsSelection) {
@@ -246,6 +249,7 @@ public class RecipientDatabase extends Database {
contentValues.put(FORCE_SMS_SELECTION, forceSmsSelection ? 1 : 0);
updateOrInsert(recipient.getAddress(), contentValues);
recipient.resolve().setForceSmsSelection(forceSmsSelection);
+ notifyRecipientListeners();
}
public void setApproved(@NonNull Recipient recipient, boolean approved) {
@@ -253,6 +257,7 @@ public class RecipientDatabase extends Database {
values.put(APPROVED, approved ? 1 : 0);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setApproved(approved);
+ notifyRecipientListeners();
}
public void setApprovedMe(@NonNull Recipient recipient, boolean approvedMe) {
@@ -260,6 +265,7 @@ public class RecipientDatabase extends Database {
values.put(APPROVED_ME, approvedMe ? 1 : 0);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setHasApprovedMe(approvedMe);
+ notifyRecipientListeners();
}
public void setBlocked(@NonNull Recipient recipient, boolean blocked) {
@@ -267,6 +273,24 @@ public class RecipientDatabase extends Database {
values.put(BLOCK, blocked ? 1 : 0);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setBlocked(blocked);
+ notifyRecipientListeners();
+ }
+
+ public void setBlocked(@NonNull List recipients, boolean blocked) {
+ SQLiteDatabase db = getWritableDatabase();
+ db.beginTransaction();
+ try {
+ ContentValues values = new ContentValues();
+ values.put(BLOCK, blocked ? 1 : 0);
+ for (Recipient recipient : recipients) {
+ db.update(TABLE_NAME, values, ADDRESS + " = ?", new String[]{recipient.getAddress().serialize()});
+ recipient.resolve().setBlocked(blocked);
+ }
+ db.setTransactionSuccessful();
+ } finally {
+ db.endTransaction();
+ }
+ notifyRecipientListeners();
}
public void setMuted(@NonNull Recipient recipient, long until) {
@@ -274,6 +298,7 @@ public class RecipientDatabase extends Database {
values.put(MUTE_UNTIL, until);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setMuted(until);
+ notifyRecipientListeners();
}
/**
@@ -287,6 +312,7 @@ public class RecipientDatabase extends Database {
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setNotifyType(notifyType);
notifyConversationListListeners();
+ notifyRecipientListeners();
}
public void setExpireMessages(@NonNull Recipient recipient, int expiration) {
@@ -296,6 +322,7 @@ public class RecipientDatabase extends Database {
values.put(EXPIRE_MESSAGES, expiration);
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setExpireMessages(expiration);
+ notifyRecipientListeners();
}
public void setUnidentifiedAccessMode(@NonNull Recipient recipient, @NonNull UnidentifiedAccessMode unidentifiedAccessMode) {
@@ -303,6 +330,7 @@ public class RecipientDatabase extends Database {
values.put(UNIDENTIFIED_ACCESS_MODE, unidentifiedAccessMode.getMode());
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setUnidentifiedAccessMode(unidentifiedAccessMode);
+ notifyRecipientListeners();
}
public void setProfileKey(@NonNull Recipient recipient, @Nullable byte[] profileKey) {
@@ -310,6 +338,7 @@ public class RecipientDatabase extends Database {
values.put(PROFILE_KEY, profileKey == null ? null : Base64.encodeBytes(profileKey));
updateOrInsert(recipient.getAddress(), values);
recipient.resolve().setProfileKey(profileKey);
+ notifyRecipientListeners();
}
public void setProfileAvatar(@NonNull Recipient recipient, @Nullable String profileAvatar) {
@@ -317,6 +346,7 @@ public class RecipientDatabase extends Database {
contentValues.put(SIGNAL_PROFILE_AVATAR, profileAvatar);
updateOrInsert(recipient.getAddress(), contentValues);
recipient.resolve().setProfileAvatar(profileAvatar);
+ notifyRecipientListeners();
}
public void setProfileName(@NonNull Recipient recipient, @Nullable String profileName) {
@@ -325,6 +355,7 @@ public class RecipientDatabase extends Database {
updateOrInsert(recipient.getAddress(), contentValues);
recipient.resolve().setName(profileName);
recipient.resolve().setProfileName(profileName);
+ notifyRecipientListeners();
}
public void setProfileSharing(@NonNull Recipient recipient, boolean enabled) {
@@ -332,6 +363,7 @@ public class RecipientDatabase extends Database {
contentValues.put(PROFILE_SHARING, enabled ? 1 : 0);
updateOrInsert(recipient.getAddress(), contentValues);
recipient.setProfileSharing(enabled);
+ notifyRecipientListeners();
}
public void setNotificationChannel(@NonNull Recipient recipient, @Nullable String notificationChannel) {
@@ -339,6 +371,7 @@ public class RecipientDatabase extends Database {
contentValues.put(NOTIFICATION_CHANNEL, notificationChannel);
updateOrInsert(recipient.getAddress(), contentValues);
recipient.setNotificationChannel(notificationChannel);
+ notifyRecipientListeners();
}
public void setRegistered(@NonNull Recipient recipient, RegisteredState registeredState) {
@@ -346,6 +379,7 @@ public class RecipientDatabase extends Database {
contentValues.put(REGISTERED, registeredState.getId());
updateOrInsert(recipient.getAddress(), contentValues);
recipient.setRegistered(registeredState);
+ notifyRecipientListeners();
}
private void updateOrInsert(Address address, ContentValues contentValues) {
@@ -365,6 +399,22 @@ public class RecipientDatabase extends Database {
database.endTransaction();
}
+ public List getBlockedContacts() {
+ SQLiteDatabase database = databaseHelper.getReadableDatabase();
+
+ Cursor cursor = database.query(TABLE_NAME, new String[] {ID, ADDRESS}, BLOCK + " = 1",
+ null, null, null, null, null);
+
+ RecipientReader reader = new RecipientReader(context, cursor);
+ List returnList = new ArrayList<>();
+ Recipient current;
+ while ((current = reader.getNext()) != null) {
+ returnList.add(current);
+ }
+ reader.close();
+ return returnList;
+ }
+
public static class RecipientReader implements Closeable {
private final Context context;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
index 508cde51a3..62c79674f6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/Storage.kt
@@ -952,4 +952,14 @@ class Storage(context: Context, helper: SQLCipherOpenHelper) : Database(context,
DatabaseComponent.get(context).reactionDatabase().deleteMessageReactions(MessageId(messageId, mms))
}
+ override fun unblock(toUnblock: List) {
+ val recipientDb = DatabaseComponent.get(context).recipientDatabase()
+ recipientDb.setBlocked(toUnblock, false)
+ }
+
+ override fun blockedContacts(): List {
+ val recipientDb = DatabaseComponent.get(context).recipientDatabase()
+ return recipientDb.blockedContacts
+ }
+
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java
index 372f142f99..6ce69a591a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/database/model/ThreadRecord.java
@@ -50,6 +50,7 @@ public class ThreadRecord extends DisplayRecord {
private final long expiresIn;
private final long lastSeen;
private final boolean pinned;
+ private final int recipientHash;
public ThreadRecord(@NonNull String body, @Nullable Uri snippetUri,
@NonNull Recipient recipient, long date, long count, int unreadCount,
@@ -65,13 +66,18 @@ public class ThreadRecord extends DisplayRecord {
this.archived = archived;
this.expiresIn = expiresIn;
this.lastSeen = lastSeen;
- this.pinned = pinned;
+ this.pinned = pinned;
+ this.recipientHash = recipient.hashCode();
}
public @Nullable Uri getSnippetUri() {
return snippetUri;
}
+ public int getRecipientHash() {
+ return recipientHash;
+ }
+
@Override
public SpannableString getDisplayBody(@NonNull Context context) {
if (isGroupUpdateMessage()) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt b/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt
index ca78b572c5..69c9b8c4f5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/glide/PlaceholderAvatarLoader.kt
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.glide
-import android.content.Context
import android.graphics.drawable.BitmapDrawable
import com.bumptech.glide.load.Options
import com.bumptech.glide.load.model.ModelLoader
@@ -9,7 +8,7 @@ import com.bumptech.glide.load.model.ModelLoaderFactory
import com.bumptech.glide.load.model.MultiModelLoaderFactory
import org.session.libsession.avatars.PlaceholderAvatarPhoto
-class PlaceholderAvatarLoader(private val context: Context): ModelLoader {
+class PlaceholderAvatarLoader(): ModelLoader {
override fun buildLoadData(
model: PlaceholderAvatarPhoto,
@@ -17,14 +16,14 @@ class PlaceholderAvatarLoader(private val context: Context): ModelLoader {
- return LoadData(model, PlaceholderAvatarFetcher(context, model))
+ return LoadData(model, PlaceholderAvatarFetcher(model.context, model))
}
override fun handles(model: PlaceholderAvatarPhoto): Boolean = true
- class Factory(private val context: Context) : ModelLoaderFactory {
+ class Factory() : ModelLoaderFactory {
override fun build(multiFactory: MultiModelLoaderFactory): ModelLoader {
- return PlaceholderAvatarLoader(context)
+ return PlaceholderAvatarLoader()
}
override fun teardown() {}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/groups/CreateGroupFragment.kt b/app/src/main/java/org/thoughtcrime/securesms/groups/CreateGroupFragment.kt
index c195525ac0..ead979b773 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/groups/CreateGroupFragment.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/groups/CreateGroupFragment.kt
@@ -7,9 +7,12 @@ import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.Toast
+import androidx.core.content.ContextCompat
import androidx.core.view.isVisible
import androidx.fragment.app.Fragment
import androidx.fragment.app.viewModels
+import androidx.recyclerview.widget.DividerItemDecoration
+import androidx.recyclerview.widget.RecyclerView
import dagger.hilt.android.AndroidEntryPoint
import network.loki.messenger.R
import network.loki.messenger.databinding.FragmentCreateGroupBinding
@@ -57,6 +60,12 @@ class CreateGroupFragment : Fragment() {
}
binding.createNewPrivateChatButton.setOnClickListener { delegate.onNewMessageSelected() }
binding.recyclerView.adapter = adapter
+ val divider = ContextCompat.getDrawable(requireActivity(), R.drawable.conversation_menu_divider)!!.let {
+ DividerItemDecoration(requireActivity(), RecyclerView.VERTICAL).apply {
+ setDrawable(it)
+ }
+ }
+ binding.recyclerView.addItemDecoration(divider)
var isLoading = false
binding.createClosedGroupButton.setOnClickListener {
if (isLoading) return@setOnClickListener
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt
index 01a1a3241e..0b3c44a548 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationOptionsBottomSheet.kt
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms.home
+import android.content.Context
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
@@ -10,7 +11,7 @@ import network.loki.messenger.databinding.FragmentConversationBottomSheetBinding
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.util.UiModeUtilities
-class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClickListener {
+class ConversationOptionsBottomSheet(private val parentContext: Context) : BottomSheetDialogFragment(), View.OnClickListener {
private lateinit var binding: FragmentConversationBottomSheetBinding
//FIXME AC: Supplying a threadRecord directly into the field from an activity
// is not the best idea. It doesn't survive configuration change.
@@ -28,8 +29,8 @@ class ConversationOptionsBottomSheet : BottomSheetDialogFragment(), View.OnClick
var onNotificationTapped: (() -> Unit)? = null
var onSetMuteTapped: ((Boolean) -> Unit)? = null
- override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
- binding = FragmentConversationBottomSheetBinding.inflate(inflater, container, false)
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
+ binding = FragmentConversationBottomSheetBinding.inflate(LayoutInflater.from(parentContext), container, false)
return binding.root
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt
index 433d17f675..bfa9b14489 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/ConversationView.kt
@@ -3,6 +3,7 @@ package org.thoughtcrime.securesms.home
import android.content.Context
import android.content.res.Resources
import android.graphics.Typeface
+import android.graphics.drawable.ColorDrawable
import android.util.AttributeSet
import android.util.TypedValue
import android.view.LayoutInflater
@@ -20,6 +21,7 @@ import org.thoughtcrime.securesms.database.RecipientDatabase.NOTIFY_TYPE_NONE
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.util.DateUtils
+import org.thoughtcrime.securesms.util.getAccentColor
import java.util.Locale
class ConversationView : LinearLayout {
@@ -41,11 +43,19 @@ class ConversationView : LinearLayout {
// region Updating
fun bind(thread: ThreadRecord, isTyping: Boolean, glide: GlideRequests) {
this.thread = thread
- background = if (thread.isPinned) {
- binding.conversationViewDisplayNameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, R.drawable.ic_pin, 0)
- ContextCompat.getDrawable(context, R.drawable.conversation_pinned_background)
+ if (thread.isPinned) {
+ binding.conversationViewDisplayNameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(
+ 0,
+ 0,
+ R.drawable.ic_pin,
+ 0
+ )
} else {
binding.conversationViewDisplayNameTextView.setCompoundDrawablesRelativeWithIntrinsicBounds(0, 0, 0, 0)
+ }
+ background = if (thread.unreadCount > 0) {
+ ContextCompat.getDrawable(context, R.drawable.conversation_unread_background)
+ } else {
ContextCompat.getDrawable(context, R.drawable.conversation_view_background)
}
binding.profilePictureView.root.glide = glide
@@ -54,7 +64,9 @@ class ConversationView : LinearLayout {
binding.accentView.setBackgroundResource(R.color.destructive)
binding.accentView.visibility = View.VISIBLE
} else {
- binding.accentView.setBackgroundResource(R.color.accent)
+ val accentColor = context.getAccentColor()
+ val background = ColorDrawable(accentColor)
+ binding.accentView.background = background
// Using thread.isRead we can determine if the last message was our own, and display it as 'read' even though previous messages may not be
// This would also not trigger the disappearing message timer which may or may not be desirable
binding.accentView.visibility = if (unreadCount > 0 && !thread.isRead) View.VISIBLE else View.INVISIBLE
@@ -65,9 +77,9 @@ class ConversationView : LinearLayout {
if (unreadCount < 10000) unreadCount.toString() else "9999+"
}
binding.unreadCountTextView.text = formattedUnreadCount
- val textSize = if (unreadCount < 10000) 12.0f else 9.0f
+ val textSize = if (unreadCount < 1000) 12.0f else 10.0f
binding.unreadCountTextView.setTextSize(TypedValue.COMPLEX_UNIT_DIP, textSize)
- binding.unreadCountTextView.setTypeface(Typeface.DEFAULT, if (unreadCount < 100) Typeface.BOLD else Typeface.NORMAL)
+ binding.unreadCountIndicator.background.setTint(context.getAccentColor())
binding.unreadCountIndicator.isVisible = (unreadCount != 0 && !thread.isRead)
val senderDisplayName = getUserDisplayName(thread.recipient)
?: thread.recipient.address.toString()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
index 429bbd39f1..2544b2a1ef 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeActivity.kt
@@ -1,6 +1,5 @@
package org.thoughtcrime.securesms.home
-import android.app.AlertDialog
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
@@ -9,6 +8,7 @@ import android.os.Bundle
import android.text.SpannableString
import android.widget.Toast
import androidx.activity.viewModels
+import androidx.appcompat.app.AlertDialog
import androidx.core.os.bundleOf
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
@@ -64,7 +64,6 @@ import org.thoughtcrime.securesms.preferences.SettingsActivity
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.util.DateUtils
import org.thoughtcrime.securesms.util.IP2Country
-import org.thoughtcrime.securesms.util.UiModeUtilities
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.push
import org.thoughtcrime.securesms.util.show
@@ -167,7 +166,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
binding.seedReminderView.isVisible = false
}
setupMessageRequestsBanner()
- setupHeaderImage()
// Set up recycler view
binding.globalSearchInputLayout.listener = this
homeAdapter.setHasStableIds(true)
@@ -276,12 +274,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
EventBus.getDefault().register(this@HomeActivity)
}
- private fun setupHeaderImage() {
- val isDayUiMode = UiModeUtilities.isDayUiMode(this)
- val headerTint = if (isDayUiMode) R.color.black else R.color.white
- binding.sessionHeaderImage.setColorFilter(getColor(headerTint))
- }
-
override fun onInputFocusChanged(hasFocus: Boolean) {
if (hasFocus) {
setSearchShown(true)
@@ -296,7 +288,6 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
binding.recyclerView.isVisible = !isShown
binding.emptyStateContainer.isVisible = (binding.recyclerView.adapter as NewHomeAdapter).itemCount == 0 && binding.recyclerView.isVisible
binding.seedReminderView.isVisible = !TextSecurePreferences.getHasViewedSeed(this) && !isShown
- binding.gradientView.isVisible = !isShown
binding.globalSearchRecycler.isVisible = isShown
binding.newConversationButton.isVisible = !isShown
}
@@ -405,7 +396,7 @@ class HomeActivity : PassphraseRequiredActionBarActivity(),
}
override fun onLongConversationClick(thread: ThreadRecord) {
- val bottomSheet = ConversationOptionsBottomSheet()
+ val bottomSheet = ConversationOptionsBottomSheet(this)
bottomSheet.thread = thread
bottomSheet.onViewDetailsTapped = {
bottomSheet.dismiss()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/HomeDiffUtil.kt b/app/src/main/java/org/thoughtcrime/securesms/home/HomeDiffUtil.kt
index 23ea811c6b..fcaf565e0d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/HomeDiffUtil.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/HomeDiffUtil.kt
@@ -28,10 +28,8 @@ class HomeDiffUtil(
if (!sameUnreads) return false
val samePinned = oldItem.isPinned == newItem.isPinned
if (!samePinned) return false
- val sameAvatar = oldItem.recipient.profileAvatar == newItem.recipient.profileAvatar
- if (!sameAvatar) return false
- val sameUsername = oldItem.recipient.name == newItem.recipient.name
- if (!sameUsername) return false
+ val sameRecipientHash = oldItem.recipientHash == newItem.recipientHash
+ if (!sameRecipientHash) return false
val sameSnippet = oldItem.getDisplayBody(context) == newItem.getDisplayBody(context)
if (!sameSnippet) return false
val sameSendStatus = oldItem.isFailed == newItem.isFailed && oldItem.isDelivered == newItem.isDelivered
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt
index c76668c418..2922044435 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/PathActivity.kt
@@ -20,6 +20,7 @@ import androidx.localbroadcastmanager.content.LocalBroadcastManager
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityPathBinding
import org.session.libsession.snode.OnionRequestAPI
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsignal.utilities.Snode
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
import org.thoughtcrime.securesms.util.GlowViewUtilities
@@ -30,6 +31,7 @@ import org.thoughtcrime.securesms.util.animateSizeChange
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.fadeIn
import org.thoughtcrime.securesms.util.fadeOut
+import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.getColorWithID
class PathActivity : PassphraseRequiredActionBarActivity() {
@@ -131,7 +133,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
lineView.layoutParams = lineViewLayoutParams
mainContainer.addView(lineView)
val titleTextView = TextView(this)
- titleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
+ titleTextView.setTextColor(getColorFromAttr(android.R.attr.textColorPrimary))
titleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.medium_font_size))
titleTextView.text = title
titleTextView.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_START
@@ -144,7 +146,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
mainContainer.addView(titleContainer)
if (subtitle != null) {
val subtitleTextView = TextView(this)
- subtitleTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
+ subtitleTextView.setTextColor(getColorFromAttr(android.R.attr.textColorPrimary))
subtitleTextView.setTextSize(TypedValue.COMPLEX_UNIT_PX, resources.getDimension(R.dimen.small_font_size))
subtitleTextView.text = subtitle
subtitleTextView.textAlignment = TextView.TEXT_ALIGNMENT_VIEW_START
@@ -185,7 +187,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private val dotView by lazy {
val result = PathDotView(context)
result.setBackgroundResource(R.drawable.accent_dot)
- result.mainColor = resources.getColorWithID(R.color.accent, context.theme)
+ result.mainColor = context.getAccentColor()
result
}
@@ -219,7 +221,7 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private fun setUpViewHierarchy() {
disableClipping()
val lineView = View(context)
- lineView.setBackgroundColor(resources.getColorWithID(R.color.text, context.theme))
+ lineView.setBackgroundColor(context.getColorFromAttr(android.R.attr.textColorPrimary))
val lineViewHeight = when (location) {
Location.Top, Location.Bottom -> resources.getDimensionPixelSize(R.dimen.path_row_height) / 2
Location.Middle -> resources.getDimensionPixelSize(R.dimen.path_row_height)
@@ -255,13 +257,17 @@ class PathActivity : PassphraseRequiredActionBarActivity() {
private fun expand() {
dotView.animateSizeChange(R.dimen.path_row_dot_size, R.dimen.path_row_expanded_dot_size)
@ColorRes val startColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
- GlowViewUtilities.animateShadowColorChange(context, dotView, startColorID, R.color.accent)
+ val startColor = context.resources.getColorWithID(startColorID, context.theme)
+ val endColor = context.getAccentColor()
+ GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
}
private fun collapse() {
dotView.animateSizeChange(R.dimen.path_row_expanded_dot_size, R.dimen.path_row_dot_size)
@ColorRes val endColorID = if (UiModeUtilities.isDayUiMode(context)) R.color.transparent_black_30 else R.color.black
- GlowViewUtilities.animateShadowColorChange(context, dotView, R.color.accent, endColorID)
+ val startColor = context.getAccentColor()
+ val endColor = context.resources.getColorWithID(endColorID, context.theme)
+ GlowViewUtilities.animateShadowColorChange(dotView, startColor, endColor)
}
}
// endregion
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt b/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt
index 85d54a977f..947bd89b4e 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/PathStatusView.kt
@@ -6,10 +6,10 @@ import android.content.Intent
import android.content.IntentFilter
import android.graphics.Canvas
import android.graphics.Paint
-import androidx.localbroadcastmanager.content.LocalBroadcastManager
import android.util.AttributeSet
import android.view.View
import androidx.annotation.ColorInt
+import androidx.localbroadcastmanager.content.LocalBroadcastManager
import network.loki.messenger.R
import org.session.libsession.snode.OnionRequestAPI
import org.thoughtcrime.securesms.util.getColorWithID
@@ -46,7 +46,9 @@ class PathStatusView : View {
}
private fun initialize() {
- update()
+ if (!isInEditMode) {
+ update()
+ }
setWillNotDraw(false)
}
@@ -87,12 +89,14 @@ class PathStatusView : View {
private fun update() {
if (OnionRequestAPI.paths.isNotEmpty()) {
setBackgroundResource(R.drawable.accent_dot)
- mainColor = resources.getColorWithID(R.color.accent, context.theme)
- sessionShadowColor = resources.getColorWithID(R.color.accent, context.theme)
+ val hasPathsColor = context.getColor(R.color.accent_green)
+ mainColor = hasPathsColor
+ sessionShadowColor = hasPathsColor
} else {
setBackgroundResource(R.drawable.paths_building_dot)
- mainColor = resources.getColorWithID(R.color.paths_building, context.theme)
- sessionShadowColor = resources.getColorWithID(R.color.paths_building, context.theme)
+ val pathsBuildingColor = resources.getColorWithID(R.color.paths_building, context.theme)
+ mainColor = pathsBuildingColor
+ sessionShadowColor = pathsBuildingColor
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt
index 37e4a90dd8..f3915abff6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/home/UserDetailsBottomSheet.kt
@@ -6,6 +6,7 @@ import android.content.ClipboardManager
import android.content.Context
import android.content.Intent
import android.os.Bundle
+import android.view.ContextThemeWrapper
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
@@ -30,7 +31,7 @@ import org.thoughtcrime.securesms.util.UiModeUtilities
import javax.inject.Inject
@AndroidEntryPoint
-class UserDetailsBottomSheet : BottomSheetDialogFragment() {
+class UserDetailsBottomSheet: BottomSheetDialogFragment() {
@Inject lateinit var threadDb: ThreadDatabase
@@ -41,7 +42,9 @@ class UserDetailsBottomSheet : BottomSheetDialogFragment() {
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
- binding = FragmentUserDetailsBottomSheetBinding.inflate(inflater, container, false)
+ val wrappedContext = ContextThemeWrapper(requireActivity(), requireActivity().theme)
+ val themedInflater = inflater.cloneInContext(wrappedContext)
+ binding = FragmentUserDetailsBottomSheetBinding.inflate(themedInflater, container, false)
return binding.root
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt
index 13a4eb6ff0..07da14b090 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/keyboard/emoji/KeyboardPageSearchView.kt
@@ -95,7 +95,6 @@ class KeyboardPageSearchView @JvmOverloads constructor(
val iconTint = typedArray.getColorStateList(R.styleable.KeyboardPageSearchView_search_icon_tint) ?: ContextCompat.getColorStateList(context, R.color.signal_icon_tint_tab_selected)
ImageViewCompat.setImageTintList(navButton, iconTint)
ImageViewCompat.setImageTintList(clearButton, iconTint)
- input.setHintTextColor(iconTint)
val clickOnly: Boolean = typedArray.getBoolean(R.styleable.KeyboardPageSearchView_click_only, false)
if (clickOnly) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt
index 5e1895b96d..fac0a402e2 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/messagerequests/MessageRequestsAdapter.kt
@@ -5,11 +5,11 @@ import android.content.res.ColorStateList
import android.database.Cursor
import android.text.SpannableString
import android.text.style.ForegroundColorSpan
+import android.view.ContextThemeWrapper
import android.view.ViewGroup
import android.widget.PopupMenu
import androidx.recyclerview.widget.RecyclerView
import network.loki.messenger.R
-import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter
import org.thoughtcrime.securesms.database.model.ThreadRecord
import org.thoughtcrime.securesms.dependencies.DatabaseComponent
@@ -47,7 +47,7 @@ class MessageRequestsAdapter(
}
private fun showPopupMenu(view: MessageRequestView) {
- val popupMenu = PopupMenu(context, view)
+ val popupMenu = PopupMenu(ContextThemeWrapper(context, R.style.PopupMenu_MessageRequests), view)
popupMenu.menuInflater.inflate(R.menu.menu_message_request, popupMenu.menu)
popupMenu.setOnMenuItemClickListener { menuItem ->
if (menuItem.itemId == R.id.menu_delete_message_request) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java
index 02172b7248..0a24c26fad 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/mms/SignalGlideModule.java
@@ -73,7 +73,7 @@ public class SignalGlideModule extends AppGlideModule {
registry.append(DecryptableUri.class, InputStream.class, new DecryptableStreamUriLoader.Factory(context));
registry.append(AttachmentModel.class, InputStream.class, new AttachmentStreamUriLoader.Factory());
registry.append(ChunkedImageUrl.class, InputStream.class, new ChunkedImageUrlLoader.Factory());
- registry.append(PlaceholderAvatarPhoto.class, BitmapDrawable.class, new PlaceholderAvatarLoader.Factory(context));
+ registry.append(PlaceholderAvatarPhoto.class, BitmapDrawable.class, new PlaceholderAvatarLoader.Factory());
registry.replace(GlideUrl.class, InputStream.class, new OkHttpUrlLoader.Factory());
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java
index 549d6eac0a..64617eb6a1 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/AbstractNotificationBuilder.java
@@ -2,7 +2,6 @@ package org.thoughtcrime.securesms.notifications;
import android.app.Notification;
import android.content.Context;
-import android.graphics.Color;
import android.net.Uri;
import android.os.Bundle;
import android.text.SpannableStringBuilder;
@@ -65,17 +64,8 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
}
private void setLed() {
- String ledColor = TextSecurePreferences.getNotificationLedColor(context);
- String ledBlinkPattern = TextSecurePreferences.getNotificationLedPattern(context);
- String ledBlinkPatternCustom = TextSecurePreferences.getNotificationLedPatternCustom(context);
-
- if (!ledColor.equals("none")) {
- String[] blinkPatternArray = parseBlinkPattern(ledBlinkPattern, ledBlinkPatternCustom);
-
- setLights(Color.parseColor(ledColor),
- Integer.parseInt(blinkPatternArray[0]),
- Integer.parseInt(blinkPatternArray[1]));
- }
+ int ledColor = TextSecurePreferences.getNotificationLedColor(context);
+ setLights(ledColor, 500,2000);
}
public void setTicker(@NonNull Recipient recipient, @Nullable CharSequence message) {
@@ -88,13 +78,6 @@ public abstract class AbstractNotificationBuilder extends NotificationCompat.Bui
}
}
- private String[] parseBlinkPattern(String blinkPattern, String blinkPatternCustom) {
- if (blinkPattern.equals("custom"))
- blinkPattern = blinkPatternCustom;
-
- return blinkPattern.split(",");
- }
-
protected @NonNull CharSequence trimToDisplayLength(@Nullable CharSequence text) {
text = text == null ? "" : text;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java
index 61c126339d..8bf1d7d8d8 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/NotificationChannels.java
@@ -1,13 +1,11 @@
package org.thoughtcrime.securesms.notifications;
import android.annotation.TargetApi;
-import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
-import android.graphics.Color;
import android.media.AudioAttributes;
import android.net.Uri;
import android.os.AsyncTask;
@@ -221,7 +219,7 @@ public class NotificationChannels {
* channels. Performs database operations and should therefore be invoked on a background thread.
*/
@WorkerThread
- public static synchronized void updateMessagesLedColor(@NonNull Context context, @NonNull String color) {
+ public static synchronized void updateMessagesLedColor(@NonNull Context context, @NonNull Integer color) {
if (!supported()) {
return;
}
@@ -472,12 +470,12 @@ public class NotificationChannels {
}
@TargetApi(26)
- private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull String ledColor) {
+ private static void setLedPreference(@NonNull NotificationChannel channel, @NonNull Integer ledColor) {
if ("none".equals(ledColor)) {
channel.enableLights(false);
} else {
channel.enableLights(true);
- channel.setLightColor(Color.parseColor(ledColor));
+ channel.setLightColor(ledColor);
}
}
@@ -509,7 +507,7 @@ public class NotificationChannels {
@WorkerThread
@TargetApi(26)
- private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull String color) {
+ private static void updateAllRecipientChannelLedColors(@NonNull Context context, @NonNull NotificationManager notificationManager, @NonNull Integer color) {
RecipientDatabase database = DatabaseComponent.get(context).recipientDatabase();
try (RecipientDatabase.RecipientReader recipients = database.getRecipientsWithNotificationChannels()) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java
index b461081cfe..7925b8556a 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/notifications/SingleRecipientNotificationBuilder.java
@@ -22,6 +22,7 @@ import androidx.annotation.StringRes;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationCompat.Action;
import androidx.core.app.RemoteInput;
+import androidx.core.content.ContextCompat;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
@@ -63,9 +64,8 @@ public class SingleRecipientNotificationBuilder extends AbstractNotificationBuil
{
super(context, privacy);
-
setSmallIcon(R.drawable.ic_notification);
- setColor(context.getResources().getColor(R.color.textsecure_primary));
+ setColor(ContextCompat.getColor(context, R.color.accent_green));
setCategory(NotificationCompat.CATEGORY_MESSAGE);
if (!NotificationChannels.supported()) {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/PNModeActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/PNModeActivity.kt
index c081e8fa90..92583d89e5 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/PNModeActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/PNModeActivity.kt
@@ -11,20 +11,22 @@ import android.view.Menu
import android.view.MenuItem
import android.view.View
import android.widget.Toast
-import androidx.annotation.ColorRes
+import androidx.annotation.ColorInt
import androidx.annotation.DrawableRes
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivityPnModeBinding
import org.session.libsession.utilities.TextSecurePreferences
+import org.session.libsession.utilities.ThemeUtil
import org.thoughtcrime.securesms.ApplicationContext
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.home.HomeActivity
+import org.thoughtcrime.securesms.util.GlowViewUtilities
+import org.thoughtcrime.securesms.util.PNModeView
import org.thoughtcrime.securesms.util.disableClipping
+import org.thoughtcrime.securesms.util.getAccentColor
import org.thoughtcrime.securesms.util.getColorWithID
import org.thoughtcrime.securesms.util.setUpActionBarSessionLogo
import org.thoughtcrime.securesms.util.show
-import org.thoughtcrime.securesms.util.GlowViewUtilities
-import org.thoughtcrime.securesms.util.PNModeView
class PNModeActivity : BaseActionBarActivity() {
private lateinit var binding: ActivityPnModeBinding
@@ -40,10 +42,10 @@ class PNModeActivity : BaseActionBarActivity() {
with(binding) {
contentView.disableClipping()
fcmOptionView.setOnClickListener { toggleFCM() }
- fcmOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
+ fcmOptionView.mainColor = ThemeUtil.getThemedColor(root.context, R.attr.colorPrimary)
fcmOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
backgroundPollingOptionView.setOnClickListener { toggleBackgroundPolling() }
- backgroundPollingOptionView.mainColor = resources.getColorWithID(R.color.pn_option_background, theme)
+ backgroundPollingOptionView.mainColor = ThemeUtil.getThemedColor(root.context, R.attr.colorPrimary)
backgroundPollingOptionView.strokeColor = resources.getColorWithID(R.color.pn_option_border, theme)
registerButton.setOnClickListener { register() }
}
@@ -84,60 +86,60 @@ class PNModeActivity : BaseActionBarActivity() {
}
private fun toggleFCM() = with(binding) {
+ val accentColor = getAccentColor()
when (selectedOptionView) {
null -> {
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, fcmOptionView, R.color.transparent, R.color.accent)
- animateStrokeColorChange(fcmOptionView, R.color.pn_option_border, R.color.accent)
+ GlowViewUtilities.animateShadowColorChange(fcmOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor)
+ animateStrokeColorChange(fcmOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor)
selectedOptionView = fcmOptionView
}
fcmOptionView -> {
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, fcmOptionView, R.color.accent, R.color.transparent)
- animateStrokeColorChange(fcmOptionView, R.color.accent, R.color.pn_option_border)
+ GlowViewUtilities.animateShadowColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme))
+ animateStrokeColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme))
selectedOptionView = null
}
backgroundPollingOptionView -> {
performTransition(R.drawable.pn_option_background_select_transition, fcmOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, fcmOptionView, R.color.transparent, R.color.accent)
- animateStrokeColorChange(fcmOptionView, R.color.pn_option_border, R.color.accent)
+ GlowViewUtilities.animateShadowColorChange(fcmOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor)
+ animateStrokeColorChange(fcmOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor)
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, backgroundPollingOptionView, R.color.accent, R.color.transparent)
- animateStrokeColorChange(backgroundPollingOptionView, R.color.accent, R.color.pn_option_border)
+ GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme))
+ animateStrokeColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme))
selectedOptionView = fcmOptionView
}
}
}
private fun toggleBackgroundPolling() = with(binding) {
+ val accentColor = getAccentColor()
when (selectedOptionView) {
null -> {
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, backgroundPollingOptionView, R.color.transparent, R.color.accent)
- animateStrokeColorChange(backgroundPollingOptionView, R.color.pn_option_border, R.color.accent)
+ GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor)
+ animateStrokeColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor)
selectedOptionView = backgroundPollingOptionView
}
backgroundPollingOptionView -> {
performTransition(R.drawable.pn_option_background_deselect_transition, backgroundPollingOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, backgroundPollingOptionView, R.color.accent, R.color.transparent)
- animateStrokeColorChange(backgroundPollingOptionView, R.color.accent, R.color.pn_option_border)
+ GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme))
+ animateStrokeColorChange(backgroundPollingOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme))
selectedOptionView = null
}
fcmOptionView -> {
performTransition(R.drawable.pn_option_background_select_transition, backgroundPollingOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, backgroundPollingOptionView, R.color.transparent, R.color.accent)
- animateStrokeColorChange(backgroundPollingOptionView, R.color.pn_option_border, R.color.accent)
+ GlowViewUtilities.animateShadowColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.transparent, theme), accentColor)
+ animateStrokeColorChange(backgroundPollingOptionView, resources.getColorWithID(R.color.pn_option_border, theme), accentColor)
performTransition(R.drawable.pn_option_background_deselect_transition, fcmOptionView)
- GlowViewUtilities.animateShadowColorChange(this@PNModeActivity, fcmOptionView, R.color.accent, R.color.transparent)
- animateStrokeColorChange(fcmOptionView, R.color.accent, R.color.pn_option_border)
+ GlowViewUtilities.animateShadowColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.transparent, theme))
+ animateStrokeColorChange(fcmOptionView, accentColor, resources.getColorWithID(R.color.pn_option_border, theme))
selectedOptionView = backgroundPollingOptionView
}
}
}
- private fun animateStrokeColorChange(bubble: PNModeView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
- val startColor = resources.getColorWithID(startColorID, theme)
- val endColor = resources.getColorWithID(endColorID, theme)
+ private fun animateStrokeColorChange(bubble: PNModeView, @ColorInt startColor: Int, @ColorInt endColor: Int) {
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
animation.duration = 250
animation.addUpdateListener { animator ->
diff --git a/app/src/main/java/org/thoughtcrime/securesms/onboarding/SeedActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/onboarding/SeedActivity.kt
index b179ce852c..0eab58fa0c 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/onboarding/SeedActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/onboarding/SeedActivity.kt
@@ -12,12 +12,13 @@ import android.widget.Toast
import network.loki.messenger.R
import network.loki.messenger.databinding.ActivitySeedBinding
import org.session.libsession.utilities.TextSecurePreferences
+import org.session.libsession.utilities.getColorFromAttr
import org.session.libsignal.crypto.MnemonicCodec
import org.session.libsignal.utilities.hexEncodedPrivateKey
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil
import org.thoughtcrime.securesms.crypto.MnemonicUtilities
-import org.thoughtcrime.securesms.util.getColorWithID
+import org.thoughtcrime.securesms.util.getAccentColor
class SeedActivity : BaseActionBarActivity() {
@@ -41,7 +42,7 @@ class SeedActivity : BaseActionBarActivity() {
setContentView(binding.root)
supportActionBar!!.title = resources.getString(R.string.activity_seed_title)
val seedReminderViewTitle = SpannableString("You're almost finished! 90%") // Intentionally not yet translated
- seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+ seedReminderViewTitle.setSpan(ForegroundColorSpan(getAccentColor()), 24, 27, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
with(binding) {
seedReminderView.title = seedReminderViewTitle
seedReminderView.subtitle = resources.getString(R.string.view_seed_reminder_subtitle_2)
@@ -55,7 +56,7 @@ class SeedActivity : BaseActionBarActivity() {
}
index += 1
}
- seedTextView.setTextColor(resources.getColorWithID(R.color.accent, theme))
+ seedTextView.setTextColor(getAccentColor())
seedTextView.text = redactedSeed
seedTextView.setOnLongClickListener { revealSeed(); true }
revealButton.setOnLongClickListener { revealSeed(); true }
@@ -67,7 +68,7 @@ class SeedActivity : BaseActionBarActivity() {
// region Updating
private fun revealSeed() {
val seedReminderViewTitle = SpannableString("Account secured! 100%") // Intentionally not yet translated
- seedReminderViewTitle.setSpan(ForegroundColorSpan(resources.getColorWithID(R.color.accent, theme)), 17, 21, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
+ seedReminderViewTitle.setSpan(ForegroundColorSpan(getAccentColor()), 17, 21, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
with(binding) {
seedReminderView.title = seedReminderViewTitle
seedReminderView.subtitle = resources.getString(R.string.view_seed_reminder_subtitle_3)
@@ -75,7 +76,7 @@ class SeedActivity : BaseActionBarActivity() {
val seedTextViewLayoutParams = seedTextView.layoutParams as LinearLayout.LayoutParams
seedTextViewLayoutParams.height = seedTextView.height
seedTextView.layoutParams = seedTextViewLayoutParams
- seedTextView.setTextColor(resources.getColorWithID(R.color.text, theme))
+ seedTextView.setTextColor(getColorFromAttr(android.R.attr.textColorPrimary))
seedTextView.text = seed
}
TextSecurePreferences.setHasViewedSeed(this, true)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java b/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java
index f2adf32cd3..999dad001d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/permissions/Permissions.java
@@ -22,8 +22,8 @@ import androidx.fragment.app.Fragment;
import com.annimon.stream.Stream;
import com.annimon.stream.function.Consumer;
-import org.thoughtcrime.securesms.util.LRUCache;
import org.session.libsession.utilities.ServiceUtil;
+import org.thoughtcrime.securesms.util.LRUCache;
import java.lang.ref.WeakReference;
import java.security.SecureRandom;
@@ -353,7 +353,7 @@ public class Permissions {
Context context = this.context.get();
if (context != null) {
- new AlertDialog.Builder(context)
+ new AlertDialog.Builder(context, R.style.ThemeOverlay_Session_AlertDialog)
.setTitle(R.string.Permissions_permission_required)
.setMessage(message)
.setPositiveButton(R.string.Permissions_continue, (dialog, which) -> context.startActivity(getApplicationSettingsIntent(context)))
diff --git a/app/src/main/java/org/thoughtcrime/securesms/permissions/RationaleDialog.java b/app/src/main/java/org/thoughtcrime/securesms/permissions/RationaleDialog.java
index e1d1d192bb..a346d591ac 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/permissions/RationaleDialog.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/permissions/RationaleDialog.java
@@ -4,8 +4,6 @@ package org.thoughtcrime.securesms.permissions;
import android.app.AlertDialog;
import android.content.Context;
import android.graphics.Color;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.NonNull;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@@ -14,13 +12,18 @@ import android.widget.ImageView;
import android.widget.LinearLayout.LayoutParams;
import android.widget.TextView;
-import network.loki.messenger.R;
+import androidx.annotation.DrawableRes;
+import androidx.annotation.NonNull;
+
import org.session.libsession.utilities.ViewUtil;
+import network.loki.messenger.R;
+
public class RationaleDialog {
public static AlertDialog.Builder createFor(@NonNull Context context, @NonNull String message, @DrawableRes int... drawables) {
View view = LayoutInflater.from(context).inflate(R.layout.permissions_rationale_dialog, null);
+ view.setClipToOutline(true);
ViewGroup header = view.findViewById(R.id.header_container);
TextView text = view.findViewById(R.id.message);
@@ -47,7 +50,7 @@ public class RationaleDialog {
text.setText(message);
- return new AlertDialog.Builder(context, R.style.Theme_TextSecure_Dialog_Rationale).setView(view);
+ return new AlertDialog.Builder(context, R.style.ThemeOverlay_Session_AlertDialog).setView(view);
}
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt
new file mode 100644
index 0000000000..504194d3a4
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsActivity.kt
@@ -0,0 +1,87 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.app.AlertDialog
+import android.os.Bundle
+import android.view.View
+import androidx.activity.viewModels
+import androidx.core.view.isVisible
+import dagger.hilt.android.AndroidEntryPoint
+import network.loki.messenger.R
+import network.loki.messenger.databinding.ActivityBlockedContactsBinding
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+
+@AndroidEntryPoint
+class BlockedContactsActivity: PassphraseRequiredActionBarActivity(), View.OnClickListener {
+
+ lateinit var binding: ActivityBlockedContactsBinding
+
+ val viewModel: BlockedContactsViewModel by viewModels()
+
+ val adapter = BlockedContactsAdapter()
+
+ override fun onClick(v: View?) {
+ if (v === binding.unblockButton && adapter.getSelectedItems().isNotEmpty()) {
+ val contactsToUnblock = adapter.getSelectedItems()
+ // show dialog
+ val title = if (contactsToUnblock.size == 1) {
+ getString(R.string.Unblock_dialog__title_single, contactsToUnblock.first().name)
+ } else {
+ getString(R.string.Unblock_dialog__title_multiple)
+ }
+
+ val message = if (contactsToUnblock.size == 1) {
+ getString(R.string.Unblock_dialog__message, contactsToUnblock.first().name)
+ } else {
+ val stringBuilder = StringBuilder()
+ val iterator = contactsToUnblock.iterator()
+ var numberAdded = 0
+ while (iterator.hasNext() && numberAdded < 3) {
+ val nextRecipient = iterator.next()
+ if (numberAdded > 0) stringBuilder.append(", ")
+
+ stringBuilder.append(nextRecipient.name)
+ numberAdded++
+ }
+ val overflow = contactsToUnblock.size - numberAdded
+ if (overflow > 0) {
+ stringBuilder.append(" ")
+ val string = resources.getQuantityString(R.plurals.Unblock_dialog__message_multiple_overflow, overflow)
+ stringBuilder.append(string.format(overflow))
+ }
+ getString(R.string.Unblock_dialog__message, stringBuilder.toString())
+ }
+
+ AlertDialog.Builder(this)
+ .setTitle(title)
+ .setMessage(message)
+ .setPositiveButton(R.string.continue_2) { d, _ ->
+ viewModel.unblock(contactsToUnblock)
+ d.dismiss()
+ }
+ .setNegativeButton(R.string.cancel) { d, _ ->
+ d.dismiss()
+ }
+ .show()
+ }
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
+ super.onCreate(savedInstanceState, ready)
+ binding = ActivityBlockedContactsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+
+ binding.recyclerView.adapter = adapter
+
+ viewModel.subscribe(this)
+ .observe(this) { newState ->
+ adapter.submitList(newState.blockedContacts)
+ val isEmpty = newState.blockedContacts.isEmpty()
+ binding.emptyStateMessageTextView.isVisible = isEmpty
+ binding.nonEmptyStateGroup.isVisible = !isEmpty
+ }
+
+ binding.unblockButton.setOnClickListener(this)
+
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt
new file mode 100644
index 0000000000..50af49b557
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsAdapter.kt
@@ -0,0 +1,68 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import network.loki.messenger.R
+import network.loki.messenger.databinding.BlockedContactLayoutBinding
+import org.session.libsession.utilities.recipients.Recipient
+import org.thoughtcrime.securesms.mms.GlideApp
+
+class BlockedContactsAdapter: ListAdapter(RecipientDiffer()) {
+
+ class RecipientDiffer: DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem === newItem
+ override fun areContentsTheSame(oldItem: Recipient, newItem: Recipient) = oldItem == newItem
+ }
+
+ private val selectedItems = mutableListOf()
+
+ fun getSelectedItems() = selectedItems
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val itemView = LayoutInflater.from(parent.context).inflate(R.layout.blocked_contact_layout, parent, false)
+ return ViewHolder(itemView)
+ }
+
+ private fun toggleSelection(recipient: Recipient, isSelected: Boolean, position: Int) {
+ if (isSelected) {
+ selectedItems -= recipient
+ } else {
+ selectedItems += recipient
+ }
+ notifyItemChanged(position)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val recipient = getItem(position)
+ val isSelected = recipient in selectedItems
+ holder.bind(recipient, isSelected) {
+ toggleSelection(recipient, isSelected, position)
+ }
+ }
+
+ override fun onViewRecycled(holder: ViewHolder) {
+ super.onViewRecycled(holder)
+ holder.binding.profilePictureView.root.recycle()
+ }
+
+ class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
+
+ val glide = GlideApp.with(itemView)
+ val binding = BlockedContactLayoutBinding.bind(itemView)
+
+ fun bind(recipient: Recipient, isSelected: Boolean, toggleSelection: () -> Unit) {
+ binding.recipientName.text = recipient.name
+ with (binding.profilePictureView.root) {
+ glide = this@ViewHolder.glide
+ update(recipient)
+ }
+ binding.root.setOnClickListener { toggleSelection() }
+ binding.selectButton.isSelected = isSelected
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsLayout.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsLayout.kt
new file mode 100644
index 0000000000..ed2970fbc4
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsLayout.kt
@@ -0,0 +1,9 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+class BlockedContactsLayout @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null
+) : FrameLayout(context, attrs)
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt
new file mode 100644
index 0000000000..254d34978d
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsPreference.kt
@@ -0,0 +1,28 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.content.Context
+import android.content.Intent
+import android.util.AttributeSet
+import android.view.View
+import androidx.preference.PreferenceCategory
+import androidx.preference.PreferenceViewHolder
+
+class BlockedContactsPreference @JvmOverloads constructor(
+ context: Context,
+ attributeSet: AttributeSet? = null) : PreferenceCategory(context, attributeSet), View.OnClickListener {
+
+ override fun onClick(v: View?) {
+ if (v is BlockedContactsLayout) {
+ val intent = Intent(context, BlockedContactsActivity::class.java)
+ context.startActivity(intent)
+ }
+ }
+
+ override fun onBindViewHolder(holder: PreferenceViewHolder) {
+ super.onBindViewHolder(holder)
+
+ val itemView = holder.itemView
+ itemView.setOnClickListener(this)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt
new file mode 100644
index 0000000000..9c0a436ebb
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/BlockedContactsViewModel.kt
@@ -0,0 +1,65 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.content.Context
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import app.cash.copper.flow.observeQuery
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.Dispatchers.IO
+import kotlinx.coroutines.Dispatchers.Main
+import kotlinx.coroutines.SupervisorJob
+import kotlinx.coroutines.channels.Channel
+import kotlinx.coroutines.flow.collect
+import kotlinx.coroutines.flow.onEach
+import kotlinx.coroutines.flow.onStart
+import kotlinx.coroutines.launch
+import kotlinx.coroutines.plus
+import kotlinx.coroutines.withContext
+import org.session.libsession.utilities.recipients.Recipient
+import org.thoughtcrime.securesms.database.DatabaseContentProviders
+import org.thoughtcrime.securesms.database.Storage
+import javax.inject.Inject
+
+@HiltViewModel
+class BlockedContactsViewModel @Inject constructor(private val storage: Storage): ViewModel() {
+
+ private val executor = viewModelScope + SupervisorJob()
+
+ private val listUpdateChannel = Channel(capacity = Channel.CONFLATED)
+
+ private val _contacts = MutableLiveData(BlockedContactsViewState(emptyList()))
+
+ fun subscribe(context: Context): LiveData {
+ executor.launch(IO) {
+ context.contentResolver
+ .observeQuery(DatabaseContentProviders.Recipient.CONTENT_URI)
+ .onStart {
+ listUpdateChannel.trySend(Unit)
+ }
+ .onEach {
+ listUpdateChannel.trySend(Unit)
+ }
+ .collect()
+ }
+ executor.launch(IO) {
+ for (update in listUpdateChannel) {
+ val blockedContactState = BlockedContactsViewState(storage.blockedContacts().sortedBy { it.name })
+ withContext(Main) {
+ _contacts.value = blockedContactState
+ }
+ }
+ }
+ return _contacts
+ }
+
+ fun unblock(toUnblock: List) {
+ storage.unblock(toUnblock)
+ }
+
+ data class BlockedContactsViewState(
+ val blockedContacts: List
+ )
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ChangeUiModeDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ChangeUiModeDialog.kt
index 594d1b47f7..3d5b9e2e99 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ChangeUiModeDialog.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ChangeUiModeDialog.kt
@@ -2,11 +2,7 @@ package org.thoughtcrime.securesms.preferences
import android.app.Dialog
import android.os.Bundle
-import androidx.appcompat.app.AlertDialog
import androidx.fragment.app.DialogFragment
-import network.loki.messenger.R
-import org.thoughtcrime.securesms.util.UiMode
-import org.thoughtcrime.securesms.util.UiModeUtilities
class ChangeUiModeDialog : DialogFragment() {
@@ -16,19 +12,8 @@ class ChangeUiModeDialog : DialogFragment() {
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
val context = requireContext()
-
- val displayNameList = UiMode.values().map { getString(it.displayNameRes) }.toTypedArray()
- val activeUiMode = UiModeUtilities.getUserSelectedUiMode(context)
-
- return AlertDialog.Builder(context)
- .setSingleChoiceItems(displayNameList, activeUiMode.ordinal) { _, selectedItemIdx: Int ->
- val uiMode = UiMode.values()[selectedItemIdx]
- UiModeUtilities.setUserSelectedUiMode(context, uiMode)
- dismiss()
- requireActivity().recreate()
- }
- .setTitle(R.string.dialog_ui_mode_title)
- .setNegativeButton(R.string.cancel) { _, _ -> dismiss() }
- .create()
+ return android.app.AlertDialog.Builder(context)
+ .setTitle("TODO: remove this")
+ .show()
}
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ChatSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ChatSettingsActivity.kt
index 67faa9da46..6852d2f63f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ChatSettingsActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ChatSettingsActivity.kt
@@ -3,14 +3,13 @@ package org.thoughtcrime.securesms.preferences
import android.os.Bundle
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
-import org.thoughtcrime.securesms.preferences.ChatsPreferenceFragment
class ChatSettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
super.onCreate(savedInstanceState, isReady)
setContentView(R.layout.activity_fragment_wrapper)
- supportActionBar!!.title = resources.getString(R.string.activity_chat_settings_title)
+ supportActionBar!!.title = resources.getString(R.string.activity_conversations_settings_title)
val fragment = ChatsPreferenceFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragmentContainer, fragment)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt
index d4d30d864b..560c137104 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ClearAllDataDialog.kt
@@ -2,8 +2,10 @@ package org.thoughtcrime.securesms.preferences
import android.view.LayoutInflater
import androidx.appcompat.app.AlertDialog
+import androidx.core.view.isGone
import androidx.core.view.isVisible
import androidx.lifecycle.lifecycleScope
+import androidx.recyclerview.widget.DividerItemDecoration
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
@@ -13,8 +15,8 @@ import network.loki.messenger.databinding.DialogClearAllDataBinding
import org.session.libsession.snode.SnodeAPI
import org.session.libsignal.utilities.Log
import org.thoughtcrime.securesms.ApplicationContext
-import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
+import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
class ClearAllDataDialog : BaseDialog() {
private lateinit var binding: DialogClearAllDataBinding
@@ -26,9 +28,6 @@ class ClearAllDataDialog : BaseDialog() {
}
var clearJob: Job? = null
- set(value) {
- field = value
- }
var step = Steps.INFO_PROMPT
set(value) {
@@ -38,19 +37,27 @@ class ClearAllDataDialog : BaseDialog() {
override fun setContentView(builder: AlertDialog.Builder) {
binding = DialogClearAllDataBinding.inflate(LayoutInflater.from(requireContext()))
+ val device = RadioOption("deviceOnly", requireContext().getString(R.string.dialog_clear_all_data_clear_device_only))
+ val network = RadioOption("deviceAndNetwork", requireContext().getString(R.string.dialog_clear_all_data_clear_device_and_network))
+ var selectedOption = device
+ val optionAdapter = RadioOptionAdapter { selectedOption = it }
+ binding.recyclerView.apply {
+ adapter = optionAdapter
+ addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL))
+ setHasFixedSize(true)
+ }
+ optionAdapter.submitList(listOf(device, network))
binding.cancelButton.setOnClickListener {
- if (step == Steps.NETWORK_PROMPT) {
- clearAllData(false)
- } else if (step != Steps.DELETING) {
- dismiss()
- }
+ dismiss()
}
binding.clearAllDataButton.setOnClickListener {
when(step) {
- Steps.INFO_PROMPT -> step = Steps.NETWORK_PROMPT
- Steps.NETWORK_PROMPT -> {
- clearAllData(true)
+ Steps.INFO_PROMPT -> if (selectedOption == network) {
+ step = Steps.NETWORK_PROMPT
+ } else {
+ clearAllData(false)
}
+ Steps.NETWORK_PROMPT -> clearAllData(true)
Steps.DELETING -> { /* do nothing intentionally */ }
}
}
@@ -64,17 +71,14 @@ class ClearAllDataDialog : BaseDialog() {
when (step) {
Steps.INFO_PROMPT -> {
- binding.dialogDescriptionText.setText(R.string.dialog_clear_all_data_explanation)
- binding.cancelButton.setText(R.string.cancel)
- binding.clearAllDataButton.setText(R.string.delete)
+ binding.dialogDescriptionText.setText(R.string.dialog_clear_all_data_message)
}
- else -> {
- binding.dialogDescriptionText.setText(R.string.dialog_clear_all_data_network_explanation)
- binding.cancelButton.setText(R.string.dialog_clear_all_data_local_only)
- binding.clearAllDataButton.setText(R.string.dialog_clear_all_data_clear_network)
+ Steps.NETWORK_PROMPT -> {
+ binding.dialogDescriptionText.setText(R.string.dialog_clear_all_data_clear_device_and_network_confirmation)
}
+ Steps.DELETING -> { /* do nothing intentionally */ }
}
-
+ binding.recyclerView.isGone = step == Steps.NETWORK_PROMPT
binding.cancelButton.isVisible = !isLoading
binding.clearAllDataButton.isVisible = !isLoading
binding.progressBar.isVisible = isLoading
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java
index 7bf9672374..badcbe66b8 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/CorrectedPreferenceFragment.java
@@ -2,9 +2,18 @@ package org.thoughtcrime.securesms.preferences;
import android.annotation.SuppressLint;
+import android.content.Context;
+import android.graphics.Typeface;
+import android.graphics.drawable.Drawable;
import android.os.Bundle;
-import androidx.fragment.app.DialogFragment;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.TextView;
+
+import androidx.annotation.NonNull;
+import androidx.core.content.ContextCompat;
import androidx.core.view.ViewCompat;
+import androidx.fragment.app.DialogFragment;
import androidx.preference.Preference;
import androidx.preference.PreferenceCategory;
import androidx.preference.PreferenceFragmentCompat;
@@ -12,19 +21,30 @@ import androidx.preference.PreferenceGroupAdapter;
import androidx.preference.PreferenceScreen;
import androidx.preference.PreferenceViewHolder;
import androidx.recyclerview.widget.RecyclerView;
-import android.view.View;
-import android.view.ViewGroup;
-import network.loki.messenger.R;
import org.thoughtcrime.securesms.components.CustomDefaultPreference;
+import org.thoughtcrime.securesms.conversation.v2.ViewUtil;
import org.thoughtcrime.securesms.preferences.widgets.ColorPickerPreference;
import org.thoughtcrime.securesms.preferences.widgets.ColorPickerPreferenceDialogFragmentCompat;
+import network.loki.messenger.R;
+
public abstract class CorrectedPreferenceFragment extends PreferenceFragmentCompat {
+ public static final int SINGLE_TYPE = 21;
+ public static final int TOP_TYPE = 22;
+ public static final int MIDDLE_TYPE = 23;
+ public static final int BOTTOM_TYPE = 24;
+ public static final int CATEGORY_TYPE = 25;
+
+ public int horizontalPadding;
+ public int verticalPadding;
+
@Override
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
+ horizontalPadding = ViewUtil.dpToPx(requireContext(), 36);
+ verticalPadding = ViewUtil.dpToPx(requireContext(), 8);
}
@Override
@@ -33,6 +53,7 @@ public abstract class CorrectedPreferenceFragment extends PreferenceFragmentComp
View lv = getView().findViewById(android.R.id.list);
if (lv != null) lv.setPadding(0, 0, 0, 0);
+ setDivider(null);
}
@Override
@@ -57,17 +78,100 @@ public abstract class CorrectedPreferenceFragment extends PreferenceFragmentComp
@SuppressLint("RestrictedApi")
protected RecyclerView.Adapter onCreateAdapter(PreferenceScreen preferenceScreen) {
return new PreferenceGroupAdapter(preferenceScreen) {
+
+ @NonNull
+ @Override
+ public PreferenceViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
+ PreferenceViewHolder viewHolder = super.onCreateViewHolder(parent, viewType);
+ return viewHolder;
+ }
+
+ private int getPreferenceType(int position) {
+ Preference preference = getItem(position);
+ if (preference instanceof PreferenceCategory) {
+ return CATEGORY_TYPE;
+ }
+ boolean isStart = isTop(position);
+ boolean isEnd = isBottom(position);
+ if (isStart && isEnd) {
+ // always show full
+ return SINGLE_TYPE;
+ } else {
+ if (isStart) {
+ return TOP_TYPE;
+ } else if (isEnd) {
+ return BOTTOM_TYPE;
+ } else {
+ return MIDDLE_TYPE;
+ }
+ }
+ }
+
+ private boolean isTop(int position) {
+ if (position == 0) {
+ return true;
+ }
+ Preference previous = getItem(position - 1);
+ return previous instanceof PreferenceCategory;
+ }
+
+ private boolean isBottom(int position) {
+ int size = getItemCount();
+ if (position == size - 1) {
+ // last one
+ return true;
+ }
+ Preference next = getItem(position + 1);
+ return next instanceof PreferenceCategory;
+ }
+
+ public Drawable getBackground(Context context, int position) {
+ int viewType = getPreferenceType(position);
+ Drawable background;
+ switch (viewType) {
+ case SINGLE_TYPE:
+ background = ContextCompat.getDrawable(context, R.drawable.preference_single);
+ break;
+ case TOP_TYPE:
+ background = ContextCompat.getDrawable(context, R.drawable.preference_top);
+ break;
+ case MIDDLE_TYPE:
+ background = ContextCompat.getDrawable(context, R.drawable.preference_middle);
+ break;
+ case BOTTOM_TYPE:
+ background = ContextCompat.getDrawable(context, R.drawable.preference_bottom);
+ break;
+ default:
+ background = null;
+ break;
+ }
+ return background;
+ }
+
@Override
public void onBindViewHolder(PreferenceViewHolder holder, int position) {
super.onBindViewHolder(holder, position);
Preference preference = getItem(position);
if (preference instanceof PreferenceCategory) {
+ ViewGroup.MarginLayoutParams layoutParams = (ViewGroup.MarginLayoutParams) holder.itemView.getLayoutParams();
+ layoutParams.topMargin = 0;
+ layoutParams.bottomMargin = 0;
+ holder.itemView.setLayoutParams(layoutParams);
setZeroPaddingToLayoutChildren(holder.itemView);
} else {
View iconFrame = holder.itemView.findViewById(R.id.icon_frame);
if (iconFrame != null) {
iconFrame.setVisibility(preference.getIcon() == null ? View.GONE : View.VISIBLE);
}
+ Drawable background = getBackground(holder.itemView.getContext(), position);
+ holder.itemView.setBackground(background);
+ TextView titleView = holder.itemView.findViewById(android.R.id.title);
+ if (titleView != null) {
+ ((TextView) titleView).setTypeface(Typeface.defaultFromStyle(Typeface.BOLD));
+ }
+ boolean isTop = isTop(position);
+ boolean isBottom = isBottom(position);
+ holder.itemView.setPadding(horizontalPadding, isTop ? verticalPadding : 0, horizontalPadding, isBottom ? verticalPadding : 0);
}
}
};
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/HelpSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/HelpSettingsActivity.kt
new file mode 100644
index 0000000000..90ffbd4b13
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/HelpSettingsActivity.kt
@@ -0,0 +1,94 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.Manifest
+import android.content.Intent
+import android.net.Uri
+import android.os.Build
+import android.os.Bundle
+import android.widget.Toast
+import androidx.preference.Preference
+import network.loki.messenger.R
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+import org.thoughtcrime.securesms.permissions.Permissions
+
+class HelpSettingsActivity: PassphraseRequiredActionBarActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
+ super.onCreate(savedInstanceState, ready)
+ setContentView(R.layout.activity_fragment_wrapper)
+ supportFragmentManager.beginTransaction()
+ .replace(R.id.fragmentContainer, HelpSettingsFragment())
+ .commit()
+ }
+}
+
+class HelpSettingsFragment: CorrectedPreferenceFragment() {
+
+ companion object {
+ private const val EXPORT_LOGS = "export_logs"
+ private const val TRANSLATE = "translate_session"
+ private const val FEEDBACK = "feedback"
+ private const val FAQ = "faq"
+ private const val SUPPORT = "support"
+
+ private const val CROWDIN_URL = "https://crowdin.com/project/session-android"
+ private const val FEEDBACK_URL = "https://getsession.org/survey"
+ private const val FAQ_URL = "https://getsession.org/faq"
+ private const val SUPPORT_URL = "https://sessionapp.zendesk.com/hc/en-us"
+ }
+
+ override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) {
+ addPreferencesFromResource(R.xml.preferences_help)
+ }
+
+ override fun onPreferenceTreeClick(preference: Preference?): Boolean {
+ preference ?: return false
+ return when (preference.key) {
+ EXPORT_LOGS -> {
+ shareLogs()
+ true
+ }
+ TRANSLATE -> {
+ openLink(CROWDIN_URL)
+ true
+ }
+ FEEDBACK -> {
+ openLink(FEEDBACK_URL)
+ true
+ }
+ FAQ -> {
+ openLink(FAQ_URL)
+ true
+ }
+ SUPPORT -> {
+ openLink(SUPPORT_URL)
+ true
+ }
+ else -> super.onPreferenceTreeClick(preference)
+ }
+ }
+
+ private fun shareLogs() {
+ Permissions.with(this)
+ .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
+ .maxSdkVersion(Build.VERSION_CODES.P)
+ .withPermanentDenialDialog(getString(R.string.MediaPreviewActivity_signal_needs_the_storage_permission_in_order_to_write_to_external_storage_but_it_has_been_permanently_denied))
+ .onAnyDenied {
+ Toast.makeText(requireActivity(), R.string.MediaPreviewActivity_unable_to_write_to_external_storage_without_permission, Toast.LENGTH_LONG).show()
+ }
+ .onAllGranted {
+ ShareLogsDialog().show(parentFragmentManager,"Share Logs Dialog")
+ }
+ .execute()
+ }
+
+ private fun openLink(url: String) {
+ try {
+ val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
+ startActivity(intent)
+ } catch (e: Exception) {
+ Toast.makeText(requireActivity(), "Can't open URL", Toast.LENGTH_LONG).show()
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt
new file mode 100644
index 0000000000..e407c67774
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListPreferenceDialog.kt
@@ -0,0 +1,42 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.view.LayoutInflater
+import androidx.appcompat.app.AlertDialog
+import androidx.preference.ListPreference
+import androidx.recyclerview.widget.DividerItemDecoration
+import network.loki.messenger.databinding.DialogListPreferenceBinding
+import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
+
+class ListPreferenceDialog(
+ private val listPreference: ListPreference,
+ private val dialogListener: () -> Unit
+) : BaseDialog() {
+ private lateinit var binding: DialogListPreferenceBinding
+
+ override fun setContentView(builder: AlertDialog.Builder) {
+ binding = DialogListPreferenceBinding.inflate(LayoutInflater.from(requireContext()))
+ binding.titleTextView.text = listPreference.dialogTitle
+ binding.messageTextView.text = listPreference.dialogMessage
+ binding.closeButton.setOnClickListener {
+ dismiss()
+ }
+ val options = listPreference.entryValues.zip(listPreference.entries) { value, title ->
+ RadioOption(value.toString(), title.toString())
+ }
+ val valueIndex = listPreference.findIndexOfValue(listPreference.value)
+ val optionAdapter = RadioOptionAdapter(valueIndex) {
+ listPreference.value = it.value
+ dismiss()
+ dialogListener.invoke()
+ }
+ binding.recyclerView.apply {
+ adapter = optionAdapter
+ addItemDecoration(DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL))
+ setHasFixedSize(true)
+ }
+ optionAdapter.submitList(options)
+ builder.setView(binding.root)
+ builder.setCancelable(false)
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/ListSummaryPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListSummaryPreferenceFragment.java
index 4b330459e6..4314b9ae62 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/ListSummaryPreferenceFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/ListSummaryPreferenceFragment.java
@@ -4,10 +4,10 @@ package org.thoughtcrime.securesms.preferences;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
-import network.loki.messenger.R;
-
import java.util.Arrays;
+import network.loki.messenger.R;
+
public abstract class ListSummaryPreferenceFragment extends CorrectedPreferenceFragment {
protected class ListSummaryListener implements Preference.OnPreferenceChangeListener {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
index 6ceb050693..9ae78fc5cf 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java
@@ -1,5 +1,7 @@
package org.thoughtcrime.securesms.preferences;
+import static android.app.Activity.RESULT_OK;
+
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.Intent;
@@ -9,20 +11,19 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.provider.Settings;
+import android.text.TextUtils;
+
import androidx.annotation.Nullable;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
-import android.text.TextUtils;
+import org.session.libsession.utilities.TextSecurePreferences;
import org.thoughtcrime.securesms.ApplicationContext;
import org.thoughtcrime.securesms.components.SwitchPreferenceCompat;
import org.thoughtcrime.securesms.notifications.NotificationChannels;
-import org.session.libsession.utilities.TextSecurePreferences;
import network.loki.messenger.R;
-import static android.app.Activity.RESULT_OK;
-
public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment {
@SuppressWarnings("unused")
@@ -42,28 +43,14 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
return true;
});
- Preference ledBlinkPref = this.findPreference(TextSecurePreferences.LED_BLINK_PREF);
-
if (NotificationChannels.supported()) {
- ledBlinkPref.setVisible(false);
TextSecurePreferences.setNotificationRingtone(getContext(), NotificationChannels.getMessageRingtone(getContext()).toString());
TextSecurePreferences.setNotificationVibrateEnabled(getContext(), NotificationChannels.getMessageVibrate(getContext()));
-
- } else {
- ledBlinkPref.setOnPreferenceChangeListener(new ListSummaryListener());
- initializeListSummary((ListPreference) ledBlinkPref);
}
-
- this.findPreference(TextSecurePreferences.LED_COLOR_PREF)
- .setOnPreferenceChangeListener(new LedColorChangeListener());
this.findPreference(TextSecurePreferences.RINGTONE_PREF)
.setOnPreferenceChangeListener(new RingtoneSummaryListener());
- this.findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF)
- .setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)
.setOnPreferenceChangeListener(new NotificationPrivacyListener());
- this.findPreference(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF)
- .setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(TextSecurePreferences.VIBRATE_PREF)
.setOnPreferenceChangeListener((preference, newValue) -> {
NotificationChannels.updateMessageVibrate(getContext(), (boolean) newValue);
@@ -86,8 +73,17 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
return true;
});
- initializeListSummary((ListPreference) findPreference(TextSecurePreferences.LED_COLOR_PREF));
- initializeListSummary((ListPreference) findPreference(TextSecurePreferences.REPEAT_ALERTS_PREF));
+ this.findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF)
+ .setOnPreferenceClickListener(preference -> {
+ ListPreference listPreference = (ListPreference) preference;
+ listPreference.setDialogMessage(R.string.preferences_notifications__content_message);
+ new ListPreferenceDialog(listPreference, () -> {
+ initializeListSummary((ListPreference) findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF));
+ return null;
+ }).show(getChildFragmentManager(), "ListPreferenceDialog");
+ return true;
+ });
+
initializeListSummary((ListPreference) findPreference(TextSecurePreferences.NOTIFICATION_PRIVACY_PREF));
if (NotificationChannels.supported()) {
@@ -99,8 +95,6 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
startActivity(intent);
return true;
});
- } else {
- initializeListSummary((ListPreference) findPreference(TextSecurePreferences.NOTIFICATION_PRIORITY_PREF));
}
initializeRingtoneSummary(findPreference(TextSecurePreferences.RINGTONE_PREF));
@@ -183,20 +177,4 @@ public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragme
}
}
- @SuppressLint("StaticFieldLeak")
- private class LedColorChangeListener extends ListSummaryListener {
- @Override
- public boolean onPreferenceChange(Preference preference, Object value) {
- if (NotificationChannels.supported()) {
- new AsyncTask() {
- @Override
- protected Void doInBackground(Void... voids) {
- NotificationChannels.updateMessagesLedColor(getActivity(), (String) value);
- return null;
- }
- }.execute();
- }
- return super.onPreferenceChange(preference, value);
- }
- }
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsActivity.kt
index bf277dc17f..b8606a3d54 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsActivity.kt
@@ -3,14 +3,14 @@ package org.thoughtcrime.securesms.preferences
import android.os.Bundle
import network.loki.messenger.R
import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
-import org.thoughtcrime.securesms.preferences.AppProtectionPreferenceFragment
class PrivacySettingsActivity : PassphraseRequiredActionBarActivity() {
override fun onCreate(savedInstanceState: Bundle?, isReady: Boolean) {
super.onCreate(savedInstanceState, isReady)
setContentView(R.layout.activity_fragment_wrapper)
- val fragment = AppProtectionPreferenceFragment()
+ val fragment =
+ PrivacySettingsPreferenceFragment()
val transaction = supportFragmentManager.beginTransaction()
transaction.replace(R.id.fragmentContainer, fragment)
transaction.commit()
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.java
similarity index 75%
rename from app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java
rename to app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.java
index 5c42f38bcd..b5774447ee 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/AppProtectionPreferenceFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/PrivacySettingsPreferenceFragment.java
@@ -12,6 +12,7 @@ import android.provider.Settings;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
+import androidx.appcompat.view.ContextThemeWrapper;
import androidx.fragment.app.Fragment;
import androidx.preference.Preference;
@@ -23,14 +24,11 @@ import org.thoughtcrime.securesms.service.KeyCachingService;
import org.thoughtcrime.securesms.util.CallNotificationBuilder;
import org.thoughtcrime.securesms.util.IntentUtils;
-import java.util.concurrent.TimeUnit;
-
import kotlin.jvm.functions.Function1;
-import mobi.upod.timedurationpicker.TimeDurationPickerDialog;
import network.loki.messenger.BuildConfig;
import network.loki.messenger.R;
-public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment {
+public class PrivacySettingsPreferenceFragment extends ListSummaryPreferenceFragment {
@Override
public void onAttach(Activity activity) {
@@ -42,7 +40,6 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
super.onCreate(paramBundle);
this.findPreference(TextSecurePreferences.SCREEN_LOCK).setOnPreferenceChangeListener(new ScreenLockListener());
- this.findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT).setOnPreferenceClickListener(new ScreenLockTimeoutListener());
this.findPreference(TextSecurePreferences.READ_RECEIPTS_PREF).setOnPreferenceChangeListener(new ReadReceiptToggleListener());
this.findPreference(TextSecurePreferences.TYPING_INDICATORS).setOnPreferenceChangeListener(new TypingIndicatorsToggleListener());
@@ -56,7 +53,7 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
((SwitchPreferenceCompat)findPreference(TextSecurePreferences.CALL_NOTIFICATIONS_ENABLED)).setChecked(isEnabled);
if (isEnabled && !CallNotificationBuilder.areNotificationsEnabled(requireActivity())) {
// show a dialog saying that calls won't work properly if you don't have notifications on at a system level
- new AlertDialog.Builder(requireActivity())
+ new AlertDialog.Builder(new ContextThemeWrapper(requireActivity(), R.style.ThemeOverlay_Session_AlertDialog))
.setTitle(R.string.CallNotificationBuilder_system_notification_title)
.setMessage(R.string.CallNotificationBuilder_system_notification_message)
.setPositiveButton(R.string.activity_notification_settings_title, (d, w) -> {
@@ -100,20 +97,6 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
@Override
public void onResume() {
super.onResume();
- if (TextSecurePreferences.isPasswordDisabled(getContext())) {
- initializeScreenLockTimeoutSummary();
- }
- }
-
- private void initializeScreenLockTimeoutSummary() {
- long timeoutSeconds = TextSecurePreferences.getScreenLockTimeout(getContext());
- long hours = TimeUnit.SECONDS.toHours(timeoutSeconds);
- long minutes = TimeUnit.SECONDS.toMinutes(timeoutSeconds) - (TimeUnit.SECONDS.toHours(timeoutSeconds) * 60 );
- long seconds = TimeUnit.SECONDS.toSeconds(timeoutSeconds) - (TimeUnit.SECONDS.toMinutes(timeoutSeconds) * 60);
-
- findPreference(TextSecurePreferences.SCREEN_LOCK_TIMEOUT)
- .setSummary(timeoutSeconds <= 0 ? getString(R.string.AppProtectionPreferenceFragment_none) :
- String.format("%02d:%02d:%02d", hours, minutes, seconds));
}
private void initializeVisibility() {
@@ -143,25 +126,6 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
}
}
- private class ScreenLockTimeoutListener implements Preference.OnPreferenceClickListener {
-
- @Override
- public boolean onPreferenceClick(Preference preference) {
- new TimeDurationPickerDialog(getContext(), (view, duration) -> {
- if (duration == 0) {
- TextSecurePreferences.setScreenLockTimeout(getContext(), 0);
- } else {
- long timeoutSeconds = TimeUnit.MILLISECONDS.toSeconds(duration);
- TextSecurePreferences.setScreenLockTimeout(getContext(), timeoutSeconds);
- }
-
- initializeScreenLockTimeoutSummary();
- }, 0).show();
-
- return true;
- }
- }
-
private class ReadReceiptToggleListener implements Preference.OnPreferenceChangeListener {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
@@ -215,20 +179,16 @@ public class AppProtectionPreferenceFragment extends CorrectedPreferenceFragment
boolean val = (boolean) newValue;
if (val) {
// check if we've shown the info dialog and check for microphone permissions
- if (TextSecurePreferences.setShownCallWarning(context.requireContext())) {
- new AlertDialog.Builder(context.requireContext())
- .setTitle(R.string.dialog_voice_video_title)
- .setMessage(R.string.dialog_voice_video_message)
- .setPositiveButton(R.string.dialog_link_preview_enable_button_title, (d, w) -> {
- requestMicrophonePermission();
- })
- .setNegativeButton(R.string.cancel, (d, w) -> {
+ new AlertDialog.Builder(new ContextThemeWrapper(context.requireContext(), R.style.ThemeOverlay_Session_AlertDialog))
+ .setTitle(R.string.dialog_voice_video_title)
+ .setMessage(R.string.dialog_voice_video_message)
+ .setPositiveButton(R.string.dialog_link_preview_enable_button_title, (d, w) -> {
+ requestMicrophonePermission();
+ })
+ .setNegativeButton(R.string.cancel, (d, w) -> {
- })
- .show();
- } else {
- requestMicrophonePermission();
- }
+ })
+ .show();
return false;
} else {
return true;
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt
new file mode 100644
index 0000000000..2cb61a0e82
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/RadioOptionAdapter.kt
@@ -0,0 +1,55 @@
+package org.thoughtcrime.securesms.preferences
+
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import network.loki.messenger.R
+import network.loki.messenger.databinding.ItemSelectableBinding
+import org.thoughtcrime.securesms.mms.GlideApp
+
+class RadioOptionAdapter(
+ var selectedOptionPosition: Int = 0,
+ private val onClickListener: (RadioOption) -> Unit
+) : ListAdapter(RadioOptionDiffer()) {
+
+ class RadioOptionDiffer: DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem === newItem
+ override fun areContentsTheSame(oldItem: RadioOption, newItem: RadioOption) = oldItem == newItem
+ }
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ val itemView = LayoutInflater.from(parent.context).inflate(R.layout.item_selectable, parent, false)
+ return ViewHolder(itemView)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ val option = getItem(position)
+ val isSelected = position == selectedOptionPosition
+ holder.bind(option, isSelected) {
+ onClickListener(it)
+ selectedOptionPosition = position
+ notifyDataSetChanged()
+ }
+ }
+
+ class ViewHolder(itemView: View): RecyclerView.ViewHolder(itemView) {
+
+ val glide = GlideApp.with(itemView)
+ val binding = ItemSelectableBinding.bind(itemView)
+
+ fun bind(option: RadioOption, isSelected: Boolean, toggleSelection: (RadioOption) -> Unit) {
+ binding.titleTextView.text = option.title
+ binding.root.setOnClickListener { toggleSelection(option) }
+ binding.selectButton.isSelected = isSelected
+ }
+ }
+
+}
+
+data class RadioOption(
+ val value: String,
+ val title: String
+)
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SeedDialog.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SeedDialog.kt
index 32624129dd..e7bfd60d3f 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SeedDialog.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SeedDialog.kt
@@ -30,7 +30,7 @@ class SeedDialog : BaseDialog() {
override fun setContentView(builder: AlertDialog.Builder) {
val binding = DialogSeedBinding.inflate(LayoutInflater.from(requireContext()))
binding.seedTextView.text = seed
- binding.cancelButton.setOnClickListener { dismiss() }
+ binding.closeButton.setOnClickListener { dismiss() }
binding.copyButton.setOnClickListener { copySeed() }
builder.setView(binding.root)
}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt
index 934b9e4ea5..0a56c5058d 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/SettingsActivity.kt
@@ -8,10 +8,11 @@ import android.content.Context
import android.content.Intent
import android.net.Uri
import android.os.AsyncTask
-import android.os.Build
import android.os.Bundle
import android.os.Handler
import android.os.Looper
+import android.os.Parcelable
+import android.util.SparseArray
import android.view.ActionMode
import android.view.Menu
import android.view.MenuItem
@@ -39,11 +40,11 @@ import org.thoughtcrime.securesms.messagerequests.MessageRequestsActivity
import org.thoughtcrime.securesms.mms.GlideApp
import org.thoughtcrime.securesms.mms.GlideRequests
import org.thoughtcrime.securesms.permissions.Permissions
+import org.thoughtcrime.securesms.preferences.appearance.AppearanceSettingsActivity
import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints
import org.thoughtcrime.securesms.util.BitmapDecodingException
import org.thoughtcrime.securesms.util.BitmapUtil
import org.thoughtcrime.securesms.util.ConfigurationMessageUtilities
-import org.thoughtcrime.securesms.util.UiModeUtilities
import org.thoughtcrime.securesms.util.disableClipping
import org.thoughtcrime.securesms.util.push
import org.thoughtcrime.securesms.util.show
@@ -67,6 +68,7 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
companion object {
const val updatedProfileResultCode = 1234
+ private const val SCROLL_STATE = "SCROLL_STATE"
}
// region Lifecycle
@@ -94,24 +96,31 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
notificationsButton.setOnClickListener { showNotificationSettings() }
messageRequestsButton.setOnClickListener { showMessageRequests() }
chatsButton.setOnClickListener { showChatSettings() }
- sendInvitationButton.setOnClickListener { sendInvitation() }
- faqButton.setOnClickListener { showFAQ() }
- surveyButton.setOnClickListener { showSurvey() }
- helpTranslateButton.setOnClickListener { helpTranslate() }
+ appearanceButton.setOnClickListener { showAppearanceSettings() }
+ inviteFriendButton.setOnClickListener { sendInvitation() }
+ helpButton.setOnClickListener { showHelp() }
seedButton.setOnClickListener { showSeed() }
clearAllDataButton.setOnClickListener { clearAllData() }
- debugLogButton.setOnClickListener { shareLogs() }
- val isLightMode = UiModeUtilities.isDayUiMode(this@SettingsActivity)
- oxenLogoImageView.setImageResource(if (isLightMode) R.drawable.oxen_light_mode else R.drawable.oxen_dark_mode)
versionTextView.text = String.format(getString(R.string.version_s), "${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})")
}
}
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ val scrollBundle = SparseArray()
+ binding.scrollView.saveHierarchyState(scrollBundle)
+ outState.putSparseParcelableArray(SCROLL_STATE, scrollBundle)
+ }
+
+ override fun onRestoreInstanceState(savedInstanceState: Bundle) {
+ super.onRestoreInstanceState(savedInstanceState)
+ savedInstanceState.getSparseParcelableArray(SCROLL_STATE)?.let { scrollBundle ->
+ binding.scrollView.restoreHierarchyState(scrollBundle)
+ }
+ }
+
override fun onCreateOptionsMenu(menu: Menu): Boolean {
menuInflater.inflate(R.menu.settings_general, menu)
- // Update UI mode menu icon
- val uiMode = UiModeUtilities.getUserSelectedUiMode(this)
- menu.findItem(R.id.action_change_theme).icon!!.level = uiMode.ordinal
return true
}
@@ -121,10 +130,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
showQRCode()
true
}
- R.id.action_change_theme -> {
- ChangeUiModeDialog().show(supportFragmentManager, ChangeUiModeDialog.TAG)
- true
- }
else -> super.onOptionsItemSelected(item)
}
}
@@ -295,6 +300,11 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
push(intent)
}
+ private fun showAppearanceSettings() {
+ val intent = Intent(this, AppearanceSettingsActivity::class.java)
+ push(intent)
+ }
+
private fun sendInvitation() {
val intent = Intent()
intent.action = Intent.ACTION_SEND
@@ -305,14 +315,9 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
startActivity(chooser)
}
- private fun showFAQ() {
- try {
- val url = "https://getsession.org/faq"
- val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
- startActivity(intent)
- } catch (e: Exception) {
- Toast.makeText(this, "Can't open URL", Toast.LENGTH_LONG).show()
- }
+ private fun showHelp() {
+ val intent = Intent(this, HelpSettingsActivity::class.java)
+ push(intent)
}
private fun showPath() {
@@ -320,26 +325,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
show(intent)
}
- private fun showSurvey() {
- try {
- val url = "https://getsession.org/survey"
- val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
- startActivity(intent)
- } catch (e: Exception) {
- Toast.makeText(this, "Can't open URL", Toast.LENGTH_LONG).show()
- }
- }
-
- private fun helpTranslate() {
- try {
- val url = "https://crowdin.com/project/session-android"
- val intent = Intent(Intent.ACTION_VIEW, Uri.parse(url))
- startActivity(intent)
- } catch (e: Exception) {
- Toast.makeText(this, "Can't open URL", Toast.LENGTH_LONG).show()
- }
- }
-
private fun showSeed() {
SeedDialog().show(supportFragmentManager, "Recovery Phrase Dialog")
}
@@ -348,20 +333,6 @@ class SettingsActivity : PassphraseRequiredActionBarActivity() {
ClearAllDataDialog().show(supportFragmentManager, "Clear All Data Dialog")
}
- private fun shareLogs() {
- Permissions.with(this)
- .request(Manifest.permission.WRITE_EXTERNAL_STORAGE)
- .maxSdkVersion(Build.VERSION_CODES.P)
- .withPermanentDenialDialog(getString(R.string.MediaPreviewActivity_signal_needs_the_storage_permission_in_order_to_write_to_external_storage_but_it_has_been_permanently_denied))
- .onAnyDenied {
- Toast.makeText(this, R.string.MediaPreviewActivity_unable_to_write_to_external_storage_without_permission, Toast.LENGTH_LONG).show()
- }
- .onAllGranted {
- ShareLogsDialog().show(supportFragmentManager,"Share Logs Dialog")
- }
- .execute()
- }
-
// endregion
private inner class DisplayNameEditActionModeCallback: ActionMode.Callback {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt
new file mode 100644
index 0000000000..bfeea554ee
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsActivity.kt
@@ -0,0 +1,153 @@
+package org.thoughtcrime.securesms.preferences.appearance
+
+import android.os.Bundle
+import android.os.Parcelable
+import android.util.SparseArray
+import android.view.View
+import androidx.activity.viewModels
+import androidx.appcompat.widget.SwitchCompat
+import androidx.core.view.children
+import androidx.lifecycle.lifecycleScope
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.collectLatest
+import network.loki.messenger.R
+import network.loki.messenger.databinding.ActivityAppearanceSettingsBinding
+import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_DARK
+import org.session.libsession.utilities.TextSecurePreferences.Companion.CLASSIC_LIGHT
+import org.session.libsession.utilities.TextSecurePreferences.Companion.OCEAN_DARK
+import org.session.libsession.utilities.TextSecurePreferences.Companion.OCEAN_LIGHT
+import org.thoughtcrime.securesms.PassphraseRequiredActionBarActivity
+import org.thoughtcrime.securesms.util.ThemeState
+
+@AndroidEntryPoint
+class AppearanceSettingsActivity: PassphraseRequiredActionBarActivity(), View.OnClickListener {
+
+ companion object {
+ private const val SCROLL_PARCEL = "scroll_parcel"
+ }
+
+ val viewModel: AppearanceSettingsViewModel by viewModels()
+ lateinit var binding : ActivityAppearanceSettingsBinding
+
+ var currentTheme: ThemeState? = null
+
+ private val accentColors
+ get() = mapOf(
+ binding.accentGreen to R.style.PrimaryGreen,
+ binding.accentBlue to R.style.PrimaryBlue,
+ binding.accentYellow to R.style.PrimaryYellow,
+ binding.accentPink to R.style.PrimaryPink,
+ binding.accentPurple to R.style.PrimaryPurple,
+ binding.accentOrange to R.style.PrimaryOrange,
+ binding.accentRed to R.style.PrimaryRed
+ )
+
+ private val themeViews
+ get() = listOf(
+ binding.themeOptionClassicDark,
+ binding.themeRadioClassicDark,
+ binding.themeOptionClassicLight,
+ binding.themeRadioClassicLight,
+ binding.themeOptionOceanDark,
+ binding.themeRadioOceanDark,
+ binding.themeOptionOceanLight,
+ binding.themeRadioOceanLight
+ )
+
+ override fun onClick(v: View?) {
+ v ?: return
+ val accents = accentColors
+ val themes = themeViews
+ if (v in accents) {
+ val entry = accents[v]
+ entry?.let { viewModel.setNewAccent(it) }
+ } else if (v in themes) {
+ val currentBase = if (currentTheme?.theme == R.style.Classic_Dark || currentTheme?.theme == R.style.Classic_Light) R.style.Classic else R.style.Ocean
+ val (mappedStyle, newBase) = when (v) {
+ binding.themeOptionClassicDark, binding.themeRadioClassicDark -> CLASSIC_DARK to R.style.Classic
+ binding.themeOptionClassicLight, binding.themeRadioClassicLight -> CLASSIC_LIGHT to R.style.Classic
+ binding.themeOptionOceanDark, binding.themeRadioOceanDark -> OCEAN_DARK to R.style.Ocean
+ binding.themeOptionOceanLight, binding.themeRadioOceanLight -> OCEAN_LIGHT to R.style.Ocean
+ else -> throw NullPointerException("Invalid style for view [$v]")
+ }
+ viewModel.setNewStyle(mappedStyle)
+ if (currentBase != newBase) {
+ if (newBase == R.style.Ocean) {
+ viewModel.setNewAccent(R.style.PrimaryBlue)
+ } else if (newBase == R.style.Classic) {
+ viewModel.setNewAccent(R.style.PrimaryGreen)
+ }
+ }
+ } else if (v == binding.systemSettingsSwitch) {
+ viewModel.setNewFollowSystemSettings((v as SwitchCompat).isChecked)
+ }
+ }
+
+ override fun onSaveInstanceState(outState: Bundle) {
+ super.onSaveInstanceState(outState)
+ val scrollParcelArray = SparseArray()
+ binding.scrollView.saveHierarchyState(scrollParcelArray)
+ outState.putSparseParcelableArray(SCROLL_PARCEL, scrollParcelArray)
+ }
+
+ private fun updateSelectedTheme(themeStyle: Int) {
+ mapOf(
+ R.style.Classic_Dark to binding.themeRadioClassicDark,
+ R.style.Classic_Light to binding.themeRadioClassicLight,
+ R.style.Ocean_Dark to binding.themeRadioOceanDark,
+ R.style.Ocean_Light to binding.themeRadioOceanLight
+ ).forEach { (style, view) ->
+ view.isChecked = themeStyle == style
+ }
+ }
+
+ private fun updateSelectedAccent(accentStyle: Int) {
+ accentColors.forEach { (view, style) ->
+ view.isSelected = style == accentStyle
+ }
+ }
+
+ private fun updateFollowSystemToggle(followSystemSettings: Boolean) {
+ binding.systemSettingsSwitch.isChecked = followSystemSettings
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?, ready: Boolean) {
+ super.onCreate(savedInstanceState, ready)
+ binding = ActivityAppearanceSettingsBinding.inflate(layoutInflater)
+ setContentView(binding.root)
+ savedInstanceState?.let { bundle ->
+ val scrollStateParcel = bundle.getSparseParcelableArray(SCROLL_PARCEL)
+ if (scrollStateParcel != null) {
+ binding.scrollView.restoreHierarchyState(scrollStateParcel)
+ }
+ }
+ supportActionBar!!.title = getString(R.string.activity_settings_message_appearance_button_title)
+ with (binding) {
+ // accent toggles
+ accentContainer.children.forEach { view ->
+ view.setOnClickListener(this@AppearanceSettingsActivity)
+ }
+ // theme toggles
+ themeViews.forEach {
+ it.setOnClickListener(this@AppearanceSettingsActivity)
+ }
+ // system settings toggle
+ systemSettingsSwitch.setOnClickListener(this@AppearanceSettingsActivity)
+ }
+
+ lifecycleScope.launchWhenResumed {
+ viewModel.uiState.collectLatest { themeState ->
+ val (theme, accent, followSystem) = themeState
+ updateSelectedTheme(theme)
+ updateSelectedAccent(accent)
+ updateFollowSystemToggle(followSystem)
+ if (currentTheme != null && currentTheme != themeState) {
+ recreate()
+ } else {
+ currentTheme = themeState
+ }
+ }
+ }
+
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsViewModel.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsViewModel.kt
new file mode 100644
index 0000000000..c569441382
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/appearance/AppearanceSettingsViewModel.kt
@@ -0,0 +1,36 @@
+package org.thoughtcrime.securesms.preferences.appearance
+
+import androidx.annotation.StyleRes
+import androidx.lifecycle.ViewModel
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.StateFlow
+import org.session.libsession.utilities.TextSecurePreferences
+import org.thoughtcrime.securesms.util.ThemeState
+import org.thoughtcrime.securesms.util.themeState
+import javax.inject.Inject
+
+@HiltViewModel
+class AppearanceSettingsViewModel @Inject constructor(private val prefs: TextSecurePreferences) : ViewModel() {
+
+ private val _uiState = MutableStateFlow(prefs.themeState())
+ val uiState: StateFlow = _uiState
+
+ fun setNewAccent(@StyleRes newAccentColorStyle: Int) {
+ prefs.setAccentColorStyle(newAccentColorStyle)
+ // update UI state
+ _uiState.value = prefs.themeState()
+ }
+
+ fun setNewStyle(newThemeStyle: String) {
+ prefs.setThemeStyle(newThemeStyle)
+ // update UI state
+ _uiState.value = prefs.themeState()
+ }
+
+ fun setNewFollowSystemSettings(followSystemSettings: Boolean) {
+ prefs.setFollowSystemSettings(followSystemSettings)
+ _uiState.value = prefs.themeState()
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/LEDColorListPreference.java b/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/LEDColorListPreference.java
deleted file mode 100644
index 075df3a026..0000000000
--- a/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/LEDColorListPreference.java
+++ /dev/null
@@ -1,107 +0,0 @@
-/**
- * Copyright (C) 2017 Whisper Systems
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see .
- */
-package org.thoughtcrime.securesms.preferences.widgets;
-
-import android.content.Context;
-import android.graphics.drawable.GradientDrawable;
-import androidx.annotation.NonNull;
-import androidx.preference.ListPreference;
-import androidx.preference.PreferenceViewHolder;
-import android.util.AttributeSet;
-import android.widget.ImageView;
-
-import network.loki.messenger.R;
-
-/**
- * List preference that disables dependents when set to "none", similar to a CheckBoxPreference.
- *
- * @author Taylor Kline
- */
-
-public class LEDColorListPreference extends ListPreference {
-
- private static final String TAG = LEDColorListPreference.class.getSimpleName();
-
- private ImageView colorImageView;
-
- public LEDColorListPreference(Context context, AttributeSet attrs) {
- super(context, attrs);
- setWidgetLayoutResource(R.layout.led_color_preference_widget);
- }
-
- public LEDColorListPreference(Context context) {
- super(context);
- setWidgetLayoutResource(R.layout.led_color_preference_widget);
- }
-
- @Override
- public void setValue(String value) {
- CharSequence oldEntry = getEntry();
- super.setValue(value);
- CharSequence newEntry = getEntry();
- if (oldEntry != newEntry) {
- notifyDependencyChange(shouldDisableDependents());
- }
-
- if (value != null) setPreviewColor(value);
- }
-
- @Override
- public boolean shouldDisableDependents() {
- CharSequence newEntry = getValue();
- boolean shouldDisable = newEntry.equals("none");
- return shouldDisable || super.shouldDisableDependents();
- }
-
- @Override
- public void onBindViewHolder(PreferenceViewHolder view) {
- super.onBindViewHolder(view);
- this.colorImageView = (ImageView)view.findViewById(R.id.color_view);
- setPreviewColor(getValue());
- }
-
- @Override
- public void setSummary(CharSequence summary) {
- super.setSummary(null);
- }
-
- private void setPreviewColor(@NonNull String value) {
- int color;
-
- switch (value) {
- case "green": color = getContext().getResources().getColor(R.color.green_500); break;
- case "red": color = getContext().getResources().getColor(R.color.red_500); break;
- case "blue": color = getContext().getResources().getColor(R.color.blue_500); break;
- case "yellow": color = getContext().getResources().getColor(R.color.yellow_500); break;
- case "cyan": color = getContext().getResources().getColor(R.color.cyan_500); break;
- case "magenta": color = getContext().getResources().getColor(R.color.pink_500); break;
- case "white": color = getContext().getResources().getColor(R.color.white); break;
- default: color = getContext().getResources().getColor(R.color.transparent); break;
- }
-
- if (colorImageView != null) {
- GradientDrawable drawable = new GradientDrawable();
- drawable.setShape(GradientDrawable.OVAL);
- drawable.setColor(color);
-
- colorImageView.setImageDrawable(drawable);
- }
- }
-
-
-
-}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/NotificationSettingsPreference.kt b/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/NotificationSettingsPreference.kt
new file mode 100644
index 0000000000..3c2e72779d
--- /dev/null
+++ b/app/src/main/java/org/thoughtcrime/securesms/preferences/widgets/NotificationSettingsPreference.kt
@@ -0,0 +1,16 @@
+package org.thoughtcrime.securesms.preferences.widgets
+
+import android.content.Context
+import android.util.AttributeSet
+import android.widget.FrameLayout
+
+class NotificationSettingsPreference @JvmOverloads constructor(
+ context: Context, attrs: AttributeSet? = null
+) : FrameLayout(context, attrs) {
+
+ override fun onFinishInflate() {
+ super.onFinishInflate()
+ // TODO: if we want do the spans
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsDialogFragment.java
index c327da03ba..0d4afb5911 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsDialogFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/ReactionsDialogFragment.java
@@ -68,20 +68,14 @@ public final class ReactionsDialogFragment extends BottomSheetDialogFragment imp
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
- if (ThemeUtil.isDarkTheme(requireContext())) {
- setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_TextSecure_BottomSheetDialog_Fixed_ReactWithAny);
- } else {
- setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_TextSecure_Light_BottomSheetDialog_Fixed_ReactWithAny);
- }
-
+// setStyle(DialogFragment.STYLE_NORMAL, R.style.Theme_Session_BottomSheet);
super.onCreate(savedInstanceState);
}
@Override
public @Nullable View onCreateView(@NonNull LayoutInflater inflater,
@Nullable ViewGroup container,
- @Nullable Bundle savedInstanceState)
- {
+ @Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.reactions_bottom_sheet_dialog_fragment, container, false);
}
@@ -126,7 +120,7 @@ public final class ReactionsDialogFragment extends BottomSheetDialogFragment imp
View customView = tab.getCustomView();
TextView text = customView.findViewById(R.id.reactions_pill_count);
customView.setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.reaction_pill_background_selected));
- text.setTextColor(ContextCompat.getColor(requireContext(), R.color.reactions_pill_selected_text_color));
+ text.setTextColor(ThemeUtil.getThemedColor(requireContext(), R.attr.reactionsPillSelectedTextColor));
}
@Override
@@ -134,7 +128,7 @@ public final class ReactionsDialogFragment extends BottomSheetDialogFragment imp
View customView = tab.getCustomView();
TextView text = customView.findViewById(R.id.reactions_pill_count);
customView.setBackground(ContextCompat.getDrawable(requireContext(), R.drawable.reaction_pill_dialog_background));
- text.setTextColor(ContextCompat.getColor(requireContext(), R.color.reactions_pill_text_color));
+ text.setTextColor(ThemeUtil.getThemedColor(requireContext(), R.attr.reactionsPillNormalTextColor));
}
@Override
public void onTabReselected(TabLayout.Tab tab) {}
diff --git a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiDialogFragment.java b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiDialogFragment.java
index 3c8661fd82..2fd547eab3 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiDialogFragment.java
+++ b/app/src/main/java/org/thoughtcrime/securesms/reactions/any/ReactWithAnyEmojiDialogFragment.java
@@ -14,8 +14,6 @@ import android.view.WindowManager;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-import androidx.core.view.ViewCompat;
import androidx.fragment.app.DialogFragment;
import androidx.lifecycle.ViewModelProvider;
import androidx.loader.app.LoaderManager;
@@ -24,7 +22,6 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.bottomsheet.BottomSheetDialogFragment;
import com.google.android.material.shape.CornerFamily;
-import com.google.android.material.shape.MaterialShapeDrawable;
import com.google.android.material.shape.ShapeAppearanceModel;
import org.thoughtcrime.securesms.components.emoji.EmojiEventListener;
@@ -80,7 +77,6 @@ public final class ReactWithAnyEmojiDialogFragment extends BottomSheetDialogFrag
@Override
public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
- setStyle(DialogFragment.STYLE_NORMAL, R.style.Widget_TextSecure_ReactWithAny);
}
@Override
@@ -93,22 +89,6 @@ public final class ReactWithAnyEmojiDialogFragment extends BottomSheetDialogFrag
.setTopRightCorner(CornerFamily.ROUNDED, ViewUtil.dpToPx(requireContext(), 18))
.build();
- MaterialShapeDrawable dialogBackground = new MaterialShapeDrawable(shapeAppearanceModel);
-
- dialogBackground.setTint(ContextCompat.getColor(requireContext(), R.color.react_with_any_background));
-
- dialog.getBehavior().addBottomSheetCallback(new BottomSheetBehavior.BottomSheetCallback() {
- @Override
- public void onStateChanged(@NonNull View bottomSheet, int newState) {
- if (bottomSheet.getBackground() != dialogBackground) {
- ViewCompat.setBackground(bottomSheet, dialogBackground);
- }
- }
-
- @Override
- public void onSlide(@NonNull View bottomSheet, float slideOffset) { }
- });
-
boolean shadows = requireArguments().getBoolean(ARG_SHADOWS, true);
if (!shadows) {
Window window = dialog.getWindow();
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt
index d5daba5872..d5b361ecd6 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ActivityUtilities.kt
@@ -1,14 +1,14 @@
package org.thoughtcrime.securesms.util
import android.annotation.SuppressLint
-import android.app.Activity
import android.content.Context
import android.content.Intent
-import android.os.Bundle
import android.view.View
+import androidx.annotation.StyleRes
import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.widget.Toolbar
import network.loki.messenger.R
+import org.session.libsession.utilities.TextSecurePreferences
import org.thoughtcrime.securesms.BaseActionBarActivity
import org.thoughtcrime.securesms.conversation.v2.utilities.BaseDialog
@@ -67,4 +67,35 @@ interface ActivityDispatcher {
}
fun dispatchIntent(body: (Context)->Intent?)
fun showDialog(baseDialog: BaseDialog, tag: String? = null)
-}
\ No newline at end of file
+}
+
+fun TextSecurePreferences.themeState(): ThemeState {
+ val themeStyle = getThemeStyle().getThemeStyle()
+ val accentStyle = getAccentColorStyle() ?: themeStyle.getDefaultAccentColor()
+ val followSystem = getFollowSystemSettings()
+ return ThemeState(
+ themeStyle,
+ accentStyle,
+ followSystem
+ )
+}
+
+@StyleRes
+fun String.getThemeStyle(): Int = when (this) {
+ TextSecurePreferences.CLASSIC_DARK -> R.style.Classic_Dark
+ TextSecurePreferences.CLASSIC_LIGHT -> R.style.Classic_Light
+ TextSecurePreferences.OCEAN_DARK -> R.style.Ocean_Dark
+ TextSecurePreferences.OCEAN_LIGHT -> R.style.Ocean_Light
+ else -> throw NullPointerException("The style [$this] is not supported")
+}
+
+@StyleRes
+fun Int.getDefaultAccentColor(): Int =
+ if (this == R.style.Ocean_Dark || this == R.style.Ocean_Light) R.style.PrimaryBlue
+ else R.style.PrimaryGreen
+
+data class ThemeState (
+ @StyleRes val theme: Int,
+ @StyleRes val accentStyle: Int,
+ val followSystem: Boolean
+)
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt b/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt
index 16151fd6c4..08b81e5cb7 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/GlowView.kt
@@ -3,7 +3,8 @@ package org.thoughtcrime.securesms.util
import android.animation.ArgbEvaluator
import android.animation.ValueAnimator
import android.content.Context
-import android.graphics.*
+import android.graphics.Canvas
+import android.graphics.Paint
import android.util.AttributeSet
import android.view.View
import android.widget.LinearLayout
@@ -11,8 +12,6 @@ import android.widget.RelativeLayout
import androidx.annotation.ColorInt
import androidx.annotation.ColorRes
import network.loki.messenger.R
-import org.thoughtcrime.securesms.util.getColorWithID
-import org.thoughtcrime.securesms.util.toPx
import kotlin.math.roundToInt
interface GlowView {
@@ -22,7 +21,7 @@ interface GlowView {
object GlowViewUtilities {
- fun animateColorChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
+ fun animateColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
@@ -34,7 +33,17 @@ object GlowViewUtilities {
animation.start()
}
- fun animateShadowColorChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
+ fun animateColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) {
+ val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
+ animation.duration = 250
+ animation.addUpdateListener { animator ->
+ val color = animator.animatedValue as Int
+ view.mainColor = color
+ }
+ animation.start()
+ }
+
+ fun animateShadowColorIdChange(context: Context, view: GlowView, @ColorRes startColorID: Int, @ColorRes endColorID: Int) {
val startColor = context.resources.getColorWithID(startColorID, context.theme)
val endColor = context.resources.getColorWithID(endColorID, context.theme)
val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
@@ -45,6 +54,17 @@ object GlowViewUtilities {
}
animation.start()
}
+
+ fun animateShadowColorChange(view: GlowView, @ColorInt startColor: Int, @ColorInt endColor: Int) {
+ val animation = ValueAnimator.ofObject(ArgbEvaluator(), startColor, endColor)
+ animation.duration = 250
+ animation.addUpdateListener { animator ->
+ val color = animator.animatedValue as Int
+ view.sessionShadowColor = color
+ }
+ animation.start()
+ }
+
}
class PNModeView : LinearLayout, GlowView {
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/UiModeUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/UiModeUtilities.kt
index 39df0fccca..8b716c8e20 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/UiModeUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/UiModeUtilities.kt
@@ -2,46 +2,12 @@ package org.thoughtcrime.securesms.util
import android.content.Context
import android.content.res.Configuration
-import androidx.annotation.StringRes
-import androidx.appcompat.app.AppCompatDelegate
-import androidx.preference.PreferenceManager
-import network.loki.messenger.R
/**
* Day/night UI mode related utilities.
* @see Official Documentation
*/
object UiModeUtilities {
- private const val PREF_KEY_SELECTED_UI_MODE = "SELECTED_UI_MODE"
-
- @JvmStatic
- fun setUserSelectedUiMode(context: Context, uiMode: UiMode) {
- val prefs = PreferenceManager.getDefaultSharedPreferences(context)
- prefs.edit()
- .putString(PREF_KEY_SELECTED_UI_MODE, uiMode.name)
- .apply()
- AppCompatDelegate.setDefaultNightMode(uiMode.nightModeValue)
- }
-
- @JvmStatic
- fun getUserSelectedUiMode(context: Context): UiMode {
- val prefs = PreferenceManager.getDefaultSharedPreferences(context)
- val selectedUiModeName = prefs.getString(PREF_KEY_SELECTED_UI_MODE, UiMode.SYSTEM_DEFAULT.name)!!
- var selectedUiMode: UiMode
- try {
- selectedUiMode = UiMode.valueOf(selectedUiModeName)
- } catch (e: IllegalArgumentException) {
- // Cannot recognize UiMode constant from the given string.
- selectedUiMode = UiMode.SYSTEM_DEFAULT
- }
- return selectedUiMode
- }
-
- @JvmStatic
- fun setupUiModeToUserSelected(context: Context) {
- val selectedUiMode = getUserSelectedUiMode(context)
- setUserSelectedUiMode(context, selectedUiMode)
- }
/**
* Whether the application UI is in the light mode
@@ -52,14 +18,5 @@ object UiModeUtilities {
val uiModeNightBit = context.resources.configuration.uiMode and Configuration.UI_MODE_NIGHT_MASK
return uiModeNightBit == Configuration.UI_MODE_NIGHT_NO
}
-}
-enum class UiMode(
- @StringRes
- val displayNameRes: Int,
- val nightModeValue: Int) {
-
- DAY(R.string.dialog_ui_mode_option_day, AppCompatDelegate.MODE_NIGHT_NO),
- NIGHT(R.string.dialog_ui_mode_option_night, AppCompatDelegate.MODE_NIGHT_YES),
- SYSTEM_DEFAULT(R.string.dialog_ui_mode_option_system_default, AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
\ No newline at end of file
diff --git a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
index a02033b862..7b7f3a04f3 100644
--- a/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
+++ b/app/src/main/java/org/thoughtcrime/securesms/util/ViewUtilities.kt
@@ -7,8 +7,11 @@ import android.animation.ValueAnimator
import android.content.Context
import android.graphics.PointF
import android.graphics.Rect
-import androidx.annotation.DimenRes
import android.view.View
+import androidx.annotation.ColorInt
+import androidx.annotation.DimenRes
+import network.loki.messenger.R
+import org.session.libsession.utilities.getColorFromAttr
import android.view.inputmethod.InputMethodManager
fun View.contains(point: PointF): Boolean {
@@ -22,6 +25,9 @@ val View.hitRect: Rect
return rect
}
+@ColorInt
+fun Context.getAccentColor() = getColorFromAttr(R.attr.colorAccent)
+
fun View.animateSizeChange(@DimenRes startSizeID: Int, @DimenRes endSizeID: Int, animationDuration: Long = 250) {
val startSize = resources.getDimension(startSizeID)
val endSize = resources.getDimension(endSizeID)
diff --git a/app/src/main/res/color/emoji_tab_text_color.xml b/app/src/main/res/color/emoji_tab_text_color.xml
new file mode 100644
index 0000000000..024d8d366c
--- /dev/null
+++ b/app/src/main/res/color/emoji_tab_text_color.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable-notnight/reaction_pill_background.xml b/app/src/main/res/drawable-notnight/reaction_pill_background.xml
deleted file mode 100644
index 3ff042175a..0000000000
--- a/app/src/main/res/drawable-notnight/reaction_pill_background.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable-notnight/reaction_pill_background_selected.xml b/app/src/main/res/drawable-notnight/reaction_pill_background_selected.xml
deleted file mode 100644
index 2c735fb23d..0000000000
--- a/app/src/main/res/drawable-notnight/reaction_pill_background_selected.xml
+++ /dev/null
@@ -1,6 +0,0 @@
-
-
-
-
-
-
diff --git a/app/src/main/res/drawable-notnight/reaction_pill_dialog_background.xml b/app/src/main/res/drawable-notnight/reaction_pill_dialog_background.xml
deleted file mode 100644
index 2d9fa321b8..0000000000
--- a/app/src/main/res/drawable-notnight/reaction_pill_dialog_background.xml
+++ /dev/null
@@ -1,5 +0,0 @@
-
-
-
-
-
diff --git a/app/src/main/res/drawable-notnight/unimportant_filled_button_medium_background.xml b/app/src/main/res/drawable-notnight/unimportant_filled_button_medium_background.xml
deleted file mode 100644
index f6ea907be5..0000000000
--- a/app/src/main/res/drawable-notnight/unimportant_filled_button_medium_background.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-
-
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/app/src/main/res/drawable/accent_dot.xml b/app/src/main/res/drawable/accent_dot.xml
index 2d5ffdfe0c..4506871b47 100644
--- a/app/src/main/res/drawable/accent_dot.xml
+++ b/app/src/main/res/drawable/accent_dot.xml
@@ -3,6 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="oval">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/context_menu_background.xml b/app/src/main/res/drawable/context_menu_background.xml
index e5a1ec0dd8..3691575836 100644
--- a/app/src/main/res/drawable/context_menu_background.xml
+++ b/app/src/main/res/drawable/context_menu_background.xml
@@ -4,6 +4,6 @@
android:shape="rectangle">
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/conversation_list_item_background.xml b/app/src/main/res/drawable/conversation_list_item_background.xml
index bcc1673828..2e3818f7e3 100644
--- a/app/src/main/res/drawable/conversation_list_item_background.xml
+++ b/app/src/main/res/drawable/conversation_list_item_background.xml
@@ -4,7 +4,7 @@
-
-
+
diff --git a/app/src/main/res/drawable/conversation_list_item_background_dark.xml b/app/src/main/res/drawable/conversation_list_item_background_dark.xml
index bcc1673828..2e3818f7e3 100644
--- a/app/src/main/res/drawable/conversation_list_item_background_dark.xml
+++ b/app/src/main/res/drawable/conversation_list_item_background_dark.xml
@@ -4,7 +4,7 @@
-
-
+
diff --git a/app/src/main/res/drawable/conversation_menu_divider.xml b/app/src/main/res/drawable/conversation_menu_divider.xml
new file mode 100644
index 0000000000..f6c8a9a710
--- /dev/null
+++ b/app/src/main/res/drawable/conversation_menu_divider.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/conversation_menu_gradient.xml b/app/src/main/res/drawable/conversation_menu_gradient.xml
new file mode 100644
index 0000000000..04862a87ac
--- /dev/null
+++ b/app/src/main/res/drawable/conversation_menu_gradient.xml
@@ -0,0 +1,8 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/conversation_pinned_background.xml b/app/src/main/res/drawable/conversation_pinned_background.xml
index 9a435d05f3..104b9c272e 100644
--- a/app/src/main/res/drawable/conversation_pinned_background.xml
+++ b/app/src/main/res/drawable/conversation_pinned_background.xml
@@ -1,9 +1,9 @@
+ android:color="?colorCellRipple">
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/conversation_unread_background.xml b/app/src/main/res/drawable/conversation_unread_background.xml
new file mode 100644
index 0000000000..de0f5fb688
--- /dev/null
+++ b/app/src/main/res/drawable/conversation_unread_background.xml
@@ -0,0 +1,9 @@
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/conversation_view_background.xml b/app/src/main/res/drawable/conversation_view_background.xml
index ee5f321c99..aaceb7ed54 100644
--- a/app/src/main/res/drawable/conversation_view_background.xml
+++ b/app/src/main/res/drawable/conversation_view_background.xml
@@ -1,9 +1,9 @@
+ android:color="?colorCellRipple">
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/default_bottom_sheet_background.xml b/app/src/main/res/drawable/default_bottom_sheet_background.xml
index 4b8cb781e3..63532b0d05 100644
--- a/app/src/main/res/drawable/default_bottom_sheet_background.xml
+++ b/app/src/main/res/drawable/default_bottom_sheet_background.xml
@@ -3,11 +3,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/default_dialog_background.xml b/app/src/main/res/drawable/default_dialog_background.xml
index 4cd206aca8..00953c88a4 100644
--- a/app/src/main/res/drawable/default_dialog_background.xml
+++ b/app/src/main/res/drawable/default_dialog_background.xml
@@ -5,6 +5,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/default_session_background.xml b/app/src/main/res/drawable/default_session_background.xml
index d397981ab5..e961e985e6 100644
--- a/app/src/main/res/drawable/default_session_background.xml
+++ b/app/src/main/res/drawable/default_session_background.xml
@@ -5,8 +5,8 @@
\ No newline at end of file
diff --git a/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable/destructive_dialog_text_button_background.xml
similarity index 73%
rename from app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml
rename to app/src/main/res/drawable/destructive_dialog_text_button_background.xml
index 6e0de35a5b..1eff84a69b 100644
--- a/app/src/main/res/drawable-notnight/prominent_outline_button_medium_background.xml
+++ b/app/src/main/res/drawable/destructive_dialog_text_button_background.xml
@@ -5,7 +5,7 @@
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_appearance.xml b/app/src/main/res/drawable/ic_appearance.xml
new file mode 100644
index 0000000000..bda7bf3550
--- /dev/null
+++ b/app/src/main/res/drawable/ic_appearance.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_arrow_up_circle_24.xml b/app/src/main/res/drawable/ic_arrow_up_circle_24.xml
index a13b7c5b40..fc53bc0971 100644
--- a/app/src/main/res/drawable/ic_arrow_up_circle_24.xml
+++ b/app/src/main/res/drawable/ic_arrow_up_circle_24.xml
@@ -3,7 +3,7 @@
android:height="24dp"
android:viewportWidth="24"
android:viewportHeight="24"
- android:tint="?attr/colorControlNormal">
+ android:tint="?colorAccent">
+
+
diff --git a/app/src/main/res/drawable/ic_baseline_clear_24.xml b/app/src/main/res/drawable/ic_baseline_clear_24.xml
index 16d6d37dd9..a20716a20f 100644
--- a/app/src/main/res/drawable/ic_baseline_clear_24.xml
+++ b/app/src/main/res/drawable/ic_baseline_clear_24.xml
@@ -2,8 +2,7 @@
android:width="24dp"
android:height="24dp"
android:viewportWidth="24"
- android:viewportHeight="24"
- android:tint="?attr/colorControlNormal">
+ android:viewportHeight="24">
diff --git a/app/src/main/res/drawable/ic_clear_data.xml b/app/src/main/res/drawable/ic_clear_data.xml
new file mode 100644
index 0000000000..320015bb23
--- /dev/null
+++ b/app/src/main/res/drawable/ic_clear_data.xml
@@ -0,0 +1,11 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_conversations.xml b/app/src/main/res/drawable/ic_conversations.xml
new file mode 100644
index 0000000000..a32d5ec910
--- /dev/null
+++ b/app/src/main/res/drawable/ic_conversations.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_external.xml b/app/src/main/res/drawable/ic_external.xml
new file mode 100644
index 0000000000..fb4803977c
--- /dev/null
+++ b/app/src/main/res/drawable/ic_external.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_help.xml b/app/src/main/res/drawable/ic_help.xml
new file mode 100644
index 0000000000..670a82c658
--- /dev/null
+++ b/app/src/main/res/drawable/ic_help.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_invite_friend.xml b/app/src/main/res/drawable/ic_invite_friend.xml
new file mode 100644
index 0000000000..e46d22704e
--- /dev/null
+++ b/app/src/main/res/drawable/ic_invite_friend.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_link.xml b/app/src/main/res/drawable/ic_link.xml
index 56b2c2168c..9e20c99e12 100644
--- a/app/src/main/res/drawable/ic_link.xml
+++ b/app/src/main/res/drawable/ic_link.xml
@@ -5,5 +5,5 @@
android:viewportHeight="512">
+ android:fillColor="?android:textColorPrimary"/>
diff --git a/app/src/main/res/drawable/ic_message_requests.xml b/app/src/main/res/drawable/ic_message_requests.xml
new file mode 100644
index 0000000000..de8e1a6908
--- /dev/null
+++ b/app/src/main/res/drawable/ic_message_requests.xml
@@ -0,0 +1,15 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_pin.xml b/app/src/main/res/drawable/ic_pin.xml
index 390fe36f6b..d241d605b1 100644
--- a/app/src/main/res/drawable/ic_pin.xml
+++ b/app/src/main/res/drawable/ic_pin.xml
@@ -1,9 +1,9 @@
+ android:viewportHeight="122.867">
diff --git a/app/src/main/res/drawable/ic_privacy_icon.xml b/app/src/main/res/drawable/ic_privacy_icon.xml
new file mode 100644
index 0000000000..4162beb8d1
--- /dev/null
+++ b/app/src/main/res/drawable/ic_privacy_icon.xml
@@ -0,0 +1,12 @@
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_recovery_phrase.xml b/app/src/main/res/drawable/ic_recovery_phrase.xml
new file mode 100644
index 0000000000..3d5bc18e21
--- /dev/null
+++ b/app/src/main/res/drawable/ic_recovery_phrase.xml
@@ -0,0 +1,18 @@
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/ic_speaker.xml b/app/src/main/res/drawable/ic_speaker.xml
new file mode 100644
index 0000000000..505bf988b4
--- /dev/null
+++ b/app/src/main/res/drawable/ic_speaker.xml
@@ -0,0 +1,9 @@
+
+
+
diff --git a/app/src/main/res/drawable/ic_themepreview.xml b/app/src/main/res/drawable/ic_themepreview.xml
new file mode 100644
index 0000000000..ce32d94a33
--- /dev/null
+++ b/app/src/main/res/drawable/ic_themepreview.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
diff --git a/app/src/main/res/drawable/mediarail_media_outline.xml b/app/src/main/res/drawable/mediarail_media_outline.xml
index 6b6f5a68a2..6fa4008748 100644
--- a/app/src/main/res/drawable/mediarail_media_outline.xml
+++ b/app/src/main/res/drawable/mediarail_media_outline.xml
@@ -4,5 +4,5 @@
+ android:color="?colorAccent"/>
\ No newline at end of file
diff --git a/app/src/main/res/drawable/mention_candidate_view_background.xml b/app/src/main/res/drawable/mention_candidate_view_background.xml
index 1b30b3e72e..7b179020aa 100644
--- a/app/src/main/res/drawable/mention_candidate_view_background.xml
+++ b/app/src/main/res/drawable/mention_candidate_view_background.xml
@@ -1,9 +1,9 @@
+ android:color="?mention_candidates_view_background_ripple">
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/padded_circle_accent.xml b/app/src/main/res/drawable/padded_circle_accent.xml
new file mode 100644
index 0000000000..797c6bf007
--- /dev/null
+++ b/app/src/main/res/drawable/padded_circle_accent.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/padded_circle_accent_select.xml b/app/src/main/res/drawable/padded_circle_accent_select.xml
new file mode 100644
index 0000000000..0d384e658f
--- /dev/null
+++ b/app/src/main/res/drawable/padded_circle_accent_select.xml
@@ -0,0 +1,20 @@
+
+
+ -
+
+
-
+
+
+
+
+
+
+
+ -
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/padded_circle_tintable.xml b/app/src/main/res/drawable/padded_circle_tintable.xml
new file mode 100644
index 0000000000..ad91769c73
--- /dev/null
+++ b/app/src/main/res/drawable/padded_circle_tintable.xml
@@ -0,0 +1,14 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/pill.xml b/app/src/main/res/drawable/pill.xml
index 57cfd3a85c..f279f0f921 100644
--- a/app/src/main/res/drawable/pill.xml
+++ b/app/src/main/res/drawable/pill.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/app/src/main/res/drawable/pn_option_background.xml b/app/src/main/res/drawable/pn_option_background.xml
index b43e8de341..f84067c640 100644
--- a/app/src/main/res/drawable/pn_option_background.xml
+++ b/app/src/main/res/drawable/pn_option_background.xml
@@ -4,7 +4,7 @@
android:shape="rectangle" >
+ android:color="?colorPrimary" />
+ android:color="?colorPrimary" />
diff --git a/app/src/main/res/drawable/preference_bottom.xml b/app/src/main/res/drawable/preference_bottom.xml
new file mode 100644
index 0000000000..d751c7841b
--- /dev/null
+++ b/app/src/main/res/drawable/preference_bottom.xml
@@ -0,0 +1,13 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/preference_middle.xml b/app/src/main/res/drawable/preference_middle.xml
new file mode 100644
index 0000000000..0f7229cb7f
--- /dev/null
+++ b/app/src/main/res/drawable/preference_middle.xml
@@ -0,0 +1,17 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/preference_single.xml b/app/src/main/res/drawable/preference_single.xml
new file mode 100644
index 0000000000..da856fcd18
--- /dev/null
+++ b/app/src/main/res/drawable/preference_single.xml
@@ -0,0 +1,12 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/preference_single_no_padding.xml b/app/src/main/res/drawable/preference_single_no_padding.xml
new file mode 100644
index 0000000000..252ab0aea3
--- /dev/null
+++ b/app/src/main/res/drawable/preference_single_no_padding.xml
@@ -0,0 +1,9 @@
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/preference_top.xml b/app/src/main/res/drawable/preference_top.xml
new file mode 100644
index 0000000000..a997713e23
--- /dev/null
+++ b/app/src/main/res/drawable/preference_top.xml
@@ -0,0 +1,21 @@
+
+
+ -
+
+
+
+
+
+ -
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml
index f595e4f38b..ee3bec8f7f 100644
--- a/app/src/main/res/drawable/prominent_outline_button_medium_background.xml
+++ b/app/src/main/res/drawable/prominent_outline_button_medium_background.xml
@@ -7,5 +7,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/prominent_outline_button_medium_background_accent.xml b/app/src/main/res/drawable/prominent_outline_button_medium_background_accent.xml
index f595e4f38b..5f0a51ec40 100644
--- a/app/src/main/res/drawable/prominent_outline_button_medium_background_accent.xml
+++ b/app/src/main/res/drawable/prominent_outline_button_medium_background_accent.xml
@@ -7,5 +7,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/quote_accent_line.xml b/app/src/main/res/drawable/quote_accent_line.xml
new file mode 100644
index 0000000000..5693f4991b
--- /dev/null
+++ b/app/src/main/res/drawable/quote_accent_line.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/radial_multi_select.xml b/app/src/main/res/drawable/radial_multi_select.xml
new file mode 100644
index 0000000000..c05af4e763
--- /dev/null
+++ b/app/src/main/res/drawable/radial_multi_select.xml
@@ -0,0 +1,5 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/radial_select.xml b/app/src/main/res/drawable/radial_select.xml
new file mode 100644
index 0000000000..a56519ed6e
--- /dev/null
+++ b/app/src/main/res/drawable/radial_select.xml
@@ -0,0 +1,12 @@
+
+
+ -
+
+
+
+
+ -
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/rationale_heading_background.xml b/app/src/main/res/drawable/rationale_heading_background.xml
new file mode 100644
index 0000000000..7fb5b2f808
--- /dev/null
+++ b/app/src/main/res/drawable/rationale_heading_background.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/reaction_pill_background.xml b/app/src/main/res/drawable/reaction_pill_background.xml
index 02d56da9ba..136bd9e6b0 100644
--- a/app/src/main/res/drawable/reaction_pill_background.xml
+++ b/app/src/main/res/drawable/reaction_pill_background.xml
@@ -1,6 +1,5 @@
-
-
+
diff --git a/app/src/main/res/drawable/reaction_pill_background_selected.xml b/app/src/main/res/drawable/reaction_pill_background_selected.xml
index cdc2488629..e969011b77 100644
--- a/app/src/main/res/drawable/reaction_pill_background_selected.xml
+++ b/app/src/main/res/drawable/reaction_pill_background_selected.xml
@@ -1,6 +1,6 @@
-
+
diff --git a/app/src/main/res/drawable/reaction_pill_dialog_background.xml b/app/src/main/res/drawable/reaction_pill_dialog_background.xml
index 0b79d420dd..136bd9e6b0 100644
--- a/app/src/main/res/drawable/reaction_pill_dialog_background.xml
+++ b/app/src/main/res/drawable/reaction_pill_dialog_background.xml
@@ -1,5 +1,5 @@
-
+
diff --git a/app/src/main/res/drawable/search_bar_end.xml b/app/src/main/res/drawable/search_bar_end.xml
index cf31e32384..3fb796d88c 100644
--- a/app/src/main/res/drawable/search_bar_end.xml
+++ b/app/src/main/res/drawable/search_bar_end.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/search_bar_start.xml b/app/src/main/res/drawable/search_bar_start.xml
index 8ee0f611ca..3abbe7ea96 100644
--- a/app/src/main/res/drawable/search_bar_start.xml
+++ b/app/src/main/res/drawable/search_bar_start.xml
@@ -1,5 +1,5 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/session_edit_text_cursor.xml b/app/src/main/res/drawable/session_edit_text_cursor.xml
index af3edcf4de..78aef55910 100644
--- a/app/src/main/res/drawable/session_edit_text_cursor.xml
+++ b/app/src/main/res/drawable/session_edit_text_cursor.xml
@@ -4,6 +4,6 @@
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/session_id_text_view_background.xml b/app/src/main/res/drawable/session_id_text_view_background.xml
index 3d6f49d7aa..d86bc87bcd 100644
--- a/app/src/main/res/drawable/session_id_text_view_background.xml
+++ b/app/src/main/res/drawable/session_id_text_view_background.xml
@@ -4,7 +4,7 @@
android:shape="rectangle" >
diff --git a/app/src/main/res/drawable/setting_button_background.xml b/app/src/main/res/drawable/setting_button_background.xml
index ee5f321c99..aaceb7ed54 100644
--- a/app/src/main/res/drawable/setting_button_background.xml
+++ b/app/src/main/res/drawable/setting_button_background.xml
@@ -1,9 +1,9 @@
+ android:color="?colorCellRipple">
-
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/unimportant_dialog_button_background.xml b/app/src/main/res/drawable/unimportant_dialog_button_background.xml
index a1d03bb009..c517c1a135 100644
--- a/app/src/main/res/drawable/unimportant_dialog_button_background.xml
+++ b/app/src/main/res/drawable/unimportant_dialog_button_background.xml
@@ -3,9 +3,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml b/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml
similarity index 58%
rename from app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml
rename to app/src/main/res/drawable/unimportant_dialog_text_button_background.xml
index 6f6bd22a51..1eff84a69b 100644
--- a/app/src/main/res/drawable-notnight/prominent_filled_button_medium_background.xml
+++ b/app/src/main/res/drawable/unimportant_dialog_text_button_background.xml
@@ -3,9 +3,9 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
-
+
-
+
-
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/view_lock_background.xml b/app/src/main/res/drawable/view_lock_background.xml
index 9d3510cd34..35c3203487 100644
--- a/app/src/main/res/drawable/view_lock_background.xml
+++ b/app/src/main/res/drawable/view_lock_background.xml
@@ -3,6 +3,6 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle">
-
-
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/view_scroll_to_bottom_button_background.xml b/app/src/main/res/drawable/view_scroll_to_bottom_button_background.xml
index 512b3861a7..600332f7d1 100644
--- a/app/src/main/res/drawable/view_scroll_to_bottom_button_background.xml
+++ b/app/src/main/res/drawable/view_scroll_to_bottom_button_background.xml
@@ -2,6 +2,6 @@
-
-
+
+
diff --git a/app/src/main/res/layout-sw400dp/activity_display_name.xml b/app/src/main/res/layout-sw400dp/activity_display_name.xml
index fe00d541a2..50986e7dd4 100644
--- a/app/src/main/res/layout-sw400dp/activity_display_name.xml
+++ b/app/src/main/res/layout-sw400dp/activity_display_name.xml
@@ -17,7 +17,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/very_large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_display_name_title_2" />
@@ -55,7 +55,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="@dimen/very_small_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_pn_mode_fast_mode_explanation" />
@@ -84,7 +84,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/medium_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:textStyle="bold"
android:text="@string/activity_pn_mode_slow_mode" />
@@ -93,7 +93,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="@dimen/very_small_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_pn_mode_slow_mode_explanation" />
diff --git a/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml b/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml
index b88592a68c..f801235b4f 100644
--- a/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml
+++ b/app/src/main/res/layout-sw400dp/activity_recovery_phrase_restore.xml
@@ -18,7 +18,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/very_large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_restore_title" />
diff --git a/app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml b/app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml
index ee4176b83f..9a51b14519 100644
--- a/app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml
+++ b/app/src/main/res/layout-sw400dp/fragment_recovery_phrase.xml
@@ -17,7 +17,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/very_large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/fragment_recovery_phrase_title" />
@@ -43,7 +42,7 @@
android:layout_width="260dp"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
- android:textColor="@color/text"
+ android:textColor="?android:textColor"
android:textSize="@dimen/very_small_font_size"
android:lines="2"
android:alpha="0.6"
diff --git a/app/src/main/res/layout/activity_appearance_settings.xml b/app/src/main/res/layout/activity_appearance_settings.xml
new file mode 100644
index 0000000000..fbafa632d5
--- /dev/null
+++ b/app/src/main/res/layout/activity_appearance_settings.xml
@@ -0,0 +1,298 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_blocked_contacts.xml b/app/src/main/res/layout/activity_blocked_contacts.xml
new file mode 100644
index 0000000000..69d0043009
--- /dev/null
+++ b/app/src/main/res/layout/activity_blocked_contacts.xml
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_conversation_v2.xml b/app/src/main/res/layout/activity_conversation_v2.xml
index 5f8d4ec7c6..ae7aa3c689 100644
--- a/app/src/main/res/layout/activity_conversation_v2.xml
+++ b/app/src/main/res/layout/activity_conversation_v2.xml
@@ -1,5 +1,6 @@
+ app:tint="?android:textColorPrimary" />
@@ -146,7 +151,7 @@
android:layout_centerHorizontal="true"
android:layout_alignParentTop="true"
android:background="@drawable/rounded_rectangle"
- android:backgroundTint="@color/conversation_unread_count_indicator_background">
+ android:backgroundTint="?conversation_unread_count_indicator_background">
@@ -220,7 +225,7 @@
android:alpha="0.6"
android:gravity="center_horizontal"
android:text="@string/message_requests_send_notice"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:textSize="@dimen/small_font_size" />
@@ -54,7 +54,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Muted"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:alpha="0.6"
android:textSize="@dimen/very_small_font_size"
android:maxLines="1"
diff --git a/app/src/main/res/layout/activity_display_name.xml b/app/src/main/res/layout/activity_display_name.xml
index 60a6580cef..57ebd0d7fc 100644
--- a/app/src/main/res/layout/activity_display_name.xml
+++ b/app/src/main/res/layout/activity_display_name.xml
@@ -17,7 +17,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="20sp"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_display_name_title_2" />
+ app:tint="?sessionLogoTint" />
+ app:tint="?sessionLogoTint" />
@@ -100,6 +100,7 @@
@@ -108,18 +109,12 @@
android:id="@+id/recyclerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
- android:paddingBottom="172dp"
android:clipToPadding="false"
+ android:paddingBottom="172dp"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
tools:itemCount="6"
tools:listitem="@layout/view_conversation" />
-
-
diff --git a/app/src/main/res/layout/activity_path.xml b/app/src/main/res/layout/activity_path.xml
index 6c2db06239..9a4734f540 100644
--- a/app/src/main/res/layout/activity_path.xml
+++ b/app/src/main/res/layout/activity_path.xml
@@ -14,7 +14,7 @@
android:layout_marginTop="@dimen/large_spacing"
android:layout_marginRight="@dimen/large_spacing"
android:textSize="@dimen/small_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:alpha="0.6"
android:textAlignment="center"
android:text="@string/activity_path_explanation" />
@@ -39,7 +39,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- app:SpinKit_Color="@color/text" />
+ app:SpinKit_Color="?android:textColorPrimary" />
diff --git a/app/src/main/res/layout/activity_pn_mode.xml b/app/src/main/res/layout/activity_pn_mode.xml
index 5c0f032e7b..284ca649b8 100644
--- a/app/src/main/res/layout/activity_pn_mode.xml
+++ b/app/src/main/res/layout/activity_pn_mode.xml
@@ -18,7 +18,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_pn_mode_message_notifications" />
@@ -55,7 +55,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="@dimen/very_small_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_pn_mode_fast_mode_explanation" />
@@ -84,7 +84,7 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="@dimen/medium_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:textStyle="bold"
android:text="@string/activity_pn_mode_slow_mode" />
@@ -93,7 +93,7 @@
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:textSize="@dimen/very_small_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_pn_mode_slow_mode_explanation" />
diff --git a/app/src/main/res/layout/activity_recovery_phrase_restore.xml b/app/src/main/res/layout/activity_recovery_phrase_restore.xml
index 188c592e97..e3585a0a50 100644
--- a/app/src/main/res/layout/activity_recovery_phrase_restore.xml
+++ b/app/src/main/res/layout/activity_recovery_phrase_restore.xml
@@ -18,7 +18,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_restore_title" />
diff --git a/app/src/main/res/layout/activity_register.xml b/app/src/main/res/layout/activity_register.xml
index 0f0d560b86..0d6f6a5c81 100644
--- a/app/src/main/res/layout/activity_register.xml
+++ b/app/src/main/res/layout/activity_register.xml
@@ -18,7 +18,7 @@
android:layout_marginRight="@dimen/very_large_spacing"
android:textSize="@dimen/large_font_size"
android:textStyle="bold"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_register_title" />
diff --git a/app/src/main/res/layout/activity_select_contacts.xml b/app/src/main/res/layout/activity_select_contacts.xml
index 25ea89ba80..cc695bdc7f 100644
--- a/app/src/main/res/layout/activity_select_contacts.xml
+++ b/app/src/main/res/layout/activity_select_contacts.xml
@@ -30,7 +30,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textSize="@dimen/medium_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:text="@string/activity_create_closed_group_empty_state_message" />
diff --git a/app/src/main/res/layout/activity_settings.xml b/app/src/main/res/layout/activity_settings.xml
index a54432e6a8..479ca7f8ea 100644
--- a/app/src/main/res/layout/activity_settings.xml
+++ b/app/src/main/res/layout/activity_settings.xml
@@ -10,6 +10,7 @@
tools:menu="@menu/settings_general">
@@ -51,7 +52,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:textSize="@dimen/very_large_font_size"
android:textStyle="bold" />
@@ -73,7 +74,7 @@
android:layout_marginTop="@dimen/large_spacing"
android:layout_marginRight="@dimen/large_spacing"
android:textSize="@dimen/large_font_size"
- android:textColor="@color/text"
+ android:textColor="?android:textColorPrimary"
android:fontFamily="@font/space_mono_regular"
android:textAlignment="center"
tools:text="05987d601943c267879be41830888066c6a024cbdc9a548d06813924bf3372ea78" />
@@ -95,7 +96,7 @@
android:text="@string/copy" />