package io.github.mthli.Ninja.Activity;
import android.animation.ObjectAnimator;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.AlertDialog;
import android.app.SearchManager;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.media.MediaPlayer;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.Html;
import android.text.InputType;
import android.text.TextWatcher;
import android.text.method.KeyListener;
import android.view.*;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
import android.view.animation.DecelerateInterpolator;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
import android.webkit.ValueCallback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.widget.*;
import io.github.mthli.Ninja.Browser.AdBlock;
import io.github.mthli.Ninja.Browser.AlbumController;
import io.github.mthli.Ninja.Browser.BrowserContainer;
import io.github.mthli.Ninja.Browser.BrowserController;
import io.github.mthli.Ninja.Service.ClearService;
import io.github.mthli.Ninja.Task.ScreenshotTask;
import io.github.mthli.Ninja.Database.Record;
import io.github.mthli.Ninja.Database.RecordAction;
import io.github.mthli.Ninja.R;
import io.github.mthli.Ninja.Service.HolderService;
import io.github.mthli.Ninja.Unit.BrowserUnit;
import io.github.mthli.Ninja.Unit.IntentUnit;
import io.github.mthli.Ninja.Unit.ViewUnit;
import io.github.mthli.Ninja.View.*;
import org.askerov.dynamicgrid.DynamicGridView;
import java.util.*;
public class BrowserActivity extends Activity implements BrowserController {
// Sync with NinjaToast.show() 2000ms delay
private static final int DOUBLE_TAPS_QUIT_DEFAULT = 2000;
private SwitcherPanel switcherPanel;
private int anchor;
private float dimen156dp;
private float dimen144dp;
private float dimen117dp;
private float dimen108dp;
private float dimen48dp;
private HorizontalScrollView switcherScroller;
private LinearLayout switcherContainer;
private ImageButton switcherSetting;
private ImageButton switcherBookmarks;
private ImageButton switcherHistory;
private ImageButton switcherAdd;
private RelativeLayout omnibox;
private AutoCompleteTextView inputBox;
private ImageButton omniboxBookmark;
private ImageButton omniboxRefresh;
private ImageButton omniboxOverflow;
private ProgressBar progressBar;
private RelativeLayout searchPanel;
private EditText searchBox;
private ImageButton searchUp;
private ImageButton searchDown;
private ImageButton searchCancel;
private Button relayoutOK;
private FrameLayout contentFrame;
private class VideoCompletionListener implements MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener {
@Override
public boolean onError(MediaPlayer mp, int what, int extra) {
return false;
}
@Override
public void onCompletion(MediaPlayer mp) {
onHideCustomView();
}
}
private FullscreenHolder fullscreenHolder;
private View customView;
private VideoView videoView;
private int originalOrientation;
private WebChromeClient.CustomViewCallback customViewCallback;
private ValueCallback<Uri> uploadMsg = null;
private ValueCallback<Uri[]> filePathCallback = null;
private static boolean quit = false;
private boolean create = true;
private int shortAnimTime = 0;
private int mediumAnimTime = 0;
private int longAnimTime = 0;
private AlbumController currentAlbumController = null;
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent intent) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
filePathCallback.onReceiveValue(WebChromeClient.FileChooserParams.parseResult(resultCode, intent));
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
ActivityManager.TaskDescription description = new ActivityManager.TaskDescription(
getString(R.string.app_name),
BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher),
getResources().getColor(R.color.background_dark)
);
setTaskDescription(description);
}
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
anchor = Integer.valueOf(sp.getString(getString(R.string.sp_anchor), "1"));
if (anchor == 0) {
setContentView(R.layout.main_top);
} else {
setContentView(R.layout.main_bottom);
}
create = true;
shortAnimTime = getResources().getInteger(android.R.integer.config_shortAnimTime);
mediumAnimTime = getResources().getInteger(android.R.integer.config_mediumAnimTime);
longAnimTime = getResources().getInteger(android.R.integer.config_longAnimTime);
switcherPanel = (SwitcherPanel) findViewById(R.id.switcher_panel);
switcherPanel.setStatusListener(new SwitcherPanel.StatusListener() {
@Override
public void onFling() {}
@Override
public void onExpanded() {}
@Override
public void onCollapsed() {
inputBox.clearFocus();
}
});
dimen156dp = getResources().getDimensionPixelSize(R.dimen.layout_width_156dp);
dimen144dp = getResources().getDimensionPixelSize(R.dimen.layout_width_144dp);
dimen117dp = getResources().getDimensionPixelSize(R.dimen.layout_height_117dp);
dimen108dp = getResources().getDimensionPixelSize(R.dimen.layout_height_108dp);
dimen48dp = getResources().getDimensionPixelOffset(R.dimen.layout_height_48dp);
initSwitcherView();
initOmnibox();
initSearchPanel();
relayoutOK = (Button) findViewById(R.id.main_relayout_ok);
contentFrame = (FrameLayout) findViewById(R.id.main_content);
new AdBlock(this); // For AdBlock cold boot
dispatchIntent(getIntent());
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
setIntent(intent);
}
@Override
public void onResume() {
super.onResume();
IntentUnit.setContext(this);
if (create) {
return;
}
dispatchIntent(getIntent());
if (IntentUnit.isDBChange()) {
updateBookmarks();
updateAutoComplete();
IntentUnit.setDBChange(false);
}
if (IntentUnit.isSPChange()) {
for (AlbumController controller : BrowserContainer.list()) {
if (controller instanceof NinjaWebView) {
((NinjaWebView) controller).initPreferences();
}
}
IntentUnit.setSPChange(false);
}
}
private void dispatchIntent(Intent intent) {
Intent toHolderService = new Intent(this, HolderService.class);
IntentUnit.setClear(false);
stopService(toHolderService);
if (intent != null && intent.hasExtra(IntentUnit.OPEN)) { // From HolderActivity's menu
pinAlbums(intent.getStringExtra(IntentUnit.OPEN));
} else if (intent != null && intent.getAction() != null && intent.getAction().equals(Intent.ACTION_WEB_SEARCH)) { // From ActionMode and some others
pinAlbums(intent.getStringExtra(SearchManager.QUERY));
} else if (intent != null && filePathCallback != null) {
filePathCallback = null;
} else {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
if (sp.getBoolean(getString(R.string.sp_first), true)) {
String lang;
if (getResources().getConfiguration().locale.getLanguage().equals("zh")) {
lang = BrowserUnit.INTRODUCTION_ZH;
} else {
lang = BrowserUnit.INTRODUCTION_EN;
}
pinAlbums(BrowserUnit.BASE_URL + lang);
sp.edit().putBoolean(getString(R.string.sp_first), false).commit();
} else {
pinAlbums(null);
}
}
}
@Override
public void onPause() {
Intent toHolderService = new Intent(this, HolderService.class);
IntentUnit.setClear(false);
stopService(toHolderService);
create = false;
inputBox.clearFocus();
if (currentAlbumController != null && currentAlbumController instanceof NinjaRelativeLayout) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) currentAlbumController;
if (layout.getFlag() == BrowserUnit.FLAG_HOME) {
DynamicGridView gridView = (DynamicGridView) layout.findViewById(R.id.home_grid);
if (gridView.isEditMode()) {
gridView.stopEditMode();
relayoutOK.setVisibility(View.GONE);
omnibox.setVisibility(View.VISIBLE);
initHomeGrid(layout, true);
}
}
}
IntentUnit.setContext(this);
super.onPause();
}
@Override
public void onDestroy() {
Intent toHolderService = new Intent(this, HolderService.class);
IntentUnit.setClear(true);
stopService(toHolderService);
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
boolean exit = true;
if (sp.getBoolean(getString(R.string.sp_clear_quit), false)) {
Intent toClearService = new Intent(this, ClearService.class);
startService(toClearService);
exit = false;
}
BrowserContainer.clear();
IntentUnit.setContext(null);
super.onDestroy();
if (exit) {
System.exit(0); // For remove all WebView thread
}
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
if (currentAlbumController != null && currentAlbumController instanceof NinjaRelativeLayout) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) currentAlbumController;
if (layout.getFlag() == BrowserUnit.FLAG_HOME) {
DynamicGridView gridView = (DynamicGridView) layout.findViewById(R.id.home_grid);
if (gridView.isEditMode()) {
gridView.stopEditMode();
relayoutOK.setVisibility(View.GONE);
omnibox.setVisibility(View.VISIBLE);
}
}
}
hideSoftInput(inputBox);
hideSearchPanel();
if (switcherPanel.getStatus() != SwitcherPanel.Status.EXPANDED) {
switcherPanel.expanded();
}
super.onConfigurationChanged(newConfig);
float coverHeight = ViewUnit.getWindowHeight(this) - ViewUnit.getStatusBarHeight(this) - dimen108dp - dimen48dp;
switcherPanel.setCoverHeight(coverHeight);
switcherPanel.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() {
@Override
public void onGlobalLayout() {
switcherPanel.fixKeyBoardShowing(switcherPanel.getHeight());
switcherPanel.getViewTreeObserver().removeOnGlobalLayoutListener(this);
}
});
if (currentAlbumController != null && currentAlbumController instanceof NinjaRelativeLayout) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) currentAlbumController;
if (layout.getFlag() == BrowserUnit.FLAG_HOME) {
initHomeGrid(layout, true);
}
}
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
// When video fullscreen, just control the sound
return !(fullscreenHolder != null || customView != null || videoView != null) && onKeyCodeVolumeUp();
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
// When video fullscreen, just control the sound
return !(fullscreenHolder != null || customView != null || videoView != null) && onKeyCodeVolumeDown();
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
return showOverflow();
} else if (keyCode == KeyEvent.KEYCODE_BACK) {
// When video fullscreen, first close it
if (fullscreenHolder != null || customView != null || videoView != null) {
return onHideCustomView();
}
return onKeyCodeBack(true);
}
return false;
}
@Override
public boolean onKeyUp(int keyCode, KeyEvent event) {
// When video fullscreen, just control the sound
if (fullscreenHolder != null || customView != null || videoView != null) {
return false;
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP || keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
int vc = Integer.valueOf(sp.getString(getString(R.string.sp_volume), "1"));
if (vc != 2) {
return true;
}
}
return false;
}
private void initSwitcherView() {
switcherScroller = (HorizontalScrollView) findViewById(R.id.switcher_scroller);
switcherContainer = (LinearLayout) findViewById(R.id.switcher_container);
switcherSetting = (ImageButton) findViewById(R.id.switcher_setting);
switcherBookmarks = (ImageButton) findViewById(R.id.switcher_bookmarks);
switcherHistory = (ImageButton) findViewById(R.id.switcher_history);
switcherAdd = (ImageButton) findViewById(R.id.switcher_add);
switcherSetting.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(BrowserActivity.this, SettingActivity.class);
startActivity(intent);
}
});
switcherBookmarks.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addAlbum(BrowserUnit.FLAG_BOOKMARKS);
}
});
switcherHistory.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addAlbum(BrowserUnit.FLAG_HISTORY);
}
});
switcherAdd.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
addAlbum(BrowserUnit.FLAG_HOME);
}
});
}
private void initOmnibox() {
omnibox = (RelativeLayout) findViewById(R.id.main_omnibox);
inputBox = (AutoCompleteTextView) findViewById(R.id.main_omnibox_input);
omniboxBookmark = (ImageButton) findViewById(R.id.main_omnibox_bookmark);
omniboxRefresh = (ImageButton) findViewById(R.id.main_omnibox_refresh);
omniboxOverflow = (ImageButton) findViewById(R.id.main_omnibox_overflow);
progressBar = (ProgressBar) findViewById(R.id.main_progress_bar);
inputBox.setOnTouchListener(new SwipeToBoundListener(omnibox, new SwipeToBoundListener.BoundCallback() {
private KeyListener keyListener = inputBox.getKeyListener();
@Override
public boolean canSwipe() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(BrowserActivity.this);
boolean ob = sp.getBoolean(getString(R.string.sp_omnibox_control), true);
return !switcherPanel.isKeyBoardShowing() && ob;
}
@Override
public void onSwipe() {
inputBox.setKeyListener(null);
inputBox.setFocusable(false);
inputBox.setFocusableInTouchMode(false);
inputBox.clearFocus();
}
@Override
public void onBound(boolean canSwitch, boolean left) {
inputBox.setKeyListener(keyListener);
inputBox.setFocusable(true);
inputBox.setFocusableInTouchMode(true);
inputBox.setInputType(InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS);
inputBox.clearFocus();
if (canSwitch) {
AlbumController controller = nextAlbumController(left);
showAlbum(controller, false, false, true);
NinjaToast.show(BrowserActivity.this, controller.getAlbumTitle());
}
}
}));
inputBox.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (currentAlbumController == null) { // || !(actionId == EditorInfo.IME_ACTION_DONE)
return false;
}
String query = inputBox.getText().toString().trim();
if (query.isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return true;
}
updateAlbum(query);
hideSoftInput(inputBox);
return false;
}
});
updateBookmarks();
updateAutoComplete();
omniboxBookmark.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (!prepareRecord()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_add_bookmark_failed);
return;
}
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
String title = ninjaWebView.getTitle();
String url = ninjaWebView.getUrl();
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
if (action.checkBookmark(url)) {
action.deleteBookmark(url);
NinjaToast.show(BrowserActivity.this, R.string.toast_delete_bookmark_successful);
} else {
action.addBookmark(new Record(title, url, System.currentTimeMillis()));
NinjaToast.show(BrowserActivity.this, R.string.toast_add_bookmark_successful);
}
action.close();
updateBookmarks();
updateAutoComplete();
}
});
omniboxRefresh.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
if (currentAlbumController == null) {
NinjaToast.show(BrowserActivity.this, R.string.toast_refresh_failed);
return;
}
if (currentAlbumController instanceof NinjaWebView) {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
if (ninjaWebView.isLoadFinish()) {
ninjaWebView.reload();
} else {
ninjaWebView.stopLoading();
}
} else if (currentAlbumController instanceof NinjaRelativeLayout) {
final NinjaRelativeLayout layout = (NinjaRelativeLayout) currentAlbumController;
if (layout.getFlag() == BrowserUnit.FLAG_HOME) {
initHomeGrid(layout, true);
return;
}
initBHList(layout, true);
} else {
NinjaToast.show(BrowserActivity.this, R.string.toast_refresh_failed);
}
}
});
omniboxOverflow.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
showOverflow();
}
});
}
private void initHomeGrid(final NinjaRelativeLayout layout, boolean update) {
if (update) {
updateProgress(BrowserUnit.PROGRESS_MIN);
}
RecordAction action = new RecordAction(this);
action.open(false);
final List<GridItem> gridList = action.listGrid();
action.close();
DynamicGridView gridView = (DynamicGridView) layout.findViewById(R.id.home_grid);
TextView aboutBlank = (TextView) layout.findViewById(R.id.home_about_blank);
gridView.setEmptyView(aboutBlank);
final GridAdapter gridAdapter;
if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
gridAdapter = new GridAdapter(this, gridList, 3);
} else {
gridAdapter = new GridAdapter(this, gridList, 2);
}
gridView.setAdapter(gridAdapter);
gridAdapter.notifyDataSetChanged();
/* Wait for gridAdapter.notifyDataSetChanged() */
if (update) {
gridView.postDelayed(new Runnable() {
@Override
public void run() {
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
updateProgress(BrowserUnit.PROGRESS_MAX);
}
}, shortAnimTime);
}
gridView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
updateAlbum(gridList.get(position).getURL());
}
});
gridView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showGridMenu(gridList.get(position));
return true;
}
});
}
private void initBHList(final NinjaRelativeLayout layout, boolean update) {
if (update) {
updateProgress(BrowserUnit.PROGRESS_MIN);
}
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(false);
final List<Record> list;
if (layout.getFlag() == BrowserUnit.FLAG_BOOKMARKS) {
list = action.listBookmarks();
Collections.sort(list, new Comparator<Record>() {
@Override
public int compare(Record first, Record second) {
return first.getTitle().compareTo(second.getTitle());
}
});
} else if (layout.getFlag() == BrowserUnit.FLAG_HISTORY) {
list = action.listHistory();
} else {
list = new ArrayList<>();
}
action.close();
ListView listView = (ListView) layout.findViewById(R.id.record_list);
TextView textView = (TextView) layout.findViewById(R.id.record_list_empty);
listView.setEmptyView(textView);
final RecordAdapter adapter = new RecordAdapter(BrowserActivity.this, R.layout.record_item, list);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
/* Wait for adapter.notifyDataSetChanged() */
if (update) {
listView.postDelayed(new Runnable() {
@Override
public void run() {
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
updateProgress(BrowserUnit.PROGRESS_MAX);
}
}, shortAnimTime);
}
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
updateAlbum(list.get(position).getURL());
}
});
listView.setOnItemLongClickListener(new AdapterView.OnItemLongClickListener() {
@Override
public boolean onItemLongClick(AdapterView<?> parent, View view, int position, long id) {
showListMenu(adapter, list, position);
return true;
}
});
}
private void initSearchPanel() {
searchPanel = (RelativeLayout) findViewById(R.id.main_search_panel);
searchBox = (EditText) findViewById(R.id.main_search_box);
searchUp = (ImageButton) findViewById(R.id.main_search_up);
searchDown = (ImageButton) findViewById(R.id.main_search_down);
searchCancel = (ImageButton) findViewById(R.id.main_search_cancel);
searchBox.addTextChangedListener(new TextWatcher() {
@Override
public void beforeTextChanged(CharSequence s, int start, int count, int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before, int count) {
}
@Override
public void afterTextChanged(Editable s) {
if (currentAlbumController != null && currentAlbumController instanceof NinjaWebView) {
((NinjaWebView) currentAlbumController).findAllAsync(s.toString());
}
}
});
searchBox.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId != EditorInfo.IME_ACTION_DONE) {
return false;
}
if (searchBox.getText().toString().isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return true;
}
return false;
}
});
searchUp.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String query = searchBox.getText().toString();
if (query.isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return;
}
hideSoftInput(searchBox);
if (currentAlbumController instanceof NinjaWebView) {
((NinjaWebView) currentAlbumController).findNext(false);
}
}
});
searchDown.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String query = searchBox.getText().toString();
if (query.isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return;
}
hideSoftInput(searchBox);
if (currentAlbumController instanceof NinjaWebView) {
((NinjaWebView) currentAlbumController).findNext(true);
}
}
});
searchCancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
hideSearchPanel();
}
});
}
private synchronized void addAlbum(int flag) {
final AlbumController holder;
if (flag == BrowserUnit.FLAG_BOOKMARKS) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) getLayoutInflater().inflate(R.layout.record_list, null, false);
layout.setBrowserController(this);
layout.setFlag(BrowserUnit.FLAG_BOOKMARKS);
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
layout.setAlbumTitle(getString(R.string.album_title_bookmarks));
holder = layout;
initBHList(layout, false);
} else if (flag == BrowserUnit.FLAG_HISTORY) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) getLayoutInflater().inflate(R.layout.record_list, null, false);
layout.setBrowserController(this);
layout.setFlag(BrowserUnit.FLAG_HISTORY);
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
layout.setAlbumTitle(getString(R.string.album_title_history));
holder = layout;
initBHList(layout, false);
} else if (flag == BrowserUnit.FLAG_HOME) {
NinjaRelativeLayout layout = (NinjaRelativeLayout) getLayoutInflater().inflate(R.layout.home, null, false);
layout.setBrowserController(this);
layout.setFlag(BrowserUnit.FLAG_HOME);
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
layout.setAlbumTitle(getString(R.string.album_title_home));
holder = layout;
initHomeGrid(layout, true);
} else {
return;
}
final View albumView = holder.getAlbumView();
albumView.setVisibility(View.INVISIBLE);
BrowserContainer.add(holder);
switcherContainer.addView(albumView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.album_slide_in_up);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
albumView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animation animation) {
showAlbum(holder, false, true, true);
}
});
albumView.startAnimation(animation);
}
private synchronized void addAlbum(String title, final String url, final boolean foreground, final Message resultMsg) {
final NinjaWebView webView = new NinjaWebView(this);
webView.setBrowserController(this);
webView.setFlag(BrowserUnit.FLAG_NINJA);
webView.setAlbumCover(ViewUnit.capture(webView, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
webView.setAlbumTitle(title);
ViewUnit.bound(this, webView);
final View albumView = webView.getAlbumView();
if (currentAlbumController != null && (currentAlbumController instanceof NinjaWebView) && resultMsg != null) {
int index = BrowserContainer.indexOf(currentAlbumController) + 1;
BrowserContainer.add(webView, index);
switcherContainer.addView(albumView, index, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT));
} else {
BrowserContainer.add(webView);
switcherContainer.addView(albumView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
}
if (!foreground) {
ViewUnit.bound(this, webView);
webView.loadUrl(url);
webView.deactivate();
albumView.setVisibility(View.VISIBLE);
if (currentAlbumController != null) {
switcherScroller.smoothScrollTo(currentAlbumController.getAlbumView().getLeft(), 0);
}
return;
}
albumView.setVisibility(View.INVISIBLE);
Animation animation = AnimationUtils.loadAnimation(this, R.anim.album_slide_in_up);
animation.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationRepeat(Animation animation) {
}
@Override
public void onAnimationStart(Animation animation) {
albumView.setVisibility(View.VISIBLE);
}
@Override
public void onAnimationEnd(Animation animation) {
showAlbum(webView, false, true, false);
if (url != null && !url.isEmpty()) {
webView.loadUrl(url);
} else if (resultMsg != null) {
WebView.WebViewTransport transport = (WebView.WebViewTransport) resultMsg.obj;
transport.setWebView(webView);
resultMsg.sendToTarget();
}
}
});
albumView.startAnimation(animation);
}
private synchronized void pinAlbums(String url) {
hideSoftInput(inputBox);
hideSearchPanel();
switcherContainer.removeAllViews();
for (AlbumController controller : BrowserContainer.list()) {
if (controller instanceof NinjaWebView) {
((NinjaWebView) controller).setBrowserController(this);
} else if (controller instanceof NinjaRelativeLayout) {
((NinjaRelativeLayout) controller).setBrowserController(this);
}
switcherContainer.addView(controller.getAlbumView(), LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.MATCH_PARENT);
controller.getAlbumView().setVisibility(View.VISIBLE);
controller.deactivate();
}
if (BrowserContainer.size() < 1 && url == null) {
addAlbum(BrowserUnit.FLAG_HOME);
} else if (BrowserContainer.size() >= 1 && url == null) {
if (currentAlbumController != null) {
currentAlbumController.activate();
return;
}
int index = BrowserContainer.size() - 1;
currentAlbumController = BrowserContainer.get(index);
contentFrame.removeAllViews();
contentFrame.addView((View) currentAlbumController);
currentAlbumController.activate();
updateOmnibox();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switcherScroller.smoothScrollTo(currentAlbumController.getAlbumView().getLeft(), 0);
currentAlbumController.setAlbumCover(ViewUnit.capture(((View) currentAlbumController), dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
}
}, shortAnimTime);
} else { // When url != null
NinjaWebView webView = new NinjaWebView(this);
webView.setBrowserController(this);
webView.setFlag(BrowserUnit.FLAG_NINJA);
webView.setAlbumCover(ViewUnit.capture(webView, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
webView.setAlbumTitle(getString(R.string.album_untitled));
ViewUnit.bound(this, webView);
webView.loadUrl(url);
BrowserContainer.add(webView);
final View albumView = webView.getAlbumView();
albumView.setVisibility(View.VISIBLE);
switcherContainer.addView(albumView, LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT);
contentFrame.removeAllViews();
contentFrame.addView(webView);
if (currentAlbumController != null) {
currentAlbumController.deactivate();
}
currentAlbumController = webView;
currentAlbumController.activate();
updateOmnibox();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
switcherScroller.smoothScrollTo(currentAlbumController.getAlbumView().getLeft(), 0);
currentAlbumController.setAlbumCover(ViewUnit.capture(((View) currentAlbumController), dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
}
}, shortAnimTime);
}
}
@Override
public synchronized void showAlbum(AlbumController controller, boolean anim, final boolean expand, final boolean capture) {
if (controller == null || controller == currentAlbumController) {
switcherPanel.expanded();
return;
}
if (currentAlbumController != null && anim) {
currentAlbumController.deactivate();
final View rv = (View) currentAlbumController;
final View av = (View) controller;
Animation fadeOut = AnimationUtils.loadAnimation(this, R.anim.album_fade_out);
fadeOut.setAnimationListener(new Animation.AnimationListener() {
@Override
public void onAnimationRepeat(Animation animation) {}
@Override
public void onAnimationEnd(Animation animation) {}
@Override
public void onAnimationStart(Animation animation) {
contentFrame.removeAllViews();
contentFrame.addView(av);
}
});
rv.startAnimation(fadeOut);
} else {
if (currentAlbumController != null) {
currentAlbumController.deactivate();
}
contentFrame.removeAllViews();
contentFrame.addView((View) controller);
}
currentAlbumController = controller;
currentAlbumController.activate();
switcherScroller.smoothScrollTo(currentAlbumController.getAlbumView().getLeft(), 0);
updateOmnibox();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
if (expand) {
switcherPanel.expanded();
}
if (capture) {
currentAlbumController.setAlbumCover(ViewUnit.capture(((View) currentAlbumController), dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
}
}
}, shortAnimTime);
}
private synchronized void updateAlbum() {
if (currentAlbumController == null) {
return;
}
NinjaRelativeLayout layout = (NinjaRelativeLayout) getLayoutInflater().inflate(R.layout.home, null, false);
layout.setBrowserController(this);
layout.setFlag(BrowserUnit.FLAG_HOME);
layout.setAlbumCover(ViewUnit.capture(layout, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
layout.setAlbumTitle(getString(R.string.album_title_home));
initHomeGrid(layout, true);
int index = switcherContainer.indexOfChild(currentAlbumController.getAlbumView());
currentAlbumController.deactivate();
switcherContainer.removeView(currentAlbumController.getAlbumView());
contentFrame.removeAllViews(); ///
switcherContainer.addView(layout.getAlbumView(), index, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
contentFrame.addView(layout);
BrowserContainer.set(layout, index);
currentAlbumController = layout;
updateOmnibox();
}
private synchronized void updateAlbum(String url) {
if (currentAlbumController == null) {
return;
}
if (currentAlbumController instanceof NinjaWebView) {
((NinjaWebView) currentAlbumController).loadUrl(url);
updateOmnibox();
} else if (currentAlbumController instanceof NinjaRelativeLayout) {
NinjaWebView webView = new NinjaWebView(this);
webView.setBrowserController(this);
webView.setFlag(BrowserUnit.FLAG_NINJA);
webView.setAlbumCover(ViewUnit.capture(webView, dimen144dp, dimen108dp, false, Bitmap.Config.RGB_565));
webView.setAlbumTitle(getString(R.string.album_untitled));
ViewUnit.bound(this, webView);
int index = switcherContainer.indexOfChild(currentAlbumController.getAlbumView());
currentAlbumController.deactivate();
switcherContainer.removeView(currentAlbumController.getAlbumView());
contentFrame.removeAllViews(); ///
switcherContainer.addView(webView.getAlbumView(), index, new LinearLayout.LayoutParams(LinearLayout.LayoutParams.WRAP_CONTENT, LinearLayout.LayoutParams.WRAP_CONTENT));
contentFrame.addView(webView);
BrowserContainer.set(webView, index);
currentAlbumController = webView;
webView.activate();
webView.loadUrl(url);
updateOmnibox();
} else {
NinjaToast.show(this, R.string.toast_load_error);
}
}
@Override
public synchronized void removeAlbum(AlbumController controller) {
if (currentAlbumController == null || BrowserContainer.size() <= 1) {
switcherContainer.removeView(controller.getAlbumView());
BrowserContainer.remove(controller);
addAlbum(BrowserUnit.FLAG_HOME);
return;
}
if (controller != currentAlbumController) {
switcherContainer.removeView(controller.getAlbumView());
BrowserContainer.remove(controller);
} else {
switcherContainer.removeView(controller.getAlbumView());
int index = BrowserContainer.indexOf(controller);
BrowserContainer.remove(controller);
if (index >= BrowserContainer.size()) {
index = BrowserContainer.size() - 1;
}
showAlbum(BrowserContainer.get(index), false, false, false);
}
}
@Override
public void updateAutoComplete() {
RecordAction action = new RecordAction(this);
action.open(false);
List<Record> list = action.listBookmarks();
list.addAll(action.listHistory());
action.close();
final CompleteAdapter adapter = new CompleteAdapter(this, R.layout.complete_item, list);
inputBox.setAdapter(adapter);
adapter.notifyDataSetChanged();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
inputBox.setDropDownVerticalOffset(getResources().getDimensionPixelOffset(R.dimen.layout_height_6dp));
}
inputBox.setDropDownWidth(ViewUnit.getWindowWidth(this));
inputBox.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String url = ((TextView) view.findViewById(R.id.complete_item_url)).getText().toString();
inputBox.setText(Html.fromHtml(BrowserUnit.urlWrapper(url)), EditText.BufferType.SPANNABLE);
inputBox.setSelection(url.length());
updateAlbum(url);
hideSoftInput(inputBox);
}
});
}
@Override
public void updateBookmarks() {
if (currentAlbumController == null || !(currentAlbumController instanceof NinjaWebView)) {
omniboxBookmark.setImageDrawable(ViewUnit.getDrawable(this, R.drawable.bookmark_selector_dark));
return;
}
RecordAction action = new RecordAction(this);
action.open(false);
String url = ((NinjaWebView) currentAlbumController).getUrl();
if (action.checkBookmark(url)) {
omniboxBookmark.setImageDrawable(ViewUnit.getDrawable(this, R.drawable.bookmark_selector_blue));
} else {
omniboxBookmark.setImageDrawable(ViewUnit.getDrawable(this, R.drawable.bookmark_selector_dark));
}
action.close();
}
@Override
public void updateInputBox(String query) {
if (query != null) {
inputBox.setText(Html.fromHtml(BrowserUnit.urlWrapper(query)), EditText.BufferType.SPANNABLE);
} else {
inputBox.setText(null);
}
inputBox.clearFocus();
}
private void updateOmnibox() {
if (currentAlbumController == null) {
return;
}
if (currentAlbumController instanceof NinjaRelativeLayout) {
updateProgress(BrowserUnit.PROGRESS_MAX);
updateBookmarks();
updateInputBox(null);
} else if (currentAlbumController instanceof NinjaWebView) {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
updateProgress(ninjaWebView.getProgress());
updateBookmarks();
if (ninjaWebView.getUrl() == null && ninjaWebView.getOriginalUrl() == null) {
updateInputBox(null);
} else if (ninjaWebView.getUrl() != null) {
updateInputBox(ninjaWebView.getUrl());
} else {
updateInputBox(ninjaWebView.getOriginalUrl());
}
}
}
@Override
public synchronized void updateProgress(int progress) {
if (progress > progressBar.getProgress()) {
ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "progress", progress);
animator.setDuration(shortAnimTime);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
} else if (progress < progressBar.getProgress()) {
ObjectAnimator animator = ObjectAnimator.ofInt(progressBar, "progress", 0, progress);
animator.setDuration(shortAnimTime);
animator.setInterpolator(new DecelerateInterpolator());
animator.start();
}
updateBookmarks();
if (progress < BrowserUnit.PROGRESS_MAX) {
updateRefresh(true);
progressBar.setVisibility(View.VISIBLE);
} else {
updateRefresh(false);
progressBar.setVisibility(View.GONE);
}
}
private void updateRefresh(boolean running) {
if (running) {
omniboxRefresh.setImageDrawable(ViewUnit.getDrawable(this, R.drawable.cl_selector_dark));
} else {
omniboxRefresh.setImageDrawable(ViewUnit.getDrawable(this, R.drawable.refresh_selector));
}
}
@Override
public void openFileChooser(ValueCallback<Uri> uploadMsg) {
// Because Activity launchMode is singleInstance,
// so we can not get result from onActivityResult when Android 4.X,
// what a pity
//
// this.uploadMsg = uploadMsg;
// Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// intent.addCategory(Intent.CATEGORY_OPENABLE);
// intent.setType("*/*");
// startActivityForResult(Intent.createChooser(intent, getString(R.string.main_file_chooser)), IntentUnit.REQUEST_FILE_16);
uploadMsg.onReceiveValue(null);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_desc, null, false);
TextView textView = (TextView) layout.findViewById(R.id.dialog_desc);
textView.setText(R.string.dialog_content_upload);
builder.setView(layout);
builder.create().show();
}
@Override
public void showFileChooser(ValueCallback<Uri[]> filePathCallback, WebChromeClient.FileChooserParams fileChooserParams) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
this.filePathCallback = filePathCallback;
try {
Intent intent = fileChooserParams.createIntent();
startActivityForResult(intent, IntentUnit.REQUEST_FILE_21);
} catch (Exception e) {
NinjaToast.show(this, R.string.toast_open_file_manager_failed);
}
}
}
@Override
public void onCreateView(WebView view, final Message resultMsg) {
if (resultMsg == null) {
return;
}
switcherPanel.collapsed();
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
addAlbum(getString(R.string.album_untitled), null, true, resultMsg);
}
}, shortAnimTime);
}
@Override
public boolean onShowCustomView(View view, int requestedOrientation, WebChromeClient.CustomViewCallback callback) {
return onShowCustomView(view, callback);
}
@Override
public boolean onShowCustomView(View view, WebChromeClient.CustomViewCallback callback) {
if (view == null) {
return false;
}
if (customView != null && callback != null) {
callback.onCustomViewHidden();
return false;
}
customView = view;
originalOrientation = getRequestedOrientation();
fullscreenHolder = new FullscreenHolder(this);
fullscreenHolder.addView(
customView,
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
));
FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
decorView.addView(
fullscreenHolder,
new FrameLayout.LayoutParams(
FrameLayout.LayoutParams.MATCH_PARENT,
FrameLayout.LayoutParams.MATCH_PARENT
));
customView.setKeepScreenOn(true);
((View) currentAlbumController).setVisibility(View.GONE);
setCustomFullscreen(true);
if (view instanceof FrameLayout) {
if (((FrameLayout) view).getFocusedChild() instanceof VideoView) {
videoView = (VideoView) ((FrameLayout) view).getFocusedChild();
videoView.setOnErrorListener(new VideoCompletionListener());
videoView.setOnCompletionListener(new VideoCompletionListener());
}
}
customViewCallback = callback;
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE); // Auto landscape when video shows
return true;
}
@Override
public boolean onHideCustomView() {
if (customView == null || customViewCallback == null || currentAlbumController == null) {
return false;
}
FrameLayout decorView = (FrameLayout) getWindow().getDecorView();
if (decorView != null) {
decorView.removeView(fullscreenHolder);
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
try {
customViewCallback.onCustomViewHidden();
} catch (Throwable t) {}
}
customView.setKeepScreenOn(false);
((View) currentAlbumController).setVisibility(View.VISIBLE);
setCustomFullscreen(false);
fullscreenHolder = null;
customView = null;
if (videoView != null) {
videoView.setOnErrorListener(null);
videoView.setOnCompletionListener(null);
videoView = null;
}
setRequestedOrientation(originalOrientation);
return true;
}
@Override
public void onLongPress(String url) {
WebView.HitTestResult result;
if (!(currentAlbumController instanceof NinjaWebView)) {
return;
}
result = ((NinjaWebView) currentAlbumController).getHitTestResult();
final List<String> list = new ArrayList<>();
list.add(getString(R.string.main_menu_new_tab));
list.add(getString(R.string.main_menu_copy_link));
if (result != null && (result.getType() == WebView.HitTestResult.IMAGE_TYPE || result.getType() == WebView.HitTestResult.SRC_IMAGE_ANCHOR_TYPE)) {
list.add(getString(R.string.main_menu_save));
}
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_list, null, false);
builder.setView(layout);
ListView listView = (ListView) layout.findViewById(R.id.dialog_list);
DialogAdapter adapter = new DialogAdapter(this, R.layout.dialog_text_item, list);
listView.setAdapter(adapter);
adapter.notifyDataSetChanged();
final AlertDialog dialog = builder.create();
if (url != null || (result != null && result.getExtra() != null)) {
if (url == null) {
url = result.getExtra();
}
dialog.show();
}
final String target = url;
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String s = list.get(position);
if (s.equals(getString(R.string.main_menu_new_tab))) { // New tab
addAlbum(getString(R.string.album_untitled), target, false, null);
NinjaToast.show(BrowserActivity.this, R.string.toast_new_tab_successful);
} else if (s.equals(getString(R.string.main_menu_copy_link))) { // Copy link
BrowserUnit.copyURL(BrowserActivity.this, target);
} else if (s.equals(getString(R.string.main_menu_save))) { // Save
BrowserUnit.download(BrowserActivity.this, target, target, BrowserUnit.MIME_TYPE_IMAGE);
}
dialog.hide();
dialog.dismiss();
}
});
}
private boolean onKeyCodeVolumeUp() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
int vc = Integer.valueOf(sp.getString(getString(R.string.sp_volume), "1"));
if (vc == 0) { // Switch tabs
if (switcherPanel.isKeyBoardShowing()) {
return true;
}
AlbumController controller = nextAlbumController(false);
showAlbum(controller, false, false, true);
NinjaToast.show(this, controller.getAlbumTitle());
return true;
} else if (vc == 1 && currentAlbumController instanceof NinjaWebView) { // Scroll webpage
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
int height = ninjaWebView.getMeasuredHeight();
int scrollY = ninjaWebView.getScrollY();
int distance = Math.min(height, scrollY);
ObjectAnimator anim = ObjectAnimator.ofInt(ninjaWebView, "scrollY", scrollY, scrollY - distance);
anim.setDuration(mediumAnimTime);
anim.start();
return true;
}
return false;
}
private boolean onKeyCodeVolumeDown() {
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
int vc = Integer.valueOf(sp.getString(getString(R.string.sp_volume), "1"));
if (vc == 0) { // Switch tabs
if (switcherPanel.isKeyBoardShowing()) {
return true;
}
AlbumController controller = nextAlbumController(true);
showAlbum(controller, false, false, true);
NinjaToast.show(this, controller.getAlbumTitle());
return true;
} else if (vc == 1 && currentAlbumController instanceof NinjaWebView) {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
int height = ninjaWebView.getMeasuredHeight();
int scrollY = ninjaWebView.getScrollY();
int surplus = (int) (ninjaWebView.getContentHeight() * ViewUnit.getDensity(this) - height - scrollY);
int distance = Math.min(height, surplus);
ObjectAnimator anim = ObjectAnimator.ofInt(ninjaWebView, "scrollY", scrollY, scrollY + distance);
anim.setDuration(mediumAnimTime);
anim.start();
return true;
}
return false;
}
private boolean onKeyCodeBack(boolean douQ) {
hideSoftInput(inputBox);
if (switcherPanel.getStatus() != SwitcherPanel.Status.EXPANDED) {
switcherPanel.expanded();
} else if (currentAlbumController == null) {
finish();
} else if (currentAlbumController instanceof NinjaWebView) {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
if (ninjaWebView.canGoBack()) {
ninjaWebView.goBack();
} else {
updateAlbum();
}
} else if (currentAlbumController instanceof NinjaRelativeLayout) {
switch (currentAlbumController.getFlag()) {
case BrowserUnit.FLAG_BOOKMARKS:
updateAlbum();
break;
case BrowserUnit.FLAG_HISTORY:
updateAlbum();
break;
case BrowserUnit.FLAG_HOME:
if (douQ) {
doubleTapsQuit();
}
break;
default:
finish();
break;
}
} else {
finish();
}
return true;
}
private void doubleTapsQuit() {
final Timer timer = new Timer();
if (!quit) {
quit = true;
NinjaToast.show(this, R.string.toast_double_taps_quit);
timer.schedule(new TimerTask() {
@Override
public void run() {
quit = false;
timer.cancel();
}
}, DOUBLE_TAPS_QUIT_DEFAULT);
} else {
timer.cancel();
finish();
}
}
private void hideSoftInput(View view) {
view.clearFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
private void showSoftInput(View view) {
view.requestFocus();
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
}
private void hideSearchPanel() {
hideSoftInput(searchBox);
searchBox.setText("");
searchPanel.setVisibility(View.GONE);
omnibox.setVisibility(View.VISIBLE);
}
private void showSearchPanel() {
omnibox.setVisibility(View.GONE);
searchPanel.setVisibility(View.VISIBLE);
showSoftInput(searchBox);
}
private boolean showOverflow() {
final SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(this);
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_list, null, false);
builder.setView(layout);
final String[] array = getResources().getStringArray(R.array.main_overflow);
final List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList(array));
if (currentAlbumController != null && currentAlbumController instanceof NinjaRelativeLayout) {
stringList.remove(array[0]); // Go to top
stringList.remove(array[1]); // Add to home
stringList.remove(array[2]); // Find in page
stringList.remove(array[3]); // Screenshot
stringList.remove(array[4]); // Readability
stringList.remove(array[5]); // Share
NinjaRelativeLayout ninjaRelativeLayout = (NinjaRelativeLayout) currentAlbumController;
if (ninjaRelativeLayout.getFlag() != BrowserUnit.FLAG_HOME) {
stringList.remove(array[6]); // Relayout
}
} else if (currentAlbumController != null && currentAlbumController instanceof NinjaWebView) {
if (!sp.getBoolean(getString(R.string.sp_readability), false)) {
stringList.remove(array[4]); // Readability
}
stringList.remove(array[6]); // Relayout
}
ListView listView = (ListView) layout.findViewById(R.id.dialog_list);
DialogAdapter dialogAdapter = new DialogAdapter(this, R.layout.dialog_text_item, stringList);
listView.setAdapter(dialogAdapter);
dialogAdapter.notifyDataSetChanged();
final AlertDialog dialog = builder.create();
dialog.show();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, final int position, long id) {
String s = stringList.get(position);
if (s.equals(array[0])) { // Go to top
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
ObjectAnimator anim = ObjectAnimator.ofInt(ninjaWebView, "scrollY", ninjaWebView.getScrollY(), 0);
anim.setDuration(mediumAnimTime);
anim.start();
} else if (s.equals(array[1])) { // Add to home
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
if (action.checkGridItem(ninjaWebView.getUrl())) {
NinjaToast.show(BrowserActivity.this, R.string.toast_already_exist_in_home);
} else {
String title = ninjaWebView.getTitle().trim();
String url = ninjaWebView.getUrl().trim();
Bitmap bitmap = ViewUnit.capture(ninjaWebView, dimen156dp, dimen117dp, false, Bitmap.Config.ARGB_8888);
String filename = System.currentTimeMillis() + BrowserUnit.SUFFIX_PNG;
int ordinal = action.listGrid().size();
GridItem item = new GridItem(title, url, filename, ordinal);
if (BrowserUnit.bitmap2File(BrowserActivity.this, bitmap, filename) && action.addGridItem(item)) {
NinjaToast.show(BrowserActivity.this, R.string.toast_add_to_home_successful);
} else {
NinjaToast.show(BrowserActivity.this, R.string.toast_add_to_home_failed);
}
}
action.close();
} else if (s.equals(array[2])) { // Find in page
hideSoftInput(inputBox);
showSearchPanel();
} else if (s.equals(array[3])) { // Screenshot
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
new ScreenshotTask(BrowserActivity.this, ninjaWebView).execute();
} else if (s.equals(array[4])) { // Readability
String token = sp.getString(getString(R.string.sp_readability_token), null);
if (token == null || token.trim().isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_token_empty);
} else {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
Intent intent = new Intent(BrowserActivity.this, ReadabilityActivity.class);
intent.putExtra(IntentUnit.URL, ninjaWebView.getUrl());
startActivity(intent);
}
} else if (s.equals(array[5])) { // Share
if (!prepareRecord()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_share_failed);
} else {
NinjaWebView ninjaWebView = (NinjaWebView) currentAlbumController;
IntentUnit.share(BrowserActivity.this, ninjaWebView.getTitle(), ninjaWebView.getUrl());
}
} else if (s.equals(array[6])) { // Relayout
NinjaRelativeLayout ninjaRelativeLayout = (NinjaRelativeLayout) currentAlbumController;
final DynamicGridView gridView = (DynamicGridView) ninjaRelativeLayout.findViewById(R.id.home_grid);
final List<GridItem> gridList = ((GridAdapter) gridView.getAdapter()).getList();
omnibox.setVisibility(View.GONE);
relayoutOK.setVisibility(View.VISIBLE);
relayoutOK.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
relayoutOK.setTextColor(getResources().getColor(R.color.blue_500));
} else if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
relayoutOK.setTextColor(getResources().getColor(R.color.white));
}
return false;
}
});
relayoutOK.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
gridView.stopEditMode();
relayoutOK.setVisibility(View.GONE);
omnibox.setVisibility(View.VISIBLE);
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
action.clearGrid();
for (GridItem item : gridList) {
action.addGridItem(item);
}
action.close();
NinjaToast.show(BrowserActivity.this, R.string.toast_relayout_successful);
}
});
gridView.setOnDragListener(new DynamicGridView.OnDragListener() {
private GridItem dragItem;
@Override
public void onDragStarted(int position) {
dragItem = gridList.get(position);
}
@Override
public void onDragPositionsChanged(int oldPosition, int newPosition) {
if (oldPosition < newPosition) {
for (int i = newPosition; i > oldPosition; i--) {
GridItem item = gridList.get(i);
item.setOrdinal(i - 1);
}
} else if (oldPosition > newPosition) {
for (int i = newPosition; i < oldPosition; i++) {
GridItem item = gridList.get(i);
item.setOrdinal(i + 1);
}
}
dragItem.setOrdinal(newPosition);
Collections.sort(gridList, new Comparator<GridItem>() {
@Override
public int compare(GridItem first, GridItem second) {
if (first.getOrdinal() < second.getOrdinal()) {
return -1;
} else if (first.getOrdinal() > second.getOrdinal()) {
return 1;
} else {
return 0;
}
}
});
}
});
gridView.startEditMode();
} else if (s.equals(array[7])) { // Quit
finish();
}
dialog.hide();
dialog.dismiss();
}
});
return true;
}
private void showGridMenu(final GridItem gridItem) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_list, null, false);
builder.setView(layout);
final String[] array = getResources().getStringArray(R.array.list_menu);
final List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList(array));
stringList.remove(array[1]); // Copy link
stringList.remove(array[2]); // Share
ListView listView = (ListView) layout.findViewById(R.id.dialog_list);
DialogAdapter dialogAdapter = new DialogAdapter(this, R.layout.dialog_text_item, stringList);
listView.setAdapter(dialogAdapter);
dialogAdapter.notifyDataSetChanged();
final AlertDialog dialog = builder.create();
dialog.show();
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String s = stringList.get(position);
if (s.equals(array[0])) { // New tab
addAlbum(getString(R.string.album_untitled), gridItem.getURL(), false, null);
NinjaToast.show(BrowserActivity.this, R.string.toast_new_tab_successful);
} else if (s.equals(array[3])) { // Edit
showEditDialog(gridItem);
} else if (s.equals(array[4])) { // Delete
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
action.deleteGridItem(gridItem);
action.close();
BrowserActivity.this.deleteFile(gridItem.getFilename());
initHomeGrid((NinjaRelativeLayout) currentAlbumController, true);
NinjaToast.show(BrowserActivity.this, R.string.toast_delete_successful);
}
dialog.hide();
dialog.dismiss();
}
});
}
private void showListMenu(final RecordAdapter recordAdapter, final List<Record> recordList, final int location) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_list, null, false);
builder.setView(layout);
final String[] array = getResources().getStringArray(R.array.list_menu);
final List<String> stringList = new ArrayList<>();
stringList.addAll(Arrays.asList(array));
if (currentAlbumController.getFlag() != BrowserUnit.FLAG_BOOKMARKS) {
stringList.remove(array[3]);
}
ListView listView = (ListView) layout.findViewById(R.id.dialog_list);
DialogAdapter dialogAdapter = new DialogAdapter(this, R.layout.dialog_text_item, stringList);
listView.setAdapter(dialogAdapter);
dialogAdapter.notifyDataSetChanged();
final AlertDialog dialog = builder.create();
dialog.show();
final Record record = recordList.get(location);
listView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
String s = stringList.get(position);
if (s.equals(array[0])) { // New tab
addAlbum(getString(R.string.album_untitled), record.getURL(), false, null);
NinjaToast.show(BrowserActivity.this, R.string.toast_new_tab_successful);
} else if (s.equals(array[1])) { // Copy link
BrowserUnit.copyURL(BrowserActivity.this, record.getURL());
} else if (s.equals(array[2])) { // Share
IntentUnit.share(BrowserActivity.this, record.getTitle(), record.getURL());
} else if (s.equals(array[3])) { // Edit
showEditDialog(recordAdapter, recordList, location);
} else if (s.equals(array[4])) { // Delete
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
if (currentAlbumController.getFlag() == BrowserUnit.FLAG_BOOKMARKS) {
action.deleteBookmark(record);
} else if (currentAlbumController.getFlag() == BrowserUnit.FLAG_HISTORY) {
action.deleteHistory(record);
}
action.close();
recordList.remove(location);
recordAdapter.notifyDataSetChanged();
updateBookmarks();
updateAutoComplete();
NinjaToast.show(BrowserActivity.this, R.string.toast_delete_successful);
}
dialog.hide();
dialog.dismiss();
}
});
}
private void showEditDialog(final GridItem gridItem) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_edit, null, false);
builder.setView(layout);
final AlertDialog dialog = builder.create();
dialog.show();
final EditText editText = (EditText) layout.findViewById(R.id.dialog_edit);
editText.setHint(R.string.dialog_title_hint);
editText.setText(gridItem.getTitle());
editText.setSelection(gridItem.getTitle().length());
hideSoftInput(inputBox);
showSoftInput(editText);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId != EditorInfo.IME_ACTION_DONE) {
return false;
}
String text = editText.getText().toString().trim();
if (text.isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return true;
}
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
gridItem.setTitle(text);
action.updateGridItem(gridItem);
action.close();
hideSoftInput(editText);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
dialog.hide();
dialog.dismiss();
}
}, longAnimTime);
return false;
}
});
}
private void showEditDialog(final RecordAdapter recordAdapter, List<Record> recordList, int location) {
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setCancelable(true);
FrameLayout layout = (FrameLayout) getLayoutInflater().inflate(R.layout.dialog_edit, null, false);
builder.setView(layout);
final AlertDialog dialog = builder.create();
dialog.show();
final Record record = recordList.get(location);
final EditText editText = (EditText) layout.findViewById(R.id.dialog_edit);
editText.setHint(R.string.dialog_title_hint);
editText.setText(record.getTitle());
editText.setSelection(record.getTitle().length());
hideSoftInput(inputBox);
showSoftInput(editText);
editText.setOnEditorActionListener(new TextView.OnEditorActionListener() {
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId != EditorInfo.IME_ACTION_DONE) {
return false;
}
String text = editText.getText().toString().trim();
if (text.isEmpty()) {
NinjaToast.show(BrowserActivity.this, R.string.toast_input_empty);
return true;
}
RecordAction action = new RecordAction(BrowserActivity.this);
action.open(true);
record.setTitle(text);
action.updateBookmark(record);
action.close();
recordAdapter.notifyDataSetChanged();
hideSoftInput(editText);
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
dialog.hide();
dialog.dismiss();
}
}, longAnimTime);
return false;
}
});
}
private boolean prepareRecord() {
if (currentAlbumController == null || !(currentAlbumController instanceof NinjaWebView)) {
return false;
}
NinjaWebView webView = (NinjaWebView) currentAlbumController;
String title = webView.getTitle();
String url = webView.getUrl();
if (title == null
|| title.isEmpty()
|| url == null
|| url.isEmpty()
|| url.startsWith(BrowserUnit.URL_SCHEME_ABOUT)
|| url.startsWith(BrowserUnit.URL_SCHEME_MAIL_TO)
|| url.startsWith(BrowserUnit.URL_SCHEME_INTENT)) {
return false;
}
return true;
}
private void setCustomFullscreen(boolean fullscreen) {
WindowManager.LayoutParams layoutParams = getWindow().getAttributes();
/*
* Can not use View.SYSTEM_UI_FLAG_FULLSCREEN | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION,
* so we can not hide NavigationBar :(
*/
int bits = WindowManager.LayoutParams.FLAG_FULLSCREEN;
if (fullscreen) {
layoutParams.flags |= bits;
} else {
layoutParams.flags &= ~bits;
if (customView != null) {
customView.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
} else {
contentFrame.setSystemUiVisibility(View.SYSTEM_UI_FLAG_VISIBLE);
}
}
getWindow().setAttributes(layoutParams);
}
private AlbumController nextAlbumController(boolean next) {
if (BrowserContainer.size() <= 1) {
return currentAlbumController;
}
List<AlbumController> list = BrowserContainer.list();
int index = list.indexOf(currentAlbumController);
if (next) {
index++;
if (index >= list.size()) {
index = 0;
}
} else {
index--;
if (index < 0) {
index = list.size() - 1;
}
}
return list.get(index);
}
}