diff --git a/res/layout/recipient_preference_activity.xml b/res/layout/recipient_preference_activity.xml
index a6b67bccad..5a5337147d 100644
--- a/res/layout/recipient_preference_activity.xml
+++ b/res/layout/recipient_preference_activity.xml
@@ -4,6 +4,8 @@
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
+ android:layout_marginLeft="0dp"
+ android:layout_marginRight="0dp"
android:background="@color/transparent"
xmlns:tools="http://schemas.android.com/tools">
@@ -58,14 +60,39 @@
-
+
+
+
+
+
+
+
+
+
+
+
diff --git a/res/layout/recipient_preference_photo_rail.xml b/res/layout/recipient_preference_photo_rail.xml
new file mode 100644
index 0000000000..bb3f365f58
--- /dev/null
+++ b/res/layout/recipient_preference_photo_rail.xml
@@ -0,0 +1,13 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/res/layout/recipient_preference_photo_rail_item.xml b/res/layout/recipient_preference_photo_rail_item.xml
new file mode 100644
index 0000000000..71b1d962d8
--- /dev/null
+++ b/res/layout/recipient_preference_photo_rail_item.xml
@@ -0,0 +1,17 @@
+
+
+
+
+
+
+
diff --git a/res/values/strings.xml b/res/values/strings.xml
index f87b6caef3..6a9e364e55 100644
--- a/res/values/strings.xml
+++ b/res/values/strings.xml
@@ -998,6 +998,8 @@
Color
Color for this contact
View safety number
+ Chat settings
+ Privacy
Signal Call
diff --git a/res/xml/recipient_preferences.xml b/res/xml/recipient_preferences.xml
index 6726a26f17..2fd341041d 100644
--- a/res/xml/recipient_preferences.xml
+++ b/res/xml/recipient_preferences.xml
@@ -2,48 +2,55 @@
-
+
+
-
+
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/org/thoughtcrime/securesms/ConversationActivity.java b/src/org/thoughtcrime/securesms/ConversationActivity.java
index c42953f3f8..6c022e2a29 100644
--- a/src/org/thoughtcrime/securesms/ConversationActivity.java
+++ b/src/org/thoughtcrime/securesms/ConversationActivity.java
@@ -719,7 +719,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private void handleViewMedia() {
Intent intent = new Intent(this, MediaOverviewActivity.class);
- intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
intent.putExtra(MediaOverviewActivity.ADDRESS_EXTRA, recipient.getAddress());
startActivity(intent);
}
diff --git a/src/org/thoughtcrime/securesms/ConversationItem.java b/src/org/thoughtcrime/securesms/ConversationItem.java
index e45fbbfec3..899699a48f 100644
--- a/src/org/thoughtcrime/securesms/ConversationItem.java
+++ b/src/org/thoughtcrime/securesms/ConversationItem.java
@@ -605,10 +605,9 @@ public class ConversationItem extends LinearLayout
Intent intent = new Intent(context, MediaPreviewActivity.class);
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
intent.setDataAndType(slide.getUri(), slide.getContentType());
- if (!messageRecord.isOutgoing()) intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, recipient.getAddress());
+ intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, conversationRecipient.getAddress());
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, messageRecord.getTimestamp());
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, slide.asAttachment().getSize());
- intent.putExtra(MediaPreviewActivity.THREAD_ID_EXTRA, messageRecord.getThreadId());
context.startActivity(intent);
} else if (slide.getUri() != null) {
diff --git a/src/org/thoughtcrime/securesms/MediaAdapter.java b/src/org/thoughtcrime/securesms/MediaAdapter.java
index b18d561619..4d2392ff50 100644
--- a/src/org/thoughtcrime/securesms/MediaAdapter.java
+++ b/src/org/thoughtcrime/securesms/MediaAdapter.java
@@ -29,6 +29,7 @@ import android.view.ViewGroup;
import org.thoughtcrime.securesms.MediaAdapter.ViewHolder;
import org.thoughtcrime.securesms.components.ThumbnailView;
import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
import org.thoughtcrime.securesms.mms.Slide;
@@ -38,7 +39,7 @@ public class MediaAdapter extends CursorRecyclerViewAdapter {
private static final String TAG = MediaAdapter.class.getSimpleName();
private final MasterSecret masterSecret;
- private final long threadId;
+ private final Address address;
public static class ViewHolder extends RecyclerView.ViewHolder {
public ThumbnailView imageView;
@@ -49,10 +50,10 @@ public class MediaAdapter extends CursorRecyclerViewAdapter {
}
}
- public MediaAdapter(Context context, MasterSecret masterSecret, Cursor c, long threadId) {
+ public MediaAdapter(Context context, MasterSecret masterSecret, Cursor c, Address address) {
super(context, c);
this.masterSecret = masterSecret;
- this.threadId = threadId;
+ this.address = address;
}
@Override
@@ -88,7 +89,7 @@ public class MediaAdapter extends CursorRecyclerViewAdapter {
Intent intent = new Intent(getContext(), MediaPreviewActivity.class);
intent.putExtra(MediaPreviewActivity.DATE_EXTRA, mediaRecord.getDate());
intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, mediaRecord.getAttachment().getSize());
- intent.putExtra(MediaPreviewActivity.THREAD_ID_EXTRA, threadId);
+ intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, address);
if (mediaRecord.getAddress() != null) {
intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, mediaRecord.getAddress());
diff --git a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
index 081ebb31f8..73ad46f2dc 100644
--- a/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
+++ b/src/org/thoughtcrime/securesms/MediaOverviewActivity.java
@@ -42,9 +42,9 @@ import org.thoughtcrime.securesms.database.Address;
import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.MediaDatabase.MediaRecord;
+import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
-import org.thoughtcrime.securesms.util.AbstractCursorLoader;
import org.thoughtcrime.securesms.util.DynamicLanguage;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.task.ProgressDialogAsyncTask;
@@ -59,7 +59,6 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
private final static String TAG = MediaOverviewActivity.class.getSimpleName();
public static final String ADDRESS_EXTRA = "address";
- public static final String THREAD_ID_EXTRA = "thread_id";
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
@@ -69,7 +68,6 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
private GridLayoutManager gridManager;
private TextView noImages;
private Recipient recipient;
- private long threadId;
@Override
protected void onPreCreate() {
@@ -124,8 +122,6 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
}
private void initializeResources() {
- threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
-
noImages = (TextView ) findViewById(R.id.no_images );
gridView = (RecyclerView) findViewById(R.id.media_grid);
gridManager = new GridLayoutManager(this, getResources().getInteger(R.integer.media_overview_cols));
@@ -136,8 +132,6 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
if (address != null) {
recipient = Recipient.from(this, address, true);
- } else if (threadId > -1) {
- recipient = DatabaseFactory.getThreadDatabase(this).getRecipientForThreadId(threadId);
} else {
recipient = null;
}
@@ -163,10 +157,11 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
R.string.please_wait) {
@Override
protected List doInBackground(Void... params) {
+ long threadId = DatabaseFactory.getThreadDatabase(c).getThreadIdFor(recipient);
Cursor cursor = DatabaseFactory.getMediaDatabase(c).getMediaForThread(threadId);
List attachments = new ArrayList<>(cursor.getCount());
- while (cursor != null && cursor.moveToNext()) {
+ while (cursor.moveToNext()) {
MediaRecord record = MediaRecord.from(c, masterSecret, cursor);
attachments.add(new SaveAttachmentTask.Attachment(record.getAttachment().getDataUri(),
record.getContentType(),
@@ -174,6 +169,8 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
null));
}
+ cursor.close();
+
return attachments;
}
@@ -216,13 +213,13 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
@Override
public Loader onCreateLoader(int i, Bundle bundle) {
- return new ThreadMediaLoader(this, threadId);
+ return new ThreadMediaLoader(this, masterSecret, recipient.getAddress());
}
@Override
public void onLoadFinished(Loader cursorLoader, Cursor cursor) {
Log.w(TAG, "onLoadFinished()");
- gridView.setAdapter(new MediaAdapter(this, masterSecret, cursor, threadId));
+ gridView.setAdapter(new MediaAdapter(this, masterSecret, cursor, recipient.getAddress()));
noImages.setVisibility(gridView.getAdapter().getItemCount() > 0 ? View.GONE : View.VISIBLE);
invalidateOptionsMenu();
}
@@ -232,17 +229,4 @@ public class MediaOverviewActivity extends PassphraseRequiredActionBarActivity i
((CursorRecyclerViewAdapter)gridView.getAdapter()).changeCursor(null);
}
- public static class ThreadMediaLoader extends AbstractCursorLoader {
- private final long threadId;
-
- public ThreadMediaLoader(Context context, long threadId) {
- super(context);
- this.threadId = threadId;
- }
-
- @Override
- public Cursor getCursor() {
- return DatabaseFactory.getMediaDatabase(getContext()).getMediaForThread(threadId);
- }
- }
}
diff --git a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
index 1fd13b1188..244f422dd7 100644
--- a/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
+++ b/src/org/thoughtcrime/securesms/MediaPreviewActivity.java
@@ -54,7 +54,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
private final static String TAG = MediaPreviewActivity.class.getSimpleName();
public static final String ADDRESS_EXTRA = "address";
- public static final String THREAD_ID_EXTRA = "thread_id";
public static final String DATE_EXTRA = "date";
public static final String SIZE_EXTRA = "size";
@@ -68,7 +67,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
private Uri mediaUri;
private String mediaType;
private Recipient recipient;
- private long threadId;
private long date;
private long size;
@@ -150,7 +148,6 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
mediaType = getIntent().getType();
date = getIntent().getLongExtra(DATE_EXTRA, -1);
size = getIntent().getLongExtra(SIZE_EXTRA, 0);
- threadId = getIntent().getLongExtra(THREAD_ID_EXTRA, -1);
if (address != null) {
recipient = Recipient.from(this, address, true);
@@ -194,7 +191,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
private void showOverview() {
Intent intent = new Intent(this, MediaOverviewActivity.class);
- intent.putExtra(MediaOverviewActivity.THREAD_ID_EXTRA, threadId);
+ intent.putExtra(MediaOverviewActivity.ADDRESS_EXTRA, recipient.getAddress());
startActivity(intent);
}
@@ -223,7 +220,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity im
menu.clear();
MenuInflater inflater = this.getMenuInflater();
inflater.inflate(R.menu.media_preview, menu);
- if (threadId == -1) menu.findItem(R.id.media_preview__overview).setVisible(false);
+ if (recipient == null) menu.findItem(R.id.media_preview__overview).setVisible(false);
return true;
}
diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java
index cfa9321735..1ceff5808c 100644
--- a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java
+++ b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java
@@ -123,7 +123,7 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA
fragment.setArguments(args);
getSupportFragmentManager().beginTransaction()
.replace(target, fragment)
- .commit();
+ .commitAllowingStateLoss();
return fragment;
}
diff --git a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
index 97dbb9eedd..7ccb4b4507 100644
--- a/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
+++ b/src/org/thoughtcrime/securesms/RecipientPreferenceActivity.java
@@ -5,6 +5,7 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
+import android.database.Cursor;
import android.graphics.Color;
import android.media.Ringtone;
import android.media.RingtoneManager;
@@ -12,23 +13,28 @@ import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
-import android.preference.CheckBoxPreference;
-import android.preference.ListPreference;
-import android.preference.Preference;
import android.provider.Settings;
import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
import android.support.design.widget.CollapsingToolbarLayout;
import android.support.v4.app.Fragment;
-import android.support.v4.preference.PreferenceFragment;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
import android.support.v7.app.AlertDialog;
+import android.support.v7.preference.CheckBoxPreference;
+import android.support.v7.preference.ListPreference;
+import android.support.v7.preference.Preference;
import android.support.v7.widget.Toolbar;
import android.util.Log;
import android.view.MenuItem;
+import android.view.View;
import android.view.WindowManager;
import android.widget.ImageView;
+import android.widget.TextView;
import org.thoughtcrime.securesms.color.MaterialColor;
import org.thoughtcrime.securesms.color.MaterialColors;
+import org.thoughtcrime.securesms.components.ThreadPhotoRailView;
import org.thoughtcrime.securesms.crypto.IdentityKeyParcelable;
import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.Address;
@@ -38,10 +44,12 @@ import org.thoughtcrime.securesms.database.IdentityDatabase;
import org.thoughtcrime.securesms.database.IdentityDatabase.IdentityRecord;
import org.thoughtcrime.securesms.database.RecipientDatabase;
import org.thoughtcrime.securesms.database.RecipientDatabase.VibrateState;
+import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
import org.thoughtcrime.securesms.jobs.MultiDeviceBlockedUpdateJob;
import org.thoughtcrime.securesms.jobs.MultiDeviceContactUpdateJob;
import org.thoughtcrime.securesms.preferences.AdvancedRingtonePreference;
-import org.thoughtcrime.securesms.preferences.ColorPreference;
+import org.thoughtcrime.securesms.preferences.ColorPickerPreference;
+import org.thoughtcrime.securesms.preferences.CorrectedPreferenceFragment;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.DynamicLanguage;
@@ -55,7 +63,7 @@ import org.whispersystems.libsignal.util.guava.Optional;
import java.util.concurrent.ExecutionException;
-public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener
+public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActivity implements RecipientModifiedListener, LoaderManager.LoaderCallbacks
{
private static final String TAG = RecipientPreferenceActivity.class.getSimpleName();
@@ -73,6 +81,10 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private final DynamicLanguage dynamicLanguage = new DynamicLanguage();
private ImageView avatar;
+ private MasterSecret masterSecret;
+ private Address address;
+ private TextView threadPhotoRailLabel;
+ private ThreadPhotoRailView threadPhotoRailView;
private CollapsingToolbarLayout toolbarLayout;
private BroadcastReceiver staleReceiver;
@@ -85,8 +97,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
@Override
public void onCreate(Bundle instanceState, @NonNull MasterSecret masterSecret) {
setContentView(R.layout.recipient_preference_activity);
+ this.masterSecret = masterSecret;
+ this.address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
- Address address = getIntent().getParcelableExtra(ADDRESS_EXTRA);
Recipient recipient = Recipient.from(this, address, true);
initializeToolbar();
@@ -94,9 +107,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
setHeader(recipient);
recipient.addListener(this);
- Bundle bundle = new Bundle();
- bundle.putParcelable(ADDRESS_EXTRA, address);
- initFragment(R.id.preference_fragment, new RecipientPreferenceFragment(), masterSecret, null, bundle);
+ getSupportLoaderManager().initLoader(0, null, this);
}
@Override
@@ -138,12 +149,29 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
}
private void initializeToolbar() {
- this.toolbarLayout = ViewUtil.findById(this, R.id.collapsing_toolbar);
- this.avatar = ViewUtil.findById(this, R.id.avatar);
+ this.toolbarLayout = ViewUtil.findById(this, R.id.collapsing_toolbar);
+ this.avatar = ViewUtil.findById(this, R.id.avatar);
+ this.threadPhotoRailView = ViewUtil.findById(this, R.id.recent_photos);
+ this.threadPhotoRailLabel = ViewUtil.findById(this, R.id.rail_label);
this.toolbarLayout.setExpandedTitleColor(getResources().getColor(R.color.white));
this.toolbarLayout.setCollapsedTitleTextColor(getResources().getColor(R.color.white));
+ this.threadPhotoRailView.setListener(mediaRecord -> {
+ Intent intent = new Intent(RecipientPreferenceActivity.this, MediaPreviewActivity.class);
+ intent.putExtra(MediaPreviewActivity.ADDRESS_EXTRA, address);
+ intent.putExtra(MediaPreviewActivity.DATE_EXTRA, mediaRecord.getDate());
+ intent.putExtra(MediaPreviewActivity.SIZE_EXTRA, mediaRecord.getAttachment().getSize());
+ intent.setDataAndType(mediaRecord.getAttachment().getDataUri(), mediaRecord.getContentType());
+ startActivity(intent);
+ });
+
+ this.threadPhotoRailLabel.setOnClickListener(v -> {
+ Intent intent = new Intent(this, MediaOverviewActivity.class);
+ intent.putExtra(MediaOverviewActivity.ADDRESS_EXTRA, address);
+ startActivity(intent);
+ });
+
Toolbar toolbar = ViewUtil.findById(this, R.id.toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -183,23 +211,48 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
Util.runOnMain(() -> setHeader(recipient));
}
+ @Override
+ public Loader onCreateLoader(int id, Bundle args) {
+ return new ThreadMediaLoader(this, masterSecret, address);
+ }
+
+ @Override
+ public void onLoadFinished(Loader loader, Cursor data) {
+ if (data != null && data.getCount() > 0) {
+ this.threadPhotoRailLabel.setVisibility(View.VISIBLE);
+ this.threadPhotoRailView.setVisibility(View.VISIBLE);
+ } else {
+ this.threadPhotoRailLabel.setVisibility(View.GONE);
+ this.threadPhotoRailView.setVisibility(View.GONE);
+ }
+
+ this.threadPhotoRailView.setCursor(data, masterSecret);
+
+ Bundle bundle = new Bundle();
+ bundle.putParcelable(ADDRESS_EXTRA, address);
+ initFragment(R.id.preference_fragment, new RecipientPreferenceFragment(), masterSecret, null, bundle);
+ }
+
+ @Override
+ public void onLoaderReset(Loader loader) {
+ this.threadPhotoRailView.setCursor(null, masterSecret);
+ }
+
public static class RecipientPreferenceFragment
- extends PreferenceFragment
+ extends CorrectedPreferenceFragment
implements RecipientModifiedListener
{
private Recipient recipient;
private BroadcastReceiver staleReceiver;
- private MasterSecret masterSecret;
private boolean canHaveSafetyNumber;
@Override
public void onCreate(Bundle icicle) {
+ Log.w(TAG, "onCreate (fragment)");
super.onCreate(icicle);
- addPreferencesFromResource(R.xml.recipient_preferences);
initializeRecipients();
- this.masterSecret = getArguments().getParcelable("master_secret");
this.canHaveSafetyNumber = getActivity().getIntent()
.getBooleanExtra(RecipientPreferenceActivity.CAN_HAVE_SAFETY_NUMBER_EXTRA, false);
@@ -213,7 +266,12 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
.setOnPreferenceClickListener(new BlockClickedListener());
this.findPreference(PREFERENCE_COLOR)
.setOnPreferenceChangeListener(new ColorChangeListener());
- }
+ }
+
+ @Override
+ public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
+ addPreferencesFromResource(R.xml.recipient_preferences);
+ }
@Override
public void onResume() {
@@ -255,9 +313,9 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
CheckBoxPreference mutePreference = (CheckBoxPreference) this.findPreference(PREFERENCE_MUTED);
AdvancedRingtonePreference ringtonePreference = (AdvancedRingtonePreference) this.findPreference(PREFERENCE_TONE);
ListPreference vibratePreference = (ListPreference) this.findPreference(PREFERENCE_VIBRATE);
- ColorPreference colorPreference = (ColorPreference) this.findPreference(PREFERENCE_COLOR);
+ ColorPickerPreference colorPreference = (ColorPickerPreference) this.findPreference(PREFERENCE_COLOR);
Preference blockPreference = this.findPreference(PREFERENCE_BLOCK);
- final Preference identityPreference = this.findPreference(PREFERENCE_IDENTITY);
+ Preference identityPreference = this.findPreference(PREFERENCE_IDENTITY);
mutePreference.setChecked(recipient.isMuted());
@@ -294,11 +352,11 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
if (blockPreference != null) getPreferenceScreen().removePreference(blockPreference);
if (identityPreference != null) getPreferenceScreen().removePreference(identityPreference);
} else {
- colorPreference.setChoices(MaterialColors.CONVERSATION_PALETTE.asConversationColorArray(getActivity()));
- colorPreference.setValue(recipient.getColor().toActionBarColor(getActivity()));
+ colorPreference.setColors(MaterialColors.CONVERSATION_PALETTE.asConversationColorArray(getActivity()));
+ colorPreference.setColor(recipient.getColor().toActionBarColor(getActivity()));
if (recipient.isBlocked()) blockPreference.setTitle(R.string.RecipientPreferenceActivity_unblock);
- else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block);
+ else blockPreference.setTitle(R.string.RecipientPreferenceActivity_block);
IdentityUtil.getRemoteIdentityKey(getActivity(), recipient).addListener(new ListenableFuture.Listener>() {
@Override
@@ -330,14 +388,10 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
private class RingtoneChangeListener implements Preference.OnPreferenceChangeListener {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
- String value = (String)newValue;
+ Uri value = (Uri)newValue;
- final Uri uri;
-
- if (Settings.System.DEFAULT_NOTIFICATION_URI.toString().equals(value)) {
- uri = null;
- } else {
- uri = Uri.parse(value);
+ if (Settings.System.DEFAULT_NOTIFICATION_URI.equals(value)) {
+ value = null;
}
new AsyncTask() {
@@ -347,7 +401,7 @@ public class RecipientPreferenceActivity extends PassphraseRequiredActionBarActi
.setRingtone(recipient, params[0]);
return null;
}
- }.execute(uri);
+ }.execute(value);
return false;
}
diff --git a/src/org/thoughtcrime/securesms/components/ThreadPhotoRailView.java b/src/org/thoughtcrime/securesms/components/ThreadPhotoRailView.java
new file mode 100644
index 0000000000..d5a821d1f3
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/components/ThreadPhotoRailView.java
@@ -0,0 +1,129 @@
+package org.thoughtcrime.securesms.components;
+
+
+import android.content.Context;
+import android.database.Cursor;
+import android.os.Bundle;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.app.LoaderManager;
+import android.support.v4.content.Loader;
+import android.support.v7.widget.DefaultItemAnimator;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.util.AttributeSet;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.FrameLayout;
+
+import org.thoughtcrime.securesms.R;
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
+import org.thoughtcrime.securesms.database.CursorRecyclerViewAdapter;
+import org.thoughtcrime.securesms.database.MediaDatabase;
+import org.thoughtcrime.securesms.database.loaders.ThreadMediaLoader;
+import org.thoughtcrime.securesms.mms.Slide;
+import org.thoughtcrime.securesms.util.MediaUtil;
+import org.thoughtcrime.securesms.util.ViewUtil;
+
+public class ThreadPhotoRailView extends FrameLayout {
+
+ public static final String ADDRESS_EXTRA = "address";
+ public static final String MASTER_SECRET_EXTRA = "master_secret";
+
+ @NonNull private final RecyclerView recyclerView;
+ @Nullable private OnItemClickedListener listener;
+
+ public ThreadPhotoRailView(Context context) {
+ this(context, null);
+ }
+
+ public ThreadPhotoRailView(Context context, AttributeSet attrs) {
+ this(context, attrs, 0);
+ }
+
+ public ThreadPhotoRailView(Context context, AttributeSet attrs, int defStyleAttr) {
+ super(context, attrs, defStyleAttr);
+
+ inflate(context, R.layout.recipient_preference_photo_rail, this);
+
+ this.recyclerView = ViewUtil.findById(this, R.id.photo_list);
+ this.recyclerView.setLayoutManager(new LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false));
+ this.recyclerView.setItemAnimator(new DefaultItemAnimator());
+ this.recyclerView.setNestedScrollingEnabled(true);
+ }
+
+ public void setListener(@Nullable OnItemClickedListener listener) {
+ this.listener = listener;
+
+ if (this.recyclerView.getAdapter() != null) {
+ ((ThreadPhotoRailAdapter)this.recyclerView.getAdapter()).setListener(listener);
+ }
+ }
+
+ public void setCursor(@Nullable Cursor cursor, @NonNull MasterSecret masterSecret) {
+ this.recyclerView.setAdapter(new ThreadPhotoRailAdapter(getContext(), masterSecret, cursor, this.listener));
+ }
+
+ private static class ThreadPhotoRailAdapter extends CursorRecyclerViewAdapter {
+
+ private static final String TAG = ThreadPhotoRailAdapter.class.getName();
+
+ private final MasterSecret masterSecret;
+
+ @Nullable private OnItemClickedListener clickedListener;
+
+ private ThreadPhotoRailAdapter(@NonNull Context context,
+ @NonNull MasterSecret masterSecret,
+ @NonNull Cursor cursor,
+ @Nullable OnItemClickedListener listener)
+ {
+ super(context, cursor);
+ this.masterSecret = masterSecret;
+ this.clickedListener = listener;
+ }
+
+ @Override
+ public ThreadPhotoViewHolder onCreateItemViewHolder(ViewGroup parent, int viewType) {
+ View itemView = LayoutInflater.from(parent.getContext())
+ .inflate(R.layout.recipient_preference_photo_rail_item, parent, false);
+
+ return new ThreadPhotoViewHolder(itemView);
+ }
+
+ @Override
+ public void onBindItemViewHolder(ThreadPhotoViewHolder viewHolder, @NonNull Cursor cursor) {
+ ThumbnailView imageView = viewHolder.imageView;
+ MediaDatabase.MediaRecord mediaRecord = MediaDatabase.MediaRecord.from(getContext(), masterSecret, cursor);
+ Slide slide = MediaUtil.getSlideForAttachment(getContext(), mediaRecord.getAttachment());
+
+ if (slide != null) {
+ imageView.setImageResource(masterSecret, slide, false, false);
+ }
+
+ imageView.setOnClickListener(v -> {
+ if (clickedListener != null) clickedListener.onItemClicked(mediaRecord);
+ });
+ }
+
+ public void setListener(@Nullable OnItemClickedListener listener) {
+ this.clickedListener = listener;
+ }
+
+ static class ThreadPhotoViewHolder extends RecyclerView.ViewHolder {
+
+ ThumbnailView imageView;
+
+ ThreadPhotoViewHolder(View itemView) {
+ super(itemView);
+
+ this.imageView = ViewUtil.findById(itemView, R.id.thumbnail);
+ }
+ }
+ }
+
+ public interface OnItemClickedListener {
+ public void onItemClicked(MediaDatabase.MediaRecord mediaRecord);
+ }
+}
diff --git a/src/org/thoughtcrime/securesms/database/loaders/ThreadMediaLoader.java b/src/org/thoughtcrime/securesms/database/loaders/ThreadMediaLoader.java
new file mode 100644
index 0000000000..57f37d3ee3
--- /dev/null
+++ b/src/org/thoughtcrime/securesms/database/loaders/ThreadMediaLoader.java
@@ -0,0 +1,38 @@
+package org.thoughtcrime.securesms.database.loaders;
+
+
+import android.content.Context;
+import android.database.Cursor;
+import android.support.annotation.NonNull;
+
+import org.thoughtcrime.securesms.crypto.MasterSecret;
+import org.thoughtcrime.securesms.database.Address;
+import org.thoughtcrime.securesms.database.DatabaseFactory;
+import org.thoughtcrime.securesms.recipients.Recipient;
+import org.thoughtcrime.securesms.util.AbstractCursorLoader;
+
+public class ThreadMediaLoader extends AbstractCursorLoader {
+
+ private final Address address;
+ private final MasterSecret masterSecret;
+
+ public ThreadMediaLoader(@NonNull Context context, @NonNull MasterSecret masterSecret, @NonNull Address address) {
+ super(context);
+ this.masterSecret = masterSecret;
+ this.address = address;
+ }
+
+ @Override
+ public Cursor getCursor() {
+ long threadId = DatabaseFactory.getThreadDatabase(getContext()).getThreadIdFor(Recipient.from(getContext(), address, true));
+ return DatabaseFactory.getMediaDatabase(getContext()).getMediaForThread(threadId);
+ }
+
+ public Address getAddress() {
+ return address;
+ }
+
+ public MasterSecret getMasterSecret() {
+ return masterSecret;
+ }
+}