From 91686d551a7b1f400e058270562e800363c00517 Mon Sep 17 00:00:00 2001 From: charlag Date: Sat, 23 Mar 2019 14:50:53 +0100 Subject: [PATCH] Fix crashes --- .../com/keylesspalace/tusky/MainActivity.java | 51 +++++++++++-------- .../keylesspalace/tusky/db/AccountManager.kt | 1 + .../keylesspalace/tusky/db/AppDatabase.java | 6 +-- .../tusky/fragment/NotificationsFragment.java | 8 ++- .../tusky/fragment/TimelineFragment.java | 15 +++++- 5 files changed, 54 insertions(+), 27 deletions(-) diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java index 3abff7af4..f7f750b30 100644 --- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.java +++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.java @@ -21,6 +21,7 @@ import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; import android.os.Handler; +import android.util.Log; import android.view.KeyEvent; import android.widget.ImageButton; import android.widget.ImageView; @@ -33,6 +34,7 @@ import com.keylesspalace.tusky.appstore.MainTabsChangedEvent; import com.keylesspalace.tusky.appstore.ProfileEditedEvent; import com.keylesspalace.tusky.components.conversation.ConversationsRepository; import com.keylesspalace.tusky.db.AccountEntity; +import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.entity.Account; import com.keylesspalace.tusky.interfaces.ActionButtonActivity; import com.keylesspalace.tusky.pager.MainPagerAdapter; @@ -473,36 +475,40 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut AccountEntity activeAccount = accountManager.getActiveAccount(); if (activeAccount != null) { - new AlertDialog.Builder(this) .setTitle(R.string.action_logout) .setMessage(getString(R.string.action_logout_confirm, activeAccount.getFullName())) .setPositiveButton(android.R.string.yes, (dialog, which) -> { - NotificationHelper.deleteNotificationChannelsForAccount(accountManager.getActiveAccount(), MainActivity.this); - cacheUpdater.clearForUser(activeAccount.getId()); - conversationRepository.deleteCacheForAccount(activeAccount.getId()); - AccountEntity newAccount = accountManager.logActiveAccountOut(); - - if (!NotificationHelper.areNotificationsEnabled(MainActivity.this, accountManager)) { - NotificationHelper.disablePullNotifications(); - } - - Intent intent; - if (newAccount == null) { - intent = LoginActivity.getIntent(MainActivity.this, false); - } else { - intent = new Intent(MainActivity.this, MainActivity.class); - } - startActivity(intent); - finishWithoutSlideOutAnimation(); }) .setNegativeButton(android.R.string.no, null) .show(); } } + private void doLogout() { + AccountEntity activeAccount = accountManager.getActiveAccount(); + NotificationHelper.deleteNotificationChannelsForAccount(activeAccount, MainActivity.this); + cacheUpdater.clearForUser(activeAccount.getId()); + conversationRepository.deleteCacheForAccount(activeAccount.getId()); + + AccountEntity newAccount = accountManager.logActiveAccountOut(); + + if (!NotificationHelper.areNotificationsEnabled(MainActivity.this, accountManager)) { + NotificationHelper.disablePullNotifications(); + } + + Intent intent; + if (newAccount == null) { + intent = LoginActivity.getIntent(MainActivity.this, false); + } else { + intent = new Intent(MainActivity.this, MainActivity.class); + } + startActivity(intent); + finishWithoutSlideOutAnimation(); + } + private void fetchUserInfo() { mastodonApi.accountVerifyCredentials() .onErrorResumeNext((verifyError) -> { @@ -513,12 +519,17 @@ public final class MainActivity extends BottomSheetActivity implements ActionBut } return Single.error(verifyError); }) + .observeOn(AndroidSchedulers.mainThread()) .as(autoDisposable(from(this))) .subscribe( this::onFetchUserInfoSuccess, (err) -> { - accountManager.logActiveAccountOut(); - redirectIfNotLoggedIn(); + if (err instanceof AccountManager.NoRefreshTokenException + || isNotAuthenticatedException(err)) { + doLogout(); + } else { + Log.w(TAG, "Failed to get user info: ", err); + } }); } diff --git a/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt b/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt index 067954454..0aa04b547 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt +++ b/app/src/main/java/com/keylesspalace/tusky/db/AccountManager.kt @@ -230,6 +230,7 @@ class AccountManager( account.refreshToken, "refresh_token" ).doOnSuccess { tokenResponse -> + Log.d(TAG, "Successfully refreshed token for ${account.fullName}") account.accessToken = tokenResponse.accessToken // Server may or may not issue new refreshToken as per OAuth spec. // I assume that it means "use the old one" but I may be wrong diff --git a/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java b/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java index 470f3e756..07e240afc 100644 --- a/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java +++ b/app/src/main/java/com/keylesspalace/tusky/db/AppDatabase.java @@ -18,11 +18,11 @@ package com.keylesspalace.tusky.db; import com.keylesspalace.tusky.TabDataKt; import com.keylesspalace.tusky.components.conversation.ConversationEntity; -import androidx.sqlite.db.SupportSQLiteDatabase; +import androidx.annotation.NonNull; import androidx.room.Database; import androidx.room.RoomDatabase; import androidx.room.migration.Migration; -import androidx.annotation.NonNull; +import androidx.sqlite.db.SupportSQLiteDatabase; /** * DB version & declare DAO @@ -269,7 +269,7 @@ public abstract class AppDatabase extends RoomDatabase { @Override public void migrate(@NonNull SupportSQLiteDatabase database) { database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `refreshToken` TEXT"); - database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `expiresIn` TEXT"); + database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `expiresAt` TEXT"); database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `clientId` TEXT"); database.execSQL("ALTER TABLE `AccountEntity` ADD COLUMN `clientSecret` TEXT"); } diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java index 43a6cc6e6..9fd8782d5 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/NotificationsFragment.java @@ -200,8 +200,12 @@ public class NotificationsFragment extends SFragment implements adapter = new NotificationsAdapter(dataSource, this, this); SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia(); - boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); + AccountEntity activeAccount = accountManager.getActiveAccount(); + if (activeAccount == null) { + return rootView; + } + alwaysShowSensitiveMedia = activeAccount.getAlwaysShowSensitiveMedia(); + boolean mediaPreviewEnabled = activeAccount.getMediaPreviewEnabled(); adapter.setMediaPreviewEnabled(mediaPreviewEnabled); boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); adapter.setUseAbsoluteTime(useAbsoluteTime); diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java index 3d682e68a..3ee0cd79b 100644 --- a/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java +++ b/app/src/main/java/com/keylesspalace/tusky/fragment/TimelineFragment.java @@ -43,6 +43,7 @@ import com.keylesspalace.tusky.appstore.ReblogEvent; import com.keylesspalace.tusky.appstore.StatusComposedEvent; import com.keylesspalace.tusky.appstore.StatusDeletedEvent; import com.keylesspalace.tusky.appstore.UnfollowEvent; +import com.keylesspalace.tusky.db.AccountEntity; import com.keylesspalace.tusky.db.AccountManager; import com.keylesspalace.tusky.di.Injectable; import com.keylesspalace.tusky.entity.Filter; @@ -242,6 +243,9 @@ public class TimelineFragment extends SFragment implements } private void sendInitialRequest() { + if (accountManager.getActiveAccount() == null) { + return; + } if (this.kind == Kind.HOME) { this.tryCache(); } else { @@ -325,9 +329,13 @@ public class TimelineFragment extends SFragment implements } private void setupTimelinePreferences() { + AccountEntity activeAccount = accountManager.getActiveAccount(); + if (activeAccount == null) { + return; + } SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(getActivity()); - alwaysShowSensitiveMedia = accountManager.getActiveAccount().getAlwaysShowSensitiveMedia(); - boolean mediaPreviewEnabled = accountManager.getActiveAccount().getMediaPreviewEnabled(); + alwaysShowSensitiveMedia = activeAccount.getAlwaysShowSensitiveMedia(); + boolean mediaPreviewEnabled = activeAccount.getMediaPreviewEnabled(); adapter.setMediaPreviewEnabled(mediaPreviewEnabled); boolean useAbsoluteTime = preferences.getBoolean("absoluteTimeView", false); adapter.setUseAbsoluteTime(useAbsoluteTime); @@ -688,6 +696,9 @@ public class TimelineFragment extends SFragment implements @Override public void onLoadMore(int position) { + if (accountManager.getActiveAccount() == null) { + return; + } //check bounds before accessing list, if (statuses.size() >= position && position > 0) { Status fromStatus = statuses.get(position - 1).asRightOrNull();