Volley is gone.
This commit is contained in:
parent
42a8f47991
commit
6f25405ad4
16 changed files with 183 additions and 357 deletions
|
@ -29,7 +29,6 @@ dependencies {
|
||||||
compile 'com.android.support:recyclerview-v7:25.2.0'
|
compile 'com.android.support:recyclerview-v7:25.2.0'
|
||||||
compile 'com.android.support:support-v13:25.2.0'
|
compile 'com.android.support:support-v13:25.2.0'
|
||||||
compile 'com.android.support:design:25.2.0'
|
compile 'com.android.support:design:25.2.0'
|
||||||
compile 'com.android.volley:volley:1.0.0'
|
|
||||||
compile 'com.squareup.picasso:picasso:2.5.2'
|
compile 'com.squareup.picasso:picasso:2.5.2'
|
||||||
compile 'com.pkmmte.view:circularimageview:1.1'
|
compile 'com.pkmmte.view:circularimageview:1.1'
|
||||||
compile 'com.github.peter9870:sparkbutton:master'
|
compile 'com.github.peter9870:sparkbutton:master'
|
||||||
|
|
|
@ -17,7 +17,6 @@ package com.keylesspalace.tusky;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
@ -30,17 +29,10 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.volley.AuthFailureError;
|
|
||||||
import com.android.volley.Request;
|
|
||||||
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.Account;
|
||||||
import com.keylesspalace.tusky.entity.Relationship;
|
import com.keylesspalace.tusky.entity.Relationship;
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
|
@ -57,8 +49,6 @@ public class AccountFragment extends Fragment implements AccountActionListener,
|
||||||
|
|
||||||
private Type type;
|
private Type type;
|
||||||
private String accountId;
|
private String accountId;
|
||||||
private String domain;
|
|
||||||
private String accessToken;
|
|
||||||
private RecyclerView recyclerView;
|
private RecyclerView recyclerView;
|
||||||
private LinearLayoutManager layoutManager;
|
private LinearLayoutManager layoutManager;
|
||||||
private EndlessOnScrollListener scrollListener;
|
private EndlessOnScrollListener scrollListener;
|
||||||
|
@ -89,11 +79,6 @@ public class AccountFragment extends Fragment implements AccountActionListener,
|
||||||
Bundle arguments = getArguments();
|
Bundle arguments = getArguments();
|
||||||
type = Type.valueOf(arguments.getString("type"));
|
type = Type.valueOf(arguments.getString("type"));
|
||||||
accountId = arguments.getString("accountId");
|
accountId = arguments.getString("accountId");
|
||||||
|
|
||||||
SharedPreferences preferences = getContext().getSharedPreferences(
|
|
||||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
|
||||||
domain = preferences.getString("domain", null);
|
|
||||||
accessToken = preferences.getString("accessToken", null);
|
|
||||||
api = ((BaseActivity) getActivity()).mastodonAPI;
|
api = ((BaseActivity) getActivity()).mastodonAPI;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -96,9 +96,11 @@ public class BaseActivity extends AppCompatActivity {
|
||||||
public Response intercept(Chain chain) throws IOException {
|
public Response intercept(Chain chain) throws IOException {
|
||||||
Request originalRequest = chain.request();
|
Request originalRequest = chain.request();
|
||||||
|
|
||||||
Request.Builder builder = originalRequest.newBuilder()
|
Request.Builder builder = originalRequest.newBuilder();
|
||||||
.header("Authorization", String.format("Bearer %s", getAccessToken()));
|
String accessToken = getAccessToken();
|
||||||
|
if (accessToken != null) {
|
||||||
|
builder.header("Authorization", String.format("Bearer %s", accessToken));
|
||||||
|
}
|
||||||
Request newRequest = builder.build();
|
Request newRequest = builder.build();
|
||||||
|
|
||||||
return chain.proceed(newRequest);
|
return chain.proceed(newRequest);
|
||||||
|
|
|
@ -28,19 +28,19 @@ import android.widget.Button;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.android.volley.Request;
|
import com.keylesspalace.tusky.entity.AccessToken;
|
||||||
import com.android.volley.Response;
|
import com.keylesspalace.tusky.entity.AppCredentials;
|
||||||
import com.android.volley.VolleyError;
|
|
||||||
import com.android.volley.toolbox.JsonObjectRequest;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
import retrofit2.Call;
|
||||||
|
import retrofit2.Callback;
|
||||||
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class LoginActivity extends BaseActivity {
|
public class LoginActivity extends BaseActivity {
|
||||||
private static final String TAG = "LoginActivity";
|
|
||||||
private static String OAUTH_SCOPES = "read write follow";
|
private static String OAUTH_SCOPES = "read write follow";
|
||||||
|
|
||||||
private SharedPreferences preferences;
|
private SharedPreferences preferences;
|
||||||
|
@ -112,50 +112,33 @@ public class LoginActivity extends BaseActivity {
|
||||||
clientSecret = prefClientSecret;
|
clientSecret = prefClientSecret;
|
||||||
redirectUserToAuthorizeAndLogin();
|
redirectUserToAuthorizeAndLogin();
|
||||||
} else {
|
} else {
|
||||||
String endpoint = getString(R.string.endpoint_apps);
|
Callback<AppCredentials> callback = new Callback<AppCredentials>() {
|
||||||
String url = "https://" + domain + endpoint;
|
@Override
|
||||||
JSONObject parameters = new JSONObject();
|
public void onResponse(Call<AppCredentials> call, Response<AppCredentials> response) {
|
||||||
try {
|
AppCredentials credentials = response.body();
|
||||||
parameters.put("client_name", getString(R.string.app_name));
|
clientId = credentials.clientId;
|
||||||
parameters.put("redirect_uris", getOauthRedirectUri());
|
clientSecret = credentials.clientSecret;
|
||||||
parameters.put("scopes", OAUTH_SCOPES);
|
SharedPreferences.Editor editor = preferences.edit();
|
||||||
parameters.put("website", getString(R.string.app_website));
|
editor.putString(domain + "/client_id", clientId);
|
||||||
} catch (JSONException e) {
|
editor.putString(domain + "/client_secret", clientSecret);
|
||||||
Log.e(TAG, "Unable to build the form data for the authentication request.");
|
editor.apply();
|
||||||
return;
|
redirectUserToAuthorizeAndLogin();
|
||||||
}
|
}
|
||||||
JsonObjectRequest request = new JsonObjectRequest(
|
|
||||||
Request.Method.POST, url, parameters,
|
@Override
|
||||||
new Response.Listener<JSONObject>() {
|
public void onFailure(Call<AppCredentials> call, Throwable t) {
|
||||||
@Override
|
editText.setError(
|
||||||
public void onResponse(JSONObject response) {
|
"This app could not obtain authentication from that server " +
|
||||||
String obtainedClientId;
|
"instance.");
|
||||||
String obtainedClientSecret;
|
t.printStackTrace();
|
||||||
try {
|
}
|
||||||
obtainedClientId = response.getString("client_id");
|
};
|
||||||
obtainedClientSecret = response.getString("client_secret");
|
|
||||||
} catch (JSONException e) {
|
List<String> redirectUris = new ArrayList<>();
|
||||||
Log.e(TAG, "Couldn't get data from the authentication response.");
|
redirectUris.add(getOauthRedirectUri());
|
||||||
return;
|
mastodonAPI.authenticateApp(getString(R.string.app_name), redirectUris, OAUTH_SCOPES,
|
||||||
}
|
getString(R.string.app_website)).enqueue(callback);
|
||||||
clientId = obtainedClientId;
|
|
||||||
clientSecret = obtainedClientSecret;
|
|
||||||
SharedPreferences.Editor editor = preferences.edit();
|
|
||||||
editor.putString(domain + "/client_id", clientId);
|
|
||||||
editor.putString(domain + "/client_secret", clientSecret);
|
|
||||||
editor.apply();
|
|
||||||
redirectUserToAuthorizeAndLogin();
|
|
||||||
}
|
|
||||||
}, new Response.ErrorListener() {
|
|
||||||
@Override
|
|
||||||
public void onErrorResponse(VolleyError error) {
|
|
||||||
editText.setError(
|
|
||||||
"This app could not obtain authentication from that server " +
|
|
||||||
"instance.");
|
|
||||||
error.printStackTrace();
|
|
||||||
}
|
|
||||||
});
|
|
||||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -251,40 +234,19 @@ public class LoginActivity extends BaseActivity {
|
||||||
clientSecret = preferences.getString("clientSecret", null);
|
clientSecret = preferences.getString("clientSecret", null);
|
||||||
/* Since authorization has succeeded, the final step to log in is to exchange
|
/* Since authorization has succeeded, the final step to log in is to exchange
|
||||||
* the authorization code for an access token. */
|
* the authorization code for an access token. */
|
||||||
JSONObject parameters = new JSONObject();
|
Callback<AccessToken> callback = new Callback<AccessToken>() {
|
||||||
try {
|
@Override
|
||||||
parameters.put("client_id", clientId);
|
public void onResponse(Call<AccessToken> call, Response<AccessToken> response) {
|
||||||
parameters.put("client_secret", clientSecret);
|
onLoginSuccess(response.body().accessToken);
|
||||||
parameters.put("redirect_uri", redirectUri);
|
}
|
||||||
parameters.put("code", code);
|
|
||||||
parameters.put("grant_type", "authorization_code");
|
@Override
|
||||||
} catch (JSONException e) {
|
public void onFailure(Call<AccessToken> call, Throwable t) {
|
||||||
errorText.setText(e.getMessage());
|
editText.setError(t.getMessage());
|
||||||
return;
|
}
|
||||||
}
|
};
|
||||||
String endpoint = getString(R.string.endpoint_token);
|
mastodonAPI.fetchOAuthToken(clientId, clientSecret, redirectUri, code,
|
||||||
String url = "https://" + domain + endpoint;
|
"authorization_code").enqueue(callback);
|
||||||
JsonObjectRequest request = new JsonObjectRequest(
|
|
||||||
Request.Method.POST, url, parameters,
|
|
||||||
new Response.Listener<JSONObject>() {
|
|
||||||
@Override
|
|
||||||
public void onResponse(JSONObject response) {
|
|
||||||
String accessToken;
|
|
||||||
try {
|
|
||||||
accessToken = response.getString("access_token");
|
|
||||||
} catch(JSONException e) {
|
|
||||||
editText.setError(e.getMessage());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
onLoginSuccess(accessToken);
|
|
||||||
}
|
|
||||||
}, new Response.ErrorListener() {
|
|
||||||
@Override
|
|
||||||
public void onErrorResponse(VolleyError error) {
|
|
||||||
editText.setError(error.getMessage());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
|
||||||
} else if (error != null) {
|
} else if (error != null) {
|
||||||
/* Authorization failed. Put the error response where the user can read it and they
|
/* Authorization failed. Put the error response where the user can read it and they
|
||||||
* can try again. */
|
* can try again. */
|
||||||
|
|
|
@ -22,27 +22,16 @@ import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.SystemClock;
|
import android.os.SystemClock;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.RequiresApi;
|
|
||||||
import android.support.design.widget.FloatingActionButton;
|
import android.support.design.widget.FloatingActionButton;
|
||||||
import android.support.design.widget.TabLayout;
|
import android.support.design.widget.TabLayout;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.v7.widget.Toolbar;
|
import android.support.v7.widget.Toolbar;
|
||||||
import android.transition.Slide;
|
|
||||||
import android.transition.TransitionInflater;
|
|
||||||
import android.view.Menu;
|
|
||||||
import android.view.MenuItem;
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
|
|
||||||
import com.android.volley.AuthFailureError;
|
|
||||||
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 com.keylesspalace.tusky.entity.Account;
|
||||||
import com.mikepenz.materialdrawer.AccountHeader;
|
import com.mikepenz.materialdrawer.AccountHeader;
|
||||||
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
|
import com.mikepenz.materialdrawer.AccountHeaderBuilder;
|
||||||
|
@ -50,18 +39,12 @@ import com.mikepenz.materialdrawer.Drawer;
|
||||||
import com.mikepenz.materialdrawer.DrawerBuilder;
|
import com.mikepenz.materialdrawer.DrawerBuilder;
|
||||||
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
|
||||||
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
|
import com.mikepenz.materialdrawer.model.ProfileDrawerItem;
|
||||||
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
|
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
import com.mikepenz.materialdrawer.model.interfaces.IDrawerItem;
|
||||||
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
import com.mikepenz.materialdrawer.model.interfaces.IProfile;
|
||||||
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader;
|
import com.mikepenz.materialdrawer.util.AbstractDrawerImageLoader;
|
||||||
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
import com.mikepenz.materialdrawer.util.DrawerImageLoader;
|
||||||
import com.squareup.picasso.Picasso;
|
import com.squareup.picasso.Picasso;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Stack;
|
import java.util.Stack;
|
||||||
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
package com.keylesspalace.tusky;
|
package com.keylesspalace.tusky;
|
||||||
|
|
||||||
|
import com.keylesspalace.tusky.entity.AccessToken;
|
||||||
import com.keylesspalace.tusky.entity.Account;
|
import com.keylesspalace.tusky.entity.Account;
|
||||||
|
import com.keylesspalace.tusky.entity.AppCredentials;
|
||||||
import com.keylesspalace.tusky.entity.Media;
|
import com.keylesspalace.tusky.entity.Media;
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
import com.keylesspalace.tusky.entity.Relationship;
|
import com.keylesspalace.tusky.entity.Relationship;
|
||||||
|
@ -10,7 +12,6 @@ import com.keylesspalace.tusky.entity.StatusContext;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
import okhttp3.RequestBody;
|
|
||||||
import okhttp3.ResponseBody;
|
import okhttp3.ResponseBody;
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.http.DELETE;
|
import retrofit2.http.DELETE;
|
||||||
|
@ -167,4 +168,22 @@ public interface MastodonAPI {
|
||||||
@FormUrlEncoded
|
@FormUrlEncoded
|
||||||
@POST("api/v1/reports")
|
@POST("api/v1/reports")
|
||||||
Call<ResponseBody> report(@Field("account_id") String accountId, @Field("status_ids[]") List<String> statusIds, @Field("comment") String comment);
|
Call<ResponseBody> report(@Field("account_id") String accountId, @Field("status_ids[]") List<String> statusIds, @Field("comment") String comment);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("api/v1/apps")
|
||||||
|
Call<AppCredentials> authenticateApp(
|
||||||
|
@Field("client_name") String clientName,
|
||||||
|
@Field("redirect_uris[]") List<String> redirectUris,
|
||||||
|
@Field("scopes") String scopes,
|
||||||
|
@Field("website") String website);
|
||||||
|
|
||||||
|
@FormUrlEncoded
|
||||||
|
@POST("oauth/token")
|
||||||
|
Call<AccessToken> fetchOAuthToken(
|
||||||
|
@Field("client_id") String clientId,
|
||||||
|
@Field("client_secret") String clientSecret,
|
||||||
|
@Field("redirect_uri") String redirectUri,
|
||||||
|
@Field("code") String code,
|
||||||
|
@Field("grant_type") String grantType
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,117 +0,0 @@
|
||||||
/* Copyright 2017 Andrew Dawson
|
|
||||||
*
|
|
||||||
* This file is part of Tusky.
|
|
||||||
*
|
|
||||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
|
||||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
|
||||||
* <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
|
||||||
|
|
||||||
import com.android.volley.NetworkResponse;
|
|
||||||
import com.android.volley.ParseError;
|
|
||||||
import com.android.volley.Request;
|
|
||||||
import com.android.volley.Response;
|
|
||||||
import com.android.volley.toolbox.HttpHeaderParser;
|
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.DataOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
|
||||||
|
|
||||||
class MultipartRequest extends Request<JSONObject> {
|
|
||||||
private static final String CHARSET = "utf-8";
|
|
||||||
private final String boundary = "something-" + System.currentTimeMillis();
|
|
||||||
|
|
||||||
private JSONObject parameters;
|
|
||||||
private Response.Listener<JSONObject> listener;
|
|
||||||
|
|
||||||
MultipartRequest(int method, String url, JSONObject parameters,
|
|
||||||
Response.Listener<JSONObject> listener, Response.ErrorListener errorListener) {
|
|
||||||
super(method, url, errorListener);
|
|
||||||
this.parameters = parameters;
|
|
||||||
this.listener = listener;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String getBodyContentType() {
|
|
||||||
return "multipart/form-data;boundary=" + boundary;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public byte[] getBody() {
|
|
||||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();
|
|
||||||
DataOutputStream stream = new DataOutputStream(byteStream);
|
|
||||||
try {
|
|
||||||
// Write the JSON parameters first.
|
|
||||||
if (parameters != null) {
|
|
||||||
stream.writeBytes(String.format("--%s\r\n", boundary));
|
|
||||||
stream.writeBytes("Content-Disposition: form-data; name=\"parameters\"\r\n");
|
|
||||||
stream.writeBytes(String.format(
|
|
||||||
"Content-Type: application/json; charset=%s\r\n", CHARSET));
|
|
||||||
stream.writeBytes("\r\n");
|
|
||||||
stream.writeBytes(parameters.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write the binary data.
|
|
||||||
DataItem data = getData();
|
|
||||||
if (data != null) {
|
|
||||||
stream.writeBytes(String.format("--%s\r\n", boundary));
|
|
||||||
stream.writeBytes(String.format(
|
|
||||||
"Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"\r\n",
|
|
||||||
data.name, data.filename));
|
|
||||||
stream.writeBytes(String.format("Content-Type: %s\r\n", data.mimeType));
|
|
||||||
stream.writeBytes(String.format("Content-Length: %s\r\n",
|
|
||||||
String.valueOf(data.content.length)));
|
|
||||||
stream.writeBytes("\r\n");
|
|
||||||
stream.write(data.content);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Close the multipart form data.
|
|
||||||
stream.writeBytes(String.format("--%s--\r\n", boundary));
|
|
||||||
|
|
||||||
return byteStream.toByteArray();
|
|
||||||
} catch (IOException e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Response<JSONObject> parseNetworkResponse(NetworkResponse response) {
|
|
||||||
try {
|
|
||||||
String jsonString = new String(response.data,
|
|
||||||
HttpHeaderParser.parseCharset(response.headers));
|
|
||||||
return Response.success(new JSONObject(jsonString),
|
|
||||||
HttpHeaderParser.parseCacheHeaders(response));
|
|
||||||
} catch (JSONException|UnsupportedEncodingException e) {
|
|
||||||
return Response.error(new ParseError(e));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void deliverResponse(JSONObject response) {
|
|
||||||
listener.onResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
public DataItem getData() {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
static class DataItem {
|
|
||||||
String name;
|
|
||||||
String filename;
|
|
||||||
String mimeType;
|
|
||||||
byte[] content;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -20,6 +20,7 @@ import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
|
import android.graphics.drawable.Drawable;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
|
@ -28,25 +29,16 @@ import android.support.v4.app.NotificationCompat;
|
||||||
import android.support.v4.app.TaskStackBuilder;
|
import android.support.v4.app.TaskStackBuilder;
|
||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
|
|
||||||
import com.android.volley.AuthFailureError;
|
|
||||||
import com.android.volley.Response;
|
|
||||||
import com.android.volley.VolleyError;
|
|
||||||
import com.android.volley.toolbox.ImageRequest;
|
|
||||||
import com.android.volley.toolbox.JsonArrayRequest;
|
|
||||||
import com.google.gson.Gson;
|
import com.google.gson.Gson;
|
||||||
import com.google.gson.GsonBuilder;
|
import com.google.gson.GsonBuilder;
|
||||||
import com.keylesspalace.tusky.entity.*;
|
import com.keylesspalace.tusky.entity.*;
|
||||||
import com.keylesspalace.tusky.entity.Notification;
|
import com.keylesspalace.tusky.entity.Notification;
|
||||||
|
import com.squareup.picasso.Picasso;
|
||||||
import org.json.JSONArray;
|
import com.squareup.picasso.Target;
|
||||||
import org.json.JSONException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import okhttp3.Interceptor;
|
import okhttp3.Interceptor;
|
||||||
import okhttp3.OkHttpClient;
|
import okhttp3.OkHttpClient;
|
||||||
|
@ -58,18 +50,12 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
||||||
|
|
||||||
public class PullNotificationService extends IntentService {
|
public class PullNotificationService extends IntentService {
|
||||||
static final int NOTIFY_ID = 6; // This is an arbitrary number.
|
static final int NOTIFY_ID = 6; // This is an arbitrary number.
|
||||||
private static final String TAG = "PullNotifications"; // logging tag and Volley request tag
|
private static final String TAG = "PullNotifications"; // logging tag
|
||||||
|
|
||||||
public PullNotificationService() {
|
public PullNotificationService() {
|
||||||
super("Tusky Pull Notification Service");
|
super("Tusky Pull Notification Service");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onDestroy() {
|
|
||||||
VolleySingleton.getInstance(this).cancelAll(TAG);
|
|
||||||
super.onDestroy();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onHandleIntent(Intent intent) {
|
protected void onHandleIntent(Intent intent) {
|
||||||
SharedPreferences preferences = getSharedPreferences(
|
SharedPreferences preferences = getSharedPreferences(
|
||||||
|
@ -173,18 +159,23 @@ public class PullNotificationService extends IntentService {
|
||||||
|
|
||||||
private void loadAvatar(final List<MentionResult> mentions, String url) {
|
private void loadAvatar(final List<MentionResult> mentions, String url) {
|
||||||
if (url != null) {
|
if (url != null) {
|
||||||
ImageRequest request = new ImageRequest(url, new Response.Listener<Bitmap>() {
|
Target target = new Target() {
|
||||||
@Override
|
@Override
|
||||||
public void onResponse(Bitmap response) {
|
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
|
||||||
updateNotification(mentions, response);
|
updateNotification(mentions, bitmap);
|
||||||
}
|
}
|
||||||
}, 0, 0, null, null, new Response.ErrorListener() {
|
|
||||||
@Override
|
@Override
|
||||||
public void onErrorResponse(VolleyError error) {
|
public void onBitmapFailed(Drawable errorDrawable) {
|
||||||
updateNotification(mentions, null);
|
updateNotification(mentions, null);
|
||||||
}
|
}
|
||||||
});
|
|
||||||
VolleySingleton.getInstance(this).addToRequestQueue(request);
|
@Override
|
||||||
|
public void onPrepareLoad(Drawable placeHolderDrawable) {}
|
||||||
|
};
|
||||||
|
Picasso.with(this)
|
||||||
|
.load(url)
|
||||||
|
.into(target);
|
||||||
} else {
|
} else {
|
||||||
updateNotification(mentions, null);
|
updateNotification(mentions, null);
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,6 @@ public class SplashActivity extends Activity {
|
||||||
String domain = preferences.getString("domain", null);
|
String domain = preferences.getString("domain", null);
|
||||||
String accessToken = preferences.getString("accessToken", null);
|
String accessToken = preferences.getString("accessToken", null);
|
||||||
|
|
||||||
|
|
||||||
final Intent intent;
|
final Intent intent;
|
||||||
|
|
||||||
if (domain != null && accessToken != null) {
|
if (domain != null && accessToken != null) {
|
||||||
|
|
|
@ -27,17 +27,9 @@ import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.android.volley.Request;
|
|
||||||
import com.android.volley.Response;
|
|
||||||
import com.android.volley.VolleyError;
|
|
||||||
import com.keylesspalace.tusky.entity.Status;
|
import com.keylesspalace.tusky.entity.Status;
|
||||||
import com.keylesspalace.tusky.entity.StatusContext;
|
import com.keylesspalace.tusky.entity.StatusContext;
|
||||||
|
|
||||||
import org.json.JSONException;
|
|
||||||
import org.json.JSONObject;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import retrofit2.Call;
|
import retrofit2.Call;
|
||||||
import retrofit2.Callback;
|
import retrofit2.Callback;
|
||||||
|
|
||||||
|
|
|
@ -1,83 +0,0 @@
|
||||||
/* Copyright 2017 Andrew Dawson
|
|
||||||
*
|
|
||||||
* This file is part of Tusky.
|
|
||||||
*
|
|
||||||
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
|
||||||
* General Public License as published by the Free Software Foundation, either version 3 of the
|
|
||||||
* License, or (at your option) any later version.
|
|
||||||
*
|
|
||||||
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
|
||||||
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
|
||||||
* Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
|
||||||
* <http://www.gnu.org/licenses/>. */
|
|
||||||
|
|
||||||
package com.keylesspalace.tusky;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.graphics.Bitmap;
|
|
||||||
import android.support.v4.util.LruCache;
|
|
||||||
|
|
||||||
import com.android.volley.Request;
|
|
||||||
import com.android.volley.RequestQueue;
|
|
||||||
import com.android.volley.toolbox.ImageLoader;
|
|
||||||
import com.android.volley.toolbox.Volley;
|
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
|
||||||
|
|
||||||
public class VolleySingleton {
|
|
||||||
private static VolleySingleton instance;
|
|
||||||
private RequestQueue requestQueue;
|
|
||||||
private ImageLoader imageLoader;
|
|
||||||
/* This is a weak reference to account for the case where it might be held onto beyond the
|
|
||||||
* lifetime of the Activity/Fragment/Service, so it can be cleaned up. */
|
|
||||||
private static WeakReference<Context> context;
|
|
||||||
|
|
||||||
private VolleySingleton(Context context) {
|
|
||||||
VolleySingleton.context = new WeakReference<>(context);
|
|
||||||
requestQueue = getRequestQueue();
|
|
||||||
imageLoader = new ImageLoader(requestQueue,
|
|
||||||
new ImageLoader.ImageCache() {
|
|
||||||
private final LruCache<String, Bitmap> cache = new LruCache<>(20);
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Bitmap getBitmap(String url) {
|
|
||||||
return cache.get(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void putBitmap(String url, Bitmap bitmap) {
|
|
||||||
cache.put(url, bitmap);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
public static synchronized VolleySingleton getInstance(Context context) {
|
|
||||||
if (instance == null) {
|
|
||||||
instance = new VolleySingleton(context);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RequestQueue getRequestQueue() {
|
|
||||||
if (requestQueue == null) {
|
|
||||||
/* getApplicationContext() is key, it keeps you from leaking the
|
|
||||||
* Activity or BroadcastReceiver if someone passes one in. */
|
|
||||||
requestQueue= Volley.newRequestQueue(context.get().getApplicationContext());
|
|
||||||
}
|
|
||||||
return requestQueue;
|
|
||||||
}
|
|
||||||
|
|
||||||
<T> void addToRequestQueue(Request<T> request) {
|
|
||||||
getRequestQueue().add(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
void cancelAll(String tag) {
|
|
||||||
getRequestQueue().cancelAll(tag);
|
|
||||||
}
|
|
||||||
|
|
||||||
ImageLoader getImageLoader() {
|
|
||||||
return imageLoader;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,23 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* This file is part of Tusky.
|
||||||
|
*
|
||||||
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
package com.keylesspalace.tusky.entity;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class AccessToken {
|
||||||
|
@SerializedName("access_token")
|
||||||
|
public String accessToken;
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* This file is part of Tusky.
|
||||||
|
*
|
||||||
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
|
package com.keylesspalace.tusky.entity;
|
||||||
|
|
||||||
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
||||||
|
public class AppCredentials {
|
||||||
|
@SerializedName("client_id")
|
||||||
|
public String clientId;
|
||||||
|
|
||||||
|
@SerializedName("client_secret")
|
||||||
|
public String clientSecret;
|
||||||
|
}
|
|
@ -1,3 +1,18 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* This file is part of Tusky.
|
||||||
|
*
|
||||||
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky.entity;
|
package com.keylesspalace.tusky.entity;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* This file is part of Tusky.
|
||||||
|
*
|
||||||
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky.entity;
|
package com.keylesspalace.tusky.entity;
|
||||||
|
|
||||||
import com.google.gson.annotations.SerializedName;
|
import com.google.gson.annotations.SerializedName;
|
||||||
|
|
|
@ -1,3 +1,18 @@
|
||||||
|
/* Copyright 2017 Andrew Dawson
|
||||||
|
*
|
||||||
|
* This file is part of Tusky.
|
||||||
|
*
|
||||||
|
* Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
|
||||||
|
* General Public License as published by the Free Software Foundation, either version 3 of the
|
||||||
|
* License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
|
||||||
|
* the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
|
||||||
|
* Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License along with Tusky. If not, see
|
||||||
|
* <http://www.gnu.org/licenses/>. */
|
||||||
|
|
||||||
package com.keylesspalace.tusky.entity;
|
package com.keylesspalace.tusky.entity;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
Loading…
Reference in a new issue