From 18e40855ad313350e21ea23026959f09f108e852 Mon Sep 17 00:00:00 2001 From: Vavassor Date: Mon, 17 Apr 2017 02:49:56 -0400 Subject: [PATCH] Profile edits for display name and bio are working. Avatar and header image picking are in but not uploaded. --- .../tusky/EditProfileActivity.java | 110 +++++++++++++++++- .../com/keylesspalace/tusky/MastodonAPI.java | 8 +- .../keylesspalace/tusky/entity/Profile.java | 17 +++ .../main/res/layout/activity_edit_profile.xml | 5 + app/src/main/res/values/strings.xml | 1 - 5 files changed, 132 insertions(+), 9 deletions(-) create mode 100644 app/src/main/java/com/keylesspalace/tusky/entity/Profile.java diff --git a/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java b/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java index 5475a0d4e..a60c0f1c3 100644 --- a/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/EditProfileActivity.java @@ -1,15 +1,26 @@ package com.keylesspalace.tusky; +import android.Manifest; +import android.content.Intent; +import android.content.pm.PackageManager; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.annotation.Nullable; +import android.support.v4.app.ActivityCompat; +import android.support.v4.content.ContextCompat; import android.support.v7.app.ActionBar; import android.support.v7.widget.Toolbar; import android.view.Menu; import android.view.MenuItem; +import android.view.View; import android.widget.Button; import android.widget.EditText; +import android.widget.TextView; import com.keylesspalace.tusky.entity.Account; +import com.keylesspalace.tusky.entity.Profile; import butterknife.BindView; import butterknife.ButterKnife; @@ -19,14 +30,18 @@ import retrofit2.Response; public class EditProfileActivity extends BaseActivity { private static final String TAG = "EditProfileActivity"; + private static final int MEDIA_PICK_RESULT = 1; + private static final int PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE = 1; @BindView(R.id.edit_profile_display_name) EditText displayNameEditText; @BindView(R.id.edit_profile_note) EditText noteEditText; @BindView(R.id.edit_profile_avatar) Button avatarButton; @BindView(R.id.edit_profile_header) Button headerButton; + @BindView(R.id.edit_profile_error) TextView errorText; private String priorDisplayName; private String priorNote; + private boolean isAlreadySaving; @Override protected void onCreate(@Nullable Bundle savedInstanceState) { @@ -46,11 +61,26 @@ public class EditProfileActivity extends BaseActivity { if (savedInstanceState != null) { priorDisplayName = savedInstanceState.getString("priorDisplayName"); priorNote = savedInstanceState.getString("priorNote"); + isAlreadySaving = savedInstanceState.getBoolean("isAlreadySaving"); } else { priorDisplayName = null; priorNote = null; + isAlreadySaving = false; } + avatarButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onMediaPick(); + } + }); + headerButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + onMediaPick(); + } + }); + mastodonAPI.accountVerifyCredentials().enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { @@ -62,7 +92,7 @@ public class EditProfileActivity extends BaseActivity { priorDisplayName = me.getDisplayName(); priorNote = me.note.toString(); displayNameEditText.setText(priorDisplayName); - noteEditText.setText(HtmlUtils.fromHtml(priorNote)); + noteEditText.setText(priorNote); } @Override @@ -76,6 +106,7 @@ public class EditProfileActivity extends BaseActivity { protected void onSaveInstanceState(Bundle outState) { outState.putString("priorDisplayName", priorDisplayName); outState.putString("priorNote", priorNote); + outState.putBoolean("isAlreadySaving", isAlreadySaving); super.onSaveInstanceState(outState); } @@ -83,6 +114,41 @@ public class EditProfileActivity extends BaseActivity { Log.e(TAG, "The account failed to load."); } + private void onMediaPick() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN && + ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + ActivityCompat.requestPermissions(this, + new String[] { Manifest.permission.READ_EXTERNAL_STORAGE }, + PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE); + } else { + initiateMediaPicking(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], + @NonNull int[] grantResults) { + switch (requestCode) { + case PERMISSIONS_REQUEST_READ_EXTERNAL_STORAGE: { + if (grantResults.length > 0 + && grantResults[0] == PackageManager.PERMISSION_GRANTED) { + initiateMediaPicking(); + } else { + errorText.setText(R.string.error_media_upload_permission); + } + break; + } + } + } + + private void initiateMediaPicking() { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.addCategory(Intent.CATEGORY_OPENABLE); + intent.setType("*/*"); + startActivityForResult(intent, MEDIA_PICK_RESULT); + } + @Override public boolean onCreateOptionsMenu(Menu menu) { getMenuInflater().inflate(R.menu.edit_profile_toolbar, menu); @@ -105,6 +171,9 @@ public class EditProfileActivity extends BaseActivity { } private void save() { + if (isAlreadySaving) { + return; + } String newDisplayName = displayNameEditText.getText().toString(); if (newDisplayName.isEmpty()) { displayNameEditText.setError(getString(R.string.error_empty)); @@ -115,7 +184,7 @@ public class EditProfileActivity extends BaseActivity { newDisplayName = null; } - String newNote = HtmlUtils.toHtml(noteEditText.getText()); + String newNote = noteEditText.getText().toString(); if (newNote.isEmpty()) { noteEditText.setError(getString(R.string.error_empty)); return; @@ -125,6 +194,41 @@ public class EditProfileActivity extends BaseActivity { newNote = null; } - mastodonAPI.accountUpdateCredentials(newDisplayName, newNote, null, null); + isAlreadySaving = true; + + Profile profile = new Profile(); + profile.displayName = newDisplayName; + profile.note = newNote; + profile.avatar = null; + profile.header = null; + mastodonAPI.accountUpdateCredentials(profile).enqueue(new Callback() { + @Override + public void onResponse(Call call, Response response) { + if (!response.isSuccessful()) { + onSaveFailure(); + return; + } + finish(); + } + + @Override + public void onFailure(Call call, Throwable t) { + onSaveFailure(); + } + }); + } + + private void onSaveFailure() { + isAlreadySaving = false; + errorText.setText(getString(R.string.error_media_upload_sending)); + } + + @Override + protected void onActivityResult(int requestCode, int resultCode, Intent data) { + super.onActivityResult(requestCode, resultCode, data); + if (requestCode == MEDIA_PICK_RESULT && resultCode == RESULT_OK && data != null) { + Uri uri = data.getData(); + Log.d(TAG, "picked: " + uri.toString()); + } } } diff --git a/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java b/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java index 5e10938a5..011fbc40a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java +++ b/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java @@ -20,6 +20,7 @@ import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.entity.AppCredentials; import com.keylesspalace.tusky.entity.Media; import com.keylesspalace.tusky.entity.Notification; +import com.keylesspalace.tusky.entity.Profile; import com.keylesspalace.tusky.entity.Relationship; import com.keylesspalace.tusky.entity.Status; import com.keylesspalace.tusky.entity.StatusContext; @@ -29,6 +30,7 @@ import java.util.List; import okhttp3.MultipartBody; import okhttp3.ResponseBody; import retrofit2.Call; +import retrofit2.http.Body; import retrofit2.http.DELETE; import retrofit2.http.Field; import retrofit2.http.FormUrlEncoded; @@ -115,11 +117,7 @@ public interface MastodonAPI { @GET("api/v1/accounts/verify_credentials") Call accountVerifyCredentials(); @PATCH("api/v1/accounts/update_credentials") - Call accountUpdateCredentials( - @Field("display_name") String displayName, - @Field("note") String note, - @Field("avatar") String avatar, - @Field("header") String header); + Call accountUpdateCredentials(@Body Profile profile); @GET("api/v1/accounts/search") Call> searchAccounts( @Query("q") String q, diff --git a/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java b/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java new file mode 100644 index 000000000..518bfcca2 --- /dev/null +++ b/app/src/main/java/com/keylesspalace/tusky/entity/Profile.java @@ -0,0 +1,17 @@ +package com.keylesspalace.tusky.entity; + +import com.google.gson.annotations.SerializedName; + +public class Profile { + @SerializedName("display_name") + public String displayName; + + @SerializedName("note") + public String note; + + @SerializedName("avatar") + public String avatar; + + @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 d861a91d4..5c4b2d6a6 100644 --- a/app/src/main/res/layout/activity_edit_profile.xml +++ b/app/src/main/res/layout/activity_edit_profile.xml @@ -19,6 +19,11 @@ android:background="@android:color/transparent" android:elevation="4dp" /> + + Images and videos cannot both be attached to the same status. The upload failed. At least one status must be reported. - This cannot be empty. Home Notifications