diff --git a/app/build.gradle b/app/build.gradle
index 550976d3..febb289f 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -125,6 +125,7 @@ dependencies {
implementation "androidx.constraintlayout:constraintlayout:1.1.3"
implementation "androidx.paging:paging-runtime-ktx:2.1.2"
implementation "androidx.viewpager2:viewpager2:1.0.0"
+ implementation "androidx.work:work-runtime:2.3.4"
implementation "androidx.room:room-runtime:$roomVersion"
implementation "androidx.room:room-rxjava2:$roomVersion"
kapt "androidx.room:room-compiler:$roomVersion"
@@ -166,8 +167,6 @@ dependencies {
implementation "com.theartofdev.edmodo:android-image-cropper:2.8.0"
- implementation "com.evernote:android-job:1.4.2"
-
implementation "de.c1710:filemojicompat:1.0.17"
testImplementation "androidx.test.ext:junit:1.1.1"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 3535d9f5..53564ace 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -174,6 +174,13 @@
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="@xml/file_paths" />
+
+
+
\ No newline at end of file
diff --git a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
index 0cfd2613..17ad57be 100644
--- a/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/MainActivity.kt
@@ -48,6 +48,7 @@ import com.keylesspalace.tusky.appstore.*
import com.keylesspalace.tusky.components.compose.ComposeActivity
import com.keylesspalace.tusky.components.compose.ComposeActivity.Companion.canHandleMimeType
import com.keylesspalace.tusky.components.conversation.ConversationsRepository
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.components.scheduled.ScheduledTootActivity
import com.keylesspalace.tusky.components.search.SearchActivity
import com.keylesspalace.tusky.db.AccountEntity
@@ -192,9 +193,9 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
// Setup push notifications
if (NotificationHelper.areNotificationsEnabled(this, accountManager)) {
- NotificationHelper.enablePullNotifications()
+ NotificationHelper.enablePullNotifications(this)
} else {
- NotificationHelper.disablePullNotifications()
+ NotificationHelper.disablePullNotifications(this)
}
eventHub.events
.observeOn(AndroidSchedulers.mainThread())
@@ -524,19 +525,18 @@ class MainActivity : BottomSheetActivity(), ActionButtonActivity, HasAndroidInje
.setTitle(R.string.action_logout)
.setMessage(getString(R.string.action_logout_confirm, activeAccount.fullName))
.setPositiveButton(android.R.string.yes) { _: DialogInterface?, _: Int ->
- NotificationHelper.deleteNotificationChannelsForAccount(activeAccount, this@MainActivity)
+ NotificationHelper.deleteNotificationChannelsForAccount(activeAccount, this)
cacheUpdater.clearForUser(activeAccount.id)
conversationRepository.deleteCacheForAccount(activeAccount.id)
removeShortcut(this, activeAccount)
val newAccount = accountManager.logActiveAccountOut()
- if (!NotificationHelper.areNotificationsEnabled(this@MainActivity, accountManager)) {
- NotificationHelper.disablePullNotifications()
+ if (!NotificationHelper.areNotificationsEnabled(this, accountManager)) {
+ NotificationHelper.disablePullNotifications(this)
}
- val intent: Intent
- intent = if (newAccount == null) {
- LoginActivity.getIntent(this@MainActivity, false)
+ val intent = if (newAccount == null) {
+ LoginActivity.getIntent(this, false)
} else {
- Intent(this@MainActivity, MainActivity::class.java)
+ Intent(this, MainActivity::class.java)
}
startActivity(intent)
finishWithoutSlideOutAnimation()
diff --git a/app/src/main/java/com/keylesspalace/tusky/SplashActivity.kt b/app/src/main/java/com/keylesspalace/tusky/SplashActivity.kt
index 8c6a877a..07c54e97 100644
--- a/app/src/main/java/com/keylesspalace/tusky/SplashActivity.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/SplashActivity.kt
@@ -21,7 +21,7 @@ import androidx.appcompat.app.AppCompatActivity
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
-import com.keylesspalace.tusky.util.NotificationHelper
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import javax.inject.Inject
class SplashActivity : AppCompatActivity(), Injectable {
diff --git a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt
index 21653d35..f41395bd 100644
--- a/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/TuskyApplication.kt
@@ -21,12 +21,10 @@ import android.content.res.Configuration
import android.util.Log
import androidx.emoji.text.EmojiCompat
import androidx.preference.PreferenceManager
-import com.evernote.android.job.JobManager
+import androidx.work.WorkManager
+import com.keylesspalace.tusky.components.notifications.NotificationWorkerFactory
import com.keylesspalace.tusky.di.AppInjector
-import com.keylesspalace.tusky.util.EmojiCompatFont
-import com.keylesspalace.tusky.util.LocaleManager
-import com.keylesspalace.tusky.util.NotificationPullJobCreator
-import com.keylesspalace.tusky.util.ThemeUtils
+import com.keylesspalace.tusky.util.*
import com.uber.autodispose.AutoDisposePlugins
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasAndroidInjector
@@ -40,7 +38,7 @@ class TuskyApplication : Application(), HasAndroidInjector {
@Inject
lateinit var androidInjector: DispatchingAndroidInjector
@Inject
- lateinit var notificationPullJobCreator: NotificationPullJobCreator
+ lateinit var notificationWorkerFactory: NotificationWorkerFactory
override fun onCreate() {
@@ -65,7 +63,12 @@ class TuskyApplication : Application(), HasAndroidInjector {
val theme = preferences.getString("appTheme", ThemeUtils.APP_THEME_DEFAULT)
ThemeUtils.setAppNightMode(theme)
- JobManager.create(this).addJobCreator(notificationPullJobCreator)
+ WorkManager.initialize(
+ this,
+ androidx.work.Configuration.Builder()
+ .setWorkerFactory(notificationWorkerFactory)
+ .build()
+ )
RxJavaPlugins.setErrorHandler {
Log.w("RxJava", "undeliverable exception", it)
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
similarity index 94%
rename from app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
rename to app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
index c98e8b5c..a094750e 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationHelper.java
+++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationHelper.java
@@ -14,7 +14,7 @@
* You should have received a copy of the GNU General Public License along with Tusky; if not,
* see . */
-package com.keylesspalace.tusky.util;
+package com.keylesspalace.tusky.components.notifications;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
@@ -38,12 +38,15 @@ import androidx.core.app.RemoteInput;
import androidx.core.app.TaskStackBuilder;
import androidx.core.content.ContextCompat;
import androidx.core.text.BidiFormatter;
+import androidx.work.Constraints;
+import androidx.work.NetworkType;
+import androidx.work.PeriodicWorkRequest;
+import androidx.work.WorkManager;
+import androidx.work.WorkRequest;
import com.bumptech.glide.Glide;
import com.bumptech.glide.load.resource.bitmap.RoundedCorners;
import com.bumptech.glide.request.FutureTarget;
-import com.evernote.android.job.JobManager;
-import com.evernote.android.job.JobRequest;
import com.keylesspalace.tusky.BuildConfig;
import com.keylesspalace.tusky.MainActivity;
import com.keylesspalace.tusky.R;
@@ -65,6 +68,7 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
@@ -118,12 +122,11 @@ public class NotificationHelper {
public static final String CHANNEL_FAVOURITE = "CHANNEL_FAVOURITE";
public static final String CHANNEL_POLL = "CHANNEL_POLL";
- /**
- * time in minutes between notification checks
- * note that this cannot be less than 15 minutes due to Android battery saving constraints
- */
- private static final int NOTIFICATION_CHECK_INTERVAL_MINUTES = 15;
+ /**
+ * WorkManager Tag
+ */
+ private static final String NOTIFICATION_PULL_TAG = "pullNotifications";
/**
* Takes a given Mastodon notification and either creates a new Android notification or updates
@@ -455,23 +458,27 @@ public class NotificationHelper {
}
- public static void enablePullNotifications() {
- long checkInterval = 1000 * 60 * NOTIFICATION_CHECK_INTERVAL_MINUTES;
+ public static void enablePullNotifications(Context context) {
+ WorkManager workManager = WorkManager.getInstance(context);
+ workManager.cancelAllWorkByTag(NOTIFICATION_PULL_TAG);
- new JobRequest.Builder(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG)
- .setPeriodic(checkInterval)
- .setUpdateCurrent(true)
- .setRequiredNetworkType(JobRequest.NetworkType.CONNECTED)
- .build()
- .scheduleAsync();
+ WorkRequest workRequest = new PeriodicWorkRequest.Builder(
+ NotificationWorker.class,
+ PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS, TimeUnit.MILLISECONDS,
+ PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS, TimeUnit.MILLISECONDS
+ )
+ .addTag(NOTIFICATION_PULL_TAG)
+ .setConstraints(new Constraints.Builder().setRequiredNetworkType(NetworkType.CONNECTED).build())
+ .build();
- Log.d(TAG, "enabled notification checks with "+ NOTIFICATION_CHECK_INTERVAL_MINUTES + "min interval");
+ workManager.enqueue(workRequest);
+
+ Log.d(TAG, "enabled notification checks with "+ PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS + "ms interval");
}
- public static void disablePullNotifications() {
- JobManager.instance().cancelAllForTag(NotificationPullJobCreator.NOTIFICATIONS_JOB_TAG);
+ public static void disablePullNotifications(Context context) {
+ WorkManager.getInstance(context).cancelAllWorkByTag(NOTIFICATION_PULL_TAG);
Log.d(TAG, "disabled notification checks");
-
}
public static void clearNotificationsForActiveAccount(@NonNull Context context, @NonNull AccountManager accountManager) {
@@ -486,8 +493,8 @@ public class NotificationHelper {
notificationManager.cancel((int) account.getId());
return true;
})
- .subscribeOn(Schedulers.io())
- .subscribe();
+ .subscribeOn(Schedulers.io())
+ .subscribe();
}
}
@@ -525,7 +532,8 @@ public class NotificationHelper {
}
}
- private static @Nullable String getChannelId(AccountEntity account, Notification notification) {
+ @Nullable
+ private static String getChannelId(AccountEntity account, Notification notification) {
switch (notification.getType()) {
case MENTION:
return CHANNEL_MENTION + account.getIdentifier();
diff --git a/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationWorker.kt b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationWorker.kt
new file mode 100644
index 00000000..9abcd3ac
--- /dev/null
+++ b/app/src/main/java/com/keylesspalace/tusky/components/notifications/NotificationWorker.kt
@@ -0,0 +1,98 @@
+/* Copyright 2020 Tusky Contributors
+ *
+ * This file is part of Tusky.
+ *
+ * Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
+ * Lesser General Public License as published by the Free Software Foundation, either version 3 of
+ * the License, or (at your option) any later version.
+ *
+ * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
+ * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License along with Tusky. If
+ * not, see . */
+
+package com.keylesspalace.tusky.components.notifications
+
+import android.content.Context
+import android.util.Log
+import androidx.work.ListenableWorker
+import androidx.work.Worker
+import androidx.work.WorkerFactory
+import androidx.work.WorkerParameters
+import com.keylesspalace.tusky.db.AccountEntity
+import com.keylesspalace.tusky.db.AccountManager
+import com.keylesspalace.tusky.entity.Notification
+import com.keylesspalace.tusky.network.MastodonApi
+import com.keylesspalace.tusky.util.isLessThan
+import java.io.IOException
+import javax.inject.Inject
+
+class NotificationWorker(
+ private val context: Context,
+ params: WorkerParameters,
+ private val mastodonApi: MastodonApi,
+ private val accountManager: AccountManager
+) : Worker(context, params) {
+
+ override fun doWork(): Result {
+ val accountList = accountManager.getAllAccountsOrderedByActive()
+ for (account in accountList) {
+ if (account.notificationsEnabled) {
+ try {
+ Log.d(TAG, "getting Notifications for " + account.fullName)
+ val notificationsResponse = mastodonApi.notificationsWithAuth(
+ String.format("Bearer %s", account.accessToken),
+ account.domain
+ ).execute()
+ val notifications = notificationsResponse.body()
+ if (notificationsResponse.isSuccessful && notifications != null) {
+ onNotificationsReceived(account, notifications)
+ } else {
+ Log.w(TAG, "error receiving notifications")
+ }
+ } catch (e: IOException) {
+ Log.w(TAG, "error receiving notifications", e)
+ }
+ }
+ }
+ return Result.success()
+ }
+
+ private fun onNotificationsReceived(account: AccountEntity, notificationList: List) {
+ val newId = account.lastNotificationId
+ var newestId = ""
+ var isFirstOfBatch = true
+ notificationList.reversed().forEach { notification ->
+ val currentId = notification.id
+ if (newestId.isLessThan(currentId)) {
+ newestId = currentId
+ }
+ if (newId.isLessThan(currentId)) {
+ NotificationHelper.make(context, notification, account, isFirstOfBatch)
+ isFirstOfBatch = false
+ }
+ }
+ account.lastNotificationId = newestId
+ accountManager.saveAccount(account)
+ }
+
+ companion object {
+ private const val TAG = "NotificationWorker"
+ }
+
+}
+
+class NotificationWorkerFactory @Inject constructor(
+ val api: MastodonApi,
+ val accountManager: AccountManager
+): WorkerFactory() {
+
+ override fun createWorker(appContext: Context, workerClassName: String, workerParameters: WorkerParameters): ListenableWorker? {
+ if(workerClassName == NotificationWorker::class.java.name) {
+ return NotificationWorker(appContext, workerParameters, api, accountManager)
+ }
+ return null
+ }
+}
diff --git a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
index 093c2308..db01b027 100644
--- a/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/fragment/preference/NotificationPreferencesFragment.kt
@@ -23,7 +23,7 @@ import androidx.preference.SwitchPreferenceCompat
import com.keylesspalace.tusky.R
import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.di.Injectable
-import com.keylesspalace.tusky.util.NotificationHelper
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import javax.inject.Inject
class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.OnPreferenceChangeListener, Injectable {
@@ -70,9 +70,9 @@ class NotificationPreferencesFragment : PreferenceFragmentCompat(), Preference.O
"notificationsEnabled" -> {
activeAccount.notificationsEnabled = newValue as Boolean
if (NotificationHelper.areNotificationsEnabled(preference.context, accountManager)) {
- NotificationHelper.enablePullNotifications()
+ NotificationHelper.enablePullNotifications(preference.context)
} else {
- NotificationHelper.disablePullNotifications()
+ NotificationHelper.disablePullNotifications(preference.context)
}
}
"notificationFilterMentions" -> activeAccount.notificationsMentioned = newValue as Boolean
diff --git a/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt b/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt
index 9e6d0dc5..d9b94857 100644
--- a/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/receiver/NotificationClearBroadcastReceiver.kt
@@ -20,7 +20,7 @@ import android.content.Context
import android.content.Intent
import com.keylesspalace.tusky.db.AccountManager
-import com.keylesspalace.tusky.util.NotificationHelper
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import dagger.android.AndroidInjection
import javax.inject.Inject
diff --git a/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
index a3f717c8..f8bf81b3 100644
--- a/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/receiver/SendStatusBroadcastReceiver.kt
@@ -30,7 +30,7 @@ import com.keylesspalace.tusky.db.AccountManager
import com.keylesspalace.tusky.entity.Status
import com.keylesspalace.tusky.service.SendTootService
import com.keylesspalace.tusky.service.TootToSend
-import com.keylesspalace.tusky.util.NotificationHelper
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.util.randomAlphanumericString
import dagger.android.AndroidInjection
import javax.inject.Inject
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/NotificationPullJobCreator.java b/app/src/main/java/com/keylesspalace/tusky/util/NotificationPullJobCreator.java
deleted file mode 100644
index 60bf626d..00000000
--- a/app/src/main/java/com/keylesspalace/tusky/util/NotificationPullJobCreator.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright 2017 Andrew Dawson
- *
- * This file is part of Tusky.
- *
- * Tusky is free software: you can redistribute it and/or modify it under the terms of the GNU
- * Lesser General Public License as published by the Free Software Foundation, either version 3 of
- * the License, or (at your option) any later version.
- *
- * Tusky is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even
- * the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser
- * General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License along with Tusky. If
- * not, see . */
-
-package com.keylesspalace.tusky.util;
-
-import android.content.Context;
-import android.util.Log;
-
-import com.evernote.android.job.Job;
-import com.evernote.android.job.JobCreator;
-import com.keylesspalace.tusky.db.AccountEntity;
-import com.keylesspalace.tusky.db.AccountManager;
-import com.keylesspalace.tusky.entity.Notification;
-import com.keylesspalace.tusky.network.MastodonApi;
-
-import java.io.IOException;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import javax.inject.Inject;
-
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import retrofit2.Response;
-
-import static com.keylesspalace.tusky.util.StringUtils.isLessThan;
-
-/**
- * Created by charlag on 31/10/17.
- */
-
-public final class NotificationPullJobCreator implements JobCreator {
-
- private static final String TAG = "NotificationPJC";
-
- static final String NOTIFICATIONS_JOB_TAG = "notifications_job_tag";
-
- private final MastodonApi api;
- private final Context context;
- private final AccountManager accountManager;
-
- @Inject NotificationPullJobCreator(MastodonApi api, Context context,
- AccountManager accountManager) {
- this.api = api;
- this.context = context;
- this.accountManager = accountManager;
- }
-
- @Nullable
- @Override
- public Job create(@NonNull String tag) {
- if (tag.equals(NOTIFICATIONS_JOB_TAG)) {
- return new NotificationPullJob(context, accountManager, api);
- }
- return null;
- }
-
- private final static class NotificationPullJob extends Job {
-
- private final Context context;
- private final AccountManager accountManager;
- private final MastodonApi mastodonApi;
-
- NotificationPullJob(Context context, AccountManager accountManager,
- MastodonApi mastodonApi) {
- this.context = context;
- this.accountManager = accountManager;
- this.mastodonApi = mastodonApi;
- }
-
- @NonNull
- @Override
- protected Result onRunJob(@NonNull Params params) {
- List accountList = new ArrayList<>(accountManager.getAllAccountsOrderedByActive());
- for (AccountEntity account : accountList) {
- if (account.getNotificationsEnabled()) {
- try {
- Log.d(TAG, "getting Notifications for " + account.getFullName());
- Response> notifications =
- mastodonApi.notificationsWithAuth(
- String.format("Bearer %s", account.getAccessToken()),
- account.getDomain()
- )
- .execute();
- if (notifications.isSuccessful()) {
- onNotificationsReceived(account, notifications.body());
- } else {
- Log.w(TAG, "error receiving notifications");
- }
- } catch (IOException e) {
- Log.w(TAG, "error receiving notifications", e);
- }
- }
-
- }
-
- return Result.SUCCESS;
- }
-
- private void onNotificationsReceived(AccountEntity account, List notificationList) {
- Collections.reverse(notificationList);
- String newId = account.getLastNotificationId();
- String newestId = "";
- boolean isFirstOfBatch = true;
-
- for (Notification notification : notificationList) {
- String currentId = notification.getId();
- if (isLessThan(newestId, currentId)) {
- newestId = currentId;
- }
- if (isLessThan(newId, currentId)) {
- NotificationHelper.make(context, notification, account, isFirstOfBatch);
- isFirstOfBatch = false;
- }
- }
-
- account.setLastNotificationId(newestId);
- accountManager.saveAccount(account);
- }
-
- }
-}
diff --git a/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt b/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt
index 5aef288c..1acf2260 100644
--- a/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt
+++ b/app/src/main/java/com/keylesspalace/tusky/util/ShareShortcutHelper.kt
@@ -29,6 +29,7 @@ import androidx.core.graphics.drawable.IconCompat
import com.bumptech.glide.Glide
import com.keylesspalace.tusky.MainActivity
import com.keylesspalace.tusky.R
+import com.keylesspalace.tusky.components.notifications.NotificationHelper
import com.keylesspalace.tusky.db.AccountEntity
import io.reactivex.Single
import io.reactivex.schedulers.Schedulers