Write notification account information to the correct account (#3697)
Don't use `accountManager.activeAccount` throughout the code. Instead, get the active account once, and use that over the life of the viewmodel. As shown in https://github.com/tuskyapp/Tusky/issues/3689#issuecomment-1567219338 the active account can change before the view model is destroyed, and if that happens account information for the account will be written to the wrong account.
This commit is contained in:
parent
61374c5180
commit
346dabffc5
|
@ -212,6 +212,13 @@ public abstract class BaseActivity extends AppCompatActivity implements Injectab
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: This changes the accountManager's activeAccount property, but does not do any
|
||||||
|
// of the work that AccountManager.setActiveAccount() does. In particular:
|
||||||
|
//
|
||||||
|
// - The current active account is not saved
|
||||||
|
// - The account passed as parameter here goes not have its `isActive` property set
|
||||||
|
//
|
||||||
|
// Is that deliberate? Or is this a bug?
|
||||||
public void openAsAccount(@NonNull String url, @NonNull AccountEntity account) {
|
public void openAsAccount(@NonNull String url, @NonNull AccountEntity account) {
|
||||||
accountManager.setActiveAccount(account);
|
accountManager.setActiveAccount(account);
|
||||||
Intent intent = new Intent(this, MainActivity.class);
|
Intent intent = new Intent(this, MainActivity.class);
|
||||||
|
|
|
@ -606,9 +606,7 @@ public class NotificationHelper {
|
||||||
Log.d(TAG, "disabled notification checks");
|
Log.d(TAG, "disabled notification checks");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void clearNotificationsForActiveAccount(@NonNull Context context, @NonNull AccountManager accountManager) {
|
public static void clearNotificationsForAccount(@NonNull Context context, @NonNull AccountEntity account) {
|
||||||
AccountEntity account = accountManager.getActiveAccount();
|
|
||||||
if (account == null) return;
|
|
||||||
int accountId = (int) account.getId();
|
int accountId = (int) account.getId();
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
|
|
@ -106,7 +106,7 @@ class NotificationsFragment :
|
||||||
|
|
||||||
adapter = NotificationsPagingAdapter(
|
adapter = NotificationsPagingAdapter(
|
||||||
notificationDiffCallback,
|
notificationDiffCallback,
|
||||||
accountId = accountManager.activeAccount!!.accountId,
|
accountId = viewModel.account.accountId,
|
||||||
statusActionListener = this,
|
statusActionListener = this,
|
||||||
notificationActionListener = this,
|
notificationActionListener = this,
|
||||||
accountActionListener = this,
|
accountActionListener = this,
|
||||||
|
@ -460,7 +460,7 @@ class NotificationsFragment :
|
||||||
override fun onRefresh() {
|
override fun onRefresh() {
|
||||||
binding.progressBar.isVisible = false
|
binding.progressBar.isVisible = false
|
||||||
adapter.refresh()
|
adapter.refresh()
|
||||||
NotificationHelper.clearNotificationsForActiveAccount(requireContext(), accountManager)
|
NotificationHelper.clearNotificationsForAccount(requireContext(), viewModel.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onPause() {
|
override fun onPause() {
|
||||||
|
@ -477,7 +477,7 @@ class NotificationsFragment :
|
||||||
|
|
||||||
override fun onResume() {
|
override fun onResume() {
|
||||||
super.onResume()
|
super.onResume()
|
||||||
NotificationHelper.clearNotificationsForActiveAccount(requireContext(), accountManager)
|
NotificationHelper.clearNotificationsForAccount(requireContext(), viewModel.account)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onReply(position: Int) {
|
override fun onReply(position: Int) {
|
||||||
|
@ -606,7 +606,7 @@ class NotificationsFragment :
|
||||||
|
|
||||||
override fun onViewReport(reportId: String) {
|
override fun onViewReport(reportId: String) {
|
||||||
requireContext().openLink(
|
requireContext().openLink(
|
||||||
"https://${accountManager.activeAccount!!.domain}/admin/reports/$reportId"
|
"https://${viewModel.account.domain}/admin/reports/$reportId"
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -622,7 +622,7 @@ class NotificationsFragment :
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private const val TAG = "NotificationF"
|
private const val TAG = "NotificationsFragment"
|
||||||
fun newInstance() = NotificationsFragment()
|
fun newInstance() = NotificationsFragment()
|
||||||
|
|
||||||
private val notificationDiffCallback: DiffUtil.ItemCallback<NotificationViewData> =
|
private val notificationDiffCallback: DiffUtil.ItemCallback<NotificationViewData> =
|
||||||
|
|
|
@ -282,6 +282,8 @@ class NotificationsViewModel @Inject constructor(
|
||||||
private val timelineCases: TimelineCases,
|
private val timelineCases: TimelineCases,
|
||||||
private val eventHub: EventHub
|
private val eventHub: EventHub
|
||||||
) : ViewModel() {
|
) : ViewModel() {
|
||||||
|
/** The account to display notifications for */
|
||||||
|
val account = accountManager.activeAccount!!
|
||||||
|
|
||||||
val uiState: StateFlow<UiState>
|
val uiState: StateFlow<UiState>
|
||||||
|
|
||||||
|
@ -316,16 +318,14 @@ class NotificationsViewModel @Inject constructor(
|
||||||
// Save each change back to the active account
|
// Save each change back to the active account
|
||||||
.onEach { action ->
|
.onEach { action ->
|
||||||
Log.d(TAG, "notificationFilter: $action")
|
Log.d(TAG, "notificationFilter: $action")
|
||||||
accountManager.activeAccount?.let { account ->
|
|
||||||
account.notificationsFilter = serialize(action.filter)
|
account.notificationsFilter = serialize(action.filter)
|
||||||
accountManager.saveAccount(account)
|
accountManager.saveAccount(account)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
// Load the initial filter from the active account
|
// Load the initial filter from the active account
|
||||||
.onStart {
|
.onStart {
|
||||||
emit(
|
emit(
|
||||||
InfallibleUiAction.ApplyFilter(
|
InfallibleUiAction.ApplyFilter(
|
||||||
filter = deserialize(accountManager.activeAccount?.notificationsFilter)
|
filter = deserialize(account.notificationsFilter)
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -336,13 +336,11 @@ class NotificationsViewModel @Inject constructor(
|
||||||
.filterIsInstance<InfallibleUiAction.SaveVisibleId>()
|
.filterIsInstance<InfallibleUiAction.SaveVisibleId>()
|
||||||
.distinctUntilChanged()
|
.distinctUntilChanged()
|
||||||
.collectLatest { action ->
|
.collectLatest { action ->
|
||||||
Log.d(TAG, "Saving visible ID: ${action.visibleId}")
|
Log.d(TAG, "Saving visible ID: ${action.visibleId}, active account = ${account.id}")
|
||||||
accountManager.activeAccount?.let { account ->
|
|
||||||
account.lastNotificationId = action.visibleId
|
account.lastNotificationId = action.visibleId
|
||||||
accountManager.saveAccount(account)
|
accountManager.saveAccount(account)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// Set initial status display options from the user's preferences.
|
// Set initial status display options from the user's preferences.
|
||||||
//
|
//
|
||||||
|
@ -351,7 +349,7 @@ class NotificationsViewModel @Inject constructor(
|
||||||
statusDisplayOptions = MutableStateFlow(
|
statusDisplayOptions = MutableStateFlow(
|
||||||
StatusDisplayOptions.from(
|
StatusDisplayOptions.from(
|
||||||
preferences,
|
preferences,
|
||||||
accountManager.activeAccount!!
|
account
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -363,7 +361,7 @@ class NotificationsViewModel @Inject constructor(
|
||||||
statusDisplayOptions.value.make(
|
statusDisplayOptions.value.make(
|
||||||
preferences,
|
preferences,
|
||||||
it.preferenceKey,
|
it.preferenceKey,
|
||||||
accountManager.activeAccount!!
|
account
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
.collect {
|
.collect {
|
||||||
|
@ -494,7 +492,7 @@ class NotificationsViewModel @Inject constructor(
|
||||||
// The database stores "0" as the last notification ID if notifications have not been
|
// The database stores "0" as the last notification ID if notifications have not been
|
||||||
// fetched. Convert to null to ensure a full fetch in this case
|
// fetched. Convert to null to ensure a full fetch in this case
|
||||||
private fun getInitialKey(): String? {
|
private fun getInitialKey(): String? {
|
||||||
val initialKey = when (val id = accountManager.activeAccount?.lastNotificationId) {
|
val initialKey = when (val id = account.lastNotificationId) {
|
||||||
"0" -> null
|
"0" -> null
|
||||||
else -> id
|
else -> id
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,7 @@ class AccountManager @Inject constructor(db: AppDatabase) {
|
||||||
/**
|
/**
|
||||||
* Adds a new account and makes it the active account.
|
* Adds a new account and makes it the active account.
|
||||||
* @param accessToken the access token for the new account
|
* @param accessToken the access token for the new account
|
||||||
* @param domain the domain of the accounts Mastodon instance
|
* @param domain the domain of the account's Mastodon instance
|
||||||
* @param clientId the oauth client id used to sign in the account
|
* @param clientId the oauth client id used to sign in the account
|
||||||
* @param clientSecret the oauth client secret used to sign in the account
|
* @param clientSecret the oauth client secret used to sign in the account
|
||||||
* @param oauthScopes the oauth scopes granted to the account
|
* @param oauthScopes the oauth scopes granted to the account
|
||||||
|
|
Loading…
Reference in New Issue