package app.fedilab.android.helper; /* Copyright 2021 Thomas Schneider * * This file is a part of Fedilab * * This program is free software; you can redistribute it and/or modify it under the terms of the * GNU General Public License as published by the Free Software Foundation; either version 3 of the * License, or (at your option) any later version. * * Fedilab 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 General * Public License for more details. * * You should have received a copy of the GNU General Public License along with Fedilab; if not, * see . */ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Looper; import androidx.annotation.NonNull; import androidx.annotation.Nullable; import com.bumptech.glide.Glide; import com.bumptech.glide.load.DataSource; import com.bumptech.glide.load.engine.GlideException; import com.bumptech.glide.request.RequestListener; import com.bumptech.glide.request.target.CustomTarget; import com.bumptech.glide.request.target.Target; import com.bumptech.glide.request.transition.Transition; import java.util.ArrayList; import java.util.List; import app.fedilab.android.R; import app.fedilab.android.activities.MainActivity; import app.fedilab.android.client.API; import app.fedilab.android.client.APIResponse; import app.fedilab.android.client.Entities.Account; import app.fedilab.android.client.Entities.Notification; import app.fedilab.android.client.GNUAPI; import app.fedilab.android.fragments.DisplayNotificationsFragment; import static app.fedilab.android.helper.BaseHelper.INTENT_ACTION; import static app.fedilab.android.helper.BaseHelper.INTENT_TARGETED_ACCOUNT; import static app.fedilab.android.helper.BaseHelper.NOTIFICATION_INTENT; import static app.fedilab.android.helper.BaseHelper.PREF_INSTANCE; import static app.fedilab.android.helper.BaseHelper.PREF_KEY_ID; import static app.fedilab.android.helper.BaseHelper.getMainLogo; import static app.fedilab.android.helper.BaseHelper.notify_user; public class NotificationsHelper { public static void task(Context context, Account account) { APIResponse apiResponse; final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); //Check which notifications the user wants to see boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true); //User disagree with all notifications if (!notif_follow && !notif_add && !notif_mention && !notif_share && !notif_poll) return; //Nothing is done //No account connected, the service is stopped if (!Helper.isLoggedIn(context)) return; //If WIFI only and on WIFI OR user defined any connections to use the service. if (!sharedpreferences.getBoolean(Helper.SET_WIFI_ONLY, false) || Helper.isOnWIFI(context)) { if (account.getSocial().compareTo("FRIENDICA") != 0 && account.getSocial().compareTo("GNU") != 0) { API api = new API(context, account.getInstance(), account.getToken()); apiResponse = api.getNotificationsSince(DisplayNotificationsFragment.Type.ALL, null, false); } else { GNUAPI gnuApi = new GNUAPI(context, account.getInstance(), account.getToken()); apiResponse = gnuApi.getNotificationsSince(DisplayNotificationsFragment.Type.ALL, null); } onRetrieveNotifications(context, apiResponse, account); } } public static void onRetrieveNotifications(Context context, APIResponse apiResponse, final Account account) { List notificationsReceived = apiResponse.getNotifications(); if (apiResponse.getError() != null || notificationsReceived == null || notificationsReceived.size() == 0 || account == null) return; final SharedPreferences sharedpreferences = context.getSharedPreferences(Helper.APP_PREFS, Context.MODE_PRIVATE); boolean notif_follow = sharedpreferences.getBoolean(Helper.SET_NOTIF_FOLLOW, true); boolean notif_add = sharedpreferences.getBoolean(Helper.SET_NOTIF_ADD, true); boolean notif_mention = sharedpreferences.getBoolean(Helper.SET_NOTIF_MENTION, true); boolean notif_share = sharedpreferences.getBoolean(Helper.SET_NOTIF_SHARE, true); boolean notif_poll = sharedpreferences.getBoolean(Helper.SET_NOTIF_POLL, true); boolean notif_status = sharedpreferences.getBoolean(Helper.SET_NOTIF_STATUS, true); final String max_id = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId() + account.getInstance(), null); final List notifications = new ArrayList<>(); int pos = 0; for (Notification notif : notificationsReceived) { if (max_id == null || notif.getId().compareTo(max_id) > 0) { notifications.add(pos, notif); pos++; } } if (notifications.size() == 0) return; //No previous notifications in cache, so no notification will be sent int newFollows = 0; int newAdds = 0; int newMentions = 0; int newShare = 0; int newPolls = 0; int newStatus = 0; String notificationUrl = null; String title = null; final String message; String targeted_account = null; Helper.NotifType notifType = Helper.NotifType.MENTION; for (Notification notification : notifications) { switch (notification.getType()) { case "mention": notifType = Helper.NotifType.MENTION; if (notif_mention) { newMentions++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_mention)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_mention)); } } break; case "status": notifType = Helper.NotifType.STATUS; if (notif_status) { newStatus++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_status)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_status)); } } break; case "reblog": notifType = Helper.NotifType.BOOST; if (notif_share) { newShare++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_reblog)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_reblog)); } } break; case "favourite": notifType = Helper.NotifType.FAV; if (notif_add) { newAdds++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_favourite)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_favourite)); } } break; case "follow_request": notifType = Helper.NotifType.FOLLLOW; if (notif_follow) { newFollows++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_follow_request)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_follow_request)); targeted_account = notification.getAccount().getId(); } } break; case "follow": notifType = Helper.NotifType.FOLLLOW; if (notif_follow) { newFollows++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); if (notification.getAccount().getDisplay_name() != null && notification.getAccount().getDisplay_name().length() > 0) title = String.format("%s %s", notification.getAccount().getDisplay_name(), context.getString(R.string.notif_follow)); else title = String.format("@%s %s", notification.getAccount().getAcct(), context.getString(R.string.notif_follow)); targeted_account = notification.getAccount().getId(); } } break; case "poll": notifType = Helper.NotifType.POLL; if (notif_poll) { newPolls++; if (notificationUrl == null) { notificationUrl = notification.getAccount().getAvatar(); String userId = sharedpreferences.getString(Helper.PREF_KEY_ID, null); if (notification.getAccount().getId() != null && notification.getAccount().getId().equals(userId)) title = context.getString(R.string.notif_poll_self); else title = context.getString(R.string.notif_poll); } } break; default: } } int allNotifCount = newFollows + newAdds + newMentions + newShare + newPolls + newStatus; if (allNotifCount > 0) { //Some others notification int other = allNotifCount - 1; if (other > 0) message = context.getResources().getQuantityString(R.plurals.other_notifications, other, other); else message = ""; final Intent intent = new Intent(context, MainActivity.class); intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); intent.putExtra(INTENT_ACTION, NOTIFICATION_INTENT); intent.putExtra(PREF_KEY_ID, account.getId()); if (targeted_account != null && notifType == Helper.NotifType.FOLLLOW) intent.putExtra(INTENT_TARGETED_ACCOUNT, targeted_account); intent.putExtra(PREF_INSTANCE, account.getInstance()); if (notificationUrl != null) { final String finalTitle = title; Handler mainHandler = new Handler(Looper.getMainLooper()); final String finalNotificationUrl = notificationUrl; Helper.NotifType finalNotifType = notifType; Runnable myRunnable = () -> Glide.with(context) .asBitmap() .load(finalNotificationUrl) .listener(new RequestListener() { @Override public boolean onResourceReady(Bitmap resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { return false; } @Override public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { notify_user(context, account, intent, BitmapFactory.decodeResource(context.getResources(), getMainLogo(context)), finalNotifType, finalTitle, message); String lastNotif = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId() + account.getInstance(), null); if (lastNotif == null || notifications.get(0).getId().compareTo(lastNotif) > 0) { SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId() + account.getInstance(), notifications.get(0).getId()); editor.apply(); } return false; } }) .into(new CustomTarget() { @Override public void onResourceReady(@NonNull Bitmap resource, Transition transition) { notify_user(context, account, intent, resource, finalNotifType, finalTitle, message); String lastNotif = sharedpreferences.getString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId() + account.getInstance(), null); if (lastNotif == null || notifications.get(0).getId().compareTo(lastNotif) > 0) { SharedPreferences.Editor editor = sharedpreferences.edit(); editor.putString(Helper.LAST_NOTIFICATION_MAX_ID + account.getId() + account.getInstance(), notifications.get(0).getId()); editor.apply(); } } @Override public void onLoadCleared(@Nullable Drawable placeholder) { } }); mainHandler.post(myRunnable); } } } }