/* * Overchan Android (Meta Imageboard Client) * Copyright (C) 2014-2016 miku-nyan <https://github.com/miku-nyan> * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package nya.miku.wishmaster.ui; import java.io.File; import java.util.List; import nya.miku.wishmaster.R; import nya.miku.wishmaster.api.ChanModule; import nya.miku.wishmaster.api.models.UrlPageModel; import nya.miku.wishmaster.common.Logger; import nya.miku.wishmaster.common.MainApplication; import nya.miku.wishmaster.lib.FileDialogActivity; import nya.miku.wishmaster.lib.dslv.DragSortController; import nya.miku.wishmaster.lib.dslv.DragSortListView; import nya.miku.wishmaster.ui.tabs.LocalHandler; import nya.miku.wishmaster.ui.tabs.UrlHandler; import android.annotation.SuppressLint; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Resources; import android.graphics.Point; import android.os.Build; import android.os.Bundle; import android.support.v4.app.Fragment; import android.text.TextUtils; import android.view.ContextMenu; import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import android.view.ContextMenu.ContextMenuInfo; import android.view.inputmethod.InputMethodManager; import android.widget.AdapterView; import android.widget.ArrayAdapter; import android.widget.Button; import android.widget.EditText; import android.widget.LinearLayout; import android.widget.ListAdapter; import android.widget.TextView; import android.widget.Toast; public class NewTabFragment extends Fragment implements AdapterView.OnItemClickListener, View.OnClickListener { private static final String TAG = "NewTabFragment"; private static final int REQUEST_FILE = 500; private MainActivity activity; private Resources resources; private DragSortListView listView; private QuickAccessAdapter adapter; private List<QuickAccess.Entry> list; private View addressBar; private boolean addressBarOpened = false; private Button openAddressBar; private EditText addressField; private Button addressGo; private Button openLocal; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); activity = (MainActivity) getActivity(); resources = MainApplication.getInstance().resources; list = QuickAccess.getQuickAccessFromPreferences(); adapter = new QuickAccessAdapter(activity, list); } @SuppressLint("ClickableViewAccessibility") @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { activity.setTitle(R.string.tabs_newtab); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) CompatibilityImpl.setActionBarDefaultIcon(activity); View v = inflater.inflate(R.layout.newtab_fragment, container, false); listView = (DragSortListView) v.findViewById(android.R.id.list); DragSortController controller = new DragSortController(listView, R.id.newtab_quickaccess_drag_handle, DragSortController.ON_DRAG, 0) { @Override public View onCreateFloatView(int position) { return adapter.getView(position, null, listView); } @Override public void onDragFloatView(View floatView, Point floatPoint, Point touchPoint) {} @Override public void onDestroyFloatView(View floatView) {} }; listView.setAdapter(adapter); listView.setOnItemClickListener(this); listView.setDragEnabled(true); listView.setFloatViewManager(controller); listView.setOnTouchListener(controller); listView.setDropListener(new DragSortListView.DropListener() { @Override public void drop(int from, int to) { if (from != to) { QuickAccess.Entry moved = list.remove(from); list.add(to, moved); adapter.setDraggingItem(-1); saveQuickAccessToPreferences(); } } }); registerForContextMenu(listView); addressBar = v.findViewById(R.id.newtab_address_bar); openAddressBar = (Button) v.findViewById(R.id.newtab_open_address_bar); openAddressBar.setOnClickListener(this); addressField = (EditText) v.findViewById(R.id.newtab_address_field); addressField.setOnKeyListener(new View.OnKeyListener() { @Override public boolean onKey(View v, int keyCode, KeyEvent event) { if ((event.getAction() == KeyEvent.ACTION_DOWN) && (keyCode == KeyEvent.KEYCODE_ENTER)) { onClick(v); return true; } return false; } }); addressGo = (Button) v.findViewById(R.id.newtab_address_go); addressGo.setOnClickListener(this); openLocal = (Button) v.findViewById(R.id.newtab_open_local); openLocal.setOnClickListener(this); return v; } /** * Обновить список (в случае изменения параметра отображения пункта-списка всех досок) */ public void updateList() { try { list = QuickAccess.getQuickAccessFromPreferences(); adapter = new QuickAccessAdapter(activity, list); listView.setAdapter(adapter); } catch (Exception e) { Logger.e(TAG, e); } } @Override public void onClick(View v) { switch (v.getId()) { case R.id.newtab_open_address_bar: if (addressBarOpened) { hideKeyboard(v); addressBar.setVisibility(View.GONE); addressBarOpened = false; } else { addressBar.setVisibility(View.VISIBLE); addressField.requestFocus(); showKeyboard(v); addressBarOpened = true; } break; case R.id.newtab_open_local: hideKeyboard(v); openLocal(); break; case R.id.newtab_address_go: case R.id.newtab_address_field: String url = addressField.getText().toString(); if (url.length() == 0) return; hideKeyboard(v); openNewTab(url); break; } } @Override public void onItemClick(AdapterView<?> parent, View view, int position, long id) { adapter.setDraggingItem(-1); hideKeyboard(listView); QuickAccess.Entry entry = adapter.getItem(position); if (entry.chan == null) { openChansList(); } else { UrlPageModel model = new UrlPageModel(); model.chanName = entry.chan.getChanName(); model.type = entry.boardName == null ? UrlPageModel.TYPE_INDEXPAGE : UrlPageModel.TYPE_BOARDPAGE; if (entry.boardName != null) { model.boardName = entry.boardName; model.boardPage = UrlPageModel.DEFAULT_FIRST_PAGE; } openNewTab(entry.chan.buildUrl(model)); } } @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); if (list.size() > 1) { menu.add(Menu.NONE, R.id.context_menu_quickaccess_move, 1, R.string.context_menu_move); } QuickAccess.Entry entry = adapter.getItem(((AdapterView.AdapterContextMenuInfo) menuInfo).position); if (entry.chan == null) return; menu.add(Menu.NONE, R.id.context_menu_quickaccess_remove, 2, R.string.context_menu_quickaccess_remove); } @Override public boolean onContextItemSelected(MenuItem item) { int position = ((AdapterView.AdapterContextMenuInfo) item.getMenuInfo()).position; switch (item.getItemId()) { case R.id.context_menu_quickaccess_move: adapter.setDraggingItem(position); return true; case R.id.context_menu_quickaccess_remove: list.remove(position); adapter.notifyDataSetChanged(); saveQuickAccessToPreferences(); return true; } return false; } private void openLocal() { if (!CompatibilityUtils.hasAccessStorage(activity)) return; final ListAdapter savedThreadsAdapter = new ArrayAdapter<Object>(activity, 0) { private static final int HEAD_ITEM = 0; private static final int NORMAL_ITEM = 1; private LayoutInflater inflater = LayoutInflater.from(activity); private int drawablePadding = (int) (resources.getDisplayMetrics().density * 5 + 0.5f); { add(new Object()); for (Database.SavedThreadEntry entity : MainApplication.getInstance().database.getSavedThreads()) { File file = new File(entity.filepath); if (file.exists()) add(entity); } } @Override public View getView(int position, View convertView, ViewGroup parent) { View v; if (position == 0) { v = convertView == null ? inflater.inflate(android.R.layout.simple_list_item_1, parent, false) : convertView; TextView tv = (TextView) v.findViewById(android.R.id.text1); tv.setText(R.string.newtab_select_local_file); } else { Database.SavedThreadEntry item = (Database.SavedThreadEntry) getItem(position); v = convertView == null ? inflater.inflate(android.R.layout.simple_list_item_2, parent, false) : convertView; TextView t1 = (TextView) v.findViewById(android.R.id.text1); TextView t2 = (TextView) v.findViewById(android.R.id.text2); t1.setSingleLine(); t2.setSingleLine(); t1.setEllipsize(TextUtils.TruncateAt.END); t2.setEllipsize(TextUtils.TruncateAt.START); t1.setText(item.title); t2.setText(item.filepath); ChanModule chan = MainApplication.getInstance().getChanModule(item.chan); if (chan != null) { t1.setCompoundDrawablesWithIntrinsicBounds(chan.getChanFavicon(), null, null, null); t1.setCompoundDrawablePadding(drawablePadding); } } return v; } @Override public int getViewTypeCount() { return 2; } @Override public int getItemViewType(int position) { return position == 0 ? HEAD_ITEM : NORMAL_ITEM; } }; if (savedThreadsAdapter.getCount() == 1) { selectFile(); return; } DialogInterface.OnClickListener listListener = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { if (which == 0) { selectFile(); } else { Database.SavedThreadEntry item = (Database.SavedThreadEntry) savedThreadsAdapter.getItem(which); LocalHandler.open(item.filepath, activity); } } }; new AlertDialog.Builder(activity). setTitle(R.string.newtab_saved_threads_title). setAdapter(savedThreadsAdapter, listListener). setNegativeButton(android.R.string.cancel, null). show(); } private void selectFile() { Intent selectFile = new Intent(activity, FileDialogActivity.class); selectFile.putExtra(FileDialogActivity.SELECTION_MODE, FileDialogActivity.SELECTION_MODE_OPEN); selectFile.putExtra(FileDialogActivity.FORMAT_FILTER, new String[] { ".zip", ".mhtml", ".html" }); selectFile.putExtra(FileDialogActivity.START_PATH, MainApplication.getInstance().settings.getDownloadDirectory().getAbsolutePath()); startActivityForResult(selectFile, REQUEST_FILE); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == REQUEST_FILE && resultCode == Activity.RESULT_OK) { String path = data.getStringExtra(FileDialogActivity.RESULT_PATH); LocalHandler.open(path, activity); } } private void openNewTab(String url) { UrlHandler.open(url, activity, MainApplication.getInstance().settings.useFakeBrowser()); } private void showKeyboard(View v) { try { ((InputMethodManager) activity.getSystemService(Context.INPUT_METHOD_SERVICE)). toggleSoftInputFromWindow(v.getWindowToken(), InputMethodManager.SHOW_FORCED, 0); } catch (Exception e) { Logger.e(TAG, e); } } private void hideKeyboard(View v) { try { InputMethodManager imm = (InputMethodManager)activity.getSystemService(Context.INPUT_METHOD_SERVICE); imm.hideSoftInputFromWindow(v.getWindowToken(), 0); } catch (Exception e) { Logger.e(TAG, e); } } private static boolean isSingleboardChan(ChanModule chan) { try { UrlPageModel index = new UrlPageModel(); index.type = UrlPageModel.TYPE_INDEXPAGE; index.chanName = chan.getChanName(); index = chan.parseUrl(chan.buildUrl(index)); return index.type != UrlPageModel.TYPE_INDEXPAGE; } catch (Exception e) { Logger.e(TAG, e); } return false; } private void openChansList() { final ArrayAdapter<ChanModule> chansAdapter = new ArrayAdapter<ChanModule>(activity, 0) { private LayoutInflater inflater = LayoutInflater.from(activity); private int drawablePadding = (int) (resources.getDisplayMetrics().density * 5 + 0.5f); { for (ChanModule chan : MainApplication.getInstance().chanModulesList) add(chan); } @Override public View getView(int position, View convertView, ViewGroup parent) { ChanModule chan = getItem(position); TextView view = (TextView) (convertView == null ? inflater.inflate(android.R.layout.simple_list_item_1, parent, false) : convertView); view.setText(chan.getDisplayingName()); view.setCompoundDrawablesWithIntrinsicBounds(chan.getChanFavicon(), null, null, null); view.setCompoundDrawablePadding(drawablePadding); return view; } }; DialogInterface.OnClickListener onChanSelected = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { ChanModule chan = chansAdapter.getItem(which); UrlPageModel model = new UrlPageModel(); model.chanName = chan.getChanName(); model.type = UrlPageModel.TYPE_INDEXPAGE; openNewTab(chan.buildUrl(model)); } }; final AlertDialog chansListDialog = new AlertDialog.Builder(activity). setTitle(R.string.newtab_quickaccess_all_boards). setAdapter(chansAdapter, onChanSelected). setNegativeButton(android.R.string.cancel, null). create(); chansListDialog.getListView().setOnCreateContextMenuListener(new View.OnCreateContextMenuListener() { @Override public void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { MenuItem.OnMenuItemClickListener contextMenuHandler = new MenuItem.OnMenuItemClickListener() { @SuppressLint("InlinedApi") @Override public boolean onMenuItemClick(MenuItem item) { final ChanModule chan = chansAdapter.getItem(((AdapterView.AdapterContextMenuInfo) item.getMenuInfo()).position); switch (item.getItemId()) { case R.id.context_menu_favorites_from_fragment: if (MainApplication.getInstance().database.isFavorite(chan.getChanName(), null, null, null)) { MainApplication.getInstance().database.removeFavorite(chan.getChanName(), null, null, null); } else { try { UrlPageModel indexPage = new UrlPageModel(); indexPage.chanName = chan.getChanName(); indexPage.type = UrlPageModel.TYPE_INDEXPAGE; MainApplication.getInstance().database.addFavorite( chan.getChanName(), null, null, null, chan.getChanName(), chan.buildUrl(indexPage)); } catch (Exception e) { Logger.e(TAG, e); } } return true; case R.id.context_menu_quickaccess_add: QuickAccess.Entry newEntry = new QuickAccess.Entry(); newEntry.chan = chan; list.add(0, newEntry); adapter.notifyDataSetChanged(); saveQuickAccessToPreferences(); chansListDialog.dismiss(); return true; case R.id.context_menu_quickaccess_custom_board: LinearLayout dialogLayout = new LinearLayout(activity); dialogLayout.setOrientation(LinearLayout.VERTICAL); final EditText boardField = new EditText(activity); final EditText descriptionField = new EditText(activity); boardField.setHint(R.string.newtab_quickaccess_addcustom_boardcode); descriptionField.setHint(R.string.newtab_quickaccess_addcustom_boarddesc); LinearLayout.LayoutParams fieldsParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.WRAP_CONTENT); dialogLayout.addView(boardField, fieldsParams); dialogLayout.addView(descriptionField, fieldsParams); DialogInterface.OnClickListener onOkClicked = new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { String boardName = boardField.getText().toString(); for (QuickAccess.Entry entry : list) if (entry.boardName != null && entry.chan != null) if (entry.chan.getChanName().equals(chan.getChanName()) && entry.boardName.equals(boardName)) { Toast.makeText(activity, R.string.newtab_quickaccess_addcustom_already_exists, Toast.LENGTH_LONG).show(); return; } try { if (boardName.trim().length() == 0) throw new Exception(); UrlPageModel boardPageModel = new UrlPageModel(); boardPageModel.type = UrlPageModel.TYPE_BOARDPAGE; boardPageModel.chanName = chan.getChanName(); boardPageModel.boardName = boardName; boardPageModel.boardPage = UrlPageModel.DEFAULT_FIRST_PAGE; chan.buildUrl(boardPageModel); //проверка, что существование такой доски на данной имиджборде возможно } catch (Exception e) { Toast.makeText(activity, R.string.newtab_quickaccess_addcustom_incorrect_code, Toast.LENGTH_LONG).show(); return; } QuickAccess.Entry newEntry = new QuickAccess.Entry(); newEntry.chan = chan; newEntry.boardName = boardName; newEntry.boardDescription = descriptionField.getText().toString(); list.add(0, newEntry); adapter.notifyDataSetChanged(); saveQuickAccessToPreferences(); chansListDialog.dismiss(); } }; new AlertDialog.Builder(activity). setTitle(resources.getString(R.string.newtab_quickaccess_addcustom_title, chan.getChanName())). setView(dialogLayout). setPositiveButton(android.R.string.ok, onOkClicked). setNegativeButton(android.R.string.cancel, null). show(); return true; } return false; } }; String thisChanName = chansAdapter.getItem(((AdapterView.AdapterContextMenuInfo) menuInfo).position).getChanName(); boolean canAddToQuickAccess = true; for (QuickAccess.Entry entry : list) if (entry.boardName == null && entry.chan != null && entry.chan.getChanName().equals(thisChanName)) { canAddToQuickAccess = false; break; } menu.add(Menu.NONE, R.id.context_menu_favorites_from_fragment, 1, MainApplication.getInstance().database.isFavorite(thisChanName, null, null, null) ? R.string.context_menu_remove_favorites : R.string.context_menu_add_favorites). setOnMenuItemClickListener(contextMenuHandler); menu.add(Menu.NONE, R.id.context_menu_quickaccess_add, 2, R.string.context_menu_quickaccess_add). setOnMenuItemClickListener(contextMenuHandler). setVisible(canAddToQuickAccess); menu.add(Menu.NONE, R.id.context_menu_quickaccess_custom_board, 3, R.string.context_menu_quickaccess_custom_board). setOnMenuItemClickListener(contextMenuHandler); if (isSingleboardChan(chansAdapter.getItem(((AdapterView.AdapterContextMenuInfo) menuInfo).position))) menu.findItem(R.id.context_menu_quickaccess_custom_board).setVisible(false); } }); chansListDialog.show(); } private static class QuickAccessAdapter extends ArrayAdapter<QuickAccess.Entry> { private Resources resources; private LayoutInflater inflater; private int drawablePadding; private int draggingItem = -1; public QuickAccessAdapter(Activity activity, List<QuickAccess.Entry> list) { super(activity, 0, list); this.resources = MainApplication.getInstance().resources; this.inflater = LayoutInflater.from(activity); this.drawablePadding = (int) (resources.getDisplayMetrics().density * 5 + 0.5f); } @Override public View getView(int position, View convertView, ViewGroup parent) { QuickAccess.Entry entry = getItem(position); View view = (convertView == null ? inflater.inflate(R.layout.newtab_quickaccess_item, parent, false) : convertView); TextView tv = (TextView) view.findViewById(R.id.newtab_quickaccess_text); if (entry.chan != null) { tv.setText(entry.boardName == null ? entry.chan.getDisplayingName() : resources.getString(R.string.boardslist_format, entry.boardName, entry.boardDescription)); tv.setCompoundDrawablesWithIntrinsicBounds(entry.chan.getChanFavicon(), null, null, null); tv.setCompoundDrawablePadding(drawablePadding); } else { tv.setText(R.string.newtab_quickaccess_all_boards); tv.setCompoundDrawablesWithIntrinsicBounds(null, null, null, null); } View dragHandler = view.findViewById(R.id.newtab_quickaccess_drag_handle); dragHandler.getLayoutParams().width = position == draggingItem ? ViewGroup.LayoutParams.WRAP_CONTENT : 0; dragHandler.setLayoutParams(dragHandler.getLayoutParams()); return view; } public void setDraggingItem(int position) { if (draggingItem != position) { draggingItem = position; notifyDataSetChanged(); } } } private void saveQuickAccessToPreferences() { QuickAccess.saveQuickAccessToPreferences(list); } }