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 extends Site> 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 extends Site> 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);