From 85d232c7f6254a8ed065637c6f7b21a55fe3f1b4 Mon Sep 17 00:00:00 2001 From: Alex Ning Date: Mon, 19 Aug 2019 11:44:19 +0800 Subject: [PATCH] Fetch all users' messages in PullNotificationWorker. Update the access token in database instead of inserting an account in AccessTokenAuthenticator to hopefully fix the problem that subscriptions database is cleared implicitly. --- app/src/main/java/Account/AccountDao.java | 6 + .../AccessTokenAuthenticator.java | 18 +- .../infinityforreddit/AppModule.java | 10 + .../LinkResolverActivity.java | 18 ++ .../infinityforreddit/MainActivity.java | 84 +++++-- .../infinityforreddit/NotificationUtils.java | 18 +- .../PullNotificationWorker.java | 233 +++++++++++------- .../ViewPostDetailActivity.java | 45 +++- .../ViewSubredditDetailActivity.java | 42 +++- .../ViewUserDetailActivity.java | 44 +++- 10 files changed, 361 insertions(+), 157 deletions(-) diff --git a/app/src/main/java/Account/AccountDao.java b/app/src/main/java/Account/AccountDao.java index aa7b7f19..c05e5552 100644 --- a/app/src/main/java/Account/AccountDao.java +++ b/app/src/main/java/Account/AccountDao.java @@ -13,6 +13,9 @@ public interface AccountDao { @Insert(onConflict = OnConflictStrategy.REPLACE) void insert(Account account); + @Query("SELECT * FROM accounts") + List getAllAccounts(); + @Query("SELECT * FROM accounts WHERE is_current_user = 0") List getAllNonCurrentAccounts(); @@ -43,4 +46,7 @@ public interface AccountDao { @Query("UPDATE accounts SET is_current_user = 1 WHERE username = :username") void markAccountCurrent(String username); + + @Query("UPDATE accounts SET access_token = :accessToken WHERE username = :username") + void changeAccessToken(String username, String accessToken); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java index 8d460c5e..609eee1f 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AccessTokenAuthenticator.java @@ -68,17 +68,15 @@ class AccessTokenAuthenticator implements Authenticator { Call accessTokenCall = api.getAccessToken(RedditUtils.getHttpBasicAuthHeader(), params); try { retrofit2.Response response = accessTokenCall.execute(); - if(response.body() == null) { - return ""; + if(response.isSuccessful() && response.body() != null) { + JSONObject jsonObject = new JSONObject((String) response.body()); + String newAccessToken = jsonObject.getString(RedditUtils.ACCESS_TOKEN_KEY); + mRedditDataRoomDatabase.accountDao().changeAccessToken(account.getUsername(), newAccessToken); + + Log.i("access token", newAccessToken); + return newAccessToken; } - - JSONObject jsonObject = new JSONObject((String) response.body()); - String newAccessToken = jsonObject.getString(RedditUtils.ACCESS_TOKEN_KEY); - account.setAccessToken(newAccessToken); - mRedditDataRoomDatabase.accountDao().insert(account); - - Log.i("access token", newAccessToken); - return newAccessToken; + return ""; } catch (IOException | JSONException e) { e.printStackTrace(); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java index 418b349a..26b5ede9 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/AppModule.java @@ -29,6 +29,16 @@ class AppModule { .build(); } + @Provides @Named("oauth_without_authenticator") + @Singleton + Retrofit provideOauthWithoutAuthenticatorRetrofit(OkHttpClient okHttpClient) { + return new Retrofit.Builder() + .baseUrl(RedditUtils.OAUTH_API_BASE_URI) + .client(okHttpClient) + .addConverterFactory(ScalarsConverterFactory.create()) + .build(); + } + @Provides @Named("no_oauth") @Singleton Retrofit provideRetrofit() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java index 1c6ee055..b095d3c0 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/LinkResolverActivity.java @@ -17,6 +17,10 @@ import static androidx.browser.customtabs.CustomTabsService.ACTION_CUSTOM_TABS_C public class LinkResolverActivity extends AppCompatActivity { + static final String EXTRA_NOTIFICATION_FULLNAME = "ENF"; + static final String EXTRA_SWITCH_ACCOUNT = "ESA"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; + private static final String POST_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/{0,1}"; private static final String COMMENT_PATTERN = "/r/\\w+/comments/\\w+/{0,1}\\w+/\\w+/{0,1}"; private static final String SUBREDDIT_PATTERN = "/r/\\w+/*"; @@ -32,12 +36,18 @@ public class LinkResolverActivity extends AppCompatActivity { path = path.substring(0, path.length() - 1); } + String notificationFullname = getIntent().getStringExtra(EXTRA_NOTIFICATION_FULLNAME); + boolean switchAccount = getIntent().getBooleanExtra(EXTRA_SWITCH_ACCOUNT, false); + String newAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); + if(path.matches(POST_PATTERN)) { List segments = uri.getPathSegments(); int commentsIndex = segments.lastIndexOf("comments"); if(commentsIndex >=0 && commentsIndex < segments.size() - 1) { Intent intent = new Intent(this, ViewPostDetailActivity.class); intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); + intent.putExtra(ViewPostDetailActivity.EXTRA_NOTIFICATION_FULLNAME, notificationFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); } else { deepLinkError(uri); @@ -49,6 +59,8 @@ public class LinkResolverActivity extends AppCompatActivity { Intent intent = new Intent(this, ViewPostDetailActivity.class); intent.putExtra(ViewPostDetailActivity.EXTRA_POST_ID, segments.get(commentsIndex + 1)); intent.putExtra(ViewPostDetailActivity.EXTRA_SINGLE_COMMENT_ID, segments.get(segments.size() - 1)); + intent.putExtra(ViewPostDetailActivity.EXTRA_NOTIFICATION_FULLNAME, notificationFullname); + intent.putExtra(ViewPostDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); } else { deepLinkError(uri); @@ -58,15 +70,21 @@ public class LinkResolverActivity extends AppCompatActivity { if(subredditName.equals("popular") || subredditName.equals("all")) { Intent intent = new Intent(this, MainActivity.class); intent.putExtra(MainActivity.EXTRA_POST_TYPE, subredditName); + intent.putExtra(MainActivity.EXTRA_NOTIFICATION_FULLNAME, notificationFullname); + intent.putExtra(MainActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); } else { Intent intent = new Intent(this, ViewSubredditDetailActivity.class); intent.putExtra(ViewSubredditDetailActivity.EXTRA_SUBREDDIT_NAME_KEY, path.substring(3)); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_NOTIFICATION_FULLNAME, notificationFullname); + intent.putExtra(ViewSubredditDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); } } else if(path.matches(USER_PATTERN)) { Intent intent = new Intent(this, ViewUserDetailActivity.class); intent.putExtra(ViewUserDetailActivity.EXTRA_USER_NAME_KEY, path.substring(6)); + intent.putExtra(ViewUserDetailActivity.EXTRA_NOTIFICATION_FULLNAME, notificationFullname); + intent.putExtra(ViewUserDetailActivity.EXTRA_NEW_ACCOUNT_NAME, newAccountName); startActivity(intent); } else { deepLinkError(uri); diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java index f2c58214..eb665671 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/MainActivity.java @@ -61,6 +61,8 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe PostTypeBottomSheetFragment.PostTypeSelectionCallback { static final String EXTRA_POST_TYPE = "EPT"; + static final String EXTRA_NOTIFICATION_FULLNAME = "ENF"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; private static final String FETCH_USER_INFO_STATE = "FUIS"; private static final String DRAWER_ON_ACCOUNT_SWITCH_STATE = "DOASS"; @@ -71,6 +73,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe private static final String ACCOUNT_PROFILE_IMAGE_URL_STATE = "APIUS"; private static final String ACCOUNT_BANNER_IMAGE_URL_STATE = "ABIUS"; private static final String ACCOUNT_KARMA_STATE = "AKS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; private static final int LOGIN_ACTIVITY_REQUEST_CODE = 0; @@ -117,6 +120,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe private int mKarma; private boolean mFetchUserInfoSuccess = false; private boolean mDrawerOnAccountSwitch = false; + private String mNewAccountName; private Menu mMenu; @@ -217,6 +221,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe mProfileImageUrl = savedInstanceState.getString(ACCOUNT_PROFILE_IMAGE_URL_STATE); mBannerImageUrl = savedInstanceState.getString(ACCOUNT_BANNER_IMAGE_URL_STATE); mKarma = savedInstanceState.getInt(ACCOUNT_KARMA_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); if(!mNullAccessToken && mAccessToken == null) { getCurrentAccountAndBindView(); @@ -224,6 +229,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe bindView(); } } else { + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); getCurrentAccountAndBindView(); } @@ -231,32 +237,60 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe } private void getCurrentAccountAndBindView() { - mNullAccessToken = true; - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mNullAccessToken = false; - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - mProfileImageUrl = account.getProfileImageUrl(); - mBannerImageUrl = account.getBannerImageUrl(); - mKarma = account.getKarma(); + if(mNewAccountName != null) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, () -> { + mNewAccountName = null; + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + mProfileImageUrl = account.getProfileImageUrl(); + mBannerImageUrl = account.getBannerImageUrl(); + mKarma = account.getKarma(); - Constraints constraints = new Constraints.Builder() - .setRequiredNetworkType(NetworkType.CONNECTED) - .build(); - - PeriodicWorkRequest pullNotificationRequest = - new PeriodicWorkRequest.Builder(PullNotificationWorker.class, 1, TimeUnit.HOURS) - .setConstraints(constraints) + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) .build(); - WorkManager.getInstance(this).enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, - ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); - } - bindView(); - }).execute(); + PeriodicWorkRequest pullNotificationRequest = + new PeriodicWorkRequest.Builder(PullNotificationWorker.class, 1, TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + + WorkManager.getInstance(this).enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, + ExistingPeriodicWorkPolicy.REPLACE, pullNotificationRequest); + } + bindView(); + }).execute(); + }).execute(); + } else { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + mProfileImageUrl = account.getProfileImageUrl(); + mBannerImageUrl = account.getBannerImageUrl(); + mKarma = account.getKarma(); + + Constraints constraints = new Constraints.Builder() + .setRequiredNetworkType(NetworkType.CONNECTED) + .build(); + + PeriodicWorkRequest pullNotificationRequest = + new PeriodicWorkRequest.Builder(PullNotificationWorker.class, 1, TimeUnit.HOURS) + .setConstraints(constraints) + .build(); + + WorkManager.getInstance(this).enqueueUniquePeriodicWork(PullNotificationWorker.WORKER_TAG, + ExistingPeriodicWorkPolicy.KEEP, pullNotificationRequest); + } + bindView(); + }).execute(); + } } private void bindView() { @@ -338,7 +372,8 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe accountViewModel.getAccountsExceptCurrentAccountLiveData().observe(this, adapter::changeAccountsDataset); if(getIntent().hasExtra(EXTRA_POST_TYPE)) { - if(getIntent().getExtras().getString(EXTRA_POST_TYPE).equals("popular")) { + String type = getIntent().getStringExtra(EXTRA_POST_TYPE); + if(type != null && type.equals("popular")) { viewPager.setCurrentItem(1); } else { viewPager.setCurrentItem(2); @@ -610,6 +645,7 @@ public class MainActivity extends AppCompatActivity implements SortTypeBottomShe outState.putString(ACCOUNT_PROFILE_IMAGE_URL_STATE, mProfileImageUrl); outState.putString(ACCOUNT_BANNER_IMAGE_URL_STATE, mBannerImageUrl); outState.putInt(ACCOUNT_KARMA_STATE, mKarma); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); } @Override diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java b/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java index 56bfaf88..ce71a57e 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/NotificationUtils.java @@ -11,10 +11,10 @@ class NotificationUtils { static final String CHANNEL_POST_MEDIA = "Post Media"; static final String CHANNEL_ID_NEW_COMMENTS = "new_comments"; static final String CHANNEL_NEW_COMMENTS = "New Comments"; - static final String GROUP_NEW_COMMENTS = "ml.docilealligator.infinityforreddit.NEW_COMMENTS"; - static final int SUMMARY_ID_NEW_COMMENTS = 0; + static final int SUMMARY_BASE_ID_UNREAD_MESSAGE = 0; + static final int NOTIFICATION_BASE_ID_UNREAD_MESSAGE = 1; - static final int BASE_ID_UNREAD_MESSAGE = 1; + private static final String GROUP_USER_BASE = "ml.docilealligator.infinityforreddit."; static NotificationCompat.Builder buildNotification(NotificationManagerCompat notificationManager, Context context, String title, String content, @@ -57,4 +57,16 @@ class NotificationUtils { static NotificationManagerCompat getNotificationManager(Context context) { return NotificationManagerCompat.from(context); } + + static String getAccountGroupName(String accountName) { + return GROUP_USER_BASE + accountName; + } + + static int getSummaryIdUnreadMessage(int accountIndex) { + return SUMMARY_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000; + } + + static int getNotificationIdUnreadMessage(int accountIndex, int messageIndex) { + return NOTIFICATION_BASE_ID_UNREAD_MESSAGE + accountIndex * 1000 + messageIndex; + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java index 5bf7e6a3..13bf43b5 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/PullNotificationWorker.java @@ -12,8 +12,14 @@ import androidx.core.app.NotificationManagerCompat; import androidx.work.Worker; import androidx.work.WorkerParameters; +import org.json.JSONException; +import org.json.JSONObject; + import java.io.IOException; import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import javax.inject.Inject; import javax.inject.Named; @@ -26,10 +32,11 @@ public class PullNotificationWorker extends Worker { static final String WORKER_TAG = "PNWT"; private Context context; + private RedditAPI api; @Inject - @Named("oauth") - Retrofit mOauthRetrofit; + @Named("oauth_without_authenticator") + Retrofit mOauthWithoutAuthenticatorRetrofit; @Inject RedditDataRoomDatabase redditDataRoomDatabase; @@ -38,6 +45,7 @@ public class PullNotificationWorker extends Worker { super(context, workerParams); this.context = context; ((Infinity) context.getApplicationContext()).getAppComponent().inject(this); + api = mOauthWithoutAuthenticatorRetrofit.create(RedditAPI.class); } @NonNull @@ -46,109 +54,127 @@ public class PullNotificationWorker extends Worker { Log.i("workmanager", "do"); try { Log.i("workmanager", "before response"); - Account currentAccount = redditDataRoomDatabase.accountDao().getCurrentAccount(); - Response response = mOauthRetrofit.create(RedditAPI.class).getMessages( - RedditUtils.getOAuthHeader(currentAccount.getAccessToken()), - FetchMessages.WHERE_UNREAD, null).execute(); - Log.i("workmanager", "has response"); - if(response.isSuccessful()) { - String responseBody = response.body(); - ArrayList messages = FetchMessages.parseMessage(responseBody, context.getResources().getConfiguration().locale); - if(messages != null && !messages.isEmpty()) { - NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context); + String currentAccountName = redditDataRoomDatabase.accountDao().getCurrentAccount().getUsername(); - NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context, - notificationManager, currentAccount.getUsername(), messages.size() + " new comment replies", - NotificationUtils.CHANNEL_ID_NEW_COMMENTS, NotificationUtils.CHANNEL_NEW_COMMENTS, - NotificationUtils.GROUP_NEW_COMMENTS); + List accounts = redditDataRoomDatabase.accountDao().getAllAccounts(); + for(int accountIndex = 0; accountIndex < accounts.size(); accountIndex++) { + Account account = accounts.get(accountIndex); + Log.i("workmanager", account.getUsername() + " " + account.getAccessToken()); - NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); + Response response = fetchMessages(account); - int messageSize = messages.size() >= 5 ? 5 : messages.size(); + if(response != null && response.isSuccessful()) { + Log.i("workmanager", "has response"); + String responseBody = response.body(); + ArrayList messages = FetchMessages.parseMessage(responseBody, context.getResources().getConfiguration().locale); - for(int i = messageSize - 1; i >= 0; i--) { - Message message = messages.get(i); + if(messages != null && !messages.isEmpty()) { + NotificationManagerCompat notificationManager = NotificationUtils.getNotificationManager(context); - inboxStyle.addLine(message.getAuthor() + " " + message.getBody()); + NotificationCompat.Builder summaryBuilder = NotificationUtils.buildSummaryNotification(context, + notificationManager, account.getUsername(), + context.getString(R.string.notification_new_messages, messages.size()), + NotificationUtils.CHANNEL_ID_NEW_COMMENTS, NotificationUtils.CHANNEL_NEW_COMMENTS, + NotificationUtils.getAccountGroupName(account.getUsername())); - String kind = message.getKind(); - String title; - String summary; - if(kind.equals(Message.TYPE_COMMENT) || kind.equals(Message.TYPE_LINK)) { - title = message.getAuthor(); - summary = context.getString(R.string.notification_summary_comment); - } else { - title = message.getTitle(); - if(kind.equals(Message.TYPE_ACCOUNT)) { - summary = context.getString(R.string.notification_summary_account); - } else if(kind.equals(Message.TYPE_MESSAGE)) { - summary = context.getString(R.string.notification_summary_message); - } else if(kind.equals(Message.TYPE_SUBREDDIT)) { - summary = context.getString(R.string.notification_summary_subreddit); + NotificationCompat.InboxStyle inboxStyle = new NotificationCompat.InboxStyle(); + + int messageSize = messages.size() >= 5 ? 5 : messages.size(); + + for(int messageIndex = messageSize - 1; messageIndex >= 0; messageIndex--) { + Message message = messages.get(messageIndex); + + inboxStyle.addLine(message.getAuthor() + " " + message.getBody()); + + String kind = message.getKind(); + Log.i("workmanager", kind); + String title; + String summary; + if(kind.equals(Message.TYPE_COMMENT) || kind.equals(Message.TYPE_LINK)) { + title = message.getAuthor(); + summary = message.getSubject().substring(0, 1).toUpperCase() + message.getSubject().substring(1); } else { - summary = context.getString(R.string.notification_summary_award); + title = message.getTitle() == null || message.getTitle().equals("") ? message.getSubject() : message.getTitle(); + if(kind.equals(Message.TYPE_ACCOUNT)) { + summary = context.getString(R.string.notification_summary_account); + } else if(kind.equals(Message.TYPE_MESSAGE)) { + summary = context.getString(R.string.notification_summary_message); + } else if(kind.equals(Message.TYPE_SUBREDDIT)) { + summary = context.getString(R.string.notification_summary_subreddit); + } else { + summary = context.getString(R.string.notification_summary_award); + } } + + NotificationCompat.Builder builder = NotificationUtils.buildNotification(notificationManager, + context, title, message.getBody(), summary, + NotificationUtils.CHANNEL_ID_NEW_COMMENTS, + NotificationUtils.CHANNEL_NEW_COMMENTS, + NotificationUtils.getAccountGroupName(account.getUsername())); + + if(kind.equals(Message.TYPE_COMMENT)) { + Intent intent = new Intent(context, LinkResolverActivity.class); + Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); + intent.setData(uri); + if(!account.getUsername().equals(currentAccountName)) { + intent.putExtra(LinkResolverActivity.EXTRA_SWITCH_ACCOUNT, true); + intent.putExtra(LinkResolverActivity.EXTRA_NEW_ACCOUNT_NAME, account.getUsername()); + } + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(pendingIntent); + } else if(kind.equals(Message.TYPE_ACCOUNT)) { + Intent intent = new Intent(context, ViewMessageActivity.class); + PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(summaryPendingIntent); + } else if(kind.equals(Message.TYPE_LINK)) { + Intent intent = new Intent(context, LinkResolverActivity.class); + Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); + intent.setData(uri); + if(!account.getUsername().equals(currentAccountName)) { + intent.putExtra(LinkResolverActivity.EXTRA_SWITCH_ACCOUNT, true); + intent.putExtra(LinkResolverActivity.EXTRA_NEW_ACCOUNT_NAME, account.getUsername()); + } + PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(pendingIntent); + } else if(kind.equals(Message.TYPE_MESSAGE)) { + Intent intent = new Intent(context, ViewMessageActivity.class); + PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(summaryPendingIntent); + } else if(kind.equals(Message.TYPE_SUBREDDIT)) { + Intent intent = new Intent(context, ViewMessageActivity.class); + PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(summaryPendingIntent); + } else { + Intent intent = new Intent(context, ViewMessageActivity.class); + PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); + builder.setContentIntent(summaryPendingIntent); + } + notificationManager.notify(NotificationUtils.getNotificationIdUnreadMessage(accountIndex, messageIndex), builder.build()); } - NotificationCompat.Builder builder = NotificationUtils.buildNotification(notificationManager, - context, title, message.getBody(), summary, - NotificationUtils.CHANNEL_ID_NEW_COMMENTS, - NotificationUtils.CHANNEL_NEW_COMMENTS, NotificationUtils.GROUP_NEW_COMMENTS); + inboxStyle.setBigContentTitle(context.getString(R.string.notification_new_messages, messages.size())) + .setSummaryText(account.getUsername()); - if(kind.equals(Message.TYPE_COMMENT)) { - Intent intent = new Intent(context, LinkResolverActivity.class); - Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); - intent.setData(uri); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(pendingIntent); - } else if(kind.equals(Message.TYPE_ACCOUNT)) { - Intent intent = new Intent(context, ViewMessageActivity.class); - PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(summaryPendingIntent); - } else if(kind.equals(Message.TYPE_LINK)) { - Intent intent = new Intent(context, LinkResolverActivity.class); - Uri uri = LinkResolverActivity.getRedditUriByPath(message.getContext()); - intent.setData(uri); - PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(pendingIntent); - } else if(kind.equals(Message.TYPE_MESSAGE)) { - Intent intent = new Intent(context, ViewMessageActivity.class); - PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(summaryPendingIntent); - } else if(kind.equals(Message.TYPE_SUBREDDIT)) { - Intent intent = new Intent(context, ViewMessageActivity.class); - PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(summaryPendingIntent); - } else { - Intent intent = new Intent(context, ViewMessageActivity.class); - PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, intent, 0); - builder.setContentIntent(summaryPendingIntent); - } - notificationManager.notify(NotificationUtils.BASE_ID_UNREAD_MESSAGE + i, builder.build()); + summaryBuilder.setStyle(inboxStyle); + + Intent summaryIntent = new Intent(context, ViewMessageActivity.class); + PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, summaryIntent, 0); + summaryBuilder.setContentIntent(summaryPendingIntent); + + notificationManager.notify(NotificationUtils.getSummaryIdUnreadMessage(accountIndex), summaryBuilder.build()); + + Log.i("workmanager", "message size " + messages.size()); + } else { + Log.i("workmanager", "retry1"); + return Result.retry(); } - - inboxStyle.setBigContentTitle(messages.size() + " New Messages") - .setSummaryText(currentAccount.getUsername()); - - summaryBuilder.setStyle(inboxStyle); - - Intent summaryIntent = new Intent(context, ViewMessageActivity.class); - PendingIntent summaryPendingIntent = PendingIntent.getActivity(context, 0, summaryIntent, 0); - summaryBuilder.setContentIntent(summaryPendingIntent); - - notificationManager.notify(NotificationUtils.SUMMARY_ID_NEW_COMMENTS, summaryBuilder.build()); - - Log.i("workmanager", "message size " + messages.size()); } else { - Log.i("workmanager", "retry1"); + Log.i("workmanager", "retry2 " + response.code()); return Result.retry(); } - } else { - Log.i("workmanager", "retry2 " + response.code()); - return Result.retry(); } - } catch (IOException e) { + } catch (IOException | JSONException e) { e.printStackTrace(); Log.i("workmanager", "retry3"); return Result.retry(); @@ -157,4 +183,35 @@ public class PullNotificationWorker extends Worker { Log.i("workmanager", "success"); return Result.success(); } + + private Response fetchMessages(Account account) throws IOException, JSONException { + Response response = api.getMessages( + RedditUtils.getOAuthHeader(account.getAccessToken()), + FetchMessages.WHERE_INBOX, null).execute(); + if(response.isSuccessful()) { + return response; + } else { + if(response.code() == 401) { + String refreshToken = account.getRefreshToken(); + + Map params = new HashMap<>(); + params.put(RedditUtils.GRANT_TYPE_KEY, RedditUtils.GRANT_TYPE_REFRESH_TOKEN); + params.put(RedditUtils.REFRESH_TOKEN_KEY, refreshToken); + + Response accessTokenResponse = api.getAccessToken(RedditUtils.getHttpBasicAuthHeader(), params).execute(); + if(accessTokenResponse.isSuccessful() && accessTokenResponse.body() != null) { + JSONObject jsonObject = new JSONObject((String) accessTokenResponse.body()); + String newAccessToken = jsonObject.getString(RedditUtils.ACCESS_TOKEN_KEY); + account.setAccessToken(newAccessToken); + redditDataRoomDatabase.accountDao().changeAccessToken(account.getUsername(), newAccessToken); + + return fetchMessages(account); + } else { + return null; + } + } else { + return null; + } + } + } } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java index 9e7bdb9b..c48f2697 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewPostDetailActivity.java @@ -60,6 +60,8 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo static final String EXTRA_POST_LIST_POSITION = "EPLI"; static final String EXTRA_POST_ID = "EPI"; static final String EXTRA_SINGLE_COMMENT_ID = "ESCI"; + static final String EXTRA_NOTIFICATION_FULLNAME = "ENI"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; private static final int EDIT_POST_REQUEST_CODE = 2; static final int EDIT_COMMENT_REQUEST_CODE = 3; @@ -96,6 +98,8 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo boolean loadMoreChildrenSuccess = true; @State boolean hasMoreChildren; + @State + String mNewAccountName; private boolean showToast = false; @@ -190,8 +194,11 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo mRecyclerView.setLayoutManager(mLinearLayoutManager); mSingleCommentId = getIntent().hasExtra(EXTRA_SINGLE_COMMENT_ID) ? getIntent().getExtras().getString(EXTRA_SINGLE_COMMENT_ID) : null; - if(savedInstanceState == null && mSingleCommentId != null) { - isSingleCommentThreadMode = true; + if(savedInstanceState == null) { + if(mSingleCommentId != null) { + isSingleCommentThreadMode = true; + } + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); } orientation = getResources().getConfiguration().orientation; @@ -208,16 +215,32 @@ public class ViewPostDetailActivity extends AppCompatActivity implements FlairBo } private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } + if(mNewAccountName != null) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, () -> { + mNewAccountName = null; + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } - bindView(); - }).execute(); + bindView(); + }).execute(); + }).execute(); + } else { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + + bindView(); + }).execute(); + } } private void bindView() { diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java index 39053d1a..6cba00f7 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewSubredditDetailActivity.java @@ -46,7 +46,9 @@ import retrofit2.Retrofit; public class ViewSubredditDetailActivity extends AppCompatActivity implements SortTypeBottomSheetFragment.SortTypeSelectionCallback, PostTypeBottomSheetFragment.PostTypeSelectionCallback { - public static final String EXTRA_SUBREDDIT_NAME_KEY = "ESN"; + static final String EXTRA_SUBREDDIT_NAME_KEY = "ESN"; + static final String EXTRA_NOTIFICATION_FULLNAME = "ENF"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; private static final String FETCH_SUBREDDIT_INFO_STATE = "FSIS"; private static final String FRAGMENT_OUT_STATE_KEY = "FOSK"; @@ -54,6 +56,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; private static final String ACCESS_TOKEN_STATE = "ATS"; private static final String ACCOUNT_NAME_STATE = "ANS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; @BindView(R.id.coordinator_layout_view_subreddit_detail_activity) CoordinatorLayout coordinatorLayout; @BindView(R.id.appbar_layout_view_subreddit_detail) AppBarLayout appBarLayout; @@ -76,6 +79,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So private boolean subscriptionReady = false; private boolean isInLazyMode = false; private boolean showToast = false; + private String mNewAccountName; private RequestManager glide; private Fragment mFragment; @@ -149,6 +153,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So subredditName = getIntent().getExtras().getString(EXTRA_SUBREDDIT_NAME_KEY); if(savedInstanceState == null) { + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); getCurrentAccountAndBindView(); } else { mFetchSubredditInfoSuccess = savedInstanceState.getBoolean(FETCH_SUBREDDIT_INFO_STATE); @@ -156,6 +161,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); if(!mNullAccessToken && mAccessToken == null) { getCurrentAccountAndBindView(); @@ -257,15 +263,30 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So } private void getCurrentAccountAndBindView() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if(account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - bindView(true); - }).execute(); + if(mNewAccountName != null) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, () -> { + mNewAccountName = null; + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + bindView(true); + }).execute(); + }).execute(); + } else { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if(account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + bindView(true); + }).execute(); + } } private void fetchSubredditData() { @@ -430,6 +451,7 @@ public class ViewSubredditDetailActivity extends AppCompatActivity implements So outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); outState.putString(ACCESS_TOKEN_STATE, mAccessToken); outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); getSupportFragmentManager().putFragment(outState, FRAGMENT_OUT_STATE_KEY, mFragment); } diff --git a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java index e9c54118..8875ea63 100644 --- a/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java +++ b/app/src/main/java/ml/docilealligator/infinityforreddit/ViewUserDetailActivity.java @@ -50,13 +50,16 @@ import retrofit2.Retrofit; public class ViewUserDetailActivity extends AppCompatActivity implements UserThingSortTypeBottomSheetFragment.UserThingSortTypeSelectionCallback { - public static final String EXTRA_USER_NAME_KEY = "EUNK"; + static final String EXTRA_USER_NAME_KEY = "EUNK"; + static final String EXTRA_NOTIFICATION_FULLNAME = "ENF"; + static final String EXTRA_NEW_ACCOUNT_NAME = "ENAN"; private static final String FETCH_USER_INFO_STATE = "FSIS"; private static final String NULL_ACCESS_TOKEN_STATE = "NATS"; private static final String ACCESS_TOKEN_STATE = "ATS"; private static final String ACCOUNT_NAME_STATE = "ANS"; private static final String IS_IN_LAZY_MODE_STATE = "IILMS"; + private static final String NEW_ACCOUNT_NAME_STATE = "NANS"; @BindView(R.id.coordinator_layout_view_user_detail_activity) CoordinatorLayout coordinatorLayout; @BindView(R.id.view_pager_view_user_detail_activity) ViewPager viewPager; @@ -93,6 +96,7 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi private int collapsedTabBackgroundColor; private int collapsedTabIndicatorColor; private boolean showToast = false; + private String mNewAccountName; @Inject @Named("no_oauth") @@ -114,9 +118,10 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi ((Infinity) getApplication()).getAppComponent().inject(this); - username = getIntent().getExtras().getString(EXTRA_USER_NAME_KEY); + username = getIntent().getStringExtra(EXTRA_USER_NAME_KEY); if (savedInstanceState == null) { + mNewAccountName = getIntent().getStringExtra(EXTRA_NEW_ACCOUNT_NAME); getCurrentAccountAndInitializeViewPager(); } else { mFetchUserInfoSuccess = savedInstanceState.getBoolean(FETCH_USER_INFO_STATE); @@ -124,6 +129,7 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi mAccessToken = savedInstanceState.getString(ACCESS_TOKEN_STATE); mAccountName = savedInstanceState.getString(ACCOUNT_NAME_STATE); isInLazyMode = savedInstanceState.getBoolean(IS_IN_LAZY_MODE_STATE); + mNewAccountName = savedInstanceState.getString(NEW_ACCOUNT_NAME_STATE); if (!mNullAccessToken && mAccessToken == null) { getCurrentAccountAndInitializeViewPager(); @@ -337,15 +343,30 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi } private void getCurrentAccountAndInitializeViewPager() { - new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { - if (account == null) { - mNullAccessToken = true; - } else { - mAccessToken = account.getAccessToken(); - mAccountName = account.getUsername(); - } - initializeViewPager(); - }).execute(); + if(mNewAccountName != null) { + new SwitchAccountAsyncTask(mRedditDataRoomDatabase, mNewAccountName, () -> { + mNewAccountName = null; + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if (account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPager(); + }).execute(); + }).execute(); + } else { + new GetCurrentAccountAsyncTask(mRedditDataRoomDatabase.accountDao(), account -> { + if (account == null) { + mNullAccessToken = true; + } else { + mAccessToken = account.getAccessToken(); + mAccountName = account.getUsername(); + } + initializeViewPager(); + }).execute(); + } } private void initializeViewPager() { @@ -484,6 +505,7 @@ public class ViewUserDetailActivity extends AppCompatActivity implements UserThi outState.putBoolean(NULL_ACCESS_TOKEN_STATE, mNullAccessToken); outState.putString(ACCESS_TOKEN_STATE, mAccessToken); outState.putString(ACCOUNT_NAME_STATE, mAccountName); + outState.putString(NEW_ACCOUNT_NAME_STATE, mNewAccountName); } private void showMessage(int resId, boolean retry) {