diff --git a/Clover/app/src/main/AndroidManifest.xml b/Clover/app/src/main/AndroidManifest.xml index c0c9ddd2b5..f498536f65 100644 --- a/Clover/app/src/main/AndroidManifest.xml +++ b/Clover/app/src/main/AndroidManifest.xml @@ -88,6 +88,10 @@ along with this program. If not, see . android:name=".ui.service.SavingNotification" android:exported="false" /> + + diff --git a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java index 9ee4a05b7b..7b4b5f7da0 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/manager/WatchManager.java @@ -37,9 +37,12 @@ import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.orm.Pin; import org.floens.chan.core.pool.ChanLoaderFactory; +import org.floens.chan.core.repository.PageRepository; import org.floens.chan.core.settings.ChanSettings; +import org.floens.chan.core.site.Page; import org.floens.chan.core.site.loader.ChanThreadLoader; import org.floens.chan.ui.helper.PostHelper; +import org.floens.chan.ui.service.LastPageNotification; import org.floens.chan.ui.service.WatchNotifier; import org.floens.chan.utils.Logger; @@ -122,6 +125,7 @@ public int compare(Pin lhs, Pin rhs) { private final List pins; private final DatabaseManager databaseManager; private final DatabasePinManager databasePinManager; + private final PageRepository pageRepository; private final Handler handler; @@ -134,12 +138,13 @@ public int compare(Pin lhs, Pin rhs) { private long lastBackgroundUpdateTime; @Inject - public WatchManager(DatabaseManager databaseManager, ChanLoaderFactory chanLoaderFactory) { + public WatchManager(DatabaseManager databaseManager, ChanLoaderFactory chanLoaderFactory, PageRepository pageRepository) { alarmManager = (AlarmManager) getAppContext().getSystemService(Context.ALARM_SERVICE); powerManager = (PowerManager) getAppContext().getSystemService(Context.POWER_SERVICE); this.databaseManager = databaseManager; this.chanLoaderFactory = chanLoaderFactory; + this.pageRepository = pageRepository; databasePinManager = databaseManager.getDatabasePinManager(); pins = databaseManager.runTask(databasePinManager.getPins()); @@ -678,6 +683,7 @@ public class PinWatcher implements ChanThreadLoader.ChanLoaderCallback { private final List quotes = new ArrayList<>(); private boolean wereNewQuotes = false; private boolean wereNewPosts = false; + private boolean notified = false; public PinWatcher(Pin pin) { this.pin = pin; @@ -732,6 +738,20 @@ private void onViewed() { private boolean update(boolean fromBackground) { if (!pin.isError && pin.watching) { + if (ChanSettings.watchEnabled.get() && ChanSettings.watchLastPageNotify.get() && ChanSettings.watchBackground.get() && chanLoader.getThread() != null) { + //check last page stuff, fake a post + Page p = pageRepository.getPage(chanLoader.getThread().op); + if (p == null) { + Logger.w(TAG, "Pages for page not loaded yet, will check for notification next time"); + } else if (p.page >= pin.loadable.board.pages && !notified) { + Intent pageNotifyIntent = new Intent(getAppContext(), LastPageNotification.class); + pageNotifyIntent.putExtra("pin_id", pin.id); + getAppContext().startService(pageNotifyIntent); + notified = true; + } else if (p.page < pin.loadable.board.pages) { + notified = false; + } + } if (fromBackground) { // Always load regardless of timer, since the time left is not accurate for 15min+ intervals chanLoader.clearTimer(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/model/Post.java b/Clover/app/src/main/java/org/floens/chan/core/model/Post.java index 66384b5e69..d887b03934 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/model/Post.java +++ b/Clover/app/src/main/java/org/floens/chan/core/model/Post.java @@ -32,7 +32,7 @@ * Contains all data needed to represent a single post.
* All {@code final} fields are thread-safe. */ -public class Post { +public class Post implements Comparable { public final String boardId; public final Board board; @@ -106,6 +106,16 @@ public class Post { private long lastModified; private String title = ""; + public int compareTo(Post p) { + if (this.time < p.time) { + return 1; + } else if (this.time > p.time) { + return -1; + } else { + return 0; + } + } + private Post(Builder builder) { board = builder.board; boardId = builder.board.code; diff --git a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java index cb1624c079..bde62540b3 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java +++ b/Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java @@ -139,6 +139,7 @@ public String getKey() { public static final BooleanSetting watchEnabled; public static final BooleanSetting watchCountdown; public static final BooleanSetting watchBackground; + public static final BooleanSetting watchLastPageNotify; public static final IntegerSetting watchBackgroundInterval; public static final StringSetting watchNotifyMode; public static final StringSetting watchSound; @@ -224,6 +225,7 @@ public String getKey() { watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false); watchBackground.addCallback((setting, value) -> EventBus.getDefault().post(new SettingChanged<>(watchBackground))); + watchLastPageNotify = new BooleanSetting(p, "preference_watch_last_page_notify", false); watchBackgroundInterval = new IntegerSetting(p, "preference_watch_background_interval", WatchManager.DEFAULT_BACKGROUND_INTERVAL); watchNotifyMode = new StringSetting(p, "preference_watch_notify_mode", "all"); watchSound = new StringSetting(p, "preference_watch_sound", "quotes"); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java index c26f04a52d..539d9a6d6e 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/activity/StartActivity.java @@ -320,6 +320,34 @@ protected void onNewIntent(Intent intent) { browseController.showThread(pin.loadable, false); } } + } else if (pinId != -2 && mainNavigationController.getTop() instanceof ThreadSlideController) { + if(pinId == -1) { + drawerController.onMenuClicked(); + } else { + Pin pin = watchManager.findPinById(pinId); + if(pin != null) { + List controllers = mainNavigationController.childControllers; + for (Controller controller : controllers) { + if (controller instanceof ViewThreadController) { + ((ViewThreadController) controller).loadThread(pin.loadable); + break; + } else if (controller instanceof ThreadSlideController) { + ThreadSlideController slideNav = (ThreadSlideController) controller; + if (slideNav.getRightController() instanceof ViewThreadController) { + ((ViewThreadController) slideNav.getRightController()).loadThread(pin.loadable); + slideNav.switchToController(false); + break; + } else { + ViewThreadController v = new ViewThreadController(this); + v.setLoadable(pin.loadable); + slideNav.setRightController(v); + slideNav.switchToController(false); + break; + } + } + } + } + } } } } diff --git a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java index 3177fe512c..c2feb84251 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/controller/WatchSettingsController.java @@ -36,6 +36,7 @@ public class WatchSettingsController extends SettingsController implements Compo private SettingView enableBackground; private SettingView backgroundTimeout; + private SettingView lastPageNotifyMode; private SettingView notifyMode; private SettingView soundMode; private SettingView peekMode; @@ -70,6 +71,7 @@ public void onCreate() { if (!ChanSettings.watchBackground.get()) { setSettingViewVisibility(backgroundTimeout, false, false); + setSettingViewVisibility(lastPageNotifyMode, false, false); setSettingViewVisibility(notifyMode, false, false); setSettingViewVisibility(soundMode, false, false); setSettingViewVisibility(peekMode, false, false); @@ -90,6 +92,7 @@ public void onPreferenceChange(SettingView item) { if (item == enableBackground) { boolean enabled = ChanSettings.watchBackground.get(); setSettingViewVisibility(backgroundTimeout, enabled, true); + setSettingViewVisibility(lastPageNotifyMode, enabled, true); setSettingViewVisibility(notifyMode, enabled, true); setSettingViewVisibility(soundMode, enabled, true); setSettingViewVisibility(peekMode, enabled, true); @@ -124,6 +127,8 @@ public String getBottomDescription() { } }); + lastPageNotifyMode = settings.add(new BooleanSettingView(this, ChanSettings.watchLastPageNotify, R.string.setting_thread_page_limit_notify, R.string.setting_thread_page_limit_notify_description)); + notifyMode = settings.add(new ListSettingView<>(this, ChanSettings.watchNotifyMode, R.string.setting_watch_notify_mode, context.getResources().getStringArray(R.array.setting_watch_notify_modes), new String[]{"all", "quotes"})); diff --git a/Clover/app/src/main/java/org/floens/chan/ui/service/LastPageNotification.java b/Clover/app/src/main/java/org/floens/chan/ui/service/LastPageNotification.java new file mode 100644 index 0000000000..5c32ddef5e --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/ui/service/LastPageNotification.java @@ -0,0 +1,81 @@ +package org.floens.chan.ui.service; + +import android.app.Notification; +import android.app.NotificationManager; +import android.app.PendingIntent; +import android.app.Service; +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.os.IBinder; +import android.support.annotation.Nullable; +import android.support.v4.app.NotificationCompat; +import android.support.v4.app.NotificationManagerCompat; + +import org.floens.chan.R; +import org.floens.chan.core.manager.WatchManager; +import org.floens.chan.core.model.orm.Pin; +import org.floens.chan.ui.activity.BoardActivity; + +import java.util.Random; + +import javax.inject.Inject; + +import static org.floens.chan.Chan.inject; +import static org.floens.chan.utils.AndroidUtils.getAppContext; + +public class LastPageNotification extends Service { + //random notification ID's, so one notification per thread + private Random random = new Random(); + + @Inject + WatchManager watchManager; + + @Nullable + @Override + public IBinder onBind(Intent intent) { + return null; + } + + @Override + public void onCreate() { + super.onCreate(); + inject(this); + } + + @Override + public int onStartCommand(Intent intent, int flags, int startId) { + if (intent != null && intent.getExtras() != null) { + Bundle extras = intent.getExtras(); + int pinId = extras.getInt("pin_id"); + + //NotificationManagerCompat.from(getAppContext()).notify(random.nextInt(), getNotification(pinId)); + ((NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE)).notify(random.nextInt(), getNotification(pinId)); + } + return START_STICKY; + } + + private Notification getNotification(int pinId) { + Pin pin = watchManager.findPinById(pinId); + + Intent intent = new Intent(this, BoardActivity.class); + intent.setAction(Intent.ACTION_MAIN) + .addCategory(Intent.CATEGORY_LAUNCHER) + .setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK | + Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED) + .putExtra("pin_id", pinId); + + PendingIntent pendingIntent = PendingIntent.getActivity(this, random.nextInt(), intent, PendingIntent.FLAG_ONE_SHOT); + + NotificationCompat.Builder builder = new NotificationCompat.Builder(this); + builder.setSmallIcon(R.drawable.ic_stat_notify_alert) + .setContentTitle(getString(R.string.thread_page_limit)) + .setContentText(pin.loadable.title) + .setContentIntent(pendingIntent) + .setPriority(NotificationCompat.PRIORITY_MAX) + .setTimeoutAfter(10 * 1000 * 60) + .setAutoCancel(true); + + return builder.build(); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java index dbc3eb7c21..3a8ffd7a94 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/service/WatchNotifier.java @@ -48,7 +48,6 @@ public class WatchNotifier extends Service { private static final String TAG = "WatchNotifier"; private static final int NOTIFICATION_ID = 1; - private static final PostAgeComparator POST_AGE_COMPARATOR = new PostAgeComparator(); private static final int SUBJECT_LENGTH = 6; private static final String IMAGE_TEXT = "(img) "; private static final Pattern SHORTEN_NO_PATTERN = Pattern.compile(">>\\d+(?=\\d{3})(\\d{3})"); @@ -186,7 +185,7 @@ private Notification notifyAboutPosts(List pins, List subjectPins, Lis } } - Collections.sort(postsForExpandedLines, POST_AGE_COMPARATOR); + Collections.sort(postsForExpandedLines); List expandedLines = new ArrayList<>(); for (Post postForExpandedLine : postsForExpandedLines) { CharSequence prefix; @@ -288,17 +287,4 @@ private Notification get(String title, String smallText, List expa return builder.build(); } - - private static class PostAgeComparator implements Comparator { - @Override - public int compare(Post lhs, Post rhs) { - if (lhs.time < rhs.time) { - return 1; - } else if (lhs.time > rhs.time) { - return -1; - } else { - return 0; - } - } - } } diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index 8c2d4a95e2..7e452c51d2 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -357,6 +357,8 @@ Enable \"Play videos with external player\" in the settings to play videos with Saved as \"%1$s\" Saving image failed + Thread hit last page + Setup sites History @@ -386,6 +388,8 @@ Enable \"Play videos with external player\" in the settings to play videos with Watch bookmarks when Clover is placed in the background Background update interval The interval between updates when placed in the background + Last page notifications + Notify when threads hit the last page Notify about All posts