Merge branch 'Gargron-master'
This commit is contained in:
commit
f391538984
14 changed files with 314 additions and 118 deletions
|
@ -47,6 +47,8 @@ import com.squareup.picasso.Picasso;
|
|||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
@ -63,10 +65,13 @@ public class AccountActivity extends BaseActivity {
|
|||
private TabLayout tabLayout;
|
||||
private Account loadedAccount;
|
||||
|
||||
@BindView(R.id.account_locked) ImageView accountLockedView;
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_account);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
Intent intent = getIntent();
|
||||
accountId = intent.getStringExtra("id");
|
||||
|
@ -193,6 +198,12 @@ public class AccountActivity extends BaseActivity {
|
|||
note.setLinksClickable(true);
|
||||
note.setMovementMethod(LinkMovementMethod.getInstance());
|
||||
|
||||
if (account.locked) {
|
||||
accountLockedView.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
accountLockedView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
Picasso.with(this)
|
||||
.load(account.avatar)
|
||||
.placeholder(R.drawable.avatar_default)
|
||||
|
|
|
@ -40,10 +40,13 @@ import retrofit2.Callback;
|
|||
public class AccountFragment extends Fragment implements AccountActionListener {
|
||||
private static final String TAG = "Account"; // logging tag
|
||||
|
||||
private Call<List<Account>> listCall;
|
||||
|
||||
public enum Type {
|
||||
FOLLOWS,
|
||||
FOLLOWERS,
|
||||
BLOCKS,
|
||||
MUTES,
|
||||
}
|
||||
|
||||
private Type type;
|
||||
|
@ -141,6 +144,12 @@ public class AccountFragment extends Fragment implements AccountActionListener {
|
|||
return rootView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (listCall != null) listCall.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (jumpToTopAllowed()) {
|
||||
|
@ -166,15 +175,23 @@ public class AccountFragment extends Fragment implements AccountActionListener {
|
|||
switch (type) {
|
||||
default:
|
||||
case FOLLOWS: {
|
||||
api.accountFollowing(accountId, fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.accountFollowing(accountId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case FOLLOWERS: {
|
||||
api.accountFollowers(accountId, fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.accountFollowers(accountId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case BLOCKS: {
|
||||
api.blocks(fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.blocks(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case MUTES: {
|
||||
listCall = api.mutes(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -399,11 +399,18 @@ public class ComposeActivity extends BaseActivity {
|
|||
if (intent != null) {
|
||||
inReplyToId = intent.getStringExtra("in_reply_to_id");
|
||||
String replyVisibility = intent.getStringExtra("reply_visibility");
|
||||
|
||||
if (replyVisibility != null) {
|
||||
/* Override any remembered visibilty and instead adopt the visibility of the status
|
||||
* to which this replies. */
|
||||
statusVisibility = replyVisibility;
|
||||
// Lowest possible visibility setting in response
|
||||
if (statusVisibility.equals("private") || replyVisibility.equals("private")) {
|
||||
statusVisibility = "private";
|
||||
} else if (statusVisibility.equals("unlisted") || replyVisibility.equals("unlisted")) {
|
||||
statusVisibility = "unlisted";
|
||||
} else {
|
||||
statusVisibility = replyVisibility;
|
||||
}
|
||||
}
|
||||
|
||||
mentionedUsernames = intent.getStringArrayExtra("mentioned_usernames");
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.support.v7.widget.Toolbar;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
|
@ -34,6 +33,8 @@ import com.keylesspalace.tusky.entity.AppCredentials;
|
|||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import retrofit2.Call;
|
||||
import retrofit2.Callback;
|
||||
import retrofit2.Response;
|
||||
|
@ -45,10 +46,14 @@ public class LoginActivity extends BaseActivity {
|
|||
private static String OAUTH_SCOPES = "read write follow";
|
||||
|
||||
private SharedPreferences preferences;
|
||||
|
||||
private String domain;
|
||||
private String clientId;
|
||||
private String clientSecret;
|
||||
private EditText editText;
|
||||
|
||||
@BindView(R.id.edit_text_domain) EditText editText;
|
||||
@BindView(R.id.button_login) Button button;
|
||||
@BindView(R.id.no_account) TextView noAccount;
|
||||
|
||||
/**
|
||||
* Chain together the key-value pairs into a query string, for either appending to a URL or
|
||||
|
@ -117,6 +122,7 @@ public class LoginActivity extends BaseActivity {
|
|||
* time. */
|
||||
String prefClientId = preferences.getString(domain + "/client_id", null);
|
||||
String prefClientSecret = preferences.getString(domain + "/client_secret", null);
|
||||
|
||||
if (prefClientId != null && prefClientSecret != null) {
|
||||
clientId = prefClientId;
|
||||
clientSecret = prefClientSecret;
|
||||
|
@ -126,9 +132,7 @@ public class LoginActivity extends BaseActivity {
|
|||
@Override
|
||||
public void onResponse(Call<AppCredentials> call, Response<AppCredentials> response) {
|
||||
if (!response.isSuccessful()) {
|
||||
editText.setError(
|
||||
"This app could not obtain authentication from that server " +
|
||||
"instance.");
|
||||
editText.setError(getString(R.string.error_failed_app_registration));
|
||||
Log.e(TAG, "App authentication failed. " + response.message());
|
||||
return;
|
||||
}
|
||||
|
@ -144,15 +148,17 @@ public class LoginActivity extends BaseActivity {
|
|||
|
||||
@Override
|
||||
public void onFailure(Call<AppCredentials> call, Throwable t) {
|
||||
editText.setError(
|
||||
"This app could not obtain authentication from that server " +
|
||||
"instance.");
|
||||
editText.setError(getString(R.string.error_failed_app_registration));
|
||||
t.printStackTrace();
|
||||
}
|
||||
};
|
||||
|
||||
getApiFor(domain).authenticateApp(getString(R.string.app_name), getOauthRedirectUri(), OAUTH_SCOPES,
|
||||
getString(R.string.app_website)).enqueue(callback);
|
||||
try {
|
||||
getApiFor(domain).authenticateApp(getString(R.string.app_name), getOauthRedirectUri(), OAUTH_SCOPES,
|
||||
getString(R.string.app_website)).enqueue(callback);
|
||||
} catch (IllegalArgumentException e) {
|
||||
editText.setError(getString(R.string.error_invalid_domain));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -161,25 +167,26 @@ public class LoginActivity extends BaseActivity {
|
|||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_login);
|
||||
ButterKnife.bind(this);
|
||||
|
||||
if (savedInstanceState != null) {
|
||||
domain = savedInstanceState.getString("domain");
|
||||
clientId = savedInstanceState.getString("clientId");
|
||||
clientSecret = savedInstanceState.getString("clientSecret");
|
||||
}
|
||||
Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
|
||||
setSupportActionBar(toolbar);
|
||||
|
||||
preferences = getSharedPreferences(
|
||||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
Button button = (Button) findViewById(R.id.button_login);
|
||||
editText = (EditText) findViewById(R.id.edit_text_domain);
|
||||
|
||||
button.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onButtonClick(editText);
|
||||
}
|
||||
});
|
||||
TextView noAccount = (TextView) findViewById(R.id.no_account);
|
||||
|
||||
final Context context = this;
|
||||
|
||||
noAccount.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
|
@ -233,11 +240,12 @@ public class LoginActivity extends BaseActivity {
|
|||
* redirect that was given to the server. If so, its response is here! */
|
||||
Uri uri = getIntent().getData();
|
||||
String redirectUri = getOauthRedirectUri();
|
||||
|
||||
if (uri != null && uri.toString().startsWith(redirectUri)) {
|
||||
// This should either have returned an authorization code or an error.
|
||||
String code = uri.getQueryParameter("code");
|
||||
String error = uri.getQueryParameter("error");
|
||||
final TextView errorText = (TextView) findViewById(R.id.text_error);
|
||||
|
||||
if (code != null) {
|
||||
/* During the redirect roundtrip this Activity usually dies, which wipes out the
|
||||
* instance variables, so they have to be recovered from where they were saved in
|
||||
|
@ -264,15 +272,16 @@ public class LoginActivity extends BaseActivity {
|
|||
editText.setError(t.getMessage());
|
||||
}
|
||||
};
|
||||
|
||||
getApiFor(domain).fetchOAuthToken(clientId, clientSecret, redirectUri, code,
|
||||
"authorization_code").enqueue(callback);
|
||||
} else if (error != null) {
|
||||
/* Authorization failed. Put the error response where the user can read it and they
|
||||
* can try again. */
|
||||
errorText.setText(error);
|
||||
editText.setError(error);
|
||||
} else {
|
||||
// This case means a junk response was received somehow.
|
||||
errorText.setText(getString(R.string.error_authorization_unknown));
|
||||
editText.setError(getString(R.string.error_authorization_unknown));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
|
||||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.app.NotificationManager;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
|
@ -22,12 +23,12 @@ import android.graphics.PorterDuff;
|
|||
import android.graphics.Typeface;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
import android.support.design.widget.FloatingActionButton;
|
||||
import android.support.design.widget.TabLayout;
|
||||
import android.support.v4.content.ContextCompat;
|
||||
import android.support.v4.view.ViewPager;
|
||||
import android.os.Bundle;
|
||||
import android.text.SpannableStringBuilder;
|
||||
import android.text.Spanned;
|
||||
import android.text.TextUtils;
|
||||
|
@ -187,6 +188,18 @@ public class MainActivity extends BaseActivity {
|
|||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState, PersistableBundle outPersistentState) {
|
||||
ArrayList<Integer> pageHistoryList = new ArrayList<>();
|
||||
|
|
|
@ -22,6 +22,9 @@ import com.keylesspalace.tusky.entity.Notification;
|
|||
import com.squareup.picasso.Picasso;
|
||||
import com.squareup.picasso.Target;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import okhttp3.Interceptor;
|
||||
|
@ -36,6 +39,7 @@ import retrofit2.converter.gson.GsonConverterFactory;
|
|||
public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
||||
private MastodonAPI mastodonAPI;
|
||||
private static final String TAG = "MyFirebaseMessagingService";
|
||||
public static final int NOTIFY_ID = 666;
|
||||
|
||||
@Override
|
||||
public void onMessageReceived(RemoteMessage remoteMessage) {
|
||||
|
@ -112,6 +116,34 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|||
|
||||
private void buildNotification(Notification body) {
|
||||
final SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this);
|
||||
final SharedPreferences notificationPreferences = getApplicationContext().getSharedPreferences("Notifications", MODE_PRIVATE);
|
||||
|
||||
String rawCurrentNotifications = notificationPreferences.getString("current", "[]");
|
||||
JSONArray currentNotifications;
|
||||
|
||||
try {
|
||||
currentNotifications = new JSONArray(rawCurrentNotifications);
|
||||
} catch (JSONException e) {
|
||||
currentNotifications = new JSONArray();
|
||||
}
|
||||
|
||||
boolean alreadyContains = false;
|
||||
|
||||
for(int i = 0; i < currentNotifications.length(); i++) {
|
||||
try {
|
||||
if (currentNotifications.getString(i).equals(body.account.displayName)) {
|
||||
alreadyContains = true;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
if (!alreadyContains) currentNotifications.put(body.account.displayName);
|
||||
|
||||
SharedPreferences.Editor editor = notificationPreferences.edit();
|
||||
editor.putString("current", currentNotifications.toString());
|
||||
editor.commit();
|
||||
|
||||
Intent resultIntent = new Intent(this, MainActivity.class);
|
||||
resultIntent.putExtra("tab_position", 1);
|
||||
|
@ -122,73 +154,109 @@ public class MyFirebaseMessagingService extends FirebaseMessagingService {
|
|||
|
||||
final NotificationCompat.Builder builder = new NotificationCompat.Builder(this)
|
||||
.setSmallIcon(R.drawable.ic_notify)
|
||||
.setAutoCancel(true)
|
||||
.setContentIntent(resultPendingIntent)
|
||||
.setDefaults(0); // So it doesn't ring twice, notify only in Target callback
|
||||
|
||||
final Integer mId = (int)(System.currentTimeMillis() / 1000);
|
||||
if (currentNotifications.length() == 1) {
|
||||
builder.setContentTitle(titleForType(body))
|
||||
.setContentText(truncateWithEllipses(bodyForType(body), 40));
|
||||
|
||||
Target mTarget = new Target() {
|
||||
@Override
|
||||
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
|
||||
builder.setLargeIcon(bitmap);
|
||||
Target mTarget = new Target() {
|
||||
@Override
|
||||
public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom from) {
|
||||
builder.setLargeIcon(bitmap);
|
||||
|
||||
if (preferences.getBoolean("notificationAlertSound", true)) {
|
||||
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
|
||||
setupPreferences(preferences, builder);
|
||||
|
||||
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(NOTIFY_ID, builder.build());
|
||||
}
|
||||
|
||||
if (preferences.getBoolean("notificationStyleVibrate", false)) {
|
||||
builder.setVibrate(new long[] { 500, 500 });
|
||||
@Override
|
||||
public void onBitmapFailed(Drawable errorDrawable) {
|
||||
|
||||
}
|
||||
|
||||
if (preferences.getBoolean("notificationStyleLight", false)) {
|
||||
builder.setLights(0xFF00FF8F, 300, 1000);
|
||||
@Override
|
||||
public void onPrepareLoad(Drawable placeHolderDrawable) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(mId, builder.build());
|
||||
Picasso.with(this)
|
||||
.load(body.account.avatar)
|
||||
.placeholder(R.drawable.avatar_default)
|
||||
.transform(new RoundedTransformation(7, 0))
|
||||
.into(mTarget);
|
||||
} else {
|
||||
setupPreferences(preferences, builder);
|
||||
|
||||
try {
|
||||
builder.setContentTitle(String.format(getString(R.string.notification_title_summary), currentNotifications.length()))
|
||||
.setContentText(truncateWithEllipses(joinNames(currentNotifications), 40));
|
||||
} catch (JSONException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBitmapFailed(Drawable errorDrawable) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPrepareLoad(Drawable placeHolderDrawable) {
|
||||
|
||||
}
|
||||
};
|
||||
|
||||
Picasso.with(this)
|
||||
.load(body.account.avatar)
|
||||
.placeholder(R.drawable.avatar_default)
|
||||
.transform(new RoundedTransformation(7, 0))
|
||||
.into(mTarget);
|
||||
}
|
||||
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
builder.setVisibility(android.app.Notification.VISIBILITY_PRIVATE);
|
||||
builder.setCategory(android.app.Notification.CATEGORY_SOCIAL);
|
||||
}
|
||||
|
||||
switch (body.type) {
|
||||
case MENTION:
|
||||
builder.setContentTitle(String.format(getString(R.string.notification_mention_format), body.account.getDisplayName()))
|
||||
.setContentText(truncateWithEllipses(body.status.content.toString(), 40));
|
||||
break;
|
||||
case FOLLOW:
|
||||
builder.setContentTitle(String.format(getString(R.string.notification_follow_format), body.account.getDisplayName()))
|
||||
.setContentText(truncateWithEllipses(body.account.username, 40));
|
||||
break;
|
||||
case FAVOURITE:
|
||||
builder.setContentTitle(String.format(getString(R.string.notification_favourite_format), body.account.getDisplayName()))
|
||||
.setContentText(truncateWithEllipses(body.status.content.toString(), 40));
|
||||
break;
|
||||
case REBLOG:
|
||||
builder.setContentTitle(String.format(getString(R.string.notification_reblog_format), body.account.getDisplayName()))
|
||||
.setContentText(truncateWithEllipses(body.status.content.toString(), 40));
|
||||
break;
|
||||
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(NOTIFY_ID, builder.build());
|
||||
}
|
||||
|
||||
private void setupPreferences(SharedPreferences preferences, NotificationCompat.Builder builder) {
|
||||
if (preferences.getBoolean("notificationAlertSound", true)) {
|
||||
builder.setSound(Settings.System.DEFAULT_NOTIFICATION_URI);
|
||||
}
|
||||
|
||||
((NotificationManager) (getSystemService(NOTIFICATION_SERVICE))).notify(mId, builder.build());
|
||||
if (preferences.getBoolean("notificationStyleVibrate", false)) {
|
||||
builder.setVibrate(new long[] { 500, 500 });
|
||||
}
|
||||
|
||||
if (preferences.getBoolean("notificationStyleLight", false)) {
|
||||
builder.setLights(0xFF00FF8F, 300, 1000);
|
||||
}
|
||||
}
|
||||
|
||||
private String joinNames(JSONArray array) throws JSONException {
|
||||
if (array.length() > 3) {
|
||||
return String.format(getString(R.string.notification_summary_large), array.get(0), array.get(1), array.get(2), array.length() - 3);
|
||||
} else if (array.length() == 3) {
|
||||
return String.format(getString(R.string.notification_summary_medium), array.get(0), array.get(1), array.get(2));
|
||||
} else if (array.length() == 2) {
|
||||
return String.format(getString(R.string.notification_summary_small), array.get(0), array.get(1));
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String titleForType(Notification notification) {
|
||||
switch (notification.type) {
|
||||
case MENTION:
|
||||
return String.format(getString(R.string.notification_mention_format), notification.account.getDisplayName());
|
||||
case FOLLOW:
|
||||
return String.format(getString(R.string.notification_follow_format), notification.account.getDisplayName());
|
||||
case FAVOURITE:
|
||||
return String.format(getString(R.string.notification_favourite_format), notification.account.getDisplayName());
|
||||
case REBLOG:
|
||||
return String.format(getString(R.string.notification_reblog_format), notification.account.getDisplayName());
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private String bodyForType(Notification notification) {
|
||||
switch (notification.type) {
|
||||
case FOLLOW:
|
||||
return notification.account.username;
|
||||
case MENTION:
|
||||
case FAVOURITE:
|
||||
case REBLOG:
|
||||
return notification.status.content.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -48,6 +48,7 @@ public class NotificationsFragment extends SFragment implements
|
|||
private EndlessOnScrollListener scrollListener;
|
||||
private NotificationsAdapter adapter;
|
||||
private TabLayout.OnTabSelectedListener onTabSelectedListener;
|
||||
private Call<List<Notification>> listCall;
|
||||
|
||||
public static NotificationsFragment newInstance() {
|
||||
NotificationsFragment fragment = new NotificationsFragment();
|
||||
|
@ -122,6 +123,12 @@ public class NotificationsFragment extends SFragment implements
|
|||
sendFetchNotificationsRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (listCall != null) listCall.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
TabLayout tabLayout = (TabLayout) getActivity().findViewById(R.id.tab_layout);
|
||||
|
@ -137,7 +144,9 @@ public class NotificationsFragment extends SFragment implements
|
|||
private void sendFetchNotificationsRequest(final String fromId, String uptoId) {
|
||||
MastodonAPI api = ((BaseActivity) getActivity()).mastodonAPI;
|
||||
|
||||
api.notifications(fromId, uptoId, null).enqueue(new Callback<List<Notification>>() {
|
||||
listCall = api.notifications(fromId, uptoId, null);
|
||||
|
||||
listCall.enqueue(new Callback<List<Notification>>() {
|
||||
@Override
|
||||
public void onResponse(Call<List<Notification>> call, retrofit2.Response<List<Notification>> response) {
|
||||
if (response.isSuccessful()) {
|
||||
|
|
|
@ -20,8 +20,9 @@ import android.content.Intent;
|
|||
import android.content.SharedPreferences;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.support.v7.widget.PopupMenu;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.Spanned;
|
||||
|
@ -47,7 +48,6 @@ import retrofit2.Callback;
|
|||
public class SFragment extends Fragment {
|
||||
protected String loggedInAccountId;
|
||||
protected String loggedInUsername;
|
||||
private MastodonAPI api;
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
|
@ -57,7 +57,10 @@ public class SFragment extends Fragment {
|
|||
getString(R.string.preferences_file_key), Context.MODE_PRIVATE);
|
||||
loggedInAccountId = preferences.getString("loggedInAccountId", null);
|
||||
loggedInUsername = preferences.getString("loggedInAccountUsername", null);
|
||||
api = ((BaseActivity) getActivity()).mastodonAPI;
|
||||
}
|
||||
|
||||
public MastodonAPI getApi() {
|
||||
return ((BaseActivity) getActivity()).mastodonAPI;
|
||||
}
|
||||
|
||||
protected void reply(Status status) {
|
||||
|
@ -85,6 +88,11 @@ public class SFragment extends Fragment {
|
|||
public void onResponse(Call<Status> call, retrofit2.Response<Status> response) {
|
||||
if (response.isSuccessful()) {
|
||||
status.reblogged = reblog;
|
||||
|
||||
if (status.reblog != null) {
|
||||
status.reblog.reblogged = reblog;
|
||||
}
|
||||
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
|
@ -96,9 +104,9 @@ public class SFragment extends Fragment {
|
|||
};
|
||||
|
||||
if (reblog) {
|
||||
api.reblogStatus(id).enqueue(cb);
|
||||
getApi().reblogStatus(id).enqueue(cb);
|
||||
} else {
|
||||
api.unreblogStatus(id).enqueue(cb);
|
||||
getApi().unreblogStatus(id).enqueue(cb);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +119,11 @@ public class SFragment extends Fragment {
|
|||
public void onResponse(Call<Status> call, retrofit2.Response<Status> response) {
|
||||
if (response.isSuccessful()) {
|
||||
status.favourited = favourite;
|
||||
|
||||
if (status.reblog != null) {
|
||||
status.reblog.favourited = favourite;
|
||||
}
|
||||
|
||||
adapter.notifyItemChanged(position);
|
||||
}
|
||||
}
|
||||
|
@ -122,14 +135,14 @@ public class SFragment extends Fragment {
|
|||
};
|
||||
|
||||
if (favourite) {
|
||||
api.favouriteStatus(id).enqueue(cb);
|
||||
getApi().favouriteStatus(id).enqueue(cb);
|
||||
} else {
|
||||
api.unfavouriteStatus(id).enqueue(cb);
|
||||
getApi().unfavouriteStatus(id).enqueue(cb);
|
||||
}
|
||||
}
|
||||
|
||||
private void block(String id) {
|
||||
api.blockAccount(id).enqueue(new Callback<Relationship>() {
|
||||
getApi().blockAccount(id).enqueue(new Callback<Relationship>() {
|
||||
@Override
|
||||
public void onResponse(Call<Relationship> call, retrofit2.Response<Relationship> response) {
|
||||
|
||||
|
@ -143,7 +156,7 @@ public class SFragment extends Fragment {
|
|||
}
|
||||
|
||||
private void delete(String id) {
|
||||
api.deleteStatus(id).enqueue(new Callback<ResponseBody>() {
|
||||
getApi().deleteStatus(id).enqueue(new Callback<ResponseBody>() {
|
||||
@Override
|
||||
public void onResponse(Call<ResponseBody> call, retrofit2.Response<ResponseBody> response) {
|
||||
|
||||
|
@ -206,13 +219,9 @@ public class SFragment extends Fragment {
|
|||
protected void viewMedia(String url, Status.MediaAttachment.Type type) {
|
||||
switch (type) {
|
||||
case IMAGE: {
|
||||
Fragment newFragment = ViewMediaFragment.newInstance(url);
|
||||
|
||||
FragmentManager manager = getFragmentManager();
|
||||
manager.beginTransaction()
|
||||
.add(R.id.overlay_fragment_container, newFragment)
|
||||
.addToBackStack(null)
|
||||
.commit();
|
||||
DialogFragment newFragment = ViewMediaFragment.newInstance(url);
|
||||
FragmentTransaction ft = getFragmentManager().beginTransaction();
|
||||
newFragment.show(ft, "view_media");
|
||||
break;
|
||||
}
|
||||
case GIFV:
|
||||
|
|
|
@ -39,6 +39,8 @@ public class TimelineFragment extends SFragment implements
|
|||
SwipeRefreshLayout.OnRefreshListener, StatusActionListener {
|
||||
private static final String TAG = "Timeline"; // logging tag
|
||||
|
||||
private Call<List<Status>> listCall;
|
||||
|
||||
enum Kind {
|
||||
HOME,
|
||||
PUBLIC,
|
||||
|
@ -144,6 +146,12 @@ public class TimelineFragment extends SFragment implements
|
|||
sendFetchTimelineRequest();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
if (listCall != null) listCall.cancel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroyView() {
|
||||
if (jumpToTopAllowed()) {
|
||||
|
@ -184,23 +192,28 @@ public class TimelineFragment extends SFragment implements
|
|||
switch (kind) {
|
||||
default:
|
||||
case HOME: {
|
||||
api.homeTimeline(fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.homeTimeline(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case PUBLIC: {
|
||||
api.publicTimeline(null, fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.publicTimeline(null, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case TAG: {
|
||||
api.hashtagTimeline(hashtagOrId, null, fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.hashtagTimeline(hashtagOrId, null, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case USER: {
|
||||
api.accountStatuses(hashtagOrId, fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.accountStatuses(hashtagOrId, fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
case FAVOURITES: {
|
||||
api.favourites(fromId, uptoId, null).enqueue(cb);
|
||||
listCall = api.favourites(fromId, uptoId, null);
|
||||
listCall.enqueue(cb);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -16,21 +16,27 @@
|
|||
package com.keylesspalace.tusky;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.squareup.picasso.Callback;
|
||||
import com.squareup.picasso.Picasso;
|
||||
|
||||
import butterknife.BindView;
|
||||
import butterknife.ButterKnife;
|
||||
import uk.co.senab.photoview.PhotoView;
|
||||
import uk.co.senab.photoview.PhotoViewAttacher;
|
||||
|
||||
public class ViewMediaFragment extends Fragment {
|
||||
public class ViewMediaFragment extends DialogFragment {
|
||||
|
||||
private PhotoViewAttacher attacher;
|
||||
|
||||
@BindView(R.id.view_media_image) PhotoView photoView;
|
||||
|
||||
public static ViewMediaFragment newInstance(String url) {
|
||||
Bundle arguments = new Bundle();
|
||||
ViewMediaFragment fragment = new ViewMediaFragment();
|
||||
|
@ -39,14 +45,29 @@ public class ViewMediaFragment extends Fragment {
|
|||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setStyle(DialogFragment.STYLE_NORMAL, R.style.Dialog_FullScreen);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
ViewGroup.LayoutParams params = getDialog().getWindow().getAttributes();
|
||||
params.width = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
params.height = WindowManager.LayoutParams.MATCH_PARENT;
|
||||
getDialog().getWindow().setAttributes((android.view.WindowManager.LayoutParams) params);
|
||||
super.onResume();
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, final ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View rootView = inflater.inflate(R.layout.fragment_view_media, container, false);
|
||||
ButterKnife.bind(this, rootView);
|
||||
|
||||
Bundle arguments = getArguments();
|
||||
String url = arguments.getString("url");
|
||||
PhotoView photoView = (PhotoView) rootView.findViewById(R.id.view_media_image);
|
||||
|
||||
attacher = new PhotoViewAttacher(photoView);
|
||||
|
||||
|
@ -84,8 +105,4 @@ public class ViewMediaFragment extends Fragment {
|
|||
attacher.cleanup();
|
||||
super.onDestroyView();
|
||||
}
|
||||
|
||||
private void dismiss() {
|
||||
getFragmentManager().popBackStack();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -78,14 +78,30 @@
|
|||
android:textColor="?android:textColorPrimary"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:id="@+id/account_username" />
|
||||
<RelativeLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:maxLines="1"
|
||||
android:ellipsize="end"
|
||||
android:textColor="?android:textColorSecondary"
|
||||
android:id="@+id/account_username" />
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/account_locked"
|
||||
android:visibility="gone"
|
||||
android:layout_centerVertical="true"
|
||||
android:layout_width="16sp"
|
||||
android:layout_height="16sp"
|
||||
android:layout_marginLeft="4dp"
|
||||
android:layout_marginStart="4dp"
|
||||
android:layout_toEndOf="@id/account_username"
|
||||
app:srcCompat="@drawable/reblog_disabled_light"
|
||||
android:tint="?android:textColorSecondary"
|
||||
android:layout_toRightOf="@id/account_username" />
|
||||
</RelativeLayout>
|
||||
</LinearLayout>
|
||||
|
||||
</RelativeLayout>
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:clickable="true"
|
||||
android:background="#60000000">
|
||||
android:layout_gravity="center"
|
||||
android:background="@android:color/black">
|
||||
<uk.co.senab.photoview.PhotoView
|
||||
android:id="@+id/view_media_image"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent" />
|
||||
</RelativeLayout>
|
||||
</FrameLayout>
|
|
@ -102,12 +102,8 @@
|
|||
<string name="visibility_unlisted">Everyone can see, but not on public timelines</string>
|
||||
<string name="visibility_private">Only followers and mentions can see</string>
|
||||
|
||||
<string name="notification_service_description">Allows Tusky to check for Mastodon notifications.</string>
|
||||
<string name="notification_service_several_mentions">%d new mentions</string>
|
||||
<string name="notification_service_one_mention">Mention from %s</string>
|
||||
|
||||
<string name="pref_title_notification_settings">Notifications</string>
|
||||
<string name="pref_title_pull_notifications">Enable pull notifcations</string>
|
||||
<string name="pref_title_pull_notifications">Enable pull notifications</string>
|
||||
<string name="pref_summary_pull_notifications">Check for notifications periodically</string>
|
||||
<string name="pref_title_pull_notification_check_interval">Check interval</string>
|
||||
<string name="pref_summary_pull_notification_check_interval">How often to pull</string>
|
||||
|
@ -131,5 +127,10 @@
|
|||
<string name="action_mention">Mention</string>
|
||||
<string name="tusky_api_url">https://tuskynotifier.keylesspalace.com</string>
|
||||
<string name="notification_mention_format">%s mentioned you</string>
|
||||
|
||||
<string name="error_invalid_domain">Invalid domain entered</string>
|
||||
<string name="error_failed_app_registration">This app could not obtain authentication from that server instance.</string>
|
||||
<string name="notification_summary_large">%1$s, %2$s, %3$s and %4$d others</string>
|
||||
<string name="notification_summary_medium">%1$s, %2$s, and %3$s</string>
|
||||
<string name="notification_summary_small">%1$s and %2$s</string>
|
||||
<string name="notification_title_summary">%d new interactions</string>
|
||||
</resources>
|
||||
|
|
|
@ -92,6 +92,11 @@
|
|||
<item name="windowActionBarOverlay">true</item>
|
||||
</style>
|
||||
|
||||
<style name="Dialog.FullScreen" parent="Theme.AppCompat.Dialog">
|
||||
<item name="android:padding">0dp</item>
|
||||
<item name="android:windowBackground">@android:color/black</item>
|
||||
</style>
|
||||
|
||||
<!--Light Application Theme Styles-->
|
||||
|
||||
<style name="AppTheme.Light" parent="Theme.AppCompat.Light.NoActionBar">
|
||||
|
|
Loading…
Reference in a new issue