diff --git a/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java b/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java index 23391fd9..09115c60 100644 --- a/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/AccountFragment.java @@ -36,6 +36,7 @@ import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.StringRequest; import com.keylesspalace.tusky.entity.Account; +import com.keylesspalace.tusky.entity.Relationship; import java.util.HashMap; import java.util.List; @@ -63,6 +64,7 @@ public class AccountFragment extends Fragment implements AccountActionListener, private EndlessOnScrollListener scrollListener; private AccountAdapter adapter; private TabLayout.OnTabSelectedListener onTabSelectedListener; + private MastodonAPI api; public static AccountFragment newInstance(Type type) { Bundle arguments = new Bundle(); @@ -92,6 +94,7 @@ public class AccountFragment extends Fragment implements AccountActionListener, getString(R.string.preferences_file_key), Context.MODE_PRIVATE); domain = preferences.getString("domain", null); accessToken = preferences.getString("accessToken", null); + api = ((BaseActivity) getActivity()).mastodonAPI; } @Override @@ -170,8 +173,6 @@ public class AccountFragment extends Fragment implements AccountActionListener, } private void fetchAccounts(final String fromId) { - MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI; - Callback> cb = new Callback>() { @Override public void onResponse(Call> call, retrofit2.Response> response) { @@ -265,35 +266,23 @@ public class AccountFragment extends Fragment implements AccountActionListener, } public void onBlock(final boolean block, final String id, final int position) { - String endpoint; - if (!block) { - endpoint = String.format(getString(R.string.endpoint_unblock), id); - } else { - endpoint = String.format(getString(R.string.endpoint_block), id); - } - String url = "https://" + domain + endpoint; - StringRequest request = new StringRequest(Request.Method.POST, url, - new Response.Listener() { - @Override - public void onResponse(String response) { - onBlockSuccess(block, position); - } - }, - new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onBlockFailure(block, id); - } - }) { + Callback cb = new Callback() { @Override - public Map getHeaders() throws AuthFailureError { - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - return headers; + public void onResponse(Call call, retrofit2.Response response) { + onBlockSuccess(block, position); + } + + @Override + public void onFailure(Call call, Throwable t) { + onBlockFailure(block, id); } }; - request.setTag(TAG); - VolleySingleton.getInstance(getContext()).addToRequestQueue(request); + + if (!block) { + api.unblockAccount(id).enqueue(cb); + } else { + api.blockAccount(id).enqueue(cb); + } } private void onBlockSuccess(boolean blocked, int position) { diff --git a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java index 47b3283f..4c8f2154 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ComposeActivity.java @@ -76,6 +76,7 @@ import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; +import com.keylesspalace.tusky.entity.Media; import com.keylesspalace.tusky.entity.Status; import org.json.JSONArray; @@ -96,6 +97,12 @@ import java.util.Locale; import java.util.Map; import java.util.Random; +import okhttp3.MediaType; +import okhttp3.MultipartBody; +import okhttp3.RequestBody; +import retrofit2.Call; +import retrofit2.Callback; + public class ComposeActivity extends BaseActivity { private static final String TAG = "ComposeActivity"; // logging tag, and volley request tag private static final int STATUS_CHARACTER_LIMIT = 500; @@ -138,7 +145,7 @@ public class ComposeActivity extends BaseActivity { ImageView preview; Uri uri; String id; - Request uploadRequest; + Call uploadRequest; ReadyStage readyStage; byte[] content; long mediaSize; @@ -630,53 +637,28 @@ public class ComposeActivity extends BaseActivity { private void sendStatus(String content, String visibility, boolean sensitive, String spoilerText) { - String endpoint = getString(R.string.endpoint_status); - String url = "https://" + domain + endpoint; - JSONObject parameters = new JSONObject(); - try { - parameters.put("status", content); - parameters.put("visibility", visibility); - parameters.put("sensitive", sensitive); - parameters.put("spoiler_text", spoilerText); - if (inReplyToId != null) { - parameters.put("in_reply_to_id", inReplyToId); - } - JSONArray mediaIds = new JSONArray(); - for (QueuedMedia item : mediaQueued) { - mediaIds.put(item.id); - } - if (mediaIds.length() > 0) { - parameters.put("media_ids", mediaIds); - } - } catch (JSONException e) { - onSendFailure(); - return; + ArrayList mediaIds = new ArrayList(); + + for (QueuedMedia item : mediaQueued) { + mediaIds.add(item.id); } - JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, parameters, - new Response.Listener() { - @Override - public void onResponse(JSONObject response) { - onSendSuccess(); - } - }, - new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onSendFailure(); - } - }) { + + mastodonAPI.createStatus(content, inReplyToId, spoilerText, visibility, sensitive, mediaIds).enqueue(new Callback() { @Override - public Map getHeaders() throws AuthFailureError { - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - return headers; + public void onResponse(Call call, retrofit2.Response response) { + onSendSuccess(); } - }; - VolleySingleton.getInstance(this).addToRequestQueue(request); + + @Override + public void onFailure(Call call, Throwable t) { + onSendFailure(); + } + }); } private void onSendSuccess() { - Toast.makeText(this, getString(R.string.confirmation_send), Toast.LENGTH_SHORT).show(); + Snackbar bar = Snackbar.make(findViewById(R.id.activity_compose), getString(R.string.confirmation_send), Snackbar.LENGTH_SHORT); + bar.show(); finish(); } @@ -942,9 +924,6 @@ public class ComposeActivity extends BaseActivity { private void uploadMedia(final QueuedMedia item) { item.readyStage = QueuedMedia.ReadyStage.UPLOADING; - String endpoint = getString(R.string.endpoint_media); - String url = "https://" + domain + endpoint; - final String mimeType = getContentResolver().getType(item.uri); MimeTypeMap map = MimeTypeMap.getSingleton(); String fileExtension = map.getExtensionFromMimeType(mimeType); @@ -954,58 +933,42 @@ public class ComposeActivity extends BaseActivity { randomAlphanumericString(10), fileExtension); - MultipartRequest request = new MultipartRequest(Request.Method.POST, url, null, - new Response.Listener() { - @Override - public void onResponse(JSONObject response) { - try { - item.id = response.getString("id"); - } catch (JSONException e) { - onUploadFailure(item); - return; - } - waitForMediaLatch.countDown(); - } - }, new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onUploadFailure(item); - } - }) { + byte[] content = item.content; + + if (content == null) { + InputStream stream; + + try { + stream = getContentResolver().openInputStream(item.uri); + } catch (FileNotFoundException e) { + return; + } + + content = inputStreamGetBytes(stream); + IOUtils.closeQuietly(stream); + + if (content == null) { + return; + } + } + + RequestBody requestFile = RequestBody.create(MediaType.parse(mimeType), content); + MultipartBody.Part body = MultipartBody.Part.createFormData("file", filename, requestFile); + + item.uploadRequest = mastodonAPI.uploadMedia(body); + + item.uploadRequest.enqueue(new Callback() { @Override - public Map getHeaders() throws AuthFailureError { - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - return headers; + public void onResponse(Call call, retrofit2.Response response) { + item.id = response.body().id; + waitForMediaLatch.countDown(); } @Override - public DataItem getData() { - byte[] content = item.content; - if (content == null) { - InputStream stream; - try { - stream = getContentResolver().openInputStream(item.uri); - } catch (FileNotFoundException e) { - return null; - } - content = inputStreamGetBytes(stream); - IOUtils.closeQuietly(stream); - if (content == null) { - return null; - } - } - DataItem data = new DataItem(); - data.name = "file"; - data.filename = filename; - data.mimeType = mimeType; - data.content = content; - return data; + public void onFailure(Call call, Throwable t) { + onUploadFailure(item); } - }; - request.setTag(TAG); - item.uploadRequest = request; - VolleySingleton.getInstance(this).addToRequestQueue(request); + }); } private void onUploadFailure(QueuedMedia item) { diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 3fb5b338..37f8e7bc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -41,6 +41,7 @@ import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; +import com.keylesspalace.tusky.entity.Account; import org.json.JSONException; import org.json.JSONObject; @@ -49,6 +50,9 @@ import java.util.HashMap; import java.util.Map; import java.util.Stack; +import retrofit2.Call; +import retrofit2.Callback; + public class MainActivity extends BaseActivity { private static final String TAG = "MainActivity"; // logging tag and Volley request tag @@ -148,47 +152,23 @@ public class MainActivity extends BaseActivity { private void fetchUserInfo() { SharedPreferences preferences = getSharedPreferences( getString(R.string.preferences_file_key), Context.MODE_PRIVATE); - String domain = preferences.getString("domain", null); - final String accessToken = preferences.getString("accessToken", null); String id = preferences.getString("loggedInAccountId", null); String username = preferences.getString("loggedInAccountUsername", null); if (id != null && username != null) { loggedInAccountId = id; loggedInAccountUsername = username; } else { - String endpoint = getString(R.string.endpoint_verify_credentials); - String url = "https://" + domain + endpoint; - JsonObjectRequest request = new JsonObjectRequest(Request.Method.GET, url, null, - new Response.Listener() { - @Override - public void onResponse(JSONObject response) { - String username; - String id; - try { - id = response.getString("id"); - username = response.getString("acct"); - } catch (JSONException e) { - onFetchUserInfoFailure(e); - return; - } - onFetchUserInfoSuccess(id, username); - } - }, - new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onFetchUserInfoFailure(error); - } - }) { + mastodonAPI.accountVerifyCredentials().enqueue(new Callback() { @Override - public Map getHeaders() throws AuthFailureError { - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - return headers; + public void onResponse(Call call, retrofit2.Response response) { + onFetchUserInfoSuccess(response.body().id, response.body().username); } - }; - request.setTag(TAG); - VolleySingleton.getInstance(this).addToRequestQueue(request); + + @Override + public void onFailure(Call call, Throwable t) { + onFetchUserInfoFailure((Exception) t); + } + }); } } diff --git a/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java b/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java index 9bcf7057..66019ad1 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java +++ b/app/src/main/java/com/keylesspalace/tusky/MastodonAPI.java @@ -9,6 +9,7 @@ import com.keylesspalace.tusky.entity.StatusContext; import java.util.List; +import okhttp3.MultipartBody; import okhttp3.RequestBody; import okhttp3.ResponseBody; import retrofit2.Call; @@ -54,7 +55,7 @@ public interface MastodonAPI { @Multipart @POST("api/v1/media") - Call uploadMedia(@Part("file") RequestBody file); + Call uploadMedia(@Part("file") MultipartBody.Part file); @FormUrlEncoded @POST("api/v1/statuses") @@ -162,4 +163,8 @@ public interface MastodonAPI { Call authorizeFollowRequest(@Path("id") String accountId); @POST("api/v1/follow_requests/{id}/reject") Call rejectFollowRequest(@Path("id") String accountId); + + @FormUrlEncoded + @POST("api/v1/reports") + Call report(@Field("account_id") String accountId, @Field("status_ids[]") List statusIds, @Field("comment") String comment); } diff --git a/app/src/main/java/com/keylesspalace/tusky/ReportActivity.java b/app/src/main/java/com/keylesspalace/tusky/ReportActivity.java index 34aa8694..3c13570a 100644 --- a/app/src/main/java/com/keylesspalace/tusky/ReportActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/ReportActivity.java @@ -45,10 +45,12 @@ import org.json.JSONException; import org.json.JSONObject; import java.util.ArrayList; +import java.util.Arrays; import java.util.HashMap; import java.util.List; import java.util.Map; +import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; @@ -145,45 +147,22 @@ public class ReportActivity extends BaseActivity { private void sendReport(final String accountId, final String[] statusIds, final String comment) { - JSONObject parameters = new JSONObject(); - try { - parameters.put("account_id", accountId); - parameters.put("status_ids", makeStringArrayCompat(statusIds)); - parameters.put("comment", comment); - } catch (JSONException e) { - Log.e(TAG, "Not all the report parameters have been properly set. " + e.getMessage()); - onSendFailure(accountId, statusIds, comment); - return; - } - String endpoint = getString(R.string.endpoint_reports); - String url = "https://" + domain + endpoint; - JsonObjectRequest request = new JsonObjectRequest(Request.Method.POST, url, parameters, - new Response.Listener() { - @Override - public void onResponse(JSONObject response) { - onSendSuccess(); - } - }, - new Response.ErrorListener() { - @Override - public void onErrorResponse(VolleyError error) { - onSendFailure(accountId, statusIds, comment); - } - }) { + mastodonAPI.report(accountId, Arrays.asList(statusIds), comment).enqueue(new Callback() { @Override - public Map getHeaders() throws AuthFailureError { - Map headers = new HashMap<>(); - headers.put("Authorization", "Bearer " + accessToken); - return headers; + public void onResponse(Call call, retrofit2.Response response) { + onSendSuccess(); } - }; - request.setTag(TAG); - VolleySingleton.getInstance(this).addToRequestQueue(request); + + @Override + public void onFailure(Call call, Throwable t) { + onSendFailure(accountId, statusIds, comment); + } + }); } private void onSendSuccess() { - Toast.makeText(this, getString(R.string.confirmation_reported), Toast.LENGTH_SHORT) - .show(); + Snackbar bar = Snackbar.make(anyView, getString(R.string.confirmation_reported), Snackbar.LENGTH_SHORT); + bar.show(); finish(); } diff --git a/app/src/main/java/com/keylesspalace/tusky/SFragment.java b/app/src/main/java/com/keylesspalace/tusky/SFragment.java index 7d4feda3..e95d04cf 100644 --- a/app/src/main/java/com/keylesspalace/tusky/SFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/SFragment.java @@ -33,6 +33,7 @@ import com.android.volley.Request; import com.android.volley.Response; import com.android.volley.VolleyError; import com.android.volley.toolbox.JsonObjectRequest; +import com.keylesspalace.tusky.entity.Relationship; import com.keylesspalace.tusky.entity.Status; import org.json.JSONObject; @@ -42,6 +43,7 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import okhttp3.ResponseBody; import retrofit2.Call; import retrofit2.Callback; @@ -144,15 +146,45 @@ public class SFragment extends Fragment { } protected void follow(String id) { - api.followAccount(id).enqueue(null); + api.followAccount(id).enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); } private void block(String id) { - api.blockAccount(id).enqueue(null); + api.blockAccount(id).enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); } private void delete(String id) { - api.deleteStatus(id).enqueue(null); + api.deleteStatus(id).enqueue(new Callback() { + @Override + public void onResponse(Call call, retrofit2.Response response) { + + } + + @Override + public void onFailure(Call call, Throwable t) { + + } + }); } protected void more(Status status, View view, final AdapterItemRemover adapter, diff --git a/app/src/main/java/com/keylesspalace/tusky/SpannedTypeAdapter.java b/app/src/main/java/com/keylesspalace/tusky/SpannedTypeAdapter.java index 1ef4db1c..d1e2adda 100644 --- a/app/src/main/java/com/keylesspalace/tusky/SpannedTypeAdapter.java +++ b/app/src/main/java/com/keylesspalace/tusky/SpannedTypeAdapter.java @@ -2,6 +2,7 @@ package com.keylesspalace.tusky; import android.text.Spanned; +import com.emojione.Emojione; import com.google.gson.JsonDeserializationContext; import com.google.gson.JsonDeserializer; import com.google.gson.JsonElement; @@ -12,6 +13,6 @@ import java.lang.reflect.Type; class SpannedTypeAdapter implements JsonDeserializer { @Override public Spanned deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { - return HtmlUtils.fromHtml(json.getAsString()); + return HtmlUtils.fromHtml(Emojione.shortnameToUnicode(json.getAsString(), false)); } }