From df99deb480280c09cd081243c682f1f3c93ff925 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Tue, 15 Aug 2017 21:03:31 -0700 Subject: [PATCH] Insert profile creation into registration flow, fix capture // FREEBIE --- res/values/strings.xml | 8 + .../securesms/CreateProfileActivity.java | 176 +++++++++++++----- .../PassphraseRequiredActionBarActivity.java | 6 +- .../RegistrationProgressActivity.java | 2 +- .../securesms/database/ThreadDatabase.java | 44 +++-- .../jobs/RetrieveProfileAvatarJob.java | 9 +- .../securesms/profiles/AvatarHelper.java | 49 +++++ .../profiles/AvatarPhotoUriFetcher.java | 6 +- .../securesms/util/TextSecurePreferences.java | 9 + 9 files changed, 236 insertions(+), 73 deletions(-) create mode 100644 src/org/thoughtcrime/securesms/profiles/AvatarHelper.java diff --git a/res/values/strings.xml b/res/values/strings.xml index 5a759be3b..db8b4eee1 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -226,6 +226,14 @@ Archived conversations (%d) + + Your profile info + Error setting profile photo + Problem setting profile + Updating profile + Updating and encrypting profile + Profile photo + Using custom: %s Using default: %s diff --git a/src/org/thoughtcrime/securesms/CreateProfileActivity.java b/src/org/thoughtcrime/securesms/CreateProfileActivity.java index fa3ad9e3c..ad40ed238 100644 --- a/src/org/thoughtcrime/securesms/CreateProfileActivity.java +++ b/src/org/thoughtcrime/securesms/CreateProfileActivity.java @@ -4,12 +4,17 @@ package org.thoughtcrime.securesms; import android.app.Activity; import android.content.Intent; import android.content.res.Configuration; +import android.graphics.BitmapFactory; +import android.media.CameraProfile; import android.net.Uri; +import android.os.AsyncTask; import android.os.Bundle; import android.provider.MediaStore; import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.text.TextUtils; import android.util.Log; +import android.util.Pair; import android.view.KeyEvent; import android.view.WindowManager; import android.widget.Button; @@ -17,14 +22,20 @@ import android.widget.EditText; import android.widget.ImageView; import android.widget.Toast; +import com.bumptech.glide.Glide; import com.soundcloud.android.crop.Crop; import org.thoughtcrime.securesms.components.InputAwareLayout; import org.thoughtcrime.securesms.components.emoji.EmojiDrawer; import org.thoughtcrime.securesms.components.emoji.EmojiToggle; +import org.thoughtcrime.securesms.contacts.avatars.BitmapContactPhoto; +import org.thoughtcrime.securesms.contacts.avatars.ContactPhoto; import org.thoughtcrime.securesms.contacts.avatars.ContactPhotoFactory; import org.thoughtcrime.securesms.crypto.MasterSecret; +import org.thoughtcrime.securesms.database.Address; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.profiles.AvatarHelper; +import org.thoughtcrime.securesms.profiles.AvatarPhotoUriLoader; import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints; import org.thoughtcrime.securesms.profiles.SystemProfileUtil; import org.thoughtcrime.securesms.util.Base64; @@ -46,6 +57,8 @@ import java.util.concurrent.ExecutionException; import javax.inject.Inject; +import static android.provider.MediaStore.EXTRA_OUTPUT; + public class CreateProfileActivity extends PassphraseRequiredActionBarActivity implements InjectableType { private static final String TAG = CreateProfileActivity.class.getSimpleName(); @@ -62,6 +75,7 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i private EmojiDrawer emojiDrawer; private byte[] avatarBytes; + private File captureFile; @Override public void onCreate(Bundle bundle, @NonNull MasterSecret masterSecret) { @@ -70,11 +84,12 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i setContentView(R.layout.profile_create_activity); getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_RESIZE); - getSupportActionBar().setTitle("Your profile info"); + getSupportActionBar().setTitle(R.string.CreateProfileActivity_your_profile_info); initializeResources(); initializeEmojiInput(); - initializeDeviceOwner(); + initializeProfileName(); + initializeProfileAvatar(); ApplicationContext.getInstance(this).injectDependencies(this); } @@ -102,7 +117,13 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i case REQUEST_CODE_AVATAR: if (resultCode == Activity.RESULT_OK) { Uri outputFile = Uri.fromFile(new File(getCacheDir(), "cropped")); - new Crop(data.getData()).output(outputFile).asSquare().start(this); + Uri inputFile = data.getData(); + + if (inputFile == null && captureFile != null) { + inputFile = Uri.fromFile(captureFile); + } + + new Crop(inputFile).output(outputFile).asSquare().start(this); } break; @@ -113,7 +134,7 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i avatar.setImageDrawable(ContactPhotoFactory.getGroupContactPhoto(avatarBytes).asDrawable(this, 0)); } catch (BitmapDecodingException e) { Log.w(TAG, e); - Toast.makeText(this, "Error setting profile photo", Toast.LENGTH_LONG).show(); + Toast.makeText(this, R.string.CreateProfileActivity_error_setting_profile_photo, Toast.LENGTH_LONG).show(); } } break; @@ -132,18 +153,14 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i .asDrawable(this, getResources().getColor(R.color.grey_400))); this.avatar.setOnClickListener(view -> { - Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI); - galleryIntent.setType("image/*"); - - if (!IntentUtils.isResolvable(CreateProfileActivity.this, galleryIntent)) { - galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); - galleryIntent.setType("image/*"); + try { + captureFile = File.createTempFile("capture", "jpg", getExternalCacheDir()); + } catch (IOException e) { + Log.w(TAG, e); + captureFile = null; } - Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); - Intent chooserIntent = Intent.createChooser(galleryIntent, "Profile photo"); - chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] { cameraIntent }); - + Intent chooserIntent = createAvatarSelectionIntent(captureFile); startActivityForResult(chooserIntent, REQUEST_CODE_AVATAR); }); @@ -152,36 +169,70 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i }); } - private void initializeDeviceOwner() { - SystemProfileUtil.getSystemProfileName(this).addListener(new ListenableFuture.Listener() { - @Override - public void onSuccess(String result) { - if (!TextUtils.isEmpty(result)) { - name.setText(result); - name.setSelection(result.length(), result.length()); + private void initializeProfileName() { + if (!TextUtils.isEmpty(TextSecurePreferences.getProfileName(this))) { + String profileName = TextSecurePreferences.getProfileName(this); + + name.setText(profileName); + name.setSelection(profileName.length(), profileName.length()); + } else { + SystemProfileUtil.getSystemProfileName(this).addListener(new ListenableFuture.Listener() { + @Override + public void onSuccess(String result) { + if (!TextUtils.isEmpty(result)) { + name.setText(result); + name.setSelection(result.length(), result.length()); + } } - } - @Override - public void onFailure(ExecutionException e) { - Log.w(TAG, e); - } - }); - - SystemProfileUtil.getSystemProfileAvatar(this, new ProfileMediaConstraints()).addListener(new ListenableFuture.Listener() { - @Override - public void onSuccess(byte[] result) { - if (result != null) { - avatarBytes = result; - avatar.setImageDrawable(ContactPhotoFactory.getGroupContactPhoto(result).asDrawable(CreateProfileActivity.this, 0)); + @Override + public void onFailure(ExecutionException e) { + Log.w(TAG, e); } - } + }); + } + } - @Override - public void onFailure(ExecutionException e) { - Log.w(TAG, e); - } - }); + private void initializeProfileAvatar() { + Address ourAddress = Address.fromSerialized(TextSecurePreferences.getLocalNumber(this)); + + if (AvatarHelper.getAvatarFile(this, ourAddress).exists() && AvatarHelper.getAvatarFile(this, ourAddress).length() > 0) { + new AsyncTask>() { + @Override + protected Pair doInBackground(Void... params) { + try { + byte[] data =Util.readFully(AvatarHelper.getInputStreamFor(CreateProfileActivity.this, ourAddress)); + return new Pair<>(data, ContactPhotoFactory.getSignalAvatarContactPhoto(CreateProfileActivity.this, ourAddress, null, getResources().getDimensionPixelSize(R.dimen.contact_photo_target_size))); + } catch (IOException e) { + Log.w(TAG, e); + return null; + } + } + + @Override + protected void onPostExecute(Pair result) { + if (result != null) { + avatarBytes = result.first; + avatar.setImageDrawable(result.second.asDrawable(CreateProfileActivity.this, 0)); + } + } + }.execute(); + } else { + SystemProfileUtil.getSystemProfileAvatar(this, new ProfileMediaConstraints()).addListener(new ListenableFuture.Listener() { + @Override + public void onSuccess(byte[] result) { + if (result != null) { + avatarBytes = result; + avatar.setImageDrawable(ContactPhotoFactory.getGroupContactPhoto(result).asDrawable(CreateProfileActivity.this, 0)); + } + } + + @Override + public void onFailure(ExecutionException e) { + Log.w(TAG, e); + } + }); + } } private void initializeEmojiInput() { @@ -215,6 +266,33 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i this.name.setOnClickListener(v -> container.showSoftkey(name)); } + private Intent createAvatarSelectionIntent(@Nullable File captureFile) { + Intent galleryIntent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI); + galleryIntent.setType("image/*"); + + if (!IntentUtils.isResolvable(CreateProfileActivity.this, galleryIntent)) { + galleryIntent = new Intent(Intent.ACTION_GET_CONTENT); + galleryIntent.setType("image/*"); + } + + Intent cameraIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); + + if (captureFile != null && cameraIntent.resolveActivity(getPackageManager()) != null) { + cameraIntent.putExtra(EXTRA_OUTPUT, Uri.fromFile(captureFile)); + } else { + cameraIntent = null; + } + + Intent chooserIntent = Intent.createChooser(galleryIntent, getString(R.string.CreateProfileActivity_profile_photo)); + + if (cameraIntent != null) { + chooserIntent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {cameraIntent}); + } + + return chooserIntent; + } + + private void handleUpload() { final String name; final StreamDetails avatar; @@ -226,7 +304,10 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i else avatar = new StreamDetails(new ByteArrayInputStream(avatarBytes), "image/jpeg", avatarBytes.length); - new ProgressDialogAsyncTask(this, "Updating and encrypting profile", "Updating profile") { + new ProgressDialogAsyncTask(this, + getString(R.string.CreateProfileActivity_updating_and_encrypting_profile), + getString(R.string.CreateProfileActivity_updating_profile)) + { @Override protected Boolean doInBackground(Void... params) { String encodedProfileKey = TextSecurePreferences.getProfileKey(CreateProfileActivity.this); @@ -238,13 +319,15 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i try { accountManager.setProfileName(Base64.decode(encodedProfileKey), name); + TextSecurePreferences.setProfileName(getContext(), name); } catch (IOException e) { Log.w(TAG, e); return false; } try { - accountManager.setProfileAvatar(Base64.decode(encodedProfileKey), avatar);; + accountManager.setProfileAvatar(Base64.decode(encodedProfileKey), avatar); + AvatarHelper.setAvatar(getContext(), Address.fromSerialized(TextSecurePreferences.getLocalNumber(getContext())), avatarBytes); } catch (IOException e) { Log.w(TAG, e); return false; @@ -257,8 +340,13 @@ public class CreateProfileActivity extends PassphraseRequiredActionBarActivity i public void onPostExecute(Boolean result) { super.onPostExecute(result); - if (result) finish(); - else Toast.makeText(CreateProfileActivity.this, "Problem setting profile", Toast.LENGTH_LONG).show();; + if (result) { + if (captureFile != null) captureFile.delete(); + startActivity(new Intent(CreateProfileActivity.this, ConversationListActivity.class)); + finish(); + } else { + Toast.makeText(CreateProfileActivity.this, R.string.CreateProfileActivity_problem_setting_profile, Toast.LENGTH_LONG).show(); + } } }.execute(); } diff --git a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java index 0d7d364d7..134dc6dfb 100644 --- a/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java +++ b/src/org/thoughtcrime/securesms/PassphraseRequiredActionBarActivity.java @@ -185,7 +185,11 @@ public abstract class PassphraseRequiredActionBarActivity extends BaseActionBarA } private Intent getPushRegistrationIntent(MasterSecret masterSecret) { - return getRoutedIntent(RegistrationActivity.class, getConversationListIntent(), masterSecret); + return getRoutedIntent(RegistrationActivity.class, getCreateProfileIntent(masterSecret), masterSecret); + } + + private Intent getCreateProfileIntent(MasterSecret masterSecret) { + return getRoutedIntent(CreateProfileActivity.class, getConversationListIntent(), masterSecret); } private Intent getRoutedIntent(Class destination, @Nullable Intent nextIntent, @Nullable MasterSecret masterSecret) { diff --git a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java index da89404af..589d460cd 100644 --- a/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java +++ b/src/org/thoughtcrime/securesms/RegistrationProgressActivity.java @@ -342,7 +342,7 @@ public class RegistrationProgressActivity extends BaseActionBarActivity { } shutdownService(); - startActivity(new Intent(this, ConversationListActivity.class)); + startActivity(new Intent(this, CreateProfileActivity.class)); finish(); } diff --git a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java index 77f074ccd..820734aa0 100644 --- a/src/org/thoughtcrime/securesms/database/ThreadDatabase.java +++ b/src/org/thoughtcrime/securesms/database/ThreadDatabase.java @@ -22,6 +22,7 @@ import android.database.Cursor; import android.database.MergeCursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.graphics.Path; import android.net.Uri; import android.support.annotation.Nullable; import android.text.TextUtils; @@ -606,24 +607,33 @@ public class ThreadDatabase extends Database { } public ThreadRecord getCurrent() { - long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID)); - Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS))); - Optional preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientPreferences(cursor); - Optional groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(cursor); - Recipient recipient = RecipientFactory.getRecipientFor(context, address, preferences, groupRecord, true); + long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID)); + int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE)); + Address address = Address.fromSerialized(cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.ADDRESS))); - DisplayRecord.Body body = getPlaintextBody(cursor); - long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE)); - long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT)); - long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ)); - long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE)); - int distributionType = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.TYPE)); - boolean archived = cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0; - int status = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS)); - int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.RECEIPT_COUNT)); - long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN)); - long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN)); - Uri snippetUri = getSnippetUri(cursor); + Optional preferences; + Optional groupRecord; + + if (distributionType != DistributionTypes.ARCHIVE) { + preferences = DatabaseFactory.getRecipientPreferenceDatabase(context).getRecipientPreferences(cursor); + groupRecord = DatabaseFactory.getGroupDatabase(context).getGroup(cursor); + } else { + preferences = Optional.absent(); + groupRecord = Optional.absent(); + } + + Recipient recipient = RecipientFactory.getRecipientFor(context, address, preferences, groupRecord, true); + DisplayRecord.Body body = getPlaintextBody(cursor); + long date = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.DATE)); + long count = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.MESSAGE_COUNT)); + long read = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.READ)); + long type = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.SNIPPET_TYPE)); + boolean archived = cursor.getInt(cursor.getColumnIndex(ThreadDatabase.ARCHIVED)) != 0; + int status = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.STATUS)); + int receiptCount = cursor.getInt(cursor.getColumnIndexOrThrow(ThreadDatabase.RECEIPT_COUNT)); + long expiresIn = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.EXPIRES_IN)); + long lastSeen = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.LAST_SEEN)); + Uri snippetUri = getSnippetUri(cursor); return new ThreadRecord(context, body, snippetUri, recipient, date, count, read == 1, threadId, receiptCount, status, type, distributionType, archived, diff --git a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java index ffa9bfa5d..d276eedd6 100644 --- a/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java +++ b/src/org/thoughtcrime/securesms/jobs/RetrieveProfileAvatarJob.java @@ -9,6 +9,7 @@ import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase; import org.thoughtcrime.securesms.database.RecipientPreferenceDatabase.RecipientsPreferences; import org.thoughtcrime.securesms.dependencies.InjectableType; +import org.thoughtcrime.securesms.profiles.AvatarHelper; import org.thoughtcrime.securesms.recipients.Recipient; import org.thoughtcrime.securesms.recipients.RecipientFactory; import org.thoughtcrime.securesms.util.Util; @@ -53,10 +54,6 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy public void onRun() throws IOException { RecipientPreferenceDatabase database = DatabaseFactory.getRecipientPreferenceDatabase(context); Optional recipientsPreferences = database.getRecipientsPreferences(recipient.getAddress()); - File avatarDirectory = new File(context.getFilesDir(), "avatars"); - File avatarFile = new File(avatarDirectory, new File(recipient.getAddress().serialize()).getName()); - - avatarDirectory.mkdirs(); if (!recipientsPreferences.isPresent()) { Log.w(TAG, "Recipient preference row is gone!"); @@ -75,7 +72,7 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy if (TextUtils.isEmpty(profileAvatar)) { Log.w(TAG, "Removing profile avatar for: " + recipient.getAddress().serialize()); - avatarFile.delete(); + AvatarHelper.delete(context, recipient.getAddress()); return; } @@ -86,7 +83,7 @@ public class RetrieveProfileAvatarJob extends ContextJob implements InjectableTy File decryptDestination = File.createTempFile("avatar", "jpg", context.getCacheDir()); Util.copy(avatarStream, new FileOutputStream(decryptDestination)); - decryptDestination.renameTo(avatarFile); + decryptDestination.renameTo(AvatarHelper.getAvatarFile(context, recipient.getAddress())); } finally { if (downloadDestination != null) downloadDestination.delete(); } diff --git a/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java b/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java new file mode 100644 index 000000000..49d07244f --- /dev/null +++ b/src/org/thoughtcrime/securesms/profiles/AvatarHelper.java @@ -0,0 +1,49 @@ +package org.thoughtcrime.securesms.profiles; + + +import android.content.Context; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import org.thoughtcrime.securesms.database.Address; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; + +public class AvatarHelper { + + private static final String AVATAR_DIRECTORY = "avatars"; + + public static InputStream getInputStreamFor(@NonNull Context context, @NonNull Address address) + throws IOException + { + return new FileInputStream(getAvatarFile(context, address)); + } + + public static void delete(@NonNull Context context, @NonNull Address address) { + getAvatarFile(context, address).delete(); + } + + public static @NonNull File getAvatarFile(@NonNull Context context, @NonNull Address address) { + File avatarDirectory = new File(context.getFilesDir(), AVATAR_DIRECTORY); + avatarDirectory.mkdirs(); + + return new File(avatarDirectory, new File(address.serialize()).getName()); + } + + public static void setAvatar(@NonNull Context context, @NonNull Address address, @Nullable byte[] data) + throws IOException + { + if (data == null) { + delete(context, address); + } else { + FileOutputStream out = new FileOutputStream(getAvatarFile(context, address)); + out.write(data); + out.close(); + } + } + +} diff --git a/src/org/thoughtcrime/securesms/profiles/AvatarPhotoUriFetcher.java b/src/org/thoughtcrime/securesms/profiles/AvatarPhotoUriFetcher.java index 7dfcdf7d2..b0818e7c5 100644 --- a/src/org/thoughtcrime/securesms/profiles/AvatarPhotoUriFetcher.java +++ b/src/org/thoughtcrime/securesms/profiles/AvatarPhotoUriFetcher.java @@ -28,10 +28,8 @@ public class AvatarPhotoUriFetcher implements DataFetcher { } @Override - public InputStream loadData(Priority priority) throws FileNotFoundException { - File avatarsDir = new File(context.getFilesDir(), "avatars"); - inputStream = new FileInputStream(new File(avatarsDir, address.serialize())); - + public InputStream loadData(Priority priority) throws IOException { + inputStream = AvatarHelper.getInputStreamFor(context, address); return inputStream; } diff --git a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java index 50c7c095d..11e8f3e72 100644 --- a/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java +++ b/src/org/thoughtcrime/securesms/util/TextSecurePreferences.java @@ -111,6 +111,7 @@ public class TextSecurePreferences { public static final String DIRECT_CAPTURE_CAMERA_ID = "pref_direct_capture_camera_id"; private static final String ALWAYS_RELAY_CALLS_PREF = "pref_turn_only"; private static final String PROFILE_KEY_PREF = "pref_profile_key"; + private static final String PROFILE_NAME_PREF = "pref_profile_name"; public static @Nullable String getProfileKey(Context context) { return getStringPreference(context, PROFILE_KEY_PREF, null); @@ -120,6 +121,14 @@ public class TextSecurePreferences { setStringPreference(context, PROFILE_KEY_PREF, key); } + public static void setProfileName(Context context, String name) { + setStringPreference(context, PROFILE_NAME_PREF, name); + } + + public static String getProfileName(Context context) { + return getStringPreference(context, PROFILE_NAME_PREF, null); + } + public static int getNotificationPriority(Context context) { return Integer.valueOf(getStringPreference(context, NOTIFICATION_PRIORITY_PREF, String.valueOf(NotificationCompat.PRIORITY_HIGH))); }