diff --git a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java index fd50ec56..2fa31b67 100644 --- a/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/BaseActivity.java @@ -96,8 +96,12 @@ public class BaseActivity extends AppCompatActivity { overridePendingTransition(R.anim.slide_from_left, R.anim.slide_to_right); } + protected SharedPreferences getPrivatePreferences() { + return getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + } + protected String getAccessToken() { - SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + SharedPreferences preferences = getPrivatePreferences(); return preferences.getString("accessToken", null); } @@ -107,7 +111,7 @@ public class BaseActivity extends AppCompatActivity { } protected String getBaseUrl() { - SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + SharedPreferences preferences = getPrivatePreferences(); return "https://" + preferences.getString("domain", null); } @@ -157,8 +161,7 @@ public class BaseActivity extends AppCompatActivity { } protected void redirectIfNotLoggedIn() { - SharedPreferences preferences = getSharedPreferences( - getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + SharedPreferences preferences = getPrivatePreferences(); String domain = preferences.getString("domain", null); String accessToken = preferences.getString("accessToken", null); if (domain == null || accessToken == null) { diff --git a/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java b/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java index 51c55790..84f06334 100644 --- a/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java @@ -12,6 +12,7 @@ import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; @@ -24,7 +25,6 @@ import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; import android.widget.ProgressBar; -import android.widget.TextView; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.entity.Profile; @@ -66,7 +66,7 @@ public class EditProfileActivity extends BaseActivity { @BindView(R.id.edit_profile_header) Button headerButton; @BindView(R.id.edit_profile_header_preview) ImageView headerPreview; @BindView(R.id.edit_profile_header_progress) ProgressBar headerProgress; - @BindView(R.id.edit_profile_error) TextView errorText; + @BindView(R.id.edit_profile_save_progress) ProgressBar saveProgress; private String priorDisplayName; private String priorNote; @@ -131,7 +131,7 @@ public class EditProfileActivity extends BaseActivity { @Override public void onClick(View v) { headerPreview.setImageBitmap(null); - avatarPreview.setVisibility(View.GONE); + headerPreview.setVisibility(View.GONE); headerBase64 = null; } }); @@ -173,7 +173,11 @@ public class EditProfileActivity extends BaseActivity { } private void onMediaPick(PickType pickType) { - beginMediaPicking(pickType); + if (currentlyPicking != PickType.NOTHING) { + // Ignore inputs if another pick operation is still occurring. + return; + } + currentlyPicking = pickType; if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { @@ -195,7 +199,8 @@ public class EditProfileActivity extends BaseActivity { initiateMediaPicking(); } else { endMediaPicking(); - errorText.setText(R.string.error_media_upload_permission); + Snackbar.make(avatarButton, R.string.error_media_upload_permission, + Snackbar.LENGTH_LONG).show(); } break; } @@ -205,18 +210,11 @@ public class EditProfileActivity extends BaseActivity { private void initiateMediaPicking() { Intent intent = new Intent(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); - intent.setType("*/*"); + intent.setType("image/*"); switch (currentlyPicking) { - case AVATAR: { - startActivityForResult(intent, AVATAR_PICK_RESULT); - break; - } - case HEADER: { - startActivityForResult(intent, HEADER_PICK_RESULT); - break; - } + case AVATAR: { startActivityForResult(intent, AVATAR_PICK_RESULT); break; } + case HEADER: { startActivityForResult(intent, HEADER_PICK_RESULT); break; } } - } @Override @@ -263,10 +261,15 @@ public class EditProfileActivity extends BaseActivity { // If it's not any different, don't patch it. newNote = null; } + if (newDisplayName == null && newNote == null && avatarBase64 == null + && headerBase64 == null) { + // If nothing is changed, then there's nothing to save. + return; + } - isAlreadySaving = true; + saveProgress.setVisibility(View.VISIBLE); - Log.d(TAG, "avatar " + avatarBase64); + isAlreadySaving = true; Profile profile = new Profile(); profile.displayName = newDisplayName; @@ -280,6 +283,9 @@ public class EditProfileActivity extends BaseActivity { onSaveFailure(); return; } + getPrivatePreferences().edit() + .putBoolean("refreshProfileHeader", true) + .apply(); finish(); } @@ -292,21 +298,38 @@ public class EditProfileActivity extends BaseActivity { private void onSaveFailure() { isAlreadySaving = false; - errorText.setText(getString(R.string.error_media_upload_sending)); + Snackbar.make(avatarButton, R.string.error_media_upload_sending, Snackbar.LENGTH_LONG) + .show(); + saveProgress.setVisibility(View.GONE); } - private void beginMediaPicking(PickType pickType) { - currentlyPicking = pickType; + private void beginMediaPicking() { switch (currentlyPicking) { - case AVATAR: { avatarProgress.setVisibility(View.VISIBLE); break; } - case HEADER: { headerProgress.setVisibility(View.VISIBLE); break; } + case AVATAR: { + avatarProgress.setVisibility(View.VISIBLE); + avatarPreview.setVisibility(View.INVISIBLE); + break; + } + case HEADER: { + headerProgress.setVisibility(View.VISIBLE); + headerPreview.setVisibility(View.INVISIBLE); + break; + } } } private void endMediaPicking() { switch (currentlyPicking) { - case AVATAR: { avatarProgress.setVisibility(View.GONE); break; } - case HEADER: { headerProgress.setVisibility(View.GONE); break; } + case AVATAR: { + avatarProgress.setVisibility(View.GONE); + avatarPreview.setVisibility(View.GONE); + break; + } + case HEADER: { + headerProgress.setVisibility(View.GONE); + headerPreview.setVisibility(View.GONE); + break; + } } currentlyPicking = PickType.NOTHING; } @@ -321,6 +344,8 @@ public class EditProfileActivity extends BaseActivity { .setInitialCropWindowPaddingRatio(0) .setAspectRatio(AVATAR_WIDTH, AVATAR_HEIGHT) .start(this); + } else { + endMediaPicking(); } break; } @@ -330,6 +355,8 @@ public class EditProfileActivity extends BaseActivity { .setInitialCropWindowPaddingRatio(0) .setAspectRatio(HEADER_WIDTH, HEADER_HEIGHT) .start(this); + } else { + endMediaPicking(); } break; } @@ -346,6 +373,7 @@ public class EditProfileActivity extends BaseActivity { } private void beginResize(Uri uri) { + beginMediaPicking(); int width, height; switch (currentlyPicking) { default: { @@ -366,7 +394,9 @@ public class EditProfileActivity extends BaseActivity { @Override public void onSuccess(List contentList) { Bitmap bitmap = contentList.get(0); - switch (currentlyPicking) { + PickType pickType = currentlyPicking; + endMediaPicking(); + switch (pickType) { case AVATAR: { avatarPreview.setImageBitmap(bitmap); avatarPreview.setVisibility(View.VISIBLE); @@ -380,7 +410,6 @@ public class EditProfileActivity extends BaseActivity { break; } } - endMediaPicking(); } @Override @@ -391,7 +420,8 @@ public class EditProfileActivity extends BaseActivity { } private void onResizeFailure() { - errorText.setText(getString(R.string.error_media_upload_sending)); + Snackbar.make(avatarButton, R.string.error_media_upload_sending, Snackbar.LENGTH_LONG) + .show(); endMediaPicking(); } diff --git a/app/src/main/java/com/keylesspalace/tusky/LoginActivity.java b/app/src/main/java/com/keylesspalace/tusky/LoginActivity.java index b1996d19..100bb01e 100644 --- a/app/src/main/java/com/keylesspalace/tusky/LoginActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/LoginActivity.java @@ -20,7 +20,6 @@ import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.SharedPreferences; -import android.content.pm.PackageManager; import android.net.Uri; import android.os.Bundle; import android.preference.PreferenceManager; @@ -181,10 +180,10 @@ public class LoginActivity extends AppCompatActivity { AppCredentials credentials = response.body(); clientId = credentials.clientId; clientSecret = credentials.clientSecret; - SharedPreferences.Editor editor = preferences.edit(); - editor.putString(domain + "/client_id", clientId); - editor.putString(domain + "/client_secret", clientSecret); - editor.apply(); + preferences.edit() + .putString(domain + "/client_id", clientId) + .putString(domain + "/client_secret", clientSecret) + .apply(); redirectUserToAuthorizeAndLogin(editText); } @@ -248,11 +247,11 @@ public class LoginActivity extends AppCompatActivity { protected void onStop() { super.onStop(); if (domain != null) { - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("domain", domain); - editor.putString("clientId", clientId); - editor.putString("clientSecret", clientSecret); - editor.apply(); + preferences.edit() + .putString("domain", domain) + .putString("clientId", clientId) + .putString("clientSecret", clientSecret) + .apply(); } } @@ -327,10 +326,14 @@ public class LoginActivity extends AppCompatActivity { } private void onLoginSuccess(String accessToken) { - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("domain", domain); - editor.putString("accessToken", accessToken); - editor.commit(); + boolean committed = preferences.edit() + .putString("domain", domain) + .putString("accessToken", accessToken) + .commit(); + if (!committed) { + editText.setError(getString(R.string.error_retrieving_oauth_token)); + return; + } Intent intent = new Intent(this, MainActivity.class); startActivity(intent); finish(); diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 4191ba17..e2866a92 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -16,7 +16,6 @@ package com.keylesspalace.tusky; import android.app.NotificationManager; -import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Typeface; @@ -194,12 +193,24 @@ public class MainActivity extends BaseActivity { protected void onResume() { super.onResume(); - SharedPreferences notificationPreferences = getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE); - SharedPreferences.Editor editor = notificationPreferences.edit(); - editor.putString("current", "[]"); - editor.apply(); - - ((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).cancel(MyFirebaseMessagingService.NOTIFY_ID); + SharedPreferences notificationPreferences = getApplicationContext() + .getSharedPreferences("Notifications", MODE_PRIVATE); + notificationPreferences.edit() + .putString("current", "[]") + .apply(); + + ((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))) + .cancel(MyFirebaseMessagingService.NOTIFY_ID); + + /* After editing a profile, the profile header in the navigation drawer needs to be + * refreshed */ + SharedPreferences preferences = getPrivatePreferences(); + if (preferences.getBoolean("refreshProfileHeader", false)) { + fetchUserInfo(); + preferences.edit() + .putBoolean("refreshProfileHeader", false) + .apply(); + } } @Override @@ -301,11 +312,10 @@ public class MainActivity extends BaseActivity { private void logout() { if (arePushNotificationsEnabled()) disablePushNotifications(); - SharedPreferences preferences = getSharedPreferences(getString(R.string.preferences_file_key), Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.remove("domain"); - editor.remove("accessToken"); - editor.apply(); + getPrivatePreferences().edit() + .remove("domain") + .remove("accessToken") + .apply(); Intent intent = new Intent(MainActivity.this, LoginActivity.class); startActivity(intent); @@ -375,9 +385,7 @@ public class MainActivity extends BaseActivity { } @Override - public void onSearchAction(String currentQuery) { - - } + public void onSearchAction(String currentQuery) {} }); searchView.setOnBindSuggestionCallback(new SearchSuggestionsAdapter.OnBindSuggestionCallback() { @@ -402,8 +410,7 @@ public class MainActivity extends BaseActivity { } private void fetchUserInfo() { - SharedPreferences preferences = getSharedPreferences( - getString(R.string.preferences_file_key), Context.MODE_PRIVATE); + SharedPreferences preferences = getPrivatePreferences(); final String domain = preferences.getString("domain", null); String id = preferences.getString("loggedInAccountId", null); String username = preferences.getString("loggedInAccountUsername", null); @@ -421,6 +428,8 @@ public class MainActivity extends BaseActivity { return; } + headerResult.clear(); + Account me = response.body(); ImageView background = headerResult.getHeaderBackgroundView(); int backgroundWidth = background.getWidth(); @@ -460,12 +469,10 @@ public class MainActivity extends BaseActivity { private void onFetchUserInfoSuccess(String id, String username) { loggedInAccountId = id; loggedInAccountUsername = username; - SharedPreferences preferences = getSharedPreferences( - getString(R.string.preferences_file_key), Context.MODE_PRIVATE); - SharedPreferences.Editor editor = preferences.edit(); - editor.putString("loggedInAccountId", loggedInAccountId); - editor.putString("loggedInAccountUsername", loggedInAccountUsername); - editor.apply(); + getPrivatePreferences().edit() + .putString("loggedInAccountId", loggedInAccountId) + .putString("loggedInAccountUsername", loggedInAccountUsername) + .apply(); } private void onFetchUserInfoFailure(Exception exception) { diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java b/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java index 518bfcca..dca63311 100644 --- a/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java @@ -9,9 +9,11 @@ public class Profile { @SerializedName("note") public String note; + /** Encoded in Base-64 */ @SerializedName("avatar") public String avatar; + /** Encoded in Base-64 */ @SerializedName("header") public String header; } diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml index 9975650c..4f224a72 100644 --- a/app/src/main/res/layout/activity_edit_profile.xml +++ b/app/src/main/res/layout/activity_edit_profile.xml @@ -1,6 +1,5 @@ - - - + android:maxLength="30" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" /> + android:maxLength="160" + android:layout_marginStart="16dp" + android:layout_marginEnd="16dp" + android:layout_marginBottom="16dp" /> - + android:orientation="horizontal" + android:paddingLeft="16dp"> -