Improve preference, use leakcanary, start GalleryDetailScene
This commit is contained in:
1 parent
9b6815c60c
commit
2130e7a8dd
42 files changed
+1289
-386
No files matched your search
@@ -20,11 +20,12 @@ import android.content.Context;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.imagepipeline.backends.okhttp.OkHttpImagePipelineConfigFactory;
|
||||
import com.facebook.imagepipeline.core.ImagePipelineConfig;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
import com.hippo.ehviewer.fresco.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.network.EhOkHttpClient;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.scene.SceneApplication;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.vectorold.content.VectorContext;
|
||||
|
||||
public class EhApplication extends SceneApplication {
|
||||
|
||||
@@ -34,6 +35,7 @@ public class EhApplication extends SceneApplication {
|
||||
|
||||
ImagePipelineConfig config = OkHttpImagePipelineConfigFactory
|
||||
.newBuilder(this, EhOkHttpClient.getInstance())
|
||||
.setCacheKeyFactory(EhCacheKeyFactory.getInstance())
|
||||
.build();
|
||||
Fresco.initialize(this, config);
|
||||
Config.initialize(this);
|
||||
|
||||
@@ -18,6 +18,7 @@ package com.hippo.ehviewer.client;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Process;
|
||||
|
||||
import com.hippo.ehviewer.data.GalleryDetail;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.network.EhOkHttpClient;
|
||||
import com.hippo.network.ResponseCodeException;
|
||||
@@ -120,6 +121,19 @@ public final class EhClient {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gellary detail url in target source
|
||||
*/
|
||||
public static String getDetailUrl(int source, int gid, String token, int pageIndex) {
|
||||
StringBuilder sb = new StringBuilder(getUrlHeader(source));
|
||||
sb.append("g/").append(gid).append('/').append(token).append('/');
|
||||
if (pageIndex > 0) {
|
||||
sb.append("?p=").append(pageIndex);
|
||||
}
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public interface SimpleListener {
|
||||
void onFailure(Exception e);
|
||||
}
|
||||
@@ -371,4 +385,84 @@ public final class EhClient {
|
||||
public void signIn(String username, String password, OnSignInListener listener) {
|
||||
doBgJob(new SignInHelper(username, password, listener));
|
||||
}
|
||||
|
||||
private GalleryDetail doGetGalleryDetail(int source, String url) throws Exception {
|
||||
Request request = new Request.Builder()
|
||||
.url(url)
|
||||
.build();
|
||||
Response response = mHttpClient.newCall(request).execute();
|
||||
|
||||
checkResponse(response);
|
||||
|
||||
GalleryDetailParser parser = new GalleryDetailParser();
|
||||
parser.parse(response.body().string(),
|
||||
GalleryDetailParser.REQUEST_DETAIL | GalleryDetailParser.REQUEST_TAG |
|
||||
GalleryDetailParser.REQUEST_PREVIEW_INFO |
|
||||
GalleryDetailParser.REQUEST_COMMENT,
|
||||
source);
|
||||
|
||||
GalleryDetail gd = new GalleryDetail();
|
||||
gd.gid = parser.gid;
|
||||
gd.token = parser.token;
|
||||
gd.thumb = parser.thumb;
|
||||
gd.title = parser.title;
|
||||
gd.titleJpn = parser.titleJpn;
|
||||
gd.category = parser.category;
|
||||
gd.uploader = parser.uploader;
|
||||
gd.torrentCount = parser.torrentCount;
|
||||
gd.torrentUrl = parser.torrentUrl;
|
||||
gd.posted = parser.posted;
|
||||
gd.parent = parser.parent;
|
||||
gd.visible = parser.visible;
|
||||
gd.language = parser.language;
|
||||
gd.size = parser.size;
|
||||
gd.resize = parser.resize;
|
||||
gd.pageCount = parser.pageCount;
|
||||
gd.favoredTimes = parser.favoredTimes;
|
||||
gd.isFavored = parser.isFavored;
|
||||
gd.rating = parser.rating;
|
||||
gd.ratedTimes = parser.ratedTimes;
|
||||
gd.tags = parser.tags;
|
||||
gd.comments = parser.comments;
|
||||
gd.previewPageCount = parser.previewPageCount;
|
||||
|
||||
return gd;
|
||||
}
|
||||
|
||||
public abstract static class OnGetGalleryDetailListener implements SimpleListener {
|
||||
public abstract void onSuccess(GalleryDetail galleryDetail);
|
||||
}
|
||||
|
||||
private final class GetGalleryDetailHelper extends SimpleBgJobHelper {
|
||||
|
||||
private int mSource;
|
||||
private String mUrl;
|
||||
private OnGetGalleryDetailListener mListener;
|
||||
|
||||
private GalleryDetail mGalleryDetail;
|
||||
|
||||
public GetGalleryDetailHelper(int source, String url, OnGetGalleryDetailListener listener) {
|
||||
super(listener);
|
||||
mSource = source;
|
||||
mUrl = url;
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doBgJob() throws Exception {
|
||||
mGalleryDetail = doGetGalleryDetail(mSource, mUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void doSuccessCallback() {
|
||||
mListener.onSuccess(mGalleryDetail);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get gallery detail
|
||||
*/
|
||||
public void getGalleryDetail(int source, String url, OnGetGalleryDetailListener listener) {
|
||||
doBgJob(new GetGalleryDetailHelper(source, url, listener));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
import com.hippo.ehviewer.data.Comment;
|
||||
import com.hippo.ehviewer.data.TagGroup;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.Utils;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
public class GalleryDetailParser {
|
||||
|
||||
private static final String OFFENSIVE_STRING =
|
||||
"<p>(And if you choose to ignore this warning, you lose all rights to complain about it in the future.)</p>";
|
||||
private static final String PINING_STRING =
|
||||
"<p>This gallery is pining for the fjords.</p>";
|
||||
|
||||
public static final int REQUEST_DETAIL = 0x1;
|
||||
public static final int REQUEST_TAG = 0x2;
|
||||
public static final int REQUEST_PREVIEW_INFO = 0x4;
|
||||
public static final int REQUEST_COMMENT = 0x10;
|
||||
|
||||
private static final CommentSort COMMENT_SORTER = new CommentSort();
|
||||
|
||||
public int gid;
|
||||
public String token;
|
||||
public String thumb;
|
||||
public String title;
|
||||
public String titleJpn;
|
||||
public int category;
|
||||
public String uploader;
|
||||
|
||||
public int torrentCount;
|
||||
public String torrentUrl;
|
||||
|
||||
public String posted;
|
||||
public String parent;
|
||||
public String visible;
|
||||
public String language;
|
||||
public String size;
|
||||
public String resize;
|
||||
public int pageCount;
|
||||
public int favoredTimes;
|
||||
public boolean isFavored;
|
||||
public float rating;
|
||||
public int ratedTimes;
|
||||
|
||||
public List<TagGroup> tags;
|
||||
public List<Comment> comments;
|
||||
|
||||
public int previewPageCount;
|
||||
|
||||
private String sortOut(String str) {
|
||||
return Utils.unescapeXml(str).trim();
|
||||
}
|
||||
|
||||
private int sortOutInteger(String str, int defaultValue) {
|
||||
return Utils.parseIntSafely(sortOut(str).replace(",", ""), defaultValue);
|
||||
}
|
||||
|
||||
private void parseTagGroup(TagGroup tagGroup, String body) {
|
||||
Pattern p = Pattern.compile("<div[^<>]+><a[^<>]+>([\\w\\s]+)</a></div>");
|
||||
Matcher m = p.matcher(body);
|
||||
while (m.find()) {
|
||||
tagGroup.addTag(sortOut(m.group(1)));
|
||||
}
|
||||
}
|
||||
|
||||
private void parse(String body, int request) throws EhException {
|
||||
Pattern p;
|
||||
Matcher m;
|
||||
|
||||
if (!body.startsWith("<")) {
|
||||
throw new EhException(body);
|
||||
}
|
||||
|
||||
if (body.contains(OFFENSIVE_STRING)) {
|
||||
throw new OffensiveException();
|
||||
}
|
||||
|
||||
if (body.contains(PINING_STRING)) {
|
||||
throw new PiningException();
|
||||
}
|
||||
|
||||
// TODO I can't remember what's this for
|
||||
p = Pattern.compile("<div class=\"d\">\n<p>([^<]+)</p>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
throw new EhException(m.group(1));
|
||||
}
|
||||
|
||||
if ((request & REQUEST_DETAIL) != 0) {
|
||||
p = Pattern.compile("var gid = (\\d+)" // 1 gid
|
||||
+ ".+?"
|
||||
+ "var token = \"([a-z0-9A]+)\"" // 2 token
|
||||
+ ".+?"
|
||||
+ "<div id=\"gd1\"><img src=\"([^\"]+)\"[^<>]+></div>" // 3 thumb
|
||||
+ "</div>"
|
||||
+ "<div id=\"gd2\">"
|
||||
+ "<h1 id=\"gn\">([^<>]+)</h1>" // 4 title
|
||||
+ "<h1 id=\"gj\">([^<>]*)</h1>" // 5 title_jpn might be empty string
|
||||
+ "</div>"
|
||||
+ ".+?"
|
||||
+ "<a[^<>]*onclick=\"return popUp\\('([^']+)'[^)]+\\)\">Torrent Download \\( (\\d+) \\)</a>" // 6 torrentUrl, 7 torrentCount
|
||||
+ ".+?"
|
||||
+ "<div id=\"gdc\"><a[^<>]+><[^<>]*alt=\"([\\w|\\-]+)\"[^<>]*></a></div>" // 8 category
|
||||
+ "<div id=\"gdn\"><a[^<>]+>([^<>]+)</a>" // 9 uploader
|
||||
+ ".+?"
|
||||
+ "<tr><td[^<>]*>Posted:</td><td[^<>]*>([\\w|\\-|\\s|:]+)</td></tr>" // 10 posted
|
||||
+ "<tr><td[^<>]*>Parent:</td><td[^<>]*>(?:<a[^<>]*>)?([^<>]+)(?:</a>)?</td></tr>" // 11 parent
|
||||
+ "<tr><td[^<>]*>Visible:</td><td[^<>]*>([^<>]+)</td></tr>" // 12 visible
|
||||
+ "<tr><td[^<>]*>Language:</td><td[^<>]*>([^<>]+)(?:<span[^<>]*>[^<>]*</span>)?</td></tr>" // 13 language
|
||||
+ "<tr><td[^<>]*>File Size:</td><td[^<>]*>([^<>]+)(?:<span[^<>]*>([^<>]+)</span>)?</td></tr>" // 14 File size, 15 resize
|
||||
+ "<tr><td[^<>]*>Length:</td><td[^<>]*>([\\d|,]+) pages</td></tr>" // 16 pageCount
|
||||
+ "<tr><td[^<>]*>Favorited:</td><[^<>]*>([^<>]+)</td></tr>" // 17 Favorite times "([\d|,]+) times" or "Once" or "Never"
|
||||
+ ".+?"
|
||||
+ "<td id=\"grt3\"><span id=\"rating_count\">([\\d|,]+)</span></td>" // 18 ratedTimes
|
||||
+ "</tr>"
|
||||
+ "<tr><td[^<>]*>Average: ([^<>]+)</td>" // 19 rating "Average: x.xx" or "Not Yet Rated"
|
||||
+ ".+?"
|
||||
+ "<a id=\"favoritelink\"[^<>]*>(.+?)</a>", Pattern.DOTALL); // 20 isFavored "Favorite Gallery" for favorite
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
gid = sortOutInteger(m.group(1), 0);
|
||||
token = sortOut(m.group(2));
|
||||
thumb = sortOut(m.group(3));
|
||||
title = sortOut(m.group(4));
|
||||
titleJpn = sortOut(m.group(5));
|
||||
torrentUrl = sortOut(m.group(6));
|
||||
torrentCount = sortOutInteger(m.group(7), 0);
|
||||
category = EhUtils.getCategory(sortOut(m.group(8)));
|
||||
uploader = sortOut(m.group(9));
|
||||
posted = sortOut(m.group(10));
|
||||
parent = sortOut(m.group(11));
|
||||
visible = sortOut(m.group(12));
|
||||
language = sortOut(m.group(13));
|
||||
size = sortOut(m.group(14));
|
||||
resize = sortOut(m.group(15));
|
||||
pageCount = sortOutInteger(m.group(16), 0);
|
||||
|
||||
String favTimeStr = sortOut(m.group(17));
|
||||
switch (favTimeStr) {
|
||||
case "Never":
|
||||
favoredTimes = 0;
|
||||
break;
|
||||
case "Once":
|
||||
favoredTimes = 1;
|
||||
break;
|
||||
default:
|
||||
int index = favTimeStr.indexOf(' ');
|
||||
if (index == -1) {
|
||||
favoredTimes = 0;
|
||||
} else {
|
||||
favoredTimes = Utils.parseIntSafely(favTimeStr.substring(0, index), 0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
ratedTimes = sortOutInteger(m.group(18), 0);
|
||||
|
||||
String ratingStr = sortOut(m.group(19));
|
||||
if ("Not Yet Rated".equals(ratingStr)) {
|
||||
rating = Float.NaN;
|
||||
} else {
|
||||
int index = ratingStr.indexOf(' ');
|
||||
if (index == -1 || index >= ratingStr.length()) {
|
||||
rating = 0f;
|
||||
} else {
|
||||
rating = Utils.parseFloatSafely(ratingStr.substring(index + 1), 0f);
|
||||
}
|
||||
}
|
||||
|
||||
isFavored = "Favorite Gallery".equals(sortOut(m.group(20)));
|
||||
} else {
|
||||
throw new ParseException("Parse gallery body error", body);
|
||||
}
|
||||
}
|
||||
|
||||
if ((request & REQUEST_TAG) != 0) {
|
||||
tags = new LinkedList<>();
|
||||
p = Pattern.compile("<tr><td[^<>]+>([\\w\\s]+):</td><td>(?:<div[^<>]+><a[^<>]+>[\\w\\s]+</a></div>)+</td></tr>");
|
||||
m = p.matcher(body);
|
||||
while (m.find()) {
|
||||
TagGroup tagGroup = new TagGroup();
|
||||
tagGroup.groupName = sortOut(m.group(1));
|
||||
parseTagGroup(tagGroup, m.group(0));
|
||||
}
|
||||
}
|
||||
|
||||
// Get preview info
|
||||
if ((request & REQUEST_PREVIEW_INFO) != 0) {
|
||||
p = Pattern.compile("<td[^>]+><a[^>]+>([\\d,]+)</a></td><td[^>]+>(?:<a[^>]+>)?>(?:</a>)?</td>");
|
||||
m = p.matcher(body);
|
||||
if (m.find()) {
|
||||
previewPageCount = sortOutInteger(m.group(1), 0);
|
||||
} else {
|
||||
previewPageCount = 0;
|
||||
}
|
||||
if (previewPageCount <= 0) {
|
||||
throw new ParseException("Parse preview page count error", body);
|
||||
}
|
||||
}
|
||||
|
||||
// Get comment
|
||||
if ((request & REQUEST_COMMENT) != 0) {
|
||||
p = Pattern.compile("<div class=\"c3\">Posted on ([^<>]+) by: <a[^<>]+>([^<>]+)</a>.+?<div class=\"c6\"[^>]*>(.+?)</div><div class=\"c[78]\"");
|
||||
m = p.matcher(body);
|
||||
comments = new LinkedList<>();
|
||||
while (m.find()) {
|
||||
comments.add(new Comment(sortOut(m.group(1)), sortOut(m.group(2)), m.group(3)));
|
||||
}
|
||||
Collections.sort(comments, COMMENT_SORTER);
|
||||
}
|
||||
}
|
||||
|
||||
public void parse(String body, int request, int source) throws Exception {
|
||||
AssertUtils.assertNotNull("Body is null when parse gallery list", body);
|
||||
|
||||
switch (source) {
|
||||
default:
|
||||
case EhClient.SOURCE_G:
|
||||
case EhClient.SOURCE_EX: {
|
||||
parse(body, request);
|
||||
break;
|
||||
}
|
||||
case EhClient.SOURCE_LOFI: {
|
||||
//parseLofi(body, request);
|
||||
//break;
|
||||
throw new EhException("Not support lofi now");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static class CommentSort implements Comparator<Comment> {
|
||||
private int compareNum(String n1, String n2, int median) {
|
||||
int re = 0;
|
||||
for (int i = 0; i < median; i++) {
|
||||
re *= 10;
|
||||
re += n1.charAt(i) - n2.charAt(i);
|
||||
}
|
||||
return re;
|
||||
}
|
||||
|
||||
private int getMonth(String m) {
|
||||
if (m.equals("January"))
|
||||
return 1;
|
||||
else if (m.equals("February"))
|
||||
return 2;
|
||||
else if (m.equals("March"))
|
||||
return 3;
|
||||
else if (m.equals("April"))
|
||||
return 4;
|
||||
else if (m.equals("May"))
|
||||
return 5;
|
||||
else if (m.equals("June"))
|
||||
return 6;
|
||||
else if (m.equals("July"))
|
||||
return 7;
|
||||
else if (m.equals("August"))
|
||||
return 8;
|
||||
else if (m.equals("September"))
|
||||
return 9;
|
||||
else if (m.equals("October"))
|
||||
return 10;
|
||||
else if (m.equals("November"))
|
||||
return 11;
|
||||
else if (m.equals("December"))
|
||||
return 12;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compare(Comment c1, Comment c2) {
|
||||
int re = 0;
|
||||
Pattern p = Pattern.compile("(\\d{2}) (\\w+) (\\d{4}), (\\d{2}):(\\d{2})");
|
||||
Matcher m1 = p.matcher(c1.time);
|
||||
Matcher m2 = p.matcher(c2.time);
|
||||
if (!m1.find() || !m2.find())
|
||||
return 0;
|
||||
// year
|
||||
re += compareNum(m1.group(3), m2.group(3), 4);
|
||||
re <<= 4;
|
||||
// Month
|
||||
re += getMonth(m1.group(2)) - getMonth(m2.group(2));
|
||||
re <<= 5;
|
||||
// Day
|
||||
re += compareNum(m1.group(1), m2.group(1), 2);
|
||||
re <<= 5;
|
||||
// Hour
|
||||
re += compareNum(m1.group(4), m2.group(4), 2);
|
||||
re <<= 6;
|
||||
// Minute
|
||||
re += compareNum(m1.group(5), m2.group(5), 2);
|
||||
return re;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
/**
|
||||
* It is an exception for get offensive tip for g.e-hentai.org
|
||||
*/
|
||||
public class OffensiveException extends EhException {
|
||||
|
||||
public OffensiveException() {
|
||||
super("OFFENSIVE");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
/**
|
||||
* It is an exception for parse error,
|
||||
*/
|
||||
public class ParseException extends EhException {
|
||||
|
||||
private String mBody;
|
||||
|
||||
public ParseException(String detailMessage, String body) {
|
||||
super(detailMessage);
|
||||
mBody = body;
|
||||
}
|
||||
|
||||
public String getBody() {
|
||||
return mBody;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.client;
|
||||
|
||||
public class PiningException extends EhException {
|
||||
|
||||
public PiningException() {
|
||||
super("pining for the fjords");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
|
||||
public class Comment {
|
||||
public String time;
|
||||
public String user;
|
||||
public String comment;
|
||||
|
||||
public Comment (String time, String user, String comment) {
|
||||
this.time = time;
|
||||
this.user = user;
|
||||
this.comment = comment;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class GalleryDetail extends GalleryInfo {
|
||||
|
||||
public String thumb;
|
||||
public String title;
|
||||
public String titleJpn;
|
||||
public int category;
|
||||
public String uploader;
|
||||
|
||||
public int torrentCount;
|
||||
public String torrentUrl;
|
||||
|
||||
public String posted;
|
||||
public String parent;
|
||||
public String visible;
|
||||
public String language;
|
||||
public String size;
|
||||
public String resize;
|
||||
public int pageCount;
|
||||
public int favoredTimes;
|
||||
public boolean isFavored;
|
||||
public float rating;
|
||||
public int ratedTimes;
|
||||
|
||||
public List<TagGroup> tags;
|
||||
public List<Comment> comments;
|
||||
|
||||
public int previewPageCount;
|
||||
|
||||
}
|
||||
@@ -156,10 +156,7 @@ public class GalleryInfo implements Parcelable {
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o instanceof GalleryInfo && ((GalleryInfo) o).gid == gid)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
return o instanceof GalleryInfo && ((GalleryInfo) o).gid == gid;
|
||||
}
|
||||
|
||||
public final void generateSLang() {
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class TagGroup {
|
||||
|
||||
public String groupName;
|
||||
private List<String> mTagList = new ArrayList<>();
|
||||
|
||||
public void addTag(String tag) {
|
||||
mTagList.add(tag);
|
||||
}
|
||||
|
||||
public int getTagCount() {
|
||||
return mTagList.size();
|
||||
}
|
||||
|
||||
public String getTagAt(int position) {
|
||||
return mTagList.get(position);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.fresco;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import com.facebook.cache.common.CacheKey;
|
||||
import com.facebook.cache.common.SimpleCacheKey;
|
||||
import com.facebook.imagepipeline.cache.BitmapMemoryCacheKey;
|
||||
import com.facebook.imagepipeline.cache.CacheKeyFactory;
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
|
||||
public class EhCacheKeyFactory implements CacheKeyFactory {
|
||||
|
||||
private static EhCacheKeyFactory sInstance = null;
|
||||
|
||||
private EhCacheKeyFactory() {
|
||||
}
|
||||
|
||||
public static synchronized EhCacheKeyFactory getInstance() {
|
||||
if(sInstance == null) {
|
||||
sInstance = new EhCacheKeyFactory();
|
||||
}
|
||||
return sInstance;
|
||||
}
|
||||
|
||||
private String getCommonKey(ImageRequest imageRequest) {
|
||||
if (imageRequest instanceof KeyImageRequest) {
|
||||
return ((KeyImageRequest) imageRequest).getKey();
|
||||
} else {
|
||||
return getCacheKeySourceUri(imageRequest.getSourceUri()).toString();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheKey getBitmapCacheKey(ImageRequest imageRequest) {
|
||||
return new BitmapMemoryCacheKey(
|
||||
getCommonKey(imageRequest),
|
||||
imageRequest.getResizeOptions(),
|
||||
imageRequest.getAutoRotateEnabled(),
|
||||
imageRequest.getImageDecodeOptions());
|
||||
}
|
||||
|
||||
@Override
|
||||
public CacheKey getEncodedCacheKey(ImageRequest imageRequest) {
|
||||
return new SimpleCacheKey(getCommonKey(imageRequest));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Uri getCacheKeySourceUri(Uri uri) {
|
||||
return uri;
|
||||
}
|
||||
|
||||
public static String getThumbKey(int gid) {
|
||||
return "thumb:" + gid;
|
||||
}
|
||||
|
||||
public static String getGalleryKey(int gid, int index) {
|
||||
return "gallery:" + gid + "-" + index;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.fresco;
|
||||
|
||||
import com.facebook.imagepipeline.request.ImageRequest;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
|
||||
public class KeyImageRequest extends ImageRequest {
|
||||
|
||||
private String mKey;
|
||||
|
||||
// TODO can't do ImageRequestBuilder.validate()
|
||||
public KeyImageRequest(ImageRequestBuilder builder) {
|
||||
super(builder);
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return mKey;
|
||||
}
|
||||
|
||||
public void setKey(String key) {
|
||||
mKey = key;
|
||||
}
|
||||
}
|
||||
@@ -121,10 +121,6 @@ public final class ContentActivity extends StageActivity
|
||||
lockDrawer();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReplace(Class clazz) {
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
|
||||
@@ -15,8 +15,72 @@
|
||||
|
||||
package com.hippo.ehviewer.ui.scene;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.fresco.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.fresco.KeyImageRequest;
|
||||
import com.hippo.scene.Scene;
|
||||
|
||||
public class GalleryDetailScene extends Scene {
|
||||
|
||||
public static final String KEY_GALLERY_INFO = "gallery_info";
|
||||
|
||||
private SimpleDraweeView mThumb;
|
||||
private TextView mTitle;
|
||||
private TextView mUploader;
|
||||
|
||||
|
||||
@Override
|
||||
protected void onCreate(@Nullable Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.scene_gallery_detail);
|
||||
|
||||
GalleryInfo gi = getAnnouncer().getParcelableExtra(KEY_GALLERY_INFO);
|
||||
|
||||
mThumb = (SimpleDraweeView) findViewById(R.id.thumb);
|
||||
mThumb.bringToFront();
|
||||
ViewGroup a;
|
||||
|
||||
ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(gi.thumb));
|
||||
KeyImageRequest keyImageRequest = new KeyImageRequest(builder);
|
||||
keyImageRequest.setKey(EhCacheKeyFactory.getThumbKey(gi.gid));
|
||||
DraweeController controller = Fresco.newDraweeControllerBuilder()
|
||||
.setImageRequest(keyImageRequest)
|
||||
.setTapToRetryEnabled(true)
|
||||
.setOldController(mThumb.getController()).build();
|
||||
mThumb.setController(controller);
|
||||
|
||||
mTitle = (TextView) findViewById(R.id.title);
|
||||
mTitle.setText(gi.title);
|
||||
|
||||
mUploader = (TextView) findViewById(R.id.uploader);
|
||||
mUploader.setText(gi.uploader);
|
||||
|
||||
|
||||
|
||||
/*
|
||||
int source = Config.getEhSource();
|
||||
EhClient.getInstance().getGalleryDetail(source, EhClient.getDetailUrl(source, gi.gid, gi.token, 0), new EhClient.OnGetGalleryDetailListener() {
|
||||
@Override
|
||||
public void onSuccess(GalleryDetail galleryDetail) {
|
||||
Log.d(galleryDetail.torrentUrl);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFailure(Exception e) {
|
||||
Log.d("", e);
|
||||
}
|
||||
});
|
||||
*/
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,6 @@ import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.ViewTreeObserver;
|
||||
@@ -42,6 +41,7 @@ import android.widget.Toast;
|
||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
||||
import com.facebook.drawee.interfaces.DraweeController;
|
||||
import com.facebook.drawee.view.SimpleDraweeView;
|
||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
||||
import com.hippo.animation.SimpleAnimatorListener;
|
||||
import com.hippo.drawable.AddDeleteDrawable;
|
||||
import com.hippo.effect.ViewTransition;
|
||||
@@ -51,6 +51,8 @@ import com.hippo.ehviewer.client.GalleryListParser;
|
||||
import com.hippo.ehviewer.data.GalleryInfo;
|
||||
import com.hippo.ehviewer.data.ListUrlBuilder;
|
||||
import com.hippo.ehviewer.data.UnsupportedSearchException;
|
||||
import com.hippo.ehviewer.fresco.EhCacheKeyFactory;
|
||||
import com.hippo.ehviewer.fresco.KeyImageRequest;
|
||||
import com.hippo.ehviewer.ui.ContentActivity;
|
||||
import com.hippo.ehviewer.util.Config;
|
||||
import com.hippo.ehviewer.util.EhUtils;
|
||||
@@ -61,8 +63,10 @@ import com.hippo.ehviewer.widget.SearchBar;
|
||||
import com.hippo.ehviewer.widget.SearchDatabase;
|
||||
import com.hippo.ehviewer.widget.SearchLayout;
|
||||
import com.hippo.scene.Announcer;
|
||||
import com.hippo.scene.Curtain;
|
||||
import com.hippo.scene.Scene;
|
||||
import com.hippo.scene.SimpleDialog;
|
||||
import com.hippo.scene.TransitionCurtain;
|
||||
import com.hippo.util.AnimationUtils;
|
||||
import com.hippo.util.AppHandler;
|
||||
import com.hippo.util.AssertUtils;
|
||||
@@ -70,20 +74,21 @@ import com.hippo.util.MathUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.FabLayout;
|
||||
import com.hippo.widget.FloatingActionButton;
|
||||
import com.hippo.widget.recyclerview.EasyRecyclerView;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
// TODO remeber the data in ContentHelper after screen dirction change
|
||||
// TODO Must refresh when change source
|
||||
// TODO disable click action when animating
|
||||
public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
View.OnClickListener, FabLayout.OnCancelListener,
|
||||
SearchLayout.SearhLayoutHelper {
|
||||
SearchLayout.SearhLayoutHelper, EasyRecyclerView.OnItemClickListener {
|
||||
|
||||
public static final String KEY_MODE = "mode";
|
||||
|
||||
private static final String KEY_STATE = "state";
|
||||
private static final String KEY_FAB_STATE = "fab_state";
|
||||
|
||||
public static final int MODE_HOMEPAGE = 0;
|
||||
public static final int MODE_POPULAR = 1;
|
||||
@@ -104,7 +109,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
private SearchBar mSearchBar;
|
||||
private ContentLayout mContentLayout;
|
||||
private RecyclerView mContentRecyclerView;
|
||||
private EasyRecyclerView mContentRecyclerView;
|
||||
private SearchLayout mSearchLayout;
|
||||
private FabLayout mFabLayout;
|
||||
private FloatingActionButton mCornerFab;
|
||||
@@ -133,7 +138,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
@Override
|
||||
public void onCreateCustomView(final SimpleDialog dialog, View view) {
|
||||
int currentPage = mGalleryListHelper.getCurrentPage();
|
||||
int pageSize = mGalleryListHelper.getPageSize();
|
||||
int pageSize = mGalleryListHelper.getPageCount();
|
||||
TextView pageInfo = (TextView) view.findViewById(R.id.go_to_page_info);
|
||||
pageInfo.setText(String.format(mResources.getString(R.string.go_to_page_info),
|
||||
currentPage + 1, pageSize == Integer.MAX_VALUE ?
|
||||
@@ -168,7 +173,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
return false;
|
||||
}
|
||||
targetPage = Integer.parseInt(text);
|
||||
int pageSize = mGalleryListHelper.getPageSize();
|
||||
int pageSize = mGalleryListHelper.getPageCount();
|
||||
if (targetPage <= 0 || (targetPage > pageSize)) {
|
||||
Toast.makeText(mActivity, R.string.go_to_error_invaild,
|
||||
Toast.LENGTH_SHORT).show();
|
||||
@@ -193,13 +198,25 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
return LAUNCH_MODE_SINGLE_TOP;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReplace(@NonNull Scene oldScene) {
|
||||
super.onReplace(oldScene);
|
||||
|
||||
GalleryListScene oldGalleryListScene = (GalleryListScene) oldScene;
|
||||
mGalleryListHelper = oldGalleryListScene.mGalleryListHelper
|
||||
.newInstance(getStageActivity());
|
||||
@Override
|
||||
protected void onSave(Map<String, Object> transferStop) {
|
||||
super.onSave(transferStop);
|
||||
|
||||
transferStop.put("gallery_list_helper_data", mGalleryListHelper.copyData());
|
||||
transferStop.put("gallery_list_helper_save", mGalleryListHelper.save());
|
||||
transferStop.put("gallery_list_helper_listener", mGalleryListHelper.mListener);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void onRestore(Map<String, Object> transferStop) {
|
||||
super.onRestore(transferStop);
|
||||
|
||||
mGalleryListHelper = new GalleryListHelper(getStageActivity(),
|
||||
(List<GalleryInfo>) transferStop.get("gallery_list_helper_data"),
|
||||
(int[]) transferStop.get("gallery_list_helper_save"),
|
||||
(GalleryListHelperSettable) transferStop.get("gallery_list_helper_listener"));
|
||||
}
|
||||
|
||||
private void handleAnnouncer(Announcer announcer) {
|
||||
@@ -280,12 +297,15 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
mSearchLayout.setHelper(this);
|
||||
|
||||
// Content Layout
|
||||
// OnRestore may create new GalleryListHelper
|
||||
if (mGalleryListHelper == null) {
|
||||
mGalleryListHelper = new GalleryListHelper(mActivity);
|
||||
}
|
||||
|
||||
mContentLayout.setHelper(mGalleryListHelper);
|
||||
|
||||
mContentRecyclerView.setOnItemClickListener(this);
|
||||
|
||||
// Fab Layout
|
||||
mFabLayout.setOnCancelListener(this);
|
||||
|
||||
@@ -307,6 +327,16 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy(boolean willSave) {
|
||||
super.onDestroy(willSave);
|
||||
|
||||
// Avoid memory leak
|
||||
if (mGalleryListHelper.mListener != null) {
|
||||
mGalleryListHelper.mListener.setGalleryListHelper(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void saveInstanceState(Bundle outState) {
|
||||
super.saveInstanceState(outState);
|
||||
@@ -712,6 +742,52 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
// TODO
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onItemClick(EasyRecyclerView parent, View view, int position, long id) {
|
||||
GalleryInfo gi = mGalleryListHelper.getDataAt(position);
|
||||
Announcer announcer = new Announcer();
|
||||
announcer.putExtra(GalleryDetailScene.KEY_GALLERY_INFO, gi);
|
||||
|
||||
Curtain curtain = new TransitionCurtain(new TransitonHelper(position));
|
||||
|
||||
startScene(GalleryDetailScene.class, announcer, curtain);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private class TransitonHelper implements TransitionCurtain.ViewPairSet {
|
||||
|
||||
private int mPosition;
|
||||
|
||||
public TransitonHelper(int position) {
|
||||
mPosition = position;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View[] getFromViewSet(@NonNull Scene fromScene) {
|
||||
View[] views = new View[3];
|
||||
GalleryListScene scene = (GalleryListScene) fromScene;
|
||||
RecyclerView.ViewHolder viewHolder = scene.mContentRecyclerView.findViewHolderForAdapterPosition(mPosition);
|
||||
if (viewHolder != null) {
|
||||
GalleryHolder gh = (GalleryHolder) viewHolder;
|
||||
views[0] = gh.thumb;
|
||||
views[1] = gh.title;
|
||||
views[2] = gh.uploader;
|
||||
}
|
||||
return views;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View[] getToViewSet(@NonNull Scene toScene) {
|
||||
View[] views = new View[3];
|
||||
View sceneView = toScene.getSceneView();
|
||||
views[0] = sceneView.findViewById(R.id.thumb);
|
||||
views[1] = sceneView.findViewById(R.id.title);
|
||||
views[2] = sceneView.findViewById(R.id.uploader);
|
||||
return views;
|
||||
}
|
||||
}
|
||||
|
||||
private class SearchBarMoveHelper extends RecyclerView.OnScrollListener {
|
||||
|
||||
@Override
|
||||
@@ -771,8 +847,6 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
private class GalleryListHelper extends ContentLayout.ContentHelper<GalleryInfo, GalleryHolder> {
|
||||
|
||||
private LayoutInflater mInflater;
|
||||
|
||||
private GalleryListHelperSettable mListener;
|
||||
|
||||
private Runnable mSearchBarPositionTask = new Runnable() {
|
||||
@@ -784,25 +858,16 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
public GalleryListHelper(Context context) {
|
||||
super(context);
|
||||
init();
|
||||
}
|
||||
|
||||
private GalleryListHelper(Context context, GalleryListHelper oldContentHelper) {
|
||||
super(context, oldContentHelper);
|
||||
public GalleryListHelper(Context context, List<GalleryInfo> data,
|
||||
int[] save, GalleryListHelperSettable listener) {
|
||||
super(context, data, save);
|
||||
// Update gallery listener
|
||||
mListener = oldContentHelper.mListener;
|
||||
mListener = listener;
|
||||
if (mListener != null) {
|
||||
mListener.setGalleryListHelper(this);
|
||||
}
|
||||
init();
|
||||
}
|
||||
|
||||
public GalleryListHelper newInstance(Context context) {
|
||||
return new GalleryListHelper(context, this);
|
||||
}
|
||||
|
||||
private void init() {
|
||||
mInflater = mActivity.getLayoutInflater();
|
||||
}
|
||||
|
||||
private void clearLastGalleryListHelperSettable(GalleryListHelperSettable listener) {
|
||||
@@ -859,19 +924,23 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
|
||||
@Override
|
||||
public GalleryHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
View view = mInflater.inflate(R.layout.item_gallery_list_detail, parent, false);
|
||||
View view = mActivity.getLayoutInflater().inflate(R.layout.item_gallery_list_detail, parent, false);
|
||||
return new GalleryHolder(view);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(GalleryHolder holder, int position) {
|
||||
GalleryInfo gi = getDataAt(position);
|
||||
|
||||
ImageRequestBuilder builder = ImageRequestBuilder.newBuilderWithSource(Uri.parse(gi.thumb));
|
||||
KeyImageRequest keyImageRequest = new KeyImageRequest(builder);
|
||||
keyImageRequest.setKey(EhCacheKeyFactory.getThumbKey(gi.gid));
|
||||
DraweeController controller = Fresco.newDraweeControllerBuilder()
|
||||
.setUri(Uri.parse(gi.thumb))
|
||||
.setImageRequest(keyImageRequest)
|
||||
.setTapToRetryEnabled(true)
|
||||
.setOldController(holder.thumb.getController())
|
||||
.build();
|
||||
.setOldController(holder.thumb.getController()).build();
|
||||
holder.thumb.setController(controller);
|
||||
|
||||
holder.title.setText(gi.title);
|
||||
holder.uploader.setText(gi.uploader);
|
||||
holder.rating.setRating(gi.rating);
|
||||
@@ -913,12 +982,12 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
if (mHelper != null) {
|
||||
if (mSource == EhClient.SOURCE_LOFI) {
|
||||
if (pageNum == GalleryListParser.CURRENT_PAGE_IS_LAST) {
|
||||
mHelper.setPageSize(mTargetPage);
|
||||
mHelper.setPageCount(mTargetPage);
|
||||
} else if (mTaskType == ContentLayout.ContentHelper.TYPE_REFRESH) {
|
||||
mHelper.setPageSize(Integer.MAX_VALUE);
|
||||
mHelper.setPageCount(Integer.MAX_VALUE);
|
||||
}
|
||||
} else {
|
||||
mHelper.setPageSize(pageNum);
|
||||
mHelper.setPageCount(pageNum);
|
||||
}
|
||||
mHelper.onGetPageData(mTaskId, glList);
|
||||
|
||||
@@ -954,7 +1023,7 @@ public final class GalleryListScene extends Scene implements SearchBar.Helper,
|
||||
@Override
|
||||
public void onSuccess(List<GalleryInfo> glList, long timeStamp) {
|
||||
if (mHelper != null) {
|
||||
mHelper.setPageSize(1);
|
||||
mHelper.setPageCount(1);
|
||||
mHelper.onGetPageData(mTaskId, glList);
|
||||
|
||||
mHelper.clearLastGalleryListHelperSettable(this);
|
||||
|
||||
@@ -35,15 +35,15 @@ public final class MainSettingsScene extends PreferenceHeaderScene {
|
||||
|
||||
PreferenceHeader[] phs = new PreferenceHeader[] {
|
||||
newPreferenceHeader(
|
||||
R.drawable.ic_cellphone_android_theme_primary,
|
||||
R.drawable.ic_cellphone_android_theme_accent,
|
||||
R.string.settings_display,
|
||||
DisplaySettingsScene.class),
|
||||
newPreferenceHeader(
|
||||
R.drawable.ic_eh_theme_primary,
|
||||
R.drawable.ic_eh_theme_accent,
|
||||
R.string.settings_eh,
|
||||
EHSettingsScene.class),
|
||||
newPreferenceHeader(
|
||||
R.drawable.ic_lambda_theme_primary,
|
||||
R.drawable.ic_lambda_theme_accent,
|
||||
R.string.settings_advance,
|
||||
AdvanceSettingsScene.class)
|
||||
};
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright (C) 2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.ehviewer.widget;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.AttributeSet;
|
||||
import android.widget.FrameLayout;
|
||||
|
||||
public class CircularRevealLayout extends FrameLayout {
|
||||
|
||||
public CircularRevealLayout(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
public CircularRevealLayout(Context context, AttributeSet attrs) {
|
||||
super(context, attrs);
|
||||
}
|
||||
|
||||
public CircularRevealLayout(Context context, AttributeSet attrs, int defStyleAttr) {
|
||||
super(context, attrs, defStyleAttr);
|
||||
}
|
||||
|
||||
/*
|
||||
@Override
|
||||
protected boolean drawChild(Canvas canvas, View child, long drawingTime) {
|
||||
if(mRunning && child == mRevealInfo.getTarget()){
|
||||
final int state = canvas.save();
|
||||
|
||||
mRevealPath.reset();
|
||||
mRevealPath.addCircle(mRevealInfo.centerX, mRevealInfo.centerY, mRadius, Path.Direction.CW);
|
||||
|
||||
canvas.clipPath(mRevealPath);
|
||||
|
||||
boolean isInvalided = super.drawChild(canvas, child, drawingTime);
|
||||
|
||||
canvas.restoreToCount(state);
|
||||
|
||||
return isInvalided;
|
||||
}
|
||||
|
||||
return super.drawChild(canvas, child, drawingTime);
|
||||
}
|
||||
*/
|
||||
}
|
||||
@@ -187,7 +187,7 @@ public class ContentLayout extends FrameLayout {
|
||||
/**
|
||||
* The size of page
|
||||
*/
|
||||
private int mPageSize;
|
||||
private int mPageCount;
|
||||
private int mCurrentPage;
|
||||
private int mPageVolume;
|
||||
|
||||
@@ -246,20 +246,35 @@ public class ContentLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ContentHelper(Context context, ContentHelper oldContentHelper) {
|
||||
protected ContentHelper(Context context, List<E> data, int[] save) {
|
||||
this(context);
|
||||
mData.addAll(oldContentHelper.mData);
|
||||
mData.addAll(data);
|
||||
|
||||
mFirstPage = oldContentHelper.mFirstPage;
|
||||
mLastPage = oldContentHelper.mLastPage;
|
||||
mFirstIndex = oldContentHelper.mFirstIndex;
|
||||
mLastIndex = oldContentHelper.mLastIndex;
|
||||
mPageSize = oldContentHelper.mPageSize;
|
||||
mCurrentPage = oldContentHelper.mCurrentPage;
|
||||
mPageVolume = oldContentHelper.mPageVolume;
|
||||
mCurrentTaskId = oldContentHelper.mCurrentTaskId;
|
||||
mCurrentTaskType = oldContentHelper.mCurrentTaskType;
|
||||
mCurrentTaskPage = oldContentHelper.mCurrentTaskPage;
|
||||
mFirstPage = save[0];
|
||||
mLastPage = save[1];
|
||||
mFirstIndex = save[2];
|
||||
mLastIndex = save[3];
|
||||
mPageCount = save[4];
|
||||
mCurrentPage = save[5];
|
||||
mPageVolume = save[6];
|
||||
mCurrentTaskId = save[7];
|
||||
mCurrentTaskType = save[8];
|
||||
mCurrentTaskPage = save[9];
|
||||
}
|
||||
|
||||
public int[] save() {
|
||||
int[] save = new int[10];
|
||||
save[0] = mFirstPage;
|
||||
save[1] = mLastPage;
|
||||
save[2] = mFirstIndex;
|
||||
save[3] = mLastIndex;
|
||||
save[4] = mPageCount;
|
||||
save[5] = mCurrentPage;
|
||||
save[6] = mPageVolume;
|
||||
save[7] = mCurrentTaskId;
|
||||
save[8] = mCurrentTaskType;
|
||||
save[9] = mCurrentTaskPage;
|
||||
return save;
|
||||
}
|
||||
|
||||
private void init(ContentLayout contentLayout) {
|
||||
@@ -312,6 +327,12 @@ public class ContentLayout extends FrameLayout {
|
||||
}
|
||||
}
|
||||
|
||||
public List<E> copyData() {
|
||||
List<E> data = new ArrayList<>(mData.size());
|
||||
data.addAll(mData);
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if {@code location < 0 || location >= size()}
|
||||
@@ -328,12 +349,12 @@ public class ContentLayout extends FrameLayout {
|
||||
*/
|
||||
protected abstract void getPageData(int taskId, int type, int page);
|
||||
|
||||
public void setPageSize(int pageSize) {
|
||||
mPageSize = pageSize;
|
||||
public void setPageCount(int pageSize) {
|
||||
mPageCount = pageSize;
|
||||
}
|
||||
|
||||
public int getPageSize() {
|
||||
return mPageSize;
|
||||
public int getPageCount() {
|
||||
return mPageCount;
|
||||
}
|
||||
|
||||
public int getCurrentPage() {
|
||||
@@ -341,7 +362,7 @@ public class ContentLayout extends FrameLayout {
|
||||
}
|
||||
|
||||
public void resetPageSize() {
|
||||
mPageSize = Integer.MAX_VALUE;
|
||||
mPageCount = Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
public void onGetPageData(int taskId, List<E> data) {
|
||||
@@ -446,7 +467,7 @@ public class ContentLayout extends FrameLayout {
|
||||
|
||||
@Override
|
||||
public boolean onFooterRefresh() {
|
||||
if (mLastPage >= mPageSize) {
|
||||
if (mLastPage >= mPageCount) {
|
||||
return false;
|
||||
} else {
|
||||
mCurrentTaskId = mIdGenerator.nextId();
|
||||
@@ -525,8 +546,8 @@ public class ContentLayout extends FrameLayout {
|
||||
* Only work when data is loaded
|
||||
*/
|
||||
public void goTo(int page) {
|
||||
if (page < 0 || page >= mPageSize) {
|
||||
throw new IndexOutOfBoundsException("Page size is " + mPageSize + ", page is " + page);
|
||||
if (page < 0 || page >= mPageCount) {
|
||||
throw new IndexOutOfBoundsException("Page count is " + mPageCount + ", page is " + page);
|
||||
} else if (page >= mFirstPage && page < mLastPage) {
|
||||
cancelCurrentTask();
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ import android.widget.FrameLayout;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* {@link com.hippo.scene.Scene} is a {@code Activity} of {@link android.app.Activity}.
|
||||
* <p>
|
||||
@@ -164,8 +166,11 @@ public abstract class Scene {
|
||||
}
|
||||
}
|
||||
|
||||
void destroy() {
|
||||
onDestroy();
|
||||
// TODO Tell destory is it need close
|
||||
void destroy(boolean willSave) {
|
||||
onDestroy(willSave);
|
||||
|
||||
SceneApplication.getRefWatcher(getStageActivity()).watch(this);
|
||||
}
|
||||
|
||||
void open() {
|
||||
@@ -184,8 +189,12 @@ public abstract class Scene {
|
||||
onResume();
|
||||
}
|
||||
|
||||
void replace(@NonNull Scene oldScene) {
|
||||
onReplace(oldScene);
|
||||
void save(Map<String, Object> transferStop) {
|
||||
onSave(transferStop);
|
||||
}
|
||||
|
||||
void restore(Map<String, Object> transferStop) {
|
||||
onRestore(transferStop);
|
||||
}
|
||||
|
||||
void setFitPaddingBottom(int b) {
|
||||
@@ -239,7 +248,7 @@ public abstract class Scene {
|
||||
}
|
||||
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
protected void onDestroy() {
|
||||
protected void onDestroy(boolean willSave) {
|
||||
// Make sure soft key broad is hidden
|
||||
InputMethodManager imm = (InputMethodManager) getStageActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.hideSoftInputFromWindow(mSceneView.getWindowToken(), 0);
|
||||
@@ -259,10 +268,16 @@ public abstract class Scene {
|
||||
getSceneView().setEnableTouch(true);
|
||||
}
|
||||
|
||||
protected void onReplace(@NonNull Scene oldScene) {
|
||||
mId = oldScene.mId;
|
||||
mAnnouncer = oldScene.mAnnouncer;
|
||||
mCurtain = oldScene.mCurtain;
|
||||
protected void onSave(Map<String, Object> transferStop) {
|
||||
transferStop.put("scene_id", mId);
|
||||
transferStop.put("scene_announcer", mAnnouncer);
|
||||
transferStop.put("scene_curtain", mCurtain);
|
||||
}
|
||||
|
||||
protected void onRestore(Map<String, Object> transferStop) {
|
||||
mId = (Integer) transferStop.get("scene_id");
|
||||
mAnnouncer = (Announcer) transferStop.get("scene_announcer");
|
||||
mCurtain = (Curtain) transferStop.get("scene_curtain");
|
||||
if (mCurtain != null) {
|
||||
mCurtain.onReplace();
|
||||
}
|
||||
|
||||
@@ -16,15 +16,23 @@
|
||||
package com.hippo.scene;
|
||||
|
||||
import android.app.Application;
|
||||
import android.content.Context;
|
||||
|
||||
import com.squareup.leakcanary.LeakCanary;
|
||||
import com.squareup.leakcanary.RefWatcher;
|
||||
|
||||
public class SceneApplication extends Application {
|
||||
|
||||
private SceneManager mSceneManager;
|
||||
|
||||
private RefWatcher mRefWatcher;
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
|
||||
mRefWatcher = LeakCanary.install(this);
|
||||
|
||||
mSceneManager = SceneManager.getInstance();
|
||||
StageActivity.setSceneManager(mSceneManager);
|
||||
Scene.setSceneManager(mSceneManager);
|
||||
@@ -33,4 +41,9 @@ public class SceneApplication extends Application {
|
||||
public SceneManager getSceneManager() {
|
||||
return mSceneManager;
|
||||
}
|
||||
|
||||
public static RefWatcher getRefWatcher(Context context) {
|
||||
SceneApplication application = (SceneApplication) context.getApplicationContext();
|
||||
return application.mRefWatcher;
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,9 @@ import com.hippo.util.IntIdGenerator;
|
||||
import com.hippo.util.Log;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
public class SceneManager {
|
||||
@@ -39,6 +41,8 @@ public class SceneManager {
|
||||
|
||||
private List<SceneStateListener> mSceneStateListenerList = new ArrayList<>();
|
||||
|
||||
private Map<String, Object> mTransferStop = new HashMap<>();
|
||||
|
||||
private static SceneManager sSceneManger;
|
||||
|
||||
public static SceneManager getInstance() {
|
||||
@@ -100,12 +104,6 @@ public class SceneManager {
|
||||
}
|
||||
}
|
||||
|
||||
private void notifyReplace(Class clazz) {
|
||||
for (SceneStateListener l : mSceneStateListenerList) {
|
||||
l.onReplace(clazz);
|
||||
}
|
||||
}
|
||||
|
||||
Scene createSceneByClass(@NonNull Class sceneClass) {
|
||||
try {
|
||||
return (Scene) sceneClass.newInstance();
|
||||
@@ -210,7 +208,7 @@ public class SceneManager {
|
||||
// It is the last scene, just finish the activity
|
||||
mSceneStack.remove(index);
|
||||
|
||||
scene.destroy();
|
||||
scene.destroy(false);
|
||||
scene.setState(Scene.SCENE_STATE_DESTROY);
|
||||
notifyDestroy(scene.getClass());
|
||||
|
||||
@@ -229,7 +227,7 @@ public class SceneManager {
|
||||
notifyResume(previousState.getClass());
|
||||
}
|
||||
|
||||
scene.destroy();
|
||||
scene.destroy(false);
|
||||
scene.setState(Scene.SCENE_STATE_DESTROY);
|
||||
notifyDestroy(scene.getClass());
|
||||
|
||||
@@ -298,15 +296,18 @@ public class SceneManager {
|
||||
tempStack.addAll(mSceneStack);
|
||||
mSceneStack.clear();
|
||||
|
||||
Map<String, Object> transferStop = mTransferStop;
|
||||
for (Scene oldScene : tempStack) {
|
||||
Scene newScene = createSceneByClass(oldScene.getClass());
|
||||
newScene.replace(oldScene);
|
||||
notifyReplace(newScene.getClass());
|
||||
|
||||
oldScene.destroy();
|
||||
oldScene.destroy(true);
|
||||
oldScene.setState(Scene.SCENE_STATE_DESTROY);
|
||||
notifyDestroy(oldScene.getClass());
|
||||
|
||||
oldScene.save(transferStop);
|
||||
|
||||
Scene newScene = createSceneByClass(oldScene.getClass());
|
||||
|
||||
newScene.restore(transferStop);
|
||||
|
||||
newScene.create(savedInstanceState);
|
||||
newScene.setState(Scene.SCENE_STATE_CREATE);
|
||||
notifyCreate(newScene.getClass());
|
||||
@@ -315,6 +316,8 @@ public class SceneManager {
|
||||
|
||||
newScene.setState(Scene.SCENE_STATE_RUN);
|
||||
mSceneStack.push(newScene);
|
||||
|
||||
transferStop.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -323,6 +326,5 @@ public class SceneManager {
|
||||
void onDestroy(Class clazz);
|
||||
void onPause(Class clazz);
|
||||
void onResume(Class clazz);
|
||||
void onReplace(Class clazz);
|
||||
}
|
||||
}
|
||||
@@ -37,6 +37,8 @@ import com.hippo.effect.ripple.RippleSalon;
|
||||
import com.hippo.ehviewer.R;
|
||||
import com.hippo.util.ViewUtils;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
public class SimpleDialog extends SceneDialog implements View.OnClickListener,
|
||||
SceneDialogView.OnClickOutOfDialogListener, AdapterView.OnItemClickListener {
|
||||
|
||||
@@ -103,18 +105,22 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onReplace(@NonNull Scene oldScene) {
|
||||
super.onReplace(oldScene);
|
||||
protected void onSave(Map<String, Object> transferStop) {
|
||||
super.onSave(transferStop);
|
||||
|
||||
SimpleDialog oldDialog = (SimpleDialog) oldScene;
|
||||
mBuilder = oldDialog.mBuilder;
|
||||
// Avoid memory leak
|
||||
mBuilder.mContext = getStageActivity();
|
||||
transferStop.put("builder", mBuilder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy() {
|
||||
super.onDestroy();
|
||||
protected void onRestore(Map<String, Object> transferStop) {
|
||||
super.onRestore(transferStop);
|
||||
|
||||
mBuilder = (Builder) transferStop.get("builder");
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDestroy(boolean willSave) {
|
||||
super.onDestroy(willSave);
|
||||
|
||||
OnCloseListener listener = mBuilder.mOnCloseListener;
|
||||
if (listener != null) {
|
||||
@@ -446,6 +452,9 @@ public class SimpleDialog extends SceneDialog implements View.OnClickListener,
|
||||
}
|
||||
|
||||
public @NonNull SimpleDialog build() {
|
||||
// Avoid memory leak
|
||||
mContext = null;
|
||||
|
||||
SimpleDialog dialog = new SimpleDialog();
|
||||
dialog.setBuilder(this);
|
||||
return dialog;
|
||||
|
||||
@@ -29,6 +29,7 @@ import android.widget.AbsoluteLayout;
|
||||
import com.hippo.animation.ArgbEvaluator;
|
||||
import com.hippo.animation.SimpleAnimatorListener;
|
||||
import com.hippo.util.AnimationUtils;
|
||||
import com.hippo.util.AssertUtils;
|
||||
import com.hippo.util.Log;
|
||||
import com.hippo.util.ViewUtils;
|
||||
import com.hippo.widget.GlobalLayoutSet;
|
||||
@@ -42,12 +43,12 @@ public class TransitionCurtain extends Curtain {
|
||||
|
||||
private static long ANIMATE_TIME = 300L;
|
||||
|
||||
private ViewPair[] mViewPairArray;
|
||||
private ViewPairSet mViewPairSet;
|
||||
|
||||
private AnimatorSet mAnimatorSet;
|
||||
|
||||
public TransitionCurtain(ViewPair[] viewPairArray) {
|
||||
mViewPairArray = viewPairArray;
|
||||
public TransitionCurtain(ViewPairSet viewPairSet) {
|
||||
mViewPairSet = viewPairSet;
|
||||
}
|
||||
|
||||
// TODO what if back key press before move animator start
|
||||
@@ -82,9 +83,13 @@ public class TransitionCurtain extends Curtain {
|
||||
Set<TransitionItem> transitionItemSet = new HashSet<>();
|
||||
|
||||
// Handle transit part
|
||||
for (ViewPair pair : mViewPairArray) {
|
||||
final View enterView = pair.getToView(enter);
|
||||
final View exitView = pair.getFromView(exit);
|
||||
View[] enterViews = mViewPairSet.getToViewSet(enter);
|
||||
View[] exitViews = mViewPairSet.getFromViewSet(exit);
|
||||
AssertUtils.assertEquals("From view size and to view size must be the same", enterViews.length, exitViews.length);
|
||||
int length = enterViews.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
final View enterView = enterViews[i];
|
||||
final View exitView = exitViews[i];
|
||||
if (enterView == null) {
|
||||
Log.w(TAG, "Can't get enterView when open.");
|
||||
continue;
|
||||
@@ -266,9 +271,13 @@ public class TransitionCurtain extends Curtain {
|
||||
Set<TransitionItem> transitionItemSet = new HashSet<>();
|
||||
|
||||
// Handle transit part
|
||||
for (ViewPair pair : mViewPairArray) {
|
||||
final View enterView = pair.getFromView(enter);
|
||||
final View exitView = pair.getToView(exit);
|
||||
View[] enterViews = mViewPairSet.getFromViewSet(enter);
|
||||
View[] exitViews = mViewPairSet.getToViewSet(exit);
|
||||
AssertUtils.assertEquals("From view size and to view size must be the same", enterViews.length, exitViews.length);
|
||||
int length = enterViews.length;
|
||||
for (int i = 0; i < length; i++) {
|
||||
final View enterView = enterViews[i];
|
||||
final View exitView = exitViews[i];
|
||||
if (enterView == null) {
|
||||
Log.w(TAG, "Can't get enterView when close");
|
||||
continue;
|
||||
@@ -447,28 +456,8 @@ public class TransitionCurtain extends Curtain {
|
||||
/**
|
||||
* the interface help {@link TransitionCurtain} to get the views to do transfer
|
||||
*/
|
||||
public interface ViewPair {
|
||||
View getFromView(@NonNull Scene fromScene);
|
||||
View getToView(@NonNull Scene toScene);
|
||||
}
|
||||
|
||||
public static class IdViewPair implements ViewPair {
|
||||
private int mFromId;
|
||||
private int mToId;
|
||||
|
||||
public IdViewPair(int fromId, int toId) {
|
||||
mFromId = fromId;
|
||||
mToId = toId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getFromView(@NonNull Scene fromScene) {
|
||||
return fromScene.findViewById(mFromId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getToView(@NonNull Scene toScene) {
|
||||
return toScene.findViewById(mToId);
|
||||
}
|
||||
public interface ViewPairSet {
|
||||
View[] getFromViewSet(@NonNull Scene fromScene);
|
||||
View[] getToViewSet(@NonNull Scene toScene);
|
||||
}
|
||||
}
|
||||
@@ -50,11 +50,11 @@ public class PreferenceHeaderScene extends AppbarScene {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.scene_preference_header);
|
||||
|
||||
mActivity = getStageActivity();
|
||||
|
||||
mRecyclerView = new EasyRecyclerView(getStageActivity());
|
||||
setContentView(mRecyclerView);
|
||||
mRecyclerView = (EasyRecyclerView) findViewById(R.id.recycler_view);
|
||||
|
||||
mHeaderAdapter = new HeaderAdapter();
|
||||
mRecyclerView.setAdapter(mHeaderAdapter);
|
||||
|
||||
@@ -46,9 +46,9 @@ public class PreferenceScene extends AppbarScene {
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.scene_preference);
|
||||
|
||||
mRecyclerView = new EasyRecyclerView(getStageActivity());
|
||||
setContentView(mRecyclerView);
|
||||
mRecyclerView = (EasyRecyclerView) findViewById(R.id.recycler_view);
|
||||
|
||||
mAdapter = new PreferenceAdapter();
|
||||
mRecyclerView.setAdapter(mAdapter);
|
||||
|
||||
@@ -1,230 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014-2015 Hippo Seven
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.hippo.util;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
||||
/**
|
||||
* It is the same as {@link java.io.ByteArrayOutputStream}, but buffer can be got
|
||||
* directly. So it is not safe.
|
||||
*/
|
||||
public class FastByteArrayOutputStream extends OutputStream {
|
||||
/**
|
||||
* The byte array containing the bytes written.
|
||||
*/
|
||||
protected byte[] buf;
|
||||
|
||||
/**
|
||||
* The number of bytes written.
|
||||
*/
|
||||
protected int count;
|
||||
|
||||
/**
|
||||
* Constructs a new ByteArrayOutputStream with a default size of 32 bytes.
|
||||
* If more than 32 bytes are written to this instance, the underlying byte
|
||||
* array will expand.
|
||||
*/
|
||||
public FastByteArrayOutputStream() {
|
||||
buf = new byte[32];
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code ByteArrayOutputStream} with a default size of
|
||||
* {@code size} bytes. If more than {@code size} bytes are written to this
|
||||
* instance, the underlying byte array will expand.
|
||||
*
|
||||
* @param size
|
||||
* initial size for the underlying byte array, must be
|
||||
* non-negative.
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code size} < 0.
|
||||
*/
|
||||
public FastByteArrayOutputStream(int size) {
|
||||
if (size >= 0) {
|
||||
buf = new byte[size];
|
||||
} else {
|
||||
throw new IllegalArgumentException("size < 0");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Closes this stream. This releases system resources used for this stream.
|
||||
*
|
||||
* @throws java.io.IOException
|
||||
* if an error occurs while attempting to close this stream.
|
||||
*/
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
/**
|
||||
* Although the spec claims "A closed stream cannot perform output
|
||||
* operations and cannot be reopened.", this implementation must do
|
||||
* nothing.
|
||||
*/
|
||||
super.close();
|
||||
}
|
||||
|
||||
private void expand(int i) {
|
||||
/* Can the buffer handle @i more bytes, if not expand it */
|
||||
if (count + i <= buf.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
byte[] newbuf = new byte[(count + i) * 2];
|
||||
System.arraycopy(buf, 0, newbuf, 0, count);
|
||||
buf = newbuf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets this stream to the beginning of the underlying byte array. All
|
||||
* subsequent writes will overwrite any bytes previously stored in this
|
||||
* stream.
|
||||
*/
|
||||
public synchronized void reset() {
|
||||
count = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the total number of bytes written to this stream so far.
|
||||
*
|
||||
* @return the number of bytes written to this stream.
|
||||
*/
|
||||
public int size() {
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of this ByteArrayOutputStream as a byte array. Any
|
||||
* changes made to the receiver after returning will not be reflected in the
|
||||
* byte array returned to the caller.
|
||||
*
|
||||
* @return this stream's current contents as a byte array.
|
||||
*/
|
||||
public synchronized byte[] getBuffer() {
|
||||
return buf;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of this ByteArrayOutputStream as a string. Any
|
||||
* changes made to the receiver after returning will not be reflected in the
|
||||
* string returned to the caller.
|
||||
*
|
||||
* @return this stream's current contents as a string.
|
||||
*/
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new String(buf, 0, count);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of this ByteArrayOutputStream as a string. Each byte
|
||||
* {@code b} in this stream is converted to a character {@code c} using the
|
||||
* following function:
|
||||
* {@code c == (char)(((hibyte & 0xff) << 8) | (b & 0xff))}. This method is
|
||||
* deprecated and either {@link #toString()} or {@link #toString(String)}
|
||||
* should be used.
|
||||
*
|
||||
* @param hibyte
|
||||
* the high byte of each resulting Unicode character.
|
||||
* @return this stream's current contents as a string with the high byte set
|
||||
* to {@code hibyte}.
|
||||
* @deprecated Use {@link #toString()} instead.
|
||||
*/
|
||||
@Deprecated
|
||||
public String toString(int hibyte) {
|
||||
char[] newBuf = new char[size()];
|
||||
for (int i = 0; i < newBuf.length; i++) {
|
||||
newBuf[i] = (char) (((hibyte & 0xff) << 8) | (buf[i] & 0xff));
|
||||
}
|
||||
return new String(newBuf);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the contents of this ByteArrayOutputStream as a string converted
|
||||
* according to the encoding declared in {@code charsetName}.
|
||||
*
|
||||
* @param charsetName
|
||||
* a string representing the encoding to use when translating
|
||||
* this stream to a string.
|
||||
* @return this stream's current contents as an encoded string.
|
||||
* @throws java.io.UnsupportedEncodingException
|
||||
* if the provided encoding is not supported.
|
||||
*/
|
||||
public String toString(String charsetName) throws UnsupportedEncodingException {
|
||||
return new String(buf, 0, count, charsetName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes {@code count} bytes from the byte array {@code buffer} starting at
|
||||
* offset {@code index} to this stream.
|
||||
*
|
||||
* @param buffer
|
||||
* the buffer to be written.
|
||||
* @param offset
|
||||
* the initial position in {@code buffer} to retrieve bytes.
|
||||
* @param len
|
||||
* the number of bytes of {@code buffer} to write.
|
||||
* @throws NullPointerException
|
||||
* if {@code buffer} is {@code null}.
|
||||
* @throws IndexOutOfBoundsException
|
||||
* if {@code offset < 0} or {@code len < 0}, or if
|
||||
* {@code offset + len} is greater than the length of
|
||||
* {@code buffer}.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void write(byte[] buffer, int offset, int len) {
|
||||
if ((offset | count) < 0 || offset > buffer.length || buffer.length - offset < count) {
|
||||
throw new ArrayIndexOutOfBoundsException("length=" + buffer.length + "; regionStart=" + offset
|
||||
+ "; regionLength=" + count);
|
||||
}
|
||||
if (len == 0) {
|
||||
return;
|
||||
}
|
||||
expand(len);
|
||||
System.arraycopy(buffer, offset, buf, this.count, len);
|
||||
this.count += len;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the specified byte {@code oneByte} to the OutputStream. Only the
|
||||
* low order byte of {@code oneByte} is written.
|
||||
*
|
||||
* @param oneByte
|
||||
* the byte to be written.
|
||||
*/
|
||||
@Override
|
||||
public synchronized void write(int oneByte) {
|
||||
if (count == buf.length) {
|
||||
expand(1);
|
||||
}
|
||||
buf[count++] = (byte) oneByte;
|
||||
}
|
||||
|
||||
/**
|
||||
* Takes the contents of this stream and writes it to the output stream
|
||||
* {@code out}.
|
||||
*
|
||||
* @param out
|
||||
* an OutputStream on which to write the contents of this stream.
|
||||
* @throws java.io.IOException
|
||||
* if an error occurs while writing to {@code out}.
|
||||
*/
|
||||
public synchronized void writeTo(OutputStream out) throws IOException {
|
||||
out.write(buf, 0, count);
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,10 @@ public class GlobalLayoutSet {
|
||||
mSize++;
|
||||
}
|
||||
|
||||
public int getSize() {
|
||||
return mSize;
|
||||
}
|
||||
|
||||
private class LayoutListener implements ViewTreeObserver.OnGlobalLayoutListener {
|
||||
private ViewTreeObserver mObserver;
|
||||
|
||||
|
||||
Reference in new issue
Block a user