/* * Copyright 2017 lizhaotailang * * 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.marktony.zhihudaily.detail; import android.app.Activity; import android.content.ClipData; import android.content.ClipboardManager; import android.content.ContentValues; import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.database.Cursor; import android.net.Uri; import android.support.annotation.NonNull; import android.support.customtabs.CustomTabsIntent; import android.text.Html; import android.webkit.WebView; import com.android.volley.VolleyError; import com.google.gson.Gson; import com.google.gson.JsonSyntaxException; import com.marktony.zhihudaily.R; import com.marktony.zhihudaily.bean.DoubanMomentNews; import com.marktony.zhihudaily.bean.DoubanMomentStory; import com.marktony.zhihudaily.bean.StringModelImpl; import com.marktony.zhihudaily.bean.ZhihuDailyStory; import com.marktony.zhihudaily.customtabs.CustomFallback; import com.marktony.zhihudaily.customtabs.CustomTabActivityHelper; import com.marktony.zhihudaily.db.DatabaseHelper; import com.marktony.zhihudaily.interfaze.OnStringListener; import com.marktony.zhihudaily.util.Api; import com.marktony.zhihudaily.bean.BeanType; import com.marktony.zhihudaily.util.NetworkState; import java.util.ArrayList; import static android.content.Context.CLIPBOARD_SERVICE; import static android.content.Context.MODE_PRIVATE; /** * Created by lizhaotailang on 2016/12/27. */ public class DetailPresenter implements DetailContract.Presenter { private DetailContract.View view; private StringModelImpl model; private Context context; private ZhihuDailyStory zhihuDailyStory; private String guokrStory; private DoubanMomentStory doubanMomentStory; private SharedPreferences sp; private DatabaseHelper dbHelper; private Gson gson; // the four data come from the intent extra private BeanType type; private int id; private String title; private String coverUrl; public void setType(BeanType type) { this.type = type; } public void setId(int id) { this.id = id; } public void setTitle(String title) { this.title = title; } public void setCoverUrl(String coverUrl) { this.coverUrl = coverUrl; } public DetailPresenter(@NonNull Context context, @NonNull DetailContract.View view) { this.context = context; this.view = view; this.view.setPresenter(this); model = new StringModelImpl(context); sp = context.getSharedPreferences("user_settings", MODE_PRIVATE); dbHelper = new DatabaseHelper(context, "History.db", null, 5); gson = new Gson(); } @Override public void openInBrowser() { if (checkNull()) { view.showLoadingError(); return; } try { Intent intent = new Intent(Intent.ACTION_VIEW); switch (type) { case TYPE_ZHIHU: intent.setData(Uri.parse(zhihuDailyStory.getShare_url())); break; case TYPE_GUOKR: intent.setData(Uri.parse(Api.GUOKR_ARTICLE_LINK_V1 + id)); break; case TYPE_DOUBAN: intent.setData(Uri.parse(doubanMomentStory.getShort_url())); } context.startActivity(intent); } catch (android.content.ActivityNotFoundException ex){ view.showBrowserNotFoundError(); } } @Override public void shareAsText() { if (checkNull()) { view.showSharingError(); return; } try { Intent shareIntent = new Intent().setAction(Intent.ACTION_SEND).setType("text/plain"); String shareText = "" + title + " "; switch (type) { case TYPE_ZHIHU: shareText += zhihuDailyStory.getShare_url(); break; case TYPE_GUOKR: shareText += Api.GUOKR_ARTICLE_LINK_V1 + id; break; case TYPE_DOUBAN: shareText += doubanMomentStory.getShort_url(); } shareText = shareText + "\t\t\t" + context.getString(R.string.share_extra); shareIntent.putExtra(Intent.EXTRA_TEXT,shareText); context.startActivity(Intent.createChooser(shareIntent,context.getString(R.string.share_to))); } catch (android.content.ActivityNotFoundException ex){ view.showLoadingError(); } } @Override public void openUrl(WebView webView, String url) { if (sp.getBoolean("in_app_browser",true)) { CustomTabsIntent.Builder customTabsIntent = new CustomTabsIntent.Builder() .setToolbarColor(context.getResources().getColor(R.color.colorAccent)) .setShowTitle(true); CustomTabActivityHelper.openCustomTab( (Activity) context, customTabsIntent.build(), Uri.parse(url), new CustomFallback() { @Override public void openUri(Activity activity, Uri uri) { super.openUri(activity, uri); } } ); } else { try{ context.startActivity(new Intent(Intent.ACTION_VIEW).setData(Uri.parse(url))); } catch (android.content.ActivityNotFoundException ex){ view.showBrowserNotFoundError(); } } } @Override public void copyText() { if (checkNull()) { view.showCopyTextError(); return; } ClipboardManager manager = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE); ClipData clipData = null; switch (type) { case TYPE_ZHIHU: clipData = ClipData.newPlainText("text", Html.fromHtml(title + "\n" + zhihuDailyStory.getBody()).toString()); break; case TYPE_GUOKR: clipData = ClipData.newPlainText("text", Html.fromHtml(guokrStory).toString()); break; case TYPE_DOUBAN: clipData = ClipData.newPlainText("text", Html.fromHtml(title + "\n" + doubanMomentStory.getContent()).toString()); } manager.setPrimaryClip(clipData); view.showTextCopied(); } @Override public void copyLink() { if (checkNull()) { view.showCopyTextError(); return; } ClipboardManager manager = (ClipboardManager) context.getSystemService(CLIPBOARD_SERVICE); ClipData clipData = null; switch (type) { case TYPE_ZHIHU: clipData = ClipData.newPlainText("text", Html.fromHtml(zhihuDailyStory.getShare_url()).toString()); break; case TYPE_GUOKR: clipData = ClipData.newPlainText("text", Html.fromHtml(Api.GUOKR_ARTICLE_LINK_V1 + id).toString()); break; case TYPE_DOUBAN: clipData = ClipData.newPlainText("text", Html.fromHtml(doubanMomentStory.getOriginal_url()).toString()); } manager.setPrimaryClip(clipData); view.showTextCopied(); } @Override public void addToOrDeleteFromBookmarks() { String tmpTable = ""; String tmpId = ""; switch (type) { case TYPE_ZHIHU: tmpTable = "Zhihu"; tmpId = "zhihu_id"; break; case TYPE_GUOKR: tmpTable = "Guokr"; tmpId = "guokr_id"; break; case TYPE_DOUBAN: tmpTable = "Douban"; tmpId = "douban_id"; break; default: break; } if (queryIfIsBookmarked()) { // delete // update Zhihu set bookmark = 0 where zhihu_id = id ContentValues values = new ContentValues(); values.put("bookmark", 0); dbHelper.getWritableDatabase().update(tmpTable, values, tmpId + " = ?", new String[]{String.valueOf(id)}); values.clear(); view.showDeletedFromBookmarks(); } else { // add // update Zhihu set bookmark = 1 where zhihu_id = id ContentValues values = new ContentValues(); values.put("bookmark", 1); dbHelper.getWritableDatabase().update(tmpTable, values, tmpId + " = ?", new String[]{String.valueOf(id)}); values.clear(); view.showAddedToBookmarks(); } } @Override public boolean queryIfIsBookmarked() { if (id == 0 || type == null) { view.showLoadingError(); return false; } String tempTable = ""; String tempId = ""; switch (type) { case TYPE_ZHIHU: tempTable = "Zhihu"; tempId = "zhihu_id"; break; case TYPE_GUOKR: tempTable = "Guokr"; tempId = "guokr_id"; break; case TYPE_DOUBAN: tempTable = "Douban"; tempId = "douban_id"; break; default: break; } String sql = "select * from " + tempTable + " where " + tempId + " = ?"; Cursor cursor = dbHelper.getReadableDatabase() .rawQuery(sql, new String[]{String.valueOf(id)}); if (cursor.moveToFirst()) { do { int isBookmarked = cursor.getInt(cursor.getColumnIndex("bookmark")); if (isBookmarked == 1) { return true; } } while (cursor.moveToNext()); } cursor.close(); return false; } @Override public void requestData() { if (id == 0 || type == null) { view.showLoadingError(); return; } view.showLoading(); view.setTitle(title); view.showCover(coverUrl); // set the web view whether to show the image view.setImageMode(sp.getBoolean("no_picture_mode",false)); switch (type) { case TYPE_ZHIHU: if (NetworkState.networkConnected(context)) { model.load(Api.ZHIHU_NEWS + id, new OnStringListener() { @Override public void onSuccess(String result) { { Gson gson = new Gson(); try { zhihuDailyStory = gson.fromJson(result, ZhihuDailyStory.class); if (zhihuDailyStory.getBody() == null) { view.showResultWithoutBody(zhihuDailyStory.getShare_url()); } else { view.showResult(convertZhihuContent(zhihuDailyStory.getBody())); } } catch (JsonSyntaxException e) { view.showLoadingError(); } view.stopLoading(); } } @Override public void onError(VolleyError error) { view.stopLoading(); view.showLoadingError(); } }); } else { Cursor cursor = dbHelper.getReadableDatabase() .query("Zhihu", null, null, null, null, null, null); if (cursor.moveToFirst()) { do { if (cursor.getInt(cursor.getColumnIndex("zhihu_id")) == id) { String content = cursor.getString(cursor.getColumnIndex("zhihu_content")); try { zhihuDailyStory = gson.fromJson(content, ZhihuDailyStory.class); } catch (JsonSyntaxException e) { view.showResult(content); } view.showResult(convertZhihuContent(zhihuDailyStory.getBody())); } } while (cursor.moveToNext()); } cursor.close(); } break; case TYPE_GUOKR: if (NetworkState.networkConnected(context)) { model.load(Api.GUOKR_ARTICLE_LINK_V1 + id, new OnStringListener() { @Override public void onSuccess(String result) { convertGuokrContent(result); view.showResult(guokrStory); } @Override public void onError(VolleyError error) { view.showLoadingError(); } }); } else { Cursor cursor = dbHelper.getReadableDatabase() .query("Guokr", null, null, null, null, null, null); if (cursor.moveToFirst()) { do { if (cursor.getInt(cursor.getColumnIndex("guokr_id")) == id) { guokrStory = cursor.getString(cursor.getColumnIndex("guokr_content")); convertGuokrContent(guokrStory); view.showResult(guokrStory); break; } } while (cursor.moveToNext()); } cursor.close(); } break; case TYPE_DOUBAN: if (NetworkState.networkConnected(context)) { model.load(Api.DOUBAN_ARTICLE_DETAIL + id, new OnStringListener() { @Override public void onSuccess(String result) { try { doubanMomentStory = gson.fromJson(result, DoubanMomentStory.class); view.showResult(convertDoubanContent()); } catch (JsonSyntaxException e) { view.showLoadingError(); } } @Override public void onError(VolleyError error) { view.showLoadingError(); } }); } else { Cursor cursor = dbHelper.getReadableDatabase() .rawQuery("select douban_content from Douban where douban_id = " + id, null); if (cursor.moveToFirst()) { do { if (cursor.getCount() == 1) { doubanMomentStory = gson.fromJson(cursor.getString(0), DoubanMomentStory.class); view.showResult(convertDoubanContent()); } } while (cursor.moveToNext()); } cursor.close(); break; } default: view.stopLoading(); view.showLoadingError(); break; } view.stopLoading(); } @Override public void start() { } private String convertDoubanContent() { if (doubanMomentStory.getContent() == null) { return null; } String css; if ((context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES) { css = "<link rel=\"stylesheet\" href=\"file:///android_asset/douban_dark.css\" type=\"text/css\">"; } else { css = "<link rel=\"stylesheet\" href=\"file:///android_asset/douban_light.css\" type=\"text/css\">"; } String content = doubanMomentStory.getContent(); ArrayList<DoubanMomentNews.posts.thumbs> imageList = doubanMomentStory.getPhotos(); for (int i = 0; i < imageList.size(); i++) { String old = "<img id=\"" + imageList.get(i).getTag_name() + "\" />"; String newStr = "<img id=\"" + imageList.get(i).getTag_name() + "\" " + "src=\"" + imageList.get(i).getMedium().getUrl() + "\"/>"; content = content.replace(old, newStr); } StringBuilder builder = new StringBuilder(); builder.append( "<!DOCTYPE html>\n"); builder.append("<html lang=\"ZH-CN\" xmlns=\"http://www.w3.org/1999/xhtml\">\n"); builder.append("<head>\n<meta charset=\"utf-8\" />\n"); builder.append(css); builder.append("\n</head>\n<body>\n"); builder.append("<div class=\"container bs-docs-container\">\n"); builder.append("<div class=\"post-container\">\n"); builder.append(content); builder.append("</div>\n</div>\n</body>\n</html>"); return builder.toString(); } private String convertZhihuContent(String preResult) { preResult = preResult.replace("<div class=\"img-place-holder\">", ""); preResult = preResult.replace("<div class=\"headline\">", ""); // 在api中,css的地址是以一个数组的形式给出,这里需要设置 // in fact,in api,css addresses are given as an array // api中还有js的部分,这里不再解析js // javascript is included,but here I don't use it // 不再选择加载网络css,而是加载本地assets文件夹中的css // use the css file from local assets folder,not from network String css = "<link rel=\"stylesheet\" href=\"file:///android_asset/zhihu_daily.css\" type=\"text/css\">"; // 根据主题的不同确定不同的加载内容 // load content judging by different theme String theme = "<body className=\"\" onload=\"onLoaded()\">"; if ((context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES){ theme = "<body className=\"\" onload=\"onLoaded()\" class=\"night\">"; } return new StringBuilder() .append("<!DOCTYPE html>\n") .append("<html lang=\"en\" xmlns=\"http://www.w3.org/1999/xhtml\">\n") .append("<head>\n") .append("\t<meta charset=\"utf-8\" />") .append(css) .append("\n</head>\n") .append(theme) .append(preResult) .append("</body></html>").toString(); } private void convertGuokrContent(String content) { // 简单粗暴的去掉下载的div部分 this.guokrStory = content.replace("<div class=\"down\" id=\"down-footer\">\n" + " <img src=\"http://static.guokr.com/apps/handpick/images/c324536d.jingxuan-logo.png\" class=\"jingxuan-img\">\n" + " <p class=\"jingxuan-txt\">\n" + " <span class=\"jingxuan-title\">果壳精选</span>\n" + " <span class=\"jingxuan-label\">早晚给你好看</span>\n" + " </p>\n" + " <a href=\"\" class=\"app-down\" id=\"app-down-footer\">下载</a>\n" + " </div>\n" + "\n" + " <div class=\"down-pc\" id=\"down-pc\">\n" + " <img src=\"http://static.guokr.com/apps/handpick/images/c324536d.jingxuan-logo.png\" class=\"jingxuan-img\">\n" + " <p class=\"jingxuan-txt\">\n" + " <span class=\"jingxuan-title\">果壳精选</span>\n" + " <span class=\"jingxuan-label\">早晚给你好看</span>\n" + " </p>\n" + " <a href=\"http://www.guokr.com/mobile/\" class=\"app-down\">下载</a>\n" + " </div>", ""); // 替换css文件为本地文件 guokrStory = guokrStory.replace("<link rel=\"stylesheet\" href=\"http://static.guokr.com/apps/handpick/styles/d48b771f.article.css\" />", "<link rel=\"stylesheet\" href=\"file:///android_asset/guokr.article.css\" />"); // 替换js文件为本地文件 guokrStory = guokrStory.replace("<script src=\"http://static.guokr.com/apps/handpick/scripts/9c661fc7.base.js\"></script>", "<script src=\"file:///android_asset/guokr.base.js\"></script>"); if ((context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK) == Configuration.UI_MODE_NIGHT_YES){ guokrStory = guokrStory.replace("<div class=\"article\" id=\"contentMain\">", "<div class=\"article \" id=\"contentMain\" style=\"background-color:#212b30; color:#878787\">"); } } private boolean checkNull() { return (type == BeanType.TYPE_ZHIHU && zhihuDailyStory == null) || (type == BeanType.TYPE_GUOKR && guokrStory == null) || (type == BeanType.TYPE_DOUBAN && doubanMomentStory == null); } }