@Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); restored = false; isFullscreen = getFullscreenPreferences(); UIHelper.ToggleFullscreen(this, isFullscreen); UIHelper.SetTheme(this, R.layout.activity_display_light_novel_content); UIHelper.SetActionBarDisplayHomeAsUp(this, true); // UI Helper uih = new DisplayNovelContentUIHelper(this); uih.prepareCompatSearchBox(webView); uih.prepareTopDownButton(); // custom link handler client = new BakaTsukiWebViewClient(this); webView = (NonLeakingWebView) findViewById(R.id.webViewContent); webView.setWebViewClient(client); webView.setWebChromeClient(new BakaTsukiWebChromeClient(this)); loadingText = (TextView) findViewById(R.id.emptyList); loadingBar = (ProgressBar) findViewById(R.id.loadProgress); tts = new DisplayNovelContentTTSHelper(this); Log.d(TAG, "OnCreate Completed."); }
@Override public boolean onKeyDown(int keyCode, KeyEvent event) { boolean useVolumeRocker = PreferenceManager.getDefaultSharedPreferences(this) .getBoolean(Constants.PREF_USE_VOLUME_FOR_SCROLL, false); if (useVolumeRocker) { int scrollSize = UIHelper.getIntFromPreferences(Constants.PREF_SCROLL_SIZE, 5) * 100; boolean invertScroll = PreferenceManager.getDefaultSharedPreferences(this) .getBoolean(Constants.PREF_INVERT_SCROLL, false); if (invertScroll) scrollSize = scrollSize * -1; if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) { webView.flingScroll(0, -scrollSize); Log.d("Volume", "Up Pressed"); return true; } else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) { webView.flingScroll(0, +scrollSize); Log.d("Volume", "Down Pressed"); return true; } else return super.onKeyDown(keyCode, event); } return super.onKeyDown(keyCode, event); }
@Override protected void onDestroy() { if (webView != null) { RelativeLayout rootView = (RelativeLayout) findViewById(R.id.rootView); rootView.removeView(webView); webView.removeAllViews(); webView.destroy(); } tts.unbindTtsService(); getWindow().clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON); super.onDestroy(); }
public void toggleProgressBar(boolean show) { if (webView == null || loadingBar == null || loadingText == null) return; synchronized (this) { if (show) { loadingText.setVisibility(TextView.VISIBLE); loadingBar.setVisibility(ProgressBar.VISIBLE); webView.setVisibility(ListView.GONE); } else { loadingText.setVisibility(TextView.GONE); loadingBar.setVisibility(ProgressBar.GONE); webView.setVisibility(ListView.VISIBLE); } } }
// region Search box @SuppressWarnings("deprecation") private void showSearchBox() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) webView.showFindDialog("", true); else { RelativeLayout searchBox = (RelativeLayout) findViewById(R.id.searchBox); searchBox.setVisibility(View.VISIBLE); } }
/** * Load chapter from DB * * @param pageModel * @param refresh */ @SuppressLint("NewApi") private void executeTask(PageModel pageModel, boolean refresh) { NonLeakingWebView webView = (NonLeakingWebView) findViewById(R.id.webViewContent); if (pageModel.isExternal()) { loadExternalUrl(pageModel, refresh); } else { isPageLoaded = false; task = new LoadNovelContentTask(pageModel, refresh, this); String key = TAG + ":" + pageModel.getPage(); boolean isAdded = LNReaderApplication.getInstance().addTask(key, task); if (isAdded) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) task.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR); else task.execute(); } else { if (UIHelper.getColorPreferences(this)) webView.loadData( "<p style='background: black; color: white;'>" + getResources().getString(R.string.background_task_load) + "</p>", "text/html", "utf-8"); else webView.loadData( "<p style='background: white; color: black;'>" + getResources().getString(R.string.background_task_load) + "</p>", "text/html", "utf-8"); LoadNovelContentTask tempTask = (LoadNovelContentTask) LNReaderApplication.getInstance().getTask(key); if (tempTask != null) { task = tempTask; task.owner = this; } toggleProgressBar(true); } } setPrevNextButtonState(pageModel); }
/** Setup webView */ @SuppressLint({"NewApi", "SetJavaScriptEnabled"}) private void setWebViewSettings() { NonLeakingWebView wv = (NonLeakingWebView) findViewById(R.id.webViewContent); wv.getSettings().setAllowFileAccess(true); wv.getSettings().setSupportZoom(UIHelper.getZoomPreferences(this)); wv.getSettings().setBuiltInZoomControls(UIHelper.getZoomPreferences(this)); wv.setDisplayZoomControl(UIHelper.getZoomControlPreferences(this)); wv.getSettings().setLoadWithOverviewMode(true); // wv.getSettings().setUseWideViewPort(true); wv.getSettings().setLoadsImagesAutomatically(getShowImagesPreferences()); if (UIHelper.getColorPreferences(this)) wv.setBackgroundColor(0); wv.getSettings().setJavaScriptEnabled(true); if (isPageLoaded) wv.loadUrl("javascript:toogleEnableBookmark(" + getBookmarkPreferences() + ")"); }
/** * Load chapter for external url (not hosted in Baka-Tsuki). Used local cache if available * (wac/mht). * * @param pageModel * @param refresh */ public void loadExternalUrl(PageModel pageModel, boolean refresh) { try { // check if .wac available String url = pageModel.getPage(); String wacName = Util.getSavedWacName(url); final NonLeakingWebView wv = (NonLeakingWebView) findViewById(R.id.webViewContent); if (!Util.isStringNullOrEmpty(wacName) && !refresh) { client.setExternalNeedSave(false); String[] urlParts = url.split("#", 2); if (urlParts.length == 2) { executeLoadWacTask(wacName, urlParts[1], url); } else executeLoadWacTask(wacName, "", url); } else { if (refresh) { Toast.makeText(this, "Refreshing WAC: " + wacName, Toast.LENGTH_SHORT).show(); Log.i(TAG, "Refreshing WAC: " + wacName); } else { Log.w(TAG, "WAC not available: " + wacName); } client.setExternalNeedSave(true); setWebViewSettings(); wv.loadUrl(url); Intent currIntent = this.getIntent(); currIntent.putExtra(Constants.EXTRA_PAGE, url); currIntent.putExtra(Constants.EXTRA_PAGE_IS_EXTERNAL, true); } setChapterTitle(pageModel); buildTOCMenu(pageModel); content = null; } catch (Exception ex) { Log.e(TAG, "Cannot load external content: " + pageModel.getPage(), ex); } }
/** * Used to move to the last read position upon receiving load complete event from webView client */ public void notifyLoadComplete() { isPageLoaded = true; if (webView != null && content != null) { // move to last read paragraph, delay after webView load the pages. webView.postDelayed( new Runnable() { @Override public void run() { int y = getIntent().getIntExtra(Constants.EXTRA_P_INDEX, content.getLastYScroll()); Log.d(TAG, "notifyLoadComplete(): Move to the saved pos: " + y); webView.loadUrl("javascript:goToParagraph(" + y + ")"); } }, UIHelper.getIntFromPreferences(Constants.PREF_KITKAT_WEBVIEW_FIX_DELAY, 500) + 100); } }
@Override public boolean onPrepareOptionsMenu(Menu menu) { super.onPrepareOptionsMenu(menu); _menu = menu; try { if (content != null) { setPrevNextButtonState(content.getPageModel()); _menu.findItem(R.id.menu_save_external).setVisible(false); _menu.findItem(R.id.menu_browser_back).setVisible(false); } else { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) _menu.findItem(R.id.menu_save_external).setVisible(true); _menu.findItem(R.id.menu_browser_back).setVisible(true); if (webView != null) _menu.findItem(R.id.menu_browser_back).setEnabled(webView.canGoBack()); } } catch (Exception e) { Log.w(TAG, "Cannot get current page model"); } return true; }
/** * Setup the chapter from DB, Internal page only Including JS for Bookmark highlighting, last read * position, and CSS * * @param loadedContent */ @SuppressLint("NewApi") public void setContent(NovelContentModel loadedContent) { this.content = loadedContent; try { PageModel pageModel = content.getPageModel(); if (content.getLastUpdate().getTime() < pageModel.getLastUpdate().getTime()) Toast.makeText( this, getResources() .getString( R.string.content_may_updated, content.getLastUpdate().toString(), pageModel.getLastUpdate().toString()), Toast.LENGTH_LONG) .show(); // load the contents here final NonLeakingWebView wv = (NonLeakingWebView) findViewById(R.id.webViewContent); setWebViewSettings(); int lastPos = content.getLastYScroll(); int pIndex = getIntent().getIntExtra(Constants.EXTRA_P_INDEX, -1); if (pIndex > 0) lastPos = pIndex; if (content.getLastZoom() > 0) { wv.setInitialScale((int) (content.getLastZoom() * 100)); } else { wv.setInitialScale(100); } StringBuilder html = new StringBuilder(); html.append("<html><head>"); html.append(DisplayNovelContentHtmlHelper.getCSSSheet()); html.append(DisplayNovelContentHtmlHelper.getViewPortMeta()); html.append( DisplayNovelContentHtmlHelper.prepareJavaScript( lastPos, content.getBookmarks(), getBookmarkPreferences())); html.append("</head><body onclick='toogleHighlight(this, event);' onload='setup();'>"); html.append(content.getContent()); html.append("</body></html>"); wv.loadDataWithBaseURL( UIHelper.getBaseUrl(this), html.toString(), "text/html", "utf-8", NonLeakingWebView.PREFIX_PAGEMODEL + content.getPage()); setChapterTitle(pageModel); Log.d( TAG, "Load Content: " + content.getLastXScroll() + " " + content.getLastYScroll() + " " + content.getLastZoom()); buildTOCMenu(pageModel); buildBookmarkMenu(); invalidateOptionsMenu(); Log.d(TAG, "Loaded: " + content.getPage()); Intent currIntent = this.getIntent(); currIntent.putExtra(Constants.EXTRA_PAGE, content.getPage()); currIntent.putExtra(Constants.EXTRA_PAGE_IS_EXTERNAL, false); } catch (Exception e) { Log.e(TAG, "Cannot load content.", e); } }
public void searchNext(View view) { webView.findNext(true); }
public void searchPrev(View view) { webView.findNext(false); }
public void goTop(View view) { webView.pageUp(true); }
/** Update last read chapter and the position. Run async */ @SuppressWarnings("deprecation") public void setLastReadState() { NonLeakingWebView wv = (NonLeakingWebView) findViewById(R.id.webViewContent); final float currentScale = wv.getScale(); final int lastY = wv.getScrollY() + wv.getBottom(); final int contentHeight = wv.getContentHeight(); new Thread( new Runnable() { @Override public void run() { if (content != null) { // save zoom level, position is updated from updateLastLine() content.setLastZoom(currentScale); try { content = NovelsDao.getInstance().updateNovelContent(content, false); } catch (Exception ex) { Log.e(TAG, "Error when saving state: " + ex.getMessage(), ex); } // check if complete read. if (contentHeight <= lastY) { if (content != null) { try { PageModel page = content.getPageModel(); if (!page.getPage().endsWith("&action=edit&redlink=1")) { page.setFinishedRead(true); NovelsDao.getInstance().updatePageModel(page); } } catch (Exception ex) { Log.e( TAG, "Error updating PageModel for Content: " + content.getPage(), ex); } } } Log.d( TAG, "Update Content:X=" + content.getLastXScroll() + ":Y=" + content.getLastYScroll() + ":Z=" + content.getLastZoom()); } // save for jump to last read. SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences( LNReaderApplication.getInstance()); SharedPreferences.Editor editor = sharedPrefs.edit(); String lastPage; if (content != null) { lastPage = content.getPage(); } else { lastPage = getIntent().getStringExtra(Constants.EXTRA_PAGE); } editor.putString(Constants.PREF_LAST_READ, lastPage); editor.commit(); Log.i(TAG, "Last Read State Update complete: " + lastPage); } }) .start(); }
public void goBottom(View view) { webView.pageDown(true); }
@Override public boolean onOptionsItemSelected(MenuItem item) { switch (item.getItemId()) { case R.id.menu_settings: Intent launchNewIntent = new Intent(this, DisplaySettingsActivity.class); startActivity(launchNewIntent); return true; case R.id.menu_refresh_chapter_content: /* * Implement code to refresh chapter content */ PageModel page = null; if (content != null) { try { page = content.getPageModel(); } catch (Exception e) { Log.e(TAG, "Cannot get current chapter.", e); } } else { String pageStr = getIntent().getStringExtra(Constants.EXTRA_PAGE); try { page = NovelsDao.getInstance().getExistingPageModel(new PageModel(pageStr), null); if (page == null) { // no page model, just url page = new PageModel(pageStr); page.setExternal(true); } } catch (Exception e) { Log.e(TAG, "Cannot get current chapter.", e); } } if (page != null) { executeTask(page, true); } return true; case R.id.invert_colors: /* * Implement code to invert colors */ UIHelper.ToggleColorPref(this); UIHelper.Recreate(this); return true; case R.id.menu_chapter_previous: /* * Implement code to move to previous chapter */ String currentPage = getIntent().getStringExtra(Constants.EXTRA_PAGE); try { if (novelDetails == null) novelDetails = NovelsDao.getInstance().getNovelDetails(content.getPageModel(), null, false); PageModel prev = novelDetails.getPrev( currentPage, UIHelper.getShowMissing(this), UIHelper.getShowRedlink(this)); if (prev != null) { jumpTo(prev); } else { Toast.makeText( this, getResources().getString(R.string.first_available_chapter), Toast.LENGTH_SHORT) .show(); } } catch (Exception e) { Log.e(TAG, "Cannot get previous chapter.", e); } return true; case R.id.menu_chapter_next: /* * Implement code to move to next chapter */ String currentPage2 = getIntent().getStringExtra(Constants.EXTRA_PAGE); try { if (novelDetails == null) novelDetails = NovelsDao.getInstance().getNovelDetails(content.getPageModel(), null, false); PageModel next = novelDetails.getNext( currentPage2, UIHelper.getShowMissing(this), UIHelper.getShowRedlink(this)); if (next != null) { jumpTo(next); } else { Toast.makeText( this, getResources().getString(R.string.last_available_chapter), Toast.LENGTH_SHORT) .show(); } } catch (Exception e) { Log.e(TAG, "Cannot get next chapter.", e); } return true; case R.id.menu_chapter_toc: if (tocMenu != null) tocMenu.show(); return true; case R.id.menu_search: showSearchBox(); return true; case R.id.menu_bookmarks_here: if (bookmarkMenu != null) bookmarkMenu.show(); return true; case R.id.menu_bookmarks: Intent bookmarkIntent = new Intent(this, DisplayBookmarkActivity.class); startActivity(bookmarkIntent); return true; case R.id.menu_downloads_list: Intent downloadsItent = new Intent(this, DownloadListActivity.class); startActivity(downloadsItent); return true; case R.id.menu_speak: tts.start(webView, content.getLastYScroll()); return true; case R.id.menu_pause_tts: tts.pause(); return true; case R.id.menu_save_external: // save based on current intent page name. String url = getIntent().getStringExtra(Constants.EXTRA_PAGE); NonLeakingWebView wv = (NonLeakingWebView) findViewById(R.id.webViewContent); if (!url.startsWith("http")) { url = getTitle().toString(); Log.w( TAG, "Current page is not started with http, resolve from current webView url: " + url); } if (wv != null && !Util.isStringNullOrEmpty(url)) wv.saveMyWebArchive(url); return true; case R.id.menu_browser_back: if (webView != null && webView.canGoBack()) { // only good for android 4.4++ webView.goBack(); } return true; case android.R.id.home: finish(); return true; default: return super.onOptionsItemSelected(item); } }