diff --git a/Clover/app/src/main/AndroidManifest.xml b/Clover/app/src/main/AndroidManifest.xml index b311a3cc..b474537e 100644 --- a/Clover/app/src/main/AndroidManifest.xml +++ b/Clover/app/src/main/AndroidManifest.xml @@ -72,6 +72,7 @@ along with this program. If not, see . + diff --git a/Clover/app/src/main/java/org/floens/chan/Chan.java b/Clover/app/src/main/java/org/floens/chan/Chan.java index 2efc85de..4cc209f9 100644 --- a/Clover/app/src/main/java/org/floens/chan/Chan.java +++ b/Clover/app/src/main/java/org/floens/chan/Chan.java @@ -18,9 +18,11 @@ package org.floens.chan; import android.annotation.SuppressLint; +import android.app.Activity; import android.app.Application; import android.content.pm.PackageManager; import android.os.Build; +import android.os.Bundle; import android.os.StrictMode; import org.floens.chan.core.database.DatabaseManager; @@ -39,7 +41,7 @@ import javax.inject.Inject; import dagger.ObjectGraph; import de.greenrobot.event.EventBus; -public class Chan extends Application implements UserAgentProvider { +public class Chan extends Application implements UserAgentProvider, Application.ActivityLifecycleCallbacks { private static final String TAG = "ChanApplication"; @SuppressLint("StaticFieldLeak") @@ -78,6 +80,8 @@ public class Chan extends Application implements UserAgentProvider { final long startTime = Time.startTiming(); + registerActivityLifecycleCallbacks(this); + AndroidUtils.init(); userAgent = createUserAgent(); @@ -118,7 +122,7 @@ public class Chan extends Application implements UserAgentProvider { return userAgent; } - public void activityEnteredForeground() { + private void activityEnteredForeground() { boolean lastForeground = getApplicationInForeground(); activityForegroundCounter++; @@ -128,7 +132,7 @@ public class Chan extends Application implements UserAgentProvider { } } - public void activityEnteredBackground() { + private void activityEnteredBackground() { boolean lastForeground = getApplicationInForeground(); activityForegroundCounter--; @@ -164,4 +168,34 @@ public class Chan extends Application implements UserAgentProvider { version = version.toLowerCase(Locale.ENGLISH).replace(" ", "_"); return getString(R.string.app_name) + "/" + version; } + + @Override + public void onActivityCreated(Activity activity, Bundle savedInstanceState) { + } + + @Override + public void onActivityStarted(Activity activity) { + activityEnteredForeground(); + } + + @Override + public void onActivityResumed(Activity activity) { + } + + @Override + public void onActivityPaused(Activity activity) { + } + + @Override + public void onActivityStopped(Activity activity) { + activityEnteredBackground(); + } + + @Override + public void onActivitySaveInstanceState(Activity activity, Bundle outState) { + } + + @Override + public void onActivityDestroyed(Activity activity) { + } } diff --git a/Clover/app/src/main/java/org/floens/chan/chan/ChanHelper.java b/Clover/app/src/main/java/org/floens/chan/chan/ChanHelper.java deleted file mode 100644 index 716ac2c3..00000000 --- a/Clover/app/src/main/java/org/floens/chan/chan/ChanHelper.java +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Clover - 4chan browser https://github.com/Floens/Clover/ - * Copyright (C) 2014 Floens - * - * 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. - * - * This program 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 this program. If not, see . - */ -package org.floens.chan.chan; - -import android.net.Uri; - -import org.floens.chan.core.database.DatabaseLoadableManager; -import org.floens.chan.core.database.DatabaseManager; -import org.floens.chan.core.model.orm.Board; -import org.floens.chan.core.model.orm.Loadable; -import org.floens.chan.core.site.Site; -import org.floens.chan.core.site.Sites; - -import java.util.List; - -import static org.floens.chan.Chan.getGraph; - -public class ChanHelper { - public static Loadable getLoadableFromStartUri(Uri uri) { - Loadable loadable = null; - - List parts = uri.getPathSegments(); - - // TODO(multi-site) get correct site - Site site = Sites.defaultSite(); - - if (parts.size() > 0) { - String rawBoard = parts.get(0); - DatabaseManager databaseManager = getGraph().get(DatabaseManager.class); - DatabaseLoadableManager loadableManager = databaseManager.getDatabaseLoadableManager(); - Board board = site.board(rawBoard); - if (board != null) { - if (parts.size() == 1 || (parts.size() == 2 && "catalog".equals(parts.get(1)))) { - // Board mode - loadable = loadableManager.get(Loadable.forCatalog(board)); - } else if (parts.size() >= 3) { - // Thread mode - int no = -1; - - try { - no = Integer.parseInt(parts.get(2)); - } catch (NumberFormatException ignored) { - } - - int post = -1; - String fragment = uri.getFragment(); - if (fragment != null) { - int index = fragment.indexOf("p"); - if (index >= 0) { - try { - post = Integer.parseInt(fragment.substring(index + 1)); - } catch (NumberFormatException ignored) { - } - } - } - - if (no >= 0) { - loadable = loadableManager.get(Loadable.forThread(site, board, no)); - if (post >= 0) { - loadable.markedNo = post; - } - } - } - } - } - - return loadable; - } -} diff --git a/Clover/app/src/main/java/org/floens/chan/core/database/LoadableProvider.java b/Clover/app/src/main/java/org/floens/chan/core/database/LoadableProvider.java new file mode 100644 index 00000000..d98fd0bf --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/database/LoadableProvider.java @@ -0,0 +1,35 @@ +/* + * Clover - 4chan browser https://github.com/Floens/Clover/ + * Copyright (C) 2014 Floens + * + * 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. + * + * This program 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 this program. If not, see . + */ +package org.floens.chan.core.database; + +import org.floens.chan.core.model.orm.Loadable; + +import javax.inject.Inject; + +public class LoadableProvider { + private DatabaseManager databaseManager; + + @Inject + public LoadableProvider(DatabaseManager databaseManager) { + this.databaseManager = databaseManager; + } + + public Loadable get(Loadable definition) { + return databaseManager.getDatabaseLoadableManager().get(definition); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java b/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java index 9f76e928..7d77283b 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java +++ b/Clover/app/src/main/java/org/floens/chan/core/di/AppModule.java @@ -9,6 +9,7 @@ import org.floens.chan.ChanApplication; import org.floens.chan.chan.ChanLoader; import org.floens.chan.core.cache.FileCache; import org.floens.chan.core.database.DatabaseManager; +import org.floens.chan.core.database.LoadableProvider; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.manager.FilterEngine; import org.floens.chan.core.manager.ReplyManager; @@ -61,6 +62,7 @@ import dagger.Provides; ImageLoader.class, FileCache.class, HttpCallManager.class, + LoadableProvider.class, ChanApplication.class, MainSettingsController.class, 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 70e4db7a..b1b07a03 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 @@ -188,12 +188,8 @@ public class ChanSettings { developer = new BooleanSetting(p, "preference_developer", false); saveLocation = new StringSetting(p, "preference_image_save_location", Environment.getExternalStorageDirectory() + File.separator + "Clover"); - saveLocation.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, String value) { - EventBus.getDefault().post(new SettingChanged<>(saveLocation)); - } - }); + saveLocation.addCallback((setting, value) -> + EventBus.getDefault().post(new SettingChanged<>(saveLocation))); saveOriginalFilename = new BooleanSetting(p, "preference_image_save_original", false); shareUrl = new BooleanSetting(p, "preference_image_share_url", false); networkHttps = new BooleanSetting(p, "preference_network_https", true); @@ -209,26 +205,18 @@ public class ChanSettings { volumeKeysScrolling = new BooleanSetting(p, "preference_volume_key_scrolling", false); postFullDate = new BooleanSetting(p, "preference_post_full_date", false); postFileInfo = new BooleanSetting(p, "preference_post_file_info", true); - postFilename = new BooleanSetting(p, "preference_post_filename", false); + postFilename = new BooleanSetting(p, "preference_post_filename", true); neverHideToolbar = new BooleanSetting(p, "preference_never_hide_toolbar", false); controllerSwipeable = new BooleanSetting(p, "preference_controller_swipeable", true); saveBoardFolder = new BooleanSetting(p, "preference_save_subboard", false); watchEnabled = new BooleanSetting(p, "preference_watch_enabled", false); - watchEnabled.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, Boolean value) { - EventBus.getDefault().post(new SettingChanged<>(watchEnabled)); - } - }); + watchEnabled.addCallback((setting, value) -> + EventBus.getDefault().post(new SettingChanged<>(watchEnabled))); watchCountdown = new BooleanSetting(p, "preference_watch_countdown", false); watchBackground = new BooleanSetting(p, "preference_watch_background_enabled", false); - watchBackground.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, Boolean value) { - EventBus.getDefault().post(new SettingChanged<>(watchBackground)); - } - }); + watchBackground.addCallback((setting, value) -> + EventBus.getDefault().post(new SettingChanged<>(watchBackground))); 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"); @@ -240,26 +228,12 @@ public class ChanSettings { previousVersion = new IntegerSetting(p, "preference_previous_version", 0); proxyEnabled = new BooleanSetting(p, "preference_proxy_enabled", false); - proxyEnabled.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, Boolean value) { - loadProxy(); - } - }); proxyAddress = new StringSetting(p, "preference_proxy_address", ""); - proxyAddress.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, String value) { - loadProxy(); - } - }); proxyPort = new IntegerSetting(p, "preference_proxy_port", 80); - proxyPort.addCallback(new Setting.SettingCallback() { - @Override - public void onValueChange(Setting setting, Integer value) { - loadProxy(); - } - }); + + proxyEnabled.addCallback((setting, value) -> loadProxy()); + proxyAddress.addCallback((setting, value) -> loadProxy()); + proxyPort.addCallback((setting, value) -> loadProxy()); loadProxy(); settingsOpenCounter = new CounterSetting(p, "counter_settings_open"); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Resolvable.java b/Clover/app/src/main/java/org/floens/chan/core/site/Resolvable.java index 6fdf0554..9ca282b6 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/Resolvable.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Resolvable.java @@ -8,7 +8,7 @@ public interface Resolvable { FULL_MATCH } - ResolveResult resolve(String value); + ResolveResult matchesName(String value); Class getSiteClass(); } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java index 7e7e9682..96b6a31c 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/Site.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Site.java @@ -33,6 +33,8 @@ import org.floens.chan.core.site.http.LoginResponse; import org.floens.chan.core.site.http.Reply; import org.floens.chan.core.site.http.ReplyResponse; +import okhttp3.HttpUrl; + public interface Site { enum Feature { /** @@ -129,6 +131,8 @@ public interface Site { SiteIcon icon(); + Loadable respondsTo(HttpUrl url); + boolean feature(Feature feature); boolean boardFeature(BoardFeature boardFeature, Board board); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteBase.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteBase.java index 5477ef27..d88d566e 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteBase.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteBase.java @@ -20,6 +20,7 @@ package org.floens.chan.core.site; import com.android.volley.RequestQueue; +import org.floens.chan.core.database.LoadableProvider; import org.floens.chan.core.manager.BoardManager; import org.floens.chan.core.model.json.site.SiteConfig; import org.floens.chan.core.model.json.site.SiteUserSettings; @@ -40,6 +41,7 @@ public abstract class SiteBase implements Site { protected HttpCallManager httpCallManager; protected RequestQueue requestQueue; protected BoardManager boardManager; + protected LoadableProvider loadableProvider; @Override public void initialize(int id, SiteConfig config, SiteUserSettings userSettings) { @@ -55,6 +57,7 @@ public abstract class SiteBase implements Site { httpCallManager = graph.get(HttpCallManager.class); requestQueue = graph.get(RequestQueue.class); boardManager = graph.get(BoardManager.class); + loadableProvider = graph.get(LoadableProvider.class); if (boardsType() == BoardsType.DYNAMIC) { boards(boards -> boardManager.createAll(boards.boards)); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java index 13b6c4fd..959aa59d 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteManager.java @@ -47,7 +47,7 @@ public class SiteManager { } public void addSite(String url, SiteAddCallback callback) { - SiteResolver.SiteResolverResult resolve = resolver.resolve(url); + SiteResolver.SiteResolverResult resolve = resolver.resolveSiteForUrl(url); Class siteClass; if (resolve.match == SiteResolver.SiteResolverResult.Match.BUILTIN) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteResolver.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteResolver.java index ffbd6b9e..f0ad4ed7 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteResolver.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteResolver.java @@ -18,35 +18,33 @@ package org.floens.chan.core.site; +import android.support.annotation.Nullable; + +import org.floens.chan.core.database.LoadableProvider; +import org.floens.chan.core.model.orm.Loadable; + import java.util.List; import javax.inject.Inject; import okhttp3.HttpUrl; -class SiteResolver { +public class SiteResolver { + private LoadableProvider loadableProvider; + @Inject - public SiteResolver() { + public SiteResolver(LoadableProvider loadableProvider) { + this.loadableProvider = loadableProvider; } - SiteResolverResult resolve(String url) { + SiteResolverResult resolveSiteForUrl(String url) { List resolvables = Sites.RESOLVABLES; - HttpUrl httpUrl = HttpUrl.parse(url); - - if (httpUrl == null) { - httpUrl = HttpUrl.parse("https://" + url); - } - - if (httpUrl != null) { - if (httpUrl.host().indexOf('.') < 0) { - httpUrl = null; - } - } + HttpUrl httpUrl = sanitizeUrl(url); if (httpUrl == null) { for (Resolvable resolvable : resolvables) { - if (resolvable.resolve(url) == Resolvable.ResolveResult.NAME_MATCH) { + if (resolvable.matchesName(url) == Resolvable.ResolveResult.NAME_MATCH) { return new SiteResolverResult(SiteResolverResult.Match.BUILTIN, resolvable.getSiteClass(), null); } } @@ -59,7 +57,7 @@ class SiteResolver { } for (Resolvable resolvable : resolvables) { - if (resolvable.resolve(httpUrl.toString()) == Resolvable.ResolveResult.FULL_MATCH) { + if (resolvable.matchesName(httpUrl.toString()) == Resolvable.ResolveResult.FULL_MATCH) { return new SiteResolverResult(SiteResolverResult.Match.BUILTIN, resolvable.getSiteClass(), null); } } @@ -67,6 +65,40 @@ class SiteResolver { return new SiteResolverResult(SiteResolverResult.Match.EXTERNAL, null, httpUrl); } + public LoadableResult resolveLoadableForUrl(String url) { + final HttpUrl httpUrl = sanitizeUrl(url); + + if (httpUrl == null) { + return null; + } + + for (Site site : Sites.allSites()) { + Loadable resolved = site.respondsTo(httpUrl); + + if (resolved != null) { + return new LoadableResult(resolved); + } + } + + return null; + } + + @Nullable + private HttpUrl sanitizeUrl(String url) { + HttpUrl httpUrl = HttpUrl.parse(url); + + if (httpUrl == null) { + httpUrl = HttpUrl.parse("https://" + url); + } + + if (httpUrl != null) { + if (httpUrl.host().indexOf('.') < 0) { + httpUrl = null; + } + } + return httpUrl; + } + static class SiteResolverResult { enum Match { NONE, @@ -84,4 +116,12 @@ class SiteResolver { this.externalResult = externalResult; } } + + public static class LoadableResult { + public final Loadable loadable; + + public LoadableResult(Loadable loadable) { + this.loadable = loadable; + } + } } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java index 2fb8a005..10a6ecb3 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/http/HttpCallManager.java @@ -20,6 +20,7 @@ package org.floens.chan.core.site.http; import org.floens.chan.core.di.UserAgentProvider; import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.SiteRequestModifier; import java.util.concurrent.TimeUnit; @@ -58,7 +59,10 @@ public class HttpCallManager { httpCall.setup(requestBuilder); if (site != null) { - site.requestModifier().modifyHttpCall(httpCall, requestBuilder); + final SiteRequestModifier siteRequestModifier = site.requestModifier(); + if (siteRequestModifier != null) { + siteRequestModifier.modifyHttpCall(httpCall, requestBuilder); + } } requestBuilder.header("User-Agent", userAgentProvider.getUserAgent()); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java index da990118..e2af5592 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4.java @@ -59,13 +59,14 @@ import okhttp3.Request; public class Chan4 extends SiteBase { public static final Resolvable RESOLVABLE = new Resolvable() { @Override - public ResolveResult resolve(String value) { - if (value.equals("4chan")) { - return ResolveResult.NAME_MATCH; - } else if (value.equals("https://4chan.org/")) { - return ResolveResult.FULL_MATCH; - } else { - return ResolveResult.NO; + public ResolveResult matchesName(String value) { + switch (value) { + case "4chan": + return ResolveResult.NAME_MATCH; + case "https://4chan.org/": + return ResolveResult.FULL_MATCH; + default: + return ResolveResult.NO; } } @@ -270,6 +271,59 @@ public class Chan4 extends SiteBase { return SiteIcon.fromAssets("icons/4chan.png"); } + @Override + public Loadable respondsTo(HttpUrl url) { + boolean responds = url.host().equals("4chan.org") || + url.host().equals("www.4chan.org") || + url.host().equals("boards.4chan.org"); + + if (responds) { + List parts = url.pathSegments(); + + if (!parts.isEmpty()) { + String boardCode = parts.get(0); + Board board = board(boardCode); + if (board != null) { + if (parts.size() < 3) { + // Board mode + return loadableProvider.get(Loadable.forCatalog(board)); + } else if (parts.size() >= 3) { + // Thread mode + int no = -1; + try { + no = Integer.parseInt(parts.get(2)); + } catch (NumberFormatException ignored) { + } + + int post = -1; + String fragment = url.fragment(); + if (fragment != null) { + int index = fragment.indexOf("p"); + if (index >= 0) { + try { + post = Integer.parseInt(fragment.substring(index + 1)); + } catch (NumberFormatException ignored) { + } + } + } + + if (no >= 0) { + Loadable loadable = loadableProvider.get( + Loadable.forThread(this, board, no)); + if (post >= 0) { + loadable.markedNo = post; + } + + return loadable; + } + } + } + } + } + + return null; + } + @Override public boolean feature(Feature feature) { switch (feature) { diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java index b7bfc9f0..9115d991 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan8/Chan8.java @@ -42,6 +42,7 @@ import org.floens.chan.core.site.http.LoginRequest; import org.floens.chan.core.site.http.Reply; import org.floens.chan.utils.Logger; +import java.util.List; import java.util.Locale; import java.util.Map; @@ -55,13 +56,14 @@ public class Chan8 extends SiteBase { public static final Resolvable RESOLVABLE = new Resolvable() { @Override - public ResolveResult resolve(String value) { - if (value.equals("8chan")) { - return ResolveResult.NAME_MATCH; - } else if (value.equals("https://8ch.net/")) { - return ResolveResult.FULL_MATCH; - } else { - return ResolveResult.NO; + public ResolveResult matchesName(String value) { + switch (value) { + case "8chan": + return ResolveResult.NAME_MATCH; + case "https://8ch.net/": + return ResolveResult.FULL_MATCH; + default: + return ResolveResult.NO; } } @@ -184,6 +186,54 @@ public class Chan8 extends SiteBase { return SiteIcon.fromAssets("icons/8chan.png"); } + @Override + public Loadable respondsTo(HttpUrl url) { + boolean responds = url.host().equals("8ch.net"); + + if (responds) { + List parts = url.pathSegments(); + + if (!parts.isEmpty()) { + String boardCode = parts.get(0); + Board board = board(boardCode); + if (board != null) { + if (parts.size() < 3) { + // Board mode + return loadableProvider.get(Loadable.forCatalog(board)); + } else if (parts.size() >= 3) { + // Thread mode + int no = -1; + try { + no = Integer.parseInt(parts.get(2).replace(".html", "")); + } catch (NumberFormatException ignored) { + } + + int post = -1; + String fragment = url.fragment(); + if (fragment != null) { + try { + post = Integer.parseInt(fragment); + } catch (NumberFormatException ignored) { + } + } + + if (no >= 0) { + Loadable loadable = loadableProvider.get( + Loadable.forThread(this, board, no)); + if (post >= 0) { + loadable.markedNo = post; + } + + return loadable; + } + } + } + } + } + + return null; + } + @Override public boolean feature(Feature feature) { switch (feature) { 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 ce9af43f..10fa7253 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 @@ -20,6 +20,7 @@ package org.floens.chan.ui.activity; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.net.Uri; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; import android.nfc.NfcEvent; @@ -32,7 +33,6 @@ import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.ViewGroup; -import org.floens.chan.Chan; import org.floens.chan.R; import org.floens.chan.controller.Controller; import org.floens.chan.controller.NavigationController; @@ -45,6 +45,7 @@ import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.model.orm.Pin; import org.floens.chan.core.settings.ChanSettings; import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.SiteResolver; import org.floens.chan.core.site.Sites; import org.floens.chan.ui.controller.BrowseController; import org.floens.chan.ui.controller.DoubleNavigationController; @@ -94,6 +95,9 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat @Inject WatchManager watchManager; + @Inject + SiteResolver siteResolver; + @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -132,54 +136,16 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat } private void setupFromStateOrFreshLaunch(Bundle savedInstanceState) { - boolean loadDefault = true; - /*if (savedInstanceState != null) { - // Restore the activity state from the previously saved state. - ChanState chanState = savedInstanceState.getParcelable(STATE_KEY); - if (chanState == null) { - Logger.w(TAG, "savedInstanceState was not null, but no ChanState was found!"); - } else { - Pair boardThreadPair = resolveChanState(chanState); - - if (boardThreadPair != null && boardThreadPair.first != null) { - loadDefault = false; - - browseController.setBoard(boardThreadPair.first.board); - - if (boardThreadPair.second != null) { - browseController.showThread(boardThreadPair.second); - } - } - } + boolean handled; + if (savedInstanceState != null) { + handled = restoreFromSavedState(savedInstanceState); } else { - final Uri data = getIntent().getData(); - // Start from an url launch. - if (data != null) { - Loadable fromUri = ChanHelper.getLoadableFromStartUri(data); - if (fromUri != null) { - loadDefault = false; - browseController.setBoard(fromUri.board); - - if (fromUri.isThreadMode()) { - browseController.showThread(fromUri, false); - } - } else { - new AlertDialog.Builder(this) - .setMessage(R.string.open_link_not_matched) - .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - AndroidUtils.openLink(data.toString()); - } - }) - .show(); - } - } - }*/ + handled = restoreFromUrl(); + } // Not from a state or from an url, launch the setup controller if no boards are setup up yet, // otherwise load the default saved board. - if (loadDefault) { + if (!handled) { /*if (boardManager.getSavedBoards().isEmpty()) { setupWithNoBoards(); } else { @@ -189,6 +155,60 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat } } + private boolean restoreFromUrl() { + boolean handled = false; + + final Uri data = getIntent().getData(); + // Start from an url launch. + if (data != null) { + final SiteResolver.LoadableResult loadableResult = + siteResolver.resolveLoadableForUrl(data.toString()); + + if (loadableResult != null) { + handled = true; + + Loadable loadable = loadableResult.loadable; + browseController.setBoard(loadable.board); + + if (loadable.isThreadMode()) { + browseController.showThread(loadable, false); + } + } else { + new AlertDialog.Builder(this) + .setMessage(R.string.open_link_not_matched) + .setPositiveButton(R.string.ok, (dialog, which) -> + AndroidUtils.openLink(data.toString())) + .show(); + } + } + + return handled; + } + + private boolean restoreFromSavedState(Bundle savedInstanceState) { + boolean handled = true; + + // Restore the activity state from the previously saved state. + ChanState chanState = savedInstanceState.getParcelable(STATE_KEY); + if (chanState == null) { + Logger.w(TAG, "savedInstanceState was not null, but no ChanState was found!"); + } else { + Pair boardThreadPair = resolveChanState(chanState); + + if (boardThreadPair != null && boardThreadPair.first != null) { + handled = true; + + browseController.setBoard(boardThreadPair.first.board); + + if (boardThreadPair.second != null) { + browseController.showThread(boardThreadPair.second); + } + } + } + + return handled; + } + private void setupWithNoBoards() { mainNavigationController.presentController(new SetupController(this), false); } @@ -197,17 +217,19 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat DatabaseLoadableManager loadableManager = databaseManager.getDatabaseLoadableManager(); Site site = Sites.forId(state.board.siteId); - Board board = site.board(state.board.boardCode); - if (board != null) { - state.board.site = site; - state.board.board = board; - state.thread.site = site; - state.thread.board = board; - - Loadable boardLoadable = loadableManager.get(state.board); - Loadable threadLoadable = loadableManager.get(state.thread); - - return new Pair<>(boardLoadable, threadLoadable.mode == Loadable.Mode.THREAD ? threadLoadable : null); + if (site != null) { + Board board = site.board(state.board.boardCode); + if (board != null) { + state.board.site = site; + state.board.board = board; + state.thread.site = site; + state.thread.board = board; + + Loadable boardLoadable = loadableManager.get(state.board); + Loadable threadLoadable = loadableManager.get(state.thread); + + return new Pair<>(boardLoadable, threadLoadable.mode == Loadable.Mode.THREAD ? threadLoadable : null); + } } return null; @@ -431,20 +453,6 @@ public class StartActivity extends AppCompatActivity implements NfcAdapter.Creat stack.clear(); } - @Override - protected void onStart() { - super.onStart(); - - Chan.getInstance().activityEnteredForeground(); - } - - @Override - protected void onStop() { - super.onStop(); - - Chan.getInstance().activityEnteredBackground(); - } - @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data);