diff --git a/app/src/main/java/com/hippo/ehviewer/UpdateHelper.java b/app/src/main/java/com/hippo/ehviewer/UpdateHelper.java index a0fddc623..a92a8229b 100644 --- a/app/src/main/java/com/hippo/ehviewer/UpdateHelper.java +++ b/app/src/main/java/com/hippo/ehviewer/UpdateHelper.java @@ -16,11 +16,6 @@ package com.hippo.ehviewer; -import java.io.File; - -import org.json.JSONException; -import org.json.JSONObject; - import android.app.NotificationManager; import android.content.Context; import android.content.Intent; @@ -36,6 +31,11 @@ import com.hippo.ehviewer.util.BgThread; import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.Utils; +import org.json.JSONException; +import org.json.JSONObject; + +import java.io.File; + // TODO return onFailure when downloading update or check update // TODO add disable to achieve @@ -254,5 +254,10 @@ public class UpdateHelper implements Runnable { } setEnabled(true); } + + @Override + public void onUpdateFilename(String newFilename) { + + } } } diff --git a/app/src/main/java/com/hippo/ehviewer/data/GalleryDetail.java b/app/src/main/java/com/hippo/ehviewer/data/GalleryDetail.java index aa957edf7..0080ca325 100644 --- a/app/src/main/java/com/hippo/ehviewer/data/GalleryDetail.java +++ b/app/src/main/java/com/hippo/ehviewer/data/GalleryDetail.java @@ -16,6 +16,8 @@ package com.hippo.ehviewer.data; +import android.util.Pair; + import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -43,6 +45,9 @@ public class GalleryDetail extends GalleryInfo public PreviewList[] previewLists; public List comments; + public String torrentUrl; + public Pair[] torrents; + public GalleryDetail() {} public GalleryDetail(GalleryInfo galleryInfo) { diff --git a/app/src/main/java/com/hippo/ehviewer/ehclient/DetailParser.java b/app/src/main/java/com/hippo/ehviewer/ehclient/DetailParser.java index 79c9a4a93..561d9ddfd 100644 --- a/app/src/main/java/com/hippo/ehviewer/ehclient/DetailParser.java +++ b/app/src/main/java/com/hippo/ehviewer/ehclient/DetailParser.java @@ -69,6 +69,8 @@ public class DetailParser { public LinkedHashMap> tags; public PreviewList previewList; public LinkedList comments; + public int torrentNumber; + public String torrentUrl; public void reset() { eMesg = null; @@ -92,6 +94,8 @@ public class DetailParser { tags = null; previewList = null; comments = null; + torrentNumber = 0; + torrentUrl = null; } public int parser(String body, int mode) { @@ -132,6 +136,8 @@ public class DetailParser { + "

([^<>]*)

" // title_jpn might be empty string + "" + ".+" + + "]*onclick=\"return popUp\\('([^']+)'[^)]+\\)\">Torrent Download \\( (\\d+) \\)" + + ".+" + "
]+><[^<>]*alt=\"([\\w|\\-]+)\"[^<>]*>
" // category + "
]+>([^<>]+)" // uploader + ".+" @@ -157,26 +163,28 @@ public class DetailParser { thumb = Utils.unescapeXml(m.group(1)); title = Utils.unescapeXml(m.group(2)); title_jpn = Utils.unescapeXml(m.group(3)); - category = EhUtils.getCategory(m.group(4)); - uploader = m.group(5); - posted = m.group(6); - parent = m.group(7); - visible = m.group(8); - language = Utils.unescapeXml(m.group(9)).trim(); - size = Utils.unescapeXml(m.group(10)).trim(); - resized = m.group(11); - pages = Integer.parseInt(m.group(12).replace(",", "")); - // favoriteTimes = m.group(13) - people = Integer.parseInt(m.group(14).replace(",", "")); + torrentUrl = Utils.unescapeXml(m.group(4)); + torrentNumber = Utils.parseIntSafely(m.group(5), 0); + category = EhUtils.getCategory(m.group(6)); + uploader = m.group(7); + posted = m.group(8); + parent = m.group(9); + visible = m.group(10); + language = Utils.unescapeXml(m.group(11)).trim(); + size = Utils.unescapeXml(m.group(12)).trim(); + resized = m.group(13); + pages = Integer.parseInt(m.group(14).replace(",", "")); + // favoriteTimes = m.group(15) + people = Integer.parseInt(m.group(16).replace(",", "")); Pattern pattern = Pattern.compile("([\\d|\\.]+)"); - Matcher matcher = pattern.matcher(m.group(15)); + Matcher matcher = pattern.matcher(m.group(17)); if (matcher.find()) rating = Float.parseFloat(matcher.group(1)); else rating = Float.NaN; - firstPage = m.group(16); + firstPage = m.group(18); } } // Get tag diff --git a/app/src/main/java/com/hippo/ehviewer/ehclient/EhClient.java b/app/src/main/java/com/hippo/ehviewer/ehclient/EhClient.java index 517ea9af0..f6354d134 100644 --- a/app/src/main/java/com/hippo/ehviewer/ehclient/EhClient.java +++ b/app/src/main/java/com/hippo/ehviewer/ehclient/EhClient.java @@ -22,6 +22,8 @@ import android.graphics.drawable.BitmapDrawable; import android.graphics.drawable.Drawable; import android.os.Handler; import android.os.Process; +import android.support.annotation.NonNull; +import android.util.Pair; import com.hippo.ehviewer.Analytics; import com.hippo.ehviewer.AppHandler; @@ -739,6 +741,11 @@ public class EhClient { md.previewLists = new PreviewList[md.previewSum]; md.previewLists[0] = parser.previewList; md.comments = parser.comments; + + md.torrentUrl = parser.torrentUrl; + //noinspection unchecked + md.torrents = new Pair[Math.max(parser.torrentNumber, 0)]; + responder = new GetGDetaiResponder(listener, md); } else if (result == DetailParser.ERROR) { responder = new GetGDetaiResponder(listener, parser.eMesg); @@ -754,6 +761,62 @@ public class EhClient { thread.start(); } + public interface OnGetTorrentListener { + void onSuccess(@NonNull Pair[] torrents); + void onFailure(String eMsg); + } + + private class GetTorrentResponder implements Runnable { + private final boolean isOk; + private final OnGetTorrentListener listener; + private final Pair[] torrents; + private final String eMesg; + + public GetTorrentResponder(OnGetTorrentListener listener, Pair[] torrents) { + this.isOk = true; + this.listener = listener; + this.torrents = torrents; + this.eMesg = null; + } + + public GetTorrentResponder(OnGetTorrentListener listener, String eMsg) { + this.isOk = false; + this.listener = listener; + this.torrents = null; + this.eMesg = eMsg; + } + + @Override + public void run() { + if (isOk) + listener.onSuccess(torrents); + else + listener.onFailure(eMesg); + } + } + + public void getTorrent(final String url, final Pair[] torrents, + final OnGetTorrentListener listener) { + Thread thread = new Thread(new Runnable() { + @Override + public void run() { + HttpHelper hh = new HttpHelper(mContext); + String body = hh.get(url); + GetTorrentResponder responder; + if (body == null) { + responder = new GetTorrentResponder(listener, hh.getEMsg()); + } else if (!body.contains("<")) { + responder = new GetTorrentResponder(listener, body); + } else { + responder = new GetTorrentResponder(listener, TorrentParser.parse(body, torrents)); + } + mHandler.post(responder); + } + }); + thread.setPriority(Process.THREAD_PRIORITY_BACKGROUND); + thread.start(); + } + // Get lofi gallery Detail public interface OnGetLGDetailListener { public void onSuccess(LofiGalleryDetail md, boolean isLastPage); diff --git a/app/src/main/java/com/hippo/ehviewer/ehclient/ExDownloader.java b/app/src/main/java/com/hippo/ehviewer/ehclient/ExDownloader.java index 02cce170b..a02898810 100644 --- a/app/src/main/java/com/hippo/ehviewer/ehclient/ExDownloader.java +++ b/app/src/main/java/com/hippo/ehviewer/ehclient/ExDownloader.java @@ -915,5 +915,10 @@ public final class ExDownloader implements Runnable { lastPercent = 0.0f; lastDownloadSize = 0; } + + @Override + public void onUpdateFilename(String newFilename) { + + } } } diff --git a/app/src/main/java/com/hippo/ehviewer/ehclient/TorrentParser.java b/app/src/main/java/com/hippo/ehviewer/ehclient/TorrentParser.java new file mode 100644 index 000000000..7dd16168f --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/ehclient/TorrentParser.java @@ -0,0 +1,77 @@ +package com.hippo.ehviewer.ehclient; + +import android.support.annotation.Nullable; +import android.util.Pair; + +import com.hippo.ehviewer.util.Utils; + +import java.util.LinkedList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TorrentParser { + + /** + * + * @return the param or new instance if size changed + */ + public static Pair[] parse(String body, @Nullable Pair[] torrents) { + List> torrentList; + int arrayLength; + int size = 0; + + if (torrents == null) { + arrayLength = 0; + torrentList = new LinkedList<>(); + } else { + arrayLength = torrents.length; + torrentList = null; + } + + Pattern p = Pattern.compile("   ([^<>]*)"); + Matcher m = p.matcher(body); + while (m.find()) { + size++; + + if (size > arrayLength && torrentList == null) { + torrentList = new LinkedList<>(); + // Copy data + int copySize = size - 1; + for (int i = 0; i < copySize; i++) { + torrentList.add(torrents[i]); + } + } + + // Remove ?p= to make torrent redistributable + String url = m.group(1); + if (url == null) { + size--; + continue; + } + int index = url.indexOf("?p="); + if (index != -1) { + url = url.substring(0, index); + } + + Pair newItem = new Pair<>(url, Utils.unescapeXml(m.group(2))); + if (torrentList != null) { + torrentList.add(newItem); + } else { + torrents[size - 1] = newItem; + } + } + + if (torrentList != null) { + //noinspection unchecked,SuspiciousToArrayCall + return (Pair[]) torrentList.toArray(new Pair[torrentList.size()]); + } else if (size == arrayLength){ + return torrents; + } else { + //noinspection unchecked + Pair[] result = new Pair[size]; + System.arraycopy(torrents, 0, result, 0, size); + return result; + } + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/miscellaneous/Downloader.java b/app/src/main/java/com/hippo/ehviewer/miscellaneous/Downloader.java new file mode 100644 index 000000000..ce1f21a25 --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/miscellaneous/Downloader.java @@ -0,0 +1,88 @@ +package com.hippo.ehviewer.miscellaneous; + +import android.content.Context; + +import com.hippo.ehviewer.AppHandler; +import com.hippo.ehviewer.R; +import com.hippo.ehviewer.network.HttpHelper; +import com.hippo.ehviewer.util.BgThread; +import com.hippo.ehviewer.widget.MaterialToast; + +import java.io.File; + +public class Downloader implements Runnable, HttpHelper.OnDownloadListener { + + private Context mContext; + private String mUrl; + private File mDir; + private String mFilename; + + private boolean mIsRunning = false; + + public Downloader(Context context, String url, File dir, String filename) { + mContext = context.getApplicationContext(); + mUrl = url; + mDir = dir; + mFilename = filename; + } + + public boolean isRunning() { + return mIsRunning; + } + + public void startDownload() { + if (mIsRunning) { + return; + } + + mIsRunning = true; + new BgThread(this).start(); + MaterialToast.showToast(R.string.start_saving_torrent); + } + + public void post(Runnable runnable) { + AppHandler.getInstance().post(runnable); + } + + @Override + public void run() { + HttpHelper hh = new HttpHelper(mContext); + final boolean ok = HttpHelper.DOWNLOAD_OK_STR.equals( + hh.download(mUrl, mDir, mFilename, false, null, this)); + post(new Runnable() { + @Override + public void run() { + MaterialToast.showToast(ok ? + String.format(mContext.getString(R.string.save_torrent_successful), + mDir.getAbsolutePath() + File.separatorChar + mFilename) : + mContext.getString(R.string.save_torrent_failed)); + } + }); + mIsRunning = false; + } + + @Override + public void onDownloadStartConnect() { + // Empty + } + + @Override + public void onDownloadStartDownload(int totalSize) { + // Empty + } + + @Override + public void onDownloadStatusUpdate(int downloadSize, int totalSize) { + // Empty + } + + @Override + public void onDownloadOver(int status, String eMsg) { + // Empty + } + + @Override + public void onUpdateFilename(String newFilename) { + mFilename = newFilename; + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/network/HttpHelper.java b/app/src/main/java/com/hippo/ehviewer/network/HttpHelper.java index c5bbce4a7..cabdb7a19 100644 --- a/app/src/main/java/com/hippo/ehviewer/network/HttpHelper.java +++ b/app/src/main/java/com/hippo/ehviewer/network/HttpHelper.java @@ -32,6 +32,7 @@ import java.net.URL; import java.net.URLConnection; import java.net.URLEncoder; import java.net.UnknownHostException; +import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -45,6 +46,8 @@ import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Message; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; import android.webkit.MimeTypeMap; import com.hippo.ehviewer.AppHandler; @@ -80,13 +83,20 @@ public class HttpHelper { public static final int DOWNLOAD_FAIL_CODE = 0x1; public static final int DOWNLOAD_STOP_CODE = 0x2; + // User-Agent from H@H + public static final String DEFAULT_USER_AGENT = + "Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.12) " + + "Gecko/20080201 Firefox/2.0.0.12"; + public static final String USER_AGENT = DEFAULT_USER_AGENT; + //System.getProperty("http.agent", DEFAULT_USER_AGENT); + private static final String DEFAULT_CHARSET = "utf-8"; private static final String CHARSET_KEY = "charset="; // TODO Get proxy list from server private static String[] sProxyUrls = Config.DEFAULT_PROXY_URLS; private static volatile int sProxyIndex = MathUtils.random(0, sProxyUrls.length); - private static Object sProxyIndexLock = new Object(); + private static final Object sProxyIndexLock = new Object(); public class Package { public Object obj; @@ -252,7 +262,7 @@ public class HttpHelper { while (redirectionCount++ < Constants.MAX_REDIRECTS) { conn = (HttpURLConnection) url.openConnection(); conn.setInstanceFollowRedirects(false); - conn.setRequestProperty("User-Agent", Constants.userAgent); + conn.setRequestProperty("User-Agent", USER_AGENT); conn.setConnectTimeout(Config.getHttpConnectTimeout()); conn.setReadTimeout(Config.getHttpReadTimeout()); // Set cookie if necessary @@ -336,13 +346,40 @@ public class HttpHelper { return null; } + /** + * parse string like haha=hehe; fere=bfdgds + */ + public static @NonNull Map parseMap(@Nullable String raw) { + Map map = new HashMap<>(); + if (raw != null) { + String[] pieces = raw.split(";"); + for (String p : pieces) { + int index = p.indexOf('='); + if (index != -1) { + String key = p.substring(0, index).trim(); + String value = p.substring(index + 1).trim(); + + // value might be "blabla", remove " + int valueLength = value.length(); + if (value.length() > 1 && value.charAt(0) == '"' && + value.charAt(valueLength - 1) == '"') { + value = value.substring(1, valueLength - 1); + } + map.put(key, value); + } + } + } + + return map; + } + private interface RequestHelper { /** * Get the URL to connect * @return */ - public URL getUrl() throws MalformedURLException; + URL getUrl() throws MalformedURLException; /** * Add header or do something else for HttpURLConnection before connect @@ -350,7 +387,7 @@ public class HttpHelper { * @throws Exception */ - public void onBeforeConnect(HttpURLConnection conn) throws Exception; + void onBeforeConnect(HttpURLConnection conn) throws Exception; /** * Get what do you need from HttpURLConnection after connect @@ -359,13 +396,13 @@ public class HttpHelper { * @return * @throws Exception */ - public Object onAfterConnect(HttpURLConnection conn) throws Exception; + Object onAfterConnect(HttpURLConnection conn) throws Exception; /** * Handle exception * @param e */ - public void onGetException(Exception e); + void onGetException(Exception e); } /** @@ -707,19 +744,18 @@ public class HttpHelper { public void onGetException(Exception e) {} } - public static interface OnDownloadListener { - public void onDownloadStartConnect(); + public interface OnDownloadListener { + void onDownloadStartConnect(); /** * If totalSize -1 for can't get length info - * @param totalSize */ - public void onDownloadStartDownload(int totalSize); + void onDownloadStartDownload(int totalSize); /** * If totalSize -1 for can't get length info - * @param totalSize */ - public void onDownloadStatusUpdate(int downloadSize, int totalSize); - public void onDownloadOver(int status, String eMsg); + void onDownloadStatusUpdate(int downloadSize, int totalSize); + void onDownloadOver(int status, String eMsg); + void onUpdateFilename(String newFilename); } public static class DownloadControlor { @@ -822,6 +858,12 @@ public class HttpHelper { return null; } + public String getSuitableFilename(HttpURLConnection conn) { + String contentDisposition = conn.getHeaderField("Content-Disposition"); + Map map = parseMap(contentDisposition); + return map.get("filename"); + } + @Override public Object onAfterConnect(HttpURLConnection conn) throws Exception { // Check stop @@ -837,6 +879,11 @@ public class HttpHelper { if (mListener != null) mListener.onDownloadStartDownload(mContentLength); + String filename = getSuitableFilename(conn); + if (filename != null) { + mFileName = filename; + } + // Fix extension MimeTypeMap mime = MimeTypeMap.getSingleton(); String newExtension = mime.getExtensionFromMimeType(contentType); @@ -855,6 +902,11 @@ public class HttpHelper { } } + // TODO Should check first + if (mListener != null) { + mListener.onUpdateFilename(mFileName); + } + // Make sure parent exist mDir.mkdirs(); mFile = new File(mDir, mFileName); diff --git a/app/src/main/java/com/hippo/ehviewer/ui/GalleryDetailActivity.java b/app/src/main/java/com/hippo/ehviewer/ui/GalleryDetailActivity.java index 16104f7a7..42cd6c9b6 100644 --- a/app/src/main/java/com/hippo/ehviewer/ui/GalleryDetailActivity.java +++ b/app/src/main/java/com/hippo/ehviewer/ui/GalleryDetailActivity.java @@ -20,6 +20,7 @@ import android.animation.Animator; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.app.AlertDialog; +import android.app.Dialog; import android.content.ClipData; import android.content.ClipboardManager; import android.content.Context; @@ -34,9 +35,11 @@ import android.graphics.drawable.ColorDrawable; import android.graphics.drawable.Drawable; import android.net.Uri; import android.os.Bundle; +import android.support.annotation.NonNull; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.text.Html; +import android.util.Pair; import android.view.ContextThemeWrapper; import android.view.Gravity; import android.view.LayoutInflater; @@ -46,9 +49,12 @@ import android.view.View; import android.view.ViewGroup; import android.view.animation.AlphaAnimation; import android.view.animation.Animation; +import android.widget.AdapterView; +import android.widget.ArrayAdapter; import android.widget.EditText; import android.widget.FrameLayout; import android.widget.LinearLayout; +import android.widget.ListView; import android.widget.ScrollView; import android.widget.TextSwitcher; import android.widget.TextView; @@ -78,7 +84,9 @@ import com.hippo.ehviewer.drawable.OvalDrawable; import com.hippo.ehviewer.effect.ripple.RippleSalon; import com.hippo.ehviewer.ehclient.DetailUrlParser; import com.hippo.ehviewer.ehclient.EhClient; +import com.hippo.ehviewer.miscellaneous.Downloader; import com.hippo.ehviewer.service.DownloadService; +import com.hippo.ehviewer.util.AppConfig; import com.hippo.ehviewer.util.Config; import com.hippo.ehviewer.util.Constants; import com.hippo.ehviewer.util.Favorite; @@ -100,6 +108,7 @@ import com.hippo.ehviewer.widget.recyclerview.EasyRecyclerView; import com.hippo.ehviewer.widget.recyclerview.LinearDividerItemDecoration; import com.hippo.ehviewer.windowsanimate.WindowsAnimate; +import java.io.File; import java.util.LinkedHashMap; import java.util.LinkedList; import java.util.List; @@ -138,6 +147,7 @@ public class GalleryDetailActivity extends AbsTranslucentActivity private SuperButton mReadButton; private TextView mCategory; private TextView mMoreOfUploader; + private TextView mTorrent; private TextView mSimilar; private TextSwitcher mRatingText; private ProgressiveRatingBar mRating; @@ -332,6 +342,7 @@ public class GalleryDetailActivity extends AbsTranslucentActivity mReadButton = (SuperButton) findViewById(R.id.read); mCategory = (TextView) findViewById(R.id.category); mMoreOfUploader = (TextView) findViewById(R.id.more_of_uploader); + mTorrent = (TextView) findViewById(R.id.torrent); mSimilar = (TextView) findViewById(R.id.similar); mRatingText = (TextSwitcher) mDetailRate.findViewById(R.id.rating_text); mRating = (ProgressiveRatingBar) mDetailRate.findViewById(R.id.rating); @@ -356,6 +367,9 @@ public class GalleryDetailActivity extends AbsTranslucentActivity Drawable moreOfUploaderDrawable = mResources.getDrawable(R.drawable.ic_more_of_uploader); moreOfUploaderDrawable.setBounds(rect); mMoreOfUploader.setCompoundDrawables(null, moreOfUploaderDrawable, null, null); + Drawable torrentDrawable = mResources.getDrawable(R.drawable.ic_torrent); + torrentDrawable.setBounds(rect); + mTorrent.setCompoundDrawables(null, torrentDrawable, null, null); Drawable similarDrawable = mResources.getDrawable(R.drawable.ic_similar); similarDrawable.setBounds(rect); mSimilar.setCompoundDrawables(null, similarDrawable, null, null); @@ -398,6 +412,7 @@ public class GalleryDetailActivity extends AbsTranslucentActivity mReadButton.setOnClickListener(this); mCategory.setOnClickListener(this); mMoreOfUploader.setOnClickListener(this); + mTorrent.setOnClickListener(this); mSimilar.setOnClickListener(this); mRating.setOnUserRateListener(this); mFavorite.setOnClickListener(this); @@ -635,12 +650,18 @@ public class GalleryDetailActivity extends AbsTranslucentActivity mDetailActions.setVisibility(View.VISIBLE); mCategory.setText(Ui.getCategoryText(mGalleryInfo.category)); mCategoryDrawable.setColor(Ui.getCategoryColor(mGalleryInfo.category)); + mTorrent.setVisibility(View.GONE); // Detail mDividerAM.setVisibility(View.VISIBLE); mDetailMore.setVisibility(View.VISIBLE); if (mGalleryInfo instanceof GalleryDetail) { GalleryDetail galleryDetail = (GalleryDetail)mGalleryInfo; + + if (galleryDetail.torrents.length > 0) { + mTorrent.setVisibility(View.VISIBLE); + } + ((TextView)mDetailMore.findViewById(R.id.language)).setText( getString(R.string.language) + ": " + galleryDetail.language); ((TextView)mDetailMore.findViewById(R.id.posted)).setText(galleryDetail.posted); @@ -864,6 +885,8 @@ public class GalleryDetailActivity extends AbsTranslucentActivity intent.putExtra(GalleryListActivity.KEY_MODE, ListUrls.MODE_UPLOADER); intent.putExtra(GalleryListActivity.KEY_UPLOADER, mGalleryInfo.uploader); startActivity(intent); + } else if (v == mTorrent) { + showTorrentDialog(); } else if (v == mSimilar) { Intent intent = new Intent(this, GalleryListActivity.class); intent.setAction(GalleryListActivity.ACTION_GALLERY_LIST); @@ -1011,6 +1034,88 @@ public class GalleryDetailActivity extends AbsTranslucentActivity } } + private Dialog mTorrentDialog = null; + private View mTorrentProgress = null; + private ListView mTorrentListView = null; + + public void showTorrentDialog() { + if (mTorrentDialog != null) { + return; + } + + @SuppressLint("InflateParams") + View view = getLayoutInflater().inflate(R.layout.dialog_torrent, null); + mTorrentProgress = view.findViewById(R.id.progress); + mTorrentListView = (ListView) view.findViewById(R.id.list); + + mTorrentDialog = new MaterialAlertDialog.Builder(this) + .setTitle(R.string.torrent) + .setView(view, false) + .setNegativeButton(android.R.string.cancel) + .setOnDismissListener(new MaterialAlertDialog.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + mTorrentDialog = null; + mTorrentProgress = null; + mTorrentListView = null; + } + }).show(); + + final GalleryDetail galleryDetail = (GalleryDetail) mGalleryInfo; + mClient.getTorrent(galleryDetail.torrentUrl, galleryDetail.torrents, new EhClient.OnGetTorrentListener() { + @Override + public void onSuccess(@NonNull Pair[] torrents) { + galleryDetail.torrents = torrents; + + if (mTorrentProgress != null && mTorrentListView != null) { + mTorrentProgress.setVisibility(View.GONE); + mTorrentListView.setVisibility(View.VISIBLE); + + int length = torrents.length; + String[] data = new String[torrents.length]; + for (int i = 0; i < length; i++) { + data[i] = torrents[i].second; + } + mTorrentListView.setAdapter(new ArrayAdapter<>( + ViewUtils.sContextThemeWrapper, + R.layout.select_dialog_item, + data)); + mTorrentListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { + @Override + public void onItemClick(AdapterView parent, View view, int position, long id) { + if (mTorrentDialog != null) { + mTorrentDialog.dismiss(); + } + + File dir = AppConfig.getTorrentDir(); + if (dir == null) { + MaterialToast.showToast("Can't storage device"); // TODO + return; + } + + final String url = galleryDetail.torrents[position].first; + Downloader d = new Downloader( + GalleryDetailActivity.this, + url, + dir, + "a.torrent"); // Torrent will be updated + d.startDownload(); + } + }); + } + } + + @Override + public void onFailure(String eMsg) { + if (mTorrentDialog != null) { + mTorrentDialog.dismiss(); + } + + MaterialToast.showToast(eMsg); + } + }); + } + @Override public void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int oldTop, int oldRight, int oldBottom) { diff --git a/app/src/main/java/com/hippo/ehviewer/util/AppConfig.java b/app/src/main/java/com/hippo/ehviewer/util/AppConfig.java new file mode 100644 index 000000000..24e1b6e6e --- /dev/null +++ b/app/src/main/java/com/hippo/ehviewer/util/AppConfig.java @@ -0,0 +1,62 @@ +/* + * 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.util; + +import android.os.Environment; +import android.support.annotation.Nullable; + +import java.io.File; + +/** + * Something about this app + */ +public final class AppConfig { + + private static final String APP_DIRNAME = "EhViewer"; + private static final String CRASH_DIRNAME = "crash"; + private static final String DOWNLOAD_DIRNAME = "download"; + private static final String TORRENT_DIRNAME = "torrent"; + + public static @Nullable File getAppDir() { + if (Environment.getExternalStorageState() + .equals(Environment.MEDIA_MOUNTED)) { + return new File(Environment.getExternalStorageDirectory(), APP_DIRNAME); + } else { + return null; + } + } + + public static @Nullable File getFileInAppDir(String filename) { + File appFolder = getAppDir(); + if (appFolder != null) { + return new File(appFolder, filename); + } else { + return null; + } + } + + public static @Nullable File getCrashDir() { + return getFileInAppDir(CRASH_DIRNAME); + } + + public static @Nullable File getDownloadDir() { + return getFileInAppDir(DOWNLOAD_DIRNAME); + } + + public static @Nullable File getTorrentDir() { + return getFileInAppDir(TORRENT_DIRNAME); + } +} diff --git a/app/src/main/java/com/hippo/ehviewer/util/Constants.java b/app/src/main/java/com/hippo/ehviewer/util/Constants.java index 407ef371a..1aad0b013 100644 --- a/app/src/main/java/com/hippo/ehviewer/util/Constants.java +++ b/app/src/main/java/com/hippo/ehviewer/util/Constants.java @@ -24,8 +24,6 @@ public final class Constants { public static final int ANIMATE_TIME = 300; public static final int HTTP_TEMP_REDIRECT = 307; - public static String defaultUserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/32.0.1700.76 Safari/537.36"; - public static String userAgent = System.getProperty("http.agent", defaultUserAgent); public static final int DEFAULT_TIMEOUT = 5 * 1000; public static final int MAX_REDIRECTS = 5; diff --git a/app/src/main/res/layout/dialog_torrent.xml b/app/src/main/res/layout/dialog_torrent.xml new file mode 100644 index 000000000..2812278c2 --- /dev/null +++ b/app/src/main/res/layout/dialog_torrent.xml @@ -0,0 +1,18 @@ + + + + + + + + diff --git a/app/src/main/res/layout/gallery_detail.xml b/app/src/main/res/layout/gallery_detail.xml index 78ca67587..59718efbf 100644 --- a/app/src/main/res/layout/gallery_detail.xml +++ b/app/src/main/res/layout/gallery_detail.xml @@ -142,6 +142,18 @@ android:text="@string/more_of_uploader" android:textSize="@dimen/text_super_small" /> + + - \ No newline at end of file + diff --git a/app/src/main/res/layout/select_dialog_item.xml b/app/src/main/res/layout/select_dialog_item.xml index 609b953eb..e5f67b9f2 100644 --- a/app/src/main/res/layout/select_dialog_item.xml +++ b/app/src/main/res/layout/select_dialog_item.xml @@ -26,6 +26,8 @@ android:layout_height="wrap_content" android:minHeight="48dp" android:gravity="center_vertical" - android:paddingLeft="16dip" - android:paddingRight="16dip" + android:paddingLeft="16dp" + android:paddingRight="16dp" + android:paddingTop="8dp" + android:paddingBottom="8dp" android:ellipsize="marquee" /> diff --git a/app/src/main/res/values-zh-rCN/strings.xml b/app/src/main/res/values-zh-rCN/strings.xml index 9edf090a2..cc7cf9373 100644 --- a/app/src/main/res/values-zh-rCN/strings.xml +++ b/app/src/main/res/values-zh-rCN/strings.xml @@ -91,6 +91,9 @@ 上传者更多内容 没有更多评论 暂无评论,就等你了 + 开始保存种子 + 保存种子至 %s + 保存种子失败 点击重试 @@ -386,6 +389,7 @@ 确定 + 种子 分享 过滤 清除 diff --git a/app/src/main/res/values-zh-rHK/strings.xml b/app/src/main/res/values-zh-rHK/strings.xml index 82d920c7f..b792a1e3b 100644 --- a/app/src/main/res/values-zh-rHK/strings.xml +++ b/app/src/main/res/values-zh-rHK/strings.xml @@ -79,6 +79,9 @@ 上傳者更多內容 沒有更多評論 暫無評論,就等你了 + 開始保存種子 + 保存種子至 %s + 保存種子失敗 點擊重試 @@ -374,6 +377,7 @@ 確定 + 種子 分享 過濾 清除 diff --git a/app/src/main/res/values-zh-rTW/strings.xml b/app/src/main/res/values-zh-rTW/strings.xml index 1c2caf823..4f71af5e8 100644 --- a/app/src/main/res/values-zh-rTW/strings.xml +++ b/app/src/main/res/values-zh-rTW/strings.xml @@ -79,6 +79,9 @@ 上傳者更多內容 沒有更多評論 暫無評論,就等你了 + 開始儲存種子 + 儲存種子至 %s + 儲存種子失敗 點選重試 @@ -374,6 +377,7 @@ 確定 + 種子 分享 過濾 清除 diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 15330b9da..f483a2639 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -95,6 +95,9 @@ More of uploader No more comments No comment + Start saving torrent + Save torrent to %s + Failed to save torrent Click to retry @@ -411,6 +414,7 @@ Sure + Torrent share filter clear