diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/BrowsePresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/BrowsePresenter.java index ef2801957f..922797b0da 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/BrowsePresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/BrowsePresenter.java @@ -31,7 +31,6 @@ public class BrowsePresenter implements Observer { private final DatabaseManager databaseManager; - private final BoardManager boardManager; private Callback callback; private boolean hadBoards = false; @@ -42,7 +41,6 @@ public class BrowsePresenter implements Observer { @Inject public BrowsePresenter(DatabaseManager databaseManager, BoardManager boardManager) { this.databaseManager = databaseManager; - this.boardManager = boardManager; savedBoardsObservable = boardManager.getSavedBoardsObservable(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java index 53b0183889..6bfd04cad8 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java +++ b/Clover/app/src/main/java/org/floens/chan/core/presenter/ThreadPresenter.java @@ -35,8 +35,11 @@ import org.floens.chan.core.model.orm.SavedReply; import org.floens.chan.core.pool.ChanLoaderFactory; import org.floens.chan.core.settings.ChanSettings; +import org.floens.chan.core.site.Page; +import org.floens.chan.core.site.Pages; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.SiteActions; +import org.floens.chan.core.site.ThreadTime; import org.floens.chan.core.site.http.DeleteRequest; import org.floens.chan.core.site.http.DeleteResponse; import org.floens.chan.core.site.http.HttpCall; @@ -623,6 +626,22 @@ public ChanThread getChanThread() { return chanLoader == null ? null : chanLoader.getThread(); } + public Page getPage(Post op) { + Pages pages = chanLoader.getPages(); + if(pages == null) { + return null; + } else { + for (Page page : pages.pages) { + for (ThreadTime threadTime : page.threads) { + if (op.no == threadTime.no) { + return page; + } + } + } + } + return null; + } + @Override public void onListStatusClicked() { chanLoader.requestMoreDataAndResetTimer(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Boards.java b/Clover/app/src/main/java/org/floens/chan/core/site/Boards.java index db0f1b0212..bfe4ec9137 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/Boards.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Boards.java @@ -1,3 +1,20 @@ +/* + * 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.site; import org.floens.chan.core.model.orm.Board; diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Page.java b/Clover/app/src/main/java/org/floens/chan/core/site/Page.java new file mode 100644 index 0000000000..88f0a02224 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Page.java @@ -0,0 +1,30 @@ +/* + * 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.site; + +import java.util.List; + +public class Page { + public final int page; + public final List threads; + + public Page(int page, List threads) { + this.page = page; + this.threads = threads; + } +} \ No newline at end of file diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/Pages.java b/Clover/app/src/main/java/org/floens/chan/core/site/Pages.java new file mode 100644 index 0000000000..47c994ee80 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/Pages.java @@ -0,0 +1,28 @@ +/* + * 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.site; + +import java.util.List; + +public class Pages { + public final List pages; + + public Pages(List pages) { + this.pages = pages; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteActions.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteActions.java index a740ed0530..c3f3678e94 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteActions.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteActions.java @@ -29,11 +29,16 @@ public interface SiteActions { void boards(BoardsListener boardsListener); + void pages(Board board, PagesListener pagesListener); interface BoardsListener { void onBoardsReceived(Boards boards); } + interface PagesListener { + void onPagesReceived(Pages pages); + } + void post(Reply reply, PostListener postListener); interface PostListener { diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java b/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java index a210cc4cdd..c2b495b3e9 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/SiteEndpoints.java @@ -43,6 +43,8 @@ public interface SiteEndpoints { HttpUrl boards(); + HttpUrl pages(Board board); + HttpUrl archive(Board board); HttpUrl reply(Loadable thread); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/ThreadTime.java b/Clover/app/src/main/java/org/floens/chan/core/site/ThreadTime.java new file mode 100644 index 0000000000..06d3961d44 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/ThreadTime.java @@ -0,0 +1,28 @@ +/* + * 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.site; + +public class ThreadTime { + public final int no; + public final long modified; + + public ThreadTime(int no, long modified) { + this.no = no; + this.modified = modified; + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java index c3357473ae..bdb00c9405 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/CommonSite.java @@ -29,6 +29,7 @@ import org.floens.chan.core.model.orm.Loadable; import org.floens.chan.core.settings.json.JsonSettings; import org.floens.chan.core.site.Boards; +import org.floens.chan.core.site.Pages; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.SiteActions; import org.floens.chan.core.site.SiteAuthentication; @@ -527,6 +528,10 @@ public void boards(BoardsListener boardsListener) { } } + @Override + public void pages(Board board, PagesListener pagesListener) { + } + @Override public void archive(Board board, ArchiveListener archiveListener) { } diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanEndpoints.java b/Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanEndpoints.java index 07aeeb2f83..1c8f844b26 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanEndpoints.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/common/vichan/VichanEndpoints.java @@ -68,6 +68,11 @@ public HttpUrl icon(Post.Builder post, String icon, Map arg) { return stat.url(); } + @Override + public HttpUrl pages(Board board) { + return root.builder().s(board.code).s("threads.json").url(); + } + @Override public HttpUrl reply(Loadable loadable) { return sys.builder().s("post.php").url(); diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/loader/ChanThreadLoader.java b/Clover/app/src/main/java/org/floens/chan/core/site/loader/ChanThreadLoader.java index a197639d42..f502d9aeb9 100644 --- a/Clover/app/src/main/java/org/floens/chan/core/site/loader/ChanThreadLoader.java +++ b/Clover/app/src/main/java/org/floens/chan/core/site/loader/ChanThreadLoader.java @@ -27,6 +27,9 @@ import org.floens.chan.core.model.ChanThread; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.orm.Loadable; +import org.floens.chan.core.site.Page; +import org.floens.chan.core.site.Pages; +import org.floens.chan.core.site.SiteActions; import org.floens.chan.core.site.parser.ChanReader; import org.floens.chan.core.site.parser.ChanReaderRequest; import org.floens.chan.ui.helper.PostHelper; @@ -52,7 +55,7 @@ * {@link ChanLoaderCallback}. *

For threads timers can be started with {@link #setTimer()} to do a request later. */ -public class ChanThreadLoader implements Response.ErrorListener, Response.Listener { +public class ChanThreadLoader implements Response.ErrorListener, Response.Listener, SiteActions.PagesListener { private static final String TAG = "ChanThreadLoader"; private static final ScheduledExecutorService executor = Executors.newSingleThreadScheduledExecutor(); @@ -72,6 +75,9 @@ public class ChanThreadLoader implements Response.ErrorListener, Response.Listen private long lastLoadTime; private ScheduledFuture pendingFuture; + private boolean requestedPages = false; + private Pages pages; + /** * Do not call this constructor yourself, obtain ChanLoaders through {@link org.floens.chan.core.pool.ChanLoaderFactory} */ @@ -245,6 +251,11 @@ private ChanLoaderRequest getData() { volleyRequestQueue.add(request.getVolleyRequest()); + if(!requestedPages) { + loadable.site.actions().pages(loadable.board, this); + requestedPages = true; + } + return request; } @@ -340,6 +351,16 @@ private void clearPendingRunnable() { } } + @Override + public void onPagesReceived(Pages pages) { + this.pages = pages; + requestedPages = false; + } + + public Pages getPages() { + return pages; + } + public interface ChanLoaderCallback { void onChanLoaderData(ChanThread result); 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 fc4a3ed349..288951edec 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 @@ -30,6 +30,8 @@ import org.floens.chan.core.settings.SharedPreferencesSettingProvider; import org.floens.chan.core.settings.StringSetting; import org.floens.chan.core.site.Boards; +import org.floens.chan.core.site.Page; +import org.floens.chan.core.site.Pages; import org.floens.chan.core.site.Site; import org.floens.chan.core.site.SiteActions; import org.floens.chan.core.site.SiteAuthentication; @@ -253,6 +255,14 @@ public HttpUrl boards() { .build(); } + @Override + public HttpUrl pages(Board board) { + return a.newBuilder() + .addPathSegment(board.code) + .addPathSegment("threads.json") + .build(); + } + @Override public HttpUrl archive(Board board) { return b.newBuilder() @@ -345,6 +355,16 @@ public void boards(final BoardsListener listener) { })); } + @Override + public void pages(Board board, PagesListener listener) { + requestQueue.add(new Chan4PagesRequest(Chan4.this, board, response -> { + listener.onPagesReceived(new Pages(response)); + }, (error) -> { + Logger.e(TAG, "Failed to get threads for board " + board.code); + listener.onPagesReceived(new Pages(new ArrayList())); + })); + } + @Override public void archive(Board board, ArchiveListener archiveListener) { requestQueue.add(new Chan4ArchiveRequest(Chan4.this, board, diff --git a/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PagesRequest.java b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PagesRequest.java new file mode 100644 index 0000000000..8b7bfb3745 --- /dev/null +++ b/Clover/app/src/main/java/org/floens/chan/core/site/sites/chan4/Chan4PagesRequest.java @@ -0,0 +1,104 @@ +/* + * 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.site.sites.chan4; + +import android.util.JsonReader; + +import com.android.volley.Response.ErrorListener; +import com.android.volley.Response.Listener; + +import org.floens.chan.core.model.orm.Board; +import org.floens.chan.core.net.JsonReaderRequest; +import org.floens.chan.core.site.Page; +import org.floens.chan.core.site.Site; +import org.floens.chan.core.site.ThreadTime; + +import java.util.ArrayList; +import java.util.List; + +public class Chan4PagesRequest extends JsonReaderRequest> { + + public Chan4PagesRequest(Site site, Board board, Listener> listener, ErrorListener errorListener) { + super(site.endpoints().pages(board).toString(), listener, errorListener); + } + + @Override + public List readJson(JsonReader reader) throws Exception { + List pages = new ArrayList<>(); + + reader.beginArray(); + while (reader.hasNext()) { + pages.add(readPageEntry(reader)); + } + reader.endArray(); + + return pages; + } + + private Page readPageEntry(JsonReader reader) throws Exception { + int pageNo = -1; + List threadTimes = null; + + reader.beginObject(); + while(reader.hasNext()) { + String nextName = reader.nextName(); + if(nextName.equals("page")) { + pageNo = reader.nextInt(); + } else if (nextName.equals("threads")) { + threadTimes = readThreadTimes(reader); + } else { + reader.skipValue(); + } + } + reader.endObject(); + + return new Page(pageNo, threadTimes); + } + + private List readThreadTimes(JsonReader reader) throws Exception { + List threadTimes = new ArrayList<>(); + + reader.beginArray(); + while(reader.hasNext()) { + threadTimes.add(readThreadTime(reader)); + } + reader.endArray(); + + return threadTimes; + } + + private ThreadTime readThreadTime(JsonReader reader) throws Exception { + int no = -1; + long modified = -1; + + reader.beginObject(); + while(reader.hasNext()) { + String nextName = reader.nextName(); + if (nextName.equals("no")) { + no = reader.nextInt(); + } else if (nextName.equals("last_modified")) { + modified = reader.nextLong(); + } else { + reader.skipValue(); + } + } + reader.endObject(); + + return new ThreadTime(no, modified); + } +} diff --git a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java index c681865bb5..c8915849c8 100644 --- a/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java +++ b/Clover/app/src/main/java/org/floens/chan/ui/cell/ThreadStatusCell.java @@ -33,6 +33,7 @@ import org.floens.chan.core.model.ChanThread; import org.floens.chan.core.model.Post; import org.floens.chan.core.model.orm.Board; +import org.floens.chan.core.site.Page; import static org.floens.chan.utils.AndroidUtils.ROBOTO_MEDIUM; @@ -147,6 +148,18 @@ public boolean update() { String ips = op.getUniqueIps() + "P"; finalText = TextUtils.concat(finalText, " / " + ips); } + + Page p = callback.getPage(op); + SpannableString page; + if(p != null) { + page = new SpannableString(String.valueOf(p.page)); + if (p.page > board.pages) { + page.setSpan(new StyleSpan(Typeface.ITALIC), 0, page.length(), 0); + } + } else { + page = new SpannableString("?"); + } + finalText = TextUtils.concat(finalText, " / " + getContext().getString(R.string.thread_page_no) + " " + page); } } @@ -206,6 +219,8 @@ public interface Callback { ChanThread getChanThread(); + Page getPage(Post op); + void onListStatusClicked(); } } diff --git a/Clover/app/src/main/res/values/strings.xml b/Clover/app/src/main/res/values/strings.xml index d60021d41e..2cb5e64453 100644 --- a/Clover/app/src/main/res/values/strings.xml +++ b/Clover/app/src/main/res/values/strings.xml @@ -149,6 +149,7 @@ Re-enable this permission in the app settings if you permanently disabled it."Retry Archived Closed + Page %d new post %d new posts