package org.mian.gitnex.notifications; import android.Manifest; import android.app.Notification; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.media.RingtoneManager; import android.net.Uri; import android.provider.Settings; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.app.TaskStackBuilder; import androidx.work.Worker; import androidx.work.WorkerParameters; import com.google.android.material.dialog.MaterialAlertDialogBuilder; import java.time.ZonedDateTime; import java.util.HashMap; import java.util.List; import java.util.Map; import org.gitnex.tea4j.v2.models.NotificationThread; import org.mian.gitnex.R; import org.mian.gitnex.activities.MainActivity; import org.mian.gitnex.clients.RetrofitClient; import org.mian.gitnex.database.api.BaseApi; import org.mian.gitnex.database.api.UserAccountsApi; import org.mian.gitnex.database.models.UserAccount; import org.mian.gitnex.helpers.AppDatabaseSettings; import org.mian.gitnex.helpers.Constants; import org.mian.gitnex.helpers.Version; import retrofit2.Call; import retrofit2.Response; /** * @author opyale */ public class NotificationsWorker extends Worker { private final Context context; private final Map> userAccounts; public NotificationsWorker(@NonNull Context context, @NonNull WorkerParameters workerParams) { super(context, workerParams); UserAccountsApi userAccountsApi = BaseApi.getInstance(context, UserAccountsApi.class); this.context = context; assert userAccountsApi != null; this.userAccounts = new HashMap<>(userAccountsApi.getCount()); int delay; if (Integer.parseInt( AppDatabaseSettings.getSettingsValue( context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) == 0) { delay = 15; } else if (Integer.parseInt( AppDatabaseSettings.getSettingsValue( context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) == 1) { delay = 30; } else if (Integer.parseInt( AppDatabaseSettings.getSettingsValue( context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) == 2) { delay = 45; } else if (Integer.parseInt( AppDatabaseSettings.getSettingsValue( context, AppDatabaseSettings.APP_NOTIFICATIONS_DELAY_KEY)) == 3) { delay = 60; } else { delay = Constants.defaultPollingDelay; } ZonedDateTime zdt = ZonedDateTime.now(); zdt = zdt.minusMinutes(delay); String previousTimestamp = String.valueOf(zdt.toOffsetDateTime()); for (UserAccount userAccount : userAccountsApi.loggedInUserAccounts()) { // We do also accept empty values, since the server version was not saved properly in // the beginning. if (userAccount.getServerVersion() == null || userAccount.getServerVersion().isEmpty() || new Version(userAccount.getServerVersion()).higherOrEqual("1.12.3")) { Map userAccountParameters = new HashMap<>(); userAccountParameters.put("previousTimestamp", previousTimestamp); userAccounts.put(userAccount, userAccountParameters); } } } @NonNull @Override public Result doWork() { startPolling(); return Result.success(); } private void startPolling() { for (UserAccount userAccount : userAccounts.keySet()) { Map userAccountParameters = userAccounts.get(userAccount); assert userAccountParameters != null; try { Call> call = RetrofitClient.getApiInterface( context, userAccount.getInstanceUrl(), "token " + userAccount.getToken(), null) .notifyGetList2( false, List.of("unread"), null, userAccountParameters.get("previousTimestamp"), null, 1, 25); Response> response = call.execute(); if (response.code() == 200 && response.body() != null) { List notificationThreads = response.body(); if (!notificationThreads.isEmpty()) { sendNotifications(userAccount, notificationThreads); } } } catch (Exception ignored) { } } } private void sendNotifications( @NonNull UserAccount userAccount, @NonNull List notificationThreads) { PendingIntent pendingIntent = getPendingIntent(userAccount); NotificationManagerCompat notificationManagerCompat = NotificationManagerCompat.from(context); Notification summaryNotification = new NotificationCompat.Builder(context, Constants.mainNotificationChannelId) .setContentTitle( context.getString(R.string.newMessages, userAccount.getUserName())) .setContentText( String.format( context.getString(R.string.youHaveGotNewNotifications), notificationThreads.size())) .setSmallIcon(R.drawable.gitnex_transparent) .setGroup(userAccount.getUserName()) .setGroupSummary(true) .setContentIntent(pendingIntent) .setAutoCancel(true) .build(); if (ActivityCompat.checkSelfPermission( getApplicationContext(), Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) { MaterialAlertDialogBuilder materialAlertDialogBuilder = new MaterialAlertDialogBuilder(context) .setTitle(R.string.pageTitleNotifications) .setMessage(context.getString(R.string.openAppSettings)) .setNeutralButton( R.string.cancelButton, (dialog, which) -> dialog.dismiss()) .setPositiveButton( R.string.isOpen, (dialog, which) -> { Intent intent = new Intent( Settings .ACTION_APPLICATION_DETAILS_SETTINGS); Uri uri = Uri.fromParts( "package", context.getPackageName(), null); intent.setData(uri); context.startActivity(intent); }); materialAlertDialogBuilder.create().show(); return; } notificationManagerCompat.notify(userAccount.getAccountId(), summaryNotification); for (NotificationThread notificationThread : notificationThreads) { String subjectUrl = notificationThread.getSubject().getUrl(); String issueId = context.getResources().getString(R.string.hash) + subjectUrl.substring(subjectUrl.lastIndexOf("/") + 1); String notificationHeader = issueId + " " + notificationThread.getSubject().getTitle() + " " + String.format( context.getResources() .getString(R.string.notificationExtraInfo), notificationThread.getRepository().getFullName(), notificationThread.getSubject().getType()); NotificationCompat.Builder builder1 = getBaseNotificationBuilder() .setContentTitle(notificationHeader) .setGroup(userAccount.getUserName()) .setContentIntent(pendingIntent); notificationManagerCompat.notify( Notifications.uniqueNotificationId(context), builder1.build()); } } private NotificationCompat.Builder getBaseNotificationBuilder() { return new NotificationCompat.Builder(context, Constants.mainNotificationChannelId) .setSmallIcon(R.drawable.gitnex_transparent) .setSound(RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)) .setCategory(NotificationCompat.CATEGORY_MESSAGE) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setAutoCancel(true); } private PendingIntent getPendingIntent(@NonNull UserAccount userAccount) { Intent intent = new Intent(context, MainActivity.class); intent.putExtra("launchFragment", "notifications"); intent.putExtra("switchAccountId", userAccount.getAccountId()); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK); TaskStackBuilder stackBuilder = TaskStackBuilder.create(context); stackBuilder.addNextIntentWithParentStack(intent); return stackBuilder.getPendingIntent( 1, PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE); } }