/* * Copyright (C) 2014 Arpit Khurana <arpitkh96@gmail.com>, Vishal Nehra <vishalmeham2@gmail.com> * * This file is part of Amaze File Manager. * * Amaze File Manager 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 com.amaze.filemanager.fragments; import android.content.ComponentName; import android.content.Context; import android.content.Intent; import android.content.ServiceConnection; import android.content.SharedPreferences; import android.content.res.Resources; import android.content.res.TypedArray; import android.database.Cursor; import android.graphics.drawable.ColorDrawable; import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.IBinder; import android.preference.PreferenceManager; import android.provider.MediaStore; import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; import android.util.DisplayMetrics; import android.view.ActionMode; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; import android.view.ViewTreeObserver; import android.view.Window; import android.widget.TextView; import android.widget.Toast; import com.amaze.filemanager.R; import com.amaze.filemanager.activities.MainActivity; import com.amaze.filemanager.adapters.RarAdapter; import com.amaze.filemanager.filesystem.BaseFile; import com.amaze.filemanager.services.DeleteTask; import com.amaze.filemanager.services.ExtractService; import com.amaze.filemanager.services.asynctasks.RarHelperTask; import com.amaze.filemanager.services.asynctasks.ZipHelperTask; import com.amaze.filemanager.ui.ZipObj; import com.amaze.filemanager.ui.views.DividerItemDecoration; import com.amaze.filemanager.ui.views.FastScroller; import com.amaze.filemanager.utils.OpenMode; import com.amaze.filemanager.utils.ServiceWatcherUtil; import com.amaze.filemanager.utils.Utils; import com.amaze.filemanager.utils.color.ColorUsage; import com.amaze.filemanager.utils.provider.UtilitiesProviderInterface; import com.amaze.filemanager.utils.theme.AppTheme; import com.github.junrar.Archive; import com.github.junrar.rarfile.FileHeader; import com.timehop.stickyheadersrecyclerview.StickyRecyclerHeadersDecoration; import java.io.File; import java.util.ArrayList; import java.util.Calendar; public class ZipViewer extends Fragment { private UtilitiesProviderInterface utilsProvider; public String s; public File f; /** * files to be deleted from cache * with a Map maintaining key - the root of directory created (for deletion purposes after we exit out of here * and value - the path of file to open */ public ArrayList<BaseFile> files; public Boolean selection = false; public String current; public String skin, accentColor, iconskin, year; public RarAdapter rarAdapter; public ActionMode mActionMode; public boolean coloriseIcons, showSize, showLastModified, gobackitem; SharedPreferences Sp; ZipViewer zipViewer = this; public Archive archive; public ArrayList<FileHeader> wholelistRar = new ArrayList<>(); public ArrayList<FileHeader> elementsRar = new ArrayList<>(); public ArrayList<ZipObj> wholelist = new ArrayList<>(); public ArrayList<ZipObj> elements = new ArrayList<>(); public MainActivity mainActivity; public RecyclerView listView; View rootView; boolean addheader = true; public SwipeRefreshLayout swipeRefreshLayout; StickyRecyclerHeadersDecoration headersDecor; LinearLayoutManager mLayoutManager; DividerItemDecoration dividerItemDecoration; boolean showDividers; public int paddingTop; int mToolbarHeight, hidemode; View mToolbarContainer; public Resources res; int openmode; //0 for zip 1 for rar boolean stopAnims=true; public boolean isOpen = false; // flag states whether to open file after service extracts it public static final String KEY_CACHE_FILES = "cache_files"; public static final String KEY_PATH = "path"; public static final String KEY_URI = "uri"; public static final String KEY_OPEN_MODE = "open_mode"; public static final String KEY_FILE = "file"; public static final String KEY_WHOLE_LIST = "whole_list"; public static final String KEY_ELEMENTS = "elements"; public static final String KEY_OPEN = "is_open"; @Override public void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); utilsProvider = (UtilitiesProviderInterface) getActivity(); } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { rootView = inflater.inflate(R.layout.main_frag, container, false); mainActivity = (MainActivity) getActivity(); listView = (RecyclerView) rootView.findViewById(R.id.listView); listView.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if(stopAnims) if ((!rarAdapter.stoppedAnimation) ) { stopAnim(); } rarAdapter.stoppedAnimation = true; stopAnims=false; return false; } }); swipeRefreshLayout = (SwipeRefreshLayout) rootView.findViewById(R.id.activity_main_swipe_refresh_layout); swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refresh(); } }); return rootView; } public void stopAnim(){ for (int j = 0; j < listView.getChildCount(); j++) { View v=listView.getChildAt(j); if(v!=null)v.clearAnimation(); } } @Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); Sp = PreferenceManager.getDefaultSharedPreferences(getActivity()); s = getArguments().getString(KEY_PATH); Uri uri=Uri.parse(s); f = new File(uri.getPath()); mToolbarContainer = getActivity().findViewById(R.id.lin); mToolbarContainer.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View view, MotionEvent motionEvent) { if(stopAnims) { if ((!rarAdapter.stoppedAnimation) ) { stopAnim(); } rarAdapter.stoppedAnimation = true; }stopAnims=false; return false; } }); hidemode = Sp.getInt("hidemode", 0); listView.setVisibility(View.VISIBLE); mLayoutManager = new LinearLayoutManager(getActivity()); listView.setLayoutManager(mLayoutManager); res = getResources(); mainActivity.supportInvalidateOptionsMenu(); if (utilsProvider.getAppTheme().equals(AppTheme.DARK)) rootView.setBackgroundColor(Utils.getColor(getContext(), R.color.holo_dark_background)); else listView.setBackgroundColor(Utils.getColor(getContext(), android.R.color.background_light)); gobackitem = Sp.getBoolean("goBack_checkbox", false); coloriseIcons = Sp.getBoolean("coloriseIcons", true); Calendar calendar = Calendar.getInstance(); showSize = Sp.getBoolean("showFileSize", false); showLastModified = Sp.getBoolean("showLastModified", true); showDividers = Sp.getBoolean("showDividers", true); year = ("" + calendar.get(Calendar.YEAR)).substring(2, 4); skin = mainActivity.getColorPreference().getColorAsString(ColorUsage.PRIMARY); accentColor = mainActivity.getColorPreference().getColorAsString(ColorUsage.ACCENT); iconskin = mainActivity.getColorPreference().getColorAsString(ColorUsage.ICON_SKIN); //mainActivity.findViewById(R.id.buttonbarframe).setBackgroundColor(Color.parseColor(skin)); if (savedInstanceState == null && f != null) { files = new ArrayList<>(); // adding a cache file to delete where any user interaction elements will be cached String fileName = f.getName().substring(0, f.getName().lastIndexOf(".")); files.add(new BaseFile(getActivity().getExternalCacheDir().getPath() + "/" + fileName)); if (f.getPath().endsWith(".rar")) { openmode = 1; SetupRar(null); } else { openmode = 0; SetupZip(null); } } else { f = new File(savedInstanceState.getString(KEY_FILE)); s = savedInstanceState.getString(KEY_URI); uri = Uri.parse(s); f = new File(uri.getPath()); files = savedInstanceState.getParcelableArrayList(KEY_CACHE_FILES); isOpen = savedInstanceState.getBoolean(KEY_OPEN); if (f.getPath().endsWith(".rar")) { openmode = 1; SetupRar(savedInstanceState); } else { openmode = 0; SetupZip(savedInstanceState); } } String fileName=null; try { if (uri.getScheme().equals(KEY_FILE)) { fileName = uri.getLastPathSegment(); } else { Cursor cursor = null; try { cursor = getActivity().getContentResolver().query(uri, new String[]{ MediaStore.Images.ImageColumns.DISPLAY_NAME }, null, null, null); if (cursor != null && cursor.moveToFirst()) { fileName = cursor.getString(cursor.getColumnIndex(MediaStore.Images.ImageColumns.DISPLAY_NAME)); } } finally { if (cursor != null) { cursor.close(); } } } } catch (Exception e) { e.printStackTrace(); } if(fileName==null || fileName.trim().length()==0)fileName=f.getName(); try { mainActivity.setActionBarTitle(fileName); } catch (Exception e) { mainActivity.setActionBarTitle(getResources().getString(R.string.zip_viewer)); } mainActivity.supportInvalidateOptionsMenu(); mToolbarHeight = getToolbarHeight(getActivity()); paddingTop = (mToolbarHeight) + dpToPx(72); mToolbarContainer.getViewTreeObserver().addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { paddingTop = mToolbarContainer.getHeight(); mToolbarHeight = mainActivity.toolbar.getHeight(); if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.JELLY_BEAN) { mToolbarContainer.getViewTreeObserver().removeOnGlobalLayoutListener(this); } else { mToolbarContainer.getViewTreeObserver().removeGlobalOnLayoutListener(this); } } }); } public int dpToPx(int dp) { DisplayMetrics displayMetrics = getResources().getDisplayMetrics(); int px = Math.round(dp * (displayMetrics.xdpi / DisplayMetrics.DENSITY_DEFAULT)); return px; } public static int getToolbarHeight(Context context) { final TypedArray styledAttributes = context.getTheme().obtainStyledAttributes( new int[]{android.R.attr.actionBarSize}); int toolbarHeight = (int) styledAttributes.getDimension(0, 0); styledAttributes.recycle(); return toolbarHeight; } @Override public void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); putDatatoSavedInstance(outState); } public ActionMode.Callback mActionModeCallback = new ActionMode.Callback() { private void hideOption(int id, Menu menu) { MenuItem item = menu.findItem(id); item.setVisible(false); } private void showOption(int id, Menu menu) { MenuItem item = menu.findItem(id); item.setVisible(true); } View v; // called when the action mode is created; startActionMode() was called public boolean onCreateActionMode(ActionMode mode, Menu menu) { // Inflate a menu resource providing context menu items MenuInflater inflater = mode.getMenuInflater(); v = getActivity().getLayoutInflater().inflate(R.layout.actionmode, null); mode.setCustomView(v); // assumes that you have "contexual.xml" menu resources inflater.inflate(R.menu.contextual, menu); hideOption(R.id.cpy, menu); hideOption(R.id.cut, menu); hideOption(R.id.delete, menu); hideOption(R.id.addshortcut, menu); hideOption(R.id.share, menu); hideOption(R.id.openwith, menu); showOption(R.id.all, menu); hideOption(R.id.compress, menu); hideOption(R.id.hide, menu); showOption(R.id.ex, menu); mode.setTitle(getResources().getString(R.string.select)); mainActivity.updateViews(new ColorDrawable(Utils.getColor(getContext(), R.color.holo_dark_action_mode))); if (Build.VERSION.SDK_INT >= 21) { Window window = getActivity().getWindow(); if (mainActivity.colourednavigation) window.setNavigationBarColor(Utils.getColor(getContext(), android.R.color.black)); } if (Build.VERSION.SDK_INT < 19) getActivity().findViewById(R.id.action_bar).setVisibility(View.GONE); return true; } // the following method is called each time // the action mode is shown. Always called after // onCreateActionMode, but // may be called multiple times if the mode is invalidated. public boolean onPrepareActionMode(ActionMode mode, Menu menu) { ArrayList<Integer> positions = rarAdapter.getCheckedItemPositions(); ((TextView) v.findViewById(R.id.item_count)).setText(positions.size() + ""); return false; // Return false if nothing is done } // called when the user selects a contextual menu item public boolean onActionItemClicked(ActionMode mode, MenuItem item) { switch (item.getItemId()) { case R.id.all: rarAdapter.toggleChecked(true,""); mode.invalidate(); return true; case R.id.ex: Toast.makeText(getActivity(), getResources().getString(R.string.extracting), Toast.LENGTH_SHORT).show(); Intent intent = new Intent(getActivity(), ExtractService.class); ArrayList<String> a = new ArrayList<>(); for (int i : rarAdapter.getCheckedItemPositions()) { a.add(openmode==0 ? elements.get(i).getName() : elementsRar.get(i).getFileNameString()); } intent.putExtra(ExtractService.KEY_PATH_ZIP, f.getPath()); intent.putExtra(ExtractService.KEY_ENTRIES_ZIP, a); ServiceWatcherUtil.runService(getContext(), intent); mode.finish(); return true; } return false; } @Override public void onDestroyActionMode(ActionMode actionMode) { if (rarAdapter != null) rarAdapter.toggleChecked(false, ""); selection = false; mainActivity.updateViews(mainActivity.getColorPreference().getDrawable(ColorUsage.getPrimary(MainActivity.currentTab))); if (Build.VERSION.SDK_INT >= 21) { Window window = getActivity().getWindow(); if (mainActivity.colourednavigation) window.setNavigationBarColor(mainActivity.skinStatusBar); } mActionMode = null; } }; @Override public void onDestroyView() { super.onDestroyView(); mainActivity.supportInvalidateOptionsMenu(); // needed to remove any extracted file from cache, when onResume was not called // in case of opening any unknown file inside the zip if (files.get(0).exists()) { new DeleteTask(getActivity().getContentResolver(), getActivity(), this).execute((files)); } } @Override public void onResume() { super.onResume(); mainActivity.floatingActionButton.hideMenuButton(true); Intent intent = new Intent(getActivity(), ExtractService.class); getActivity().bindService(intent, mServiceConnection, 0); } @Override public void onPause() { super.onPause(); getActivity().unbindService(mServiceConnection); } private ServiceConnection mServiceConnection = new ServiceConnection() { @Override public void onServiceConnected(ComponentName name, IBinder service) { } @Override public void onServiceDisconnected(ComponentName name) { // open file if pending if (isOpen) { // open most recent entry added to files to be deleted from cache File cacheFile = new File(files.get(files.size()-1).getPath()); if (cacheFile != null && cacheFile.exists()) utilsProvider.getFutils().openFile(cacheFile, zipViewer.mainActivity); // reset the flag and cache file, as it's root is already in the list for deletion isOpen = false; files.remove(files.size()-1); } } }; void putDatatoSavedInstance(Bundle outState) { if (openmode == 0) { outState.putParcelableArrayList(KEY_WHOLE_LIST, wholelist); outState.putParcelableArrayList(KEY_ELEMENTS, elements); } outState.putInt(KEY_OPEN_MODE, openmode); outState.putString(KEY_PATH, current); outState.putString(KEY_URI, s); outState.putString(KEY_FILE, f.getPath()); outState.putParcelableArrayList(KEY_CACHE_FILES, files); outState.putBoolean(KEY_OPEN, isOpen); } void SetupRar(Bundle savedInstanceState) { if (savedInstanceState == null) loadRarlist(f.getPath()); else { String path = savedInstanceState.getString(KEY_FILE); if (path != null && path.length() > 0) { f = new File(path); current = savedInstanceState.getString(KEY_PATH); new RarHelperTask(this, current).execute(f); } else loadRarlist(f.getPath()); } } void SetupZip(Bundle savedInstanceState) { if (savedInstanceState == null) loadlist(s); else { wholelist = savedInstanceState.getParcelableArrayList(KEY_WHOLE_LIST); elements = savedInstanceState.getParcelableArrayList(KEY_ELEMENTS); current = savedInstanceState.getString(KEY_PATH); f = new File(savedInstanceState.getString(KEY_FILE)); createviews(elements, current); } } public void loadRarlist(String path) { File f = new File(path); new RarHelperTask(this, "").execute(f); } public boolean cangoBackRar() { return !(current == null || current.trim().length() == 0); } public void goBackRar() { String path; try { path = current.substring(0, current.lastIndexOf("\\")); } catch (Exception e) { path = ""; } new RarHelperTask(this, path).execute(f); } public boolean canGoBack() { if (openmode == 1) return cangoBackRar(); else return !(current == null || current.trim().length() == 0); } public void goBack() { if (openmode == 1) { goBackRar(); return; } new ZipHelperTask(this, new File(current).getParent()).execute(s); } void refresh() { switch (openmode) { case 0: new ZipHelperTask(this, current).execute(s); break; case 1: new RarHelperTask(this, current).execute(f); break; } } public void bbar() { if (current != null && current.length()!=0) mainActivity.updatePath("/" + current, false, OpenMode.FILE,folder,file); else mainActivity.updatePath("/", false,OpenMode.FILE,folder,file); } int file=0,folder=0; public void createviews(ArrayList<ZipObj> zipEntries, String dir) { if(rarAdapter==null) { zipViewer.rarAdapter = new RarAdapter(zipViewer.getActivity(), utilsProvider, zipEntries, zipViewer,true); zipViewer.listView.setAdapter(zipViewer.rarAdapter); } else rarAdapter.generate(zipEntries,true); folder=0; file=0; for (ZipObj zipEntry:zipEntries) if(zipEntry.isDirectory())folder++; else file++; createViews(dir); openmode = 0; } public void createRarviews(ArrayList<FileHeader> zipEntries, String dir) { if(rarAdapter==null){ zipViewer.rarAdapter = new RarAdapter(zipViewer.getActivity(), utilsProvider, zipEntries, zipViewer); zipViewer.listView.setAdapter(zipViewer.rarAdapter); }else rarAdapter.generate(zipEntries); folder=0; file=0; for (FileHeader zipEntry:zipEntries) if(zipEntry.isDirectory())folder++; else file++; openmode = 1; createViews(dir); } void createViews(String dir) { stopAnims=true; if (!addheader) { listView.removeItemDecoration(dividerItemDecoration); listView.removeItemDecoration(headersDecor); addheader = true; } if (addheader) { dividerItemDecoration = new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST, true, showDividers); listView.addItemDecoration(dividerItemDecoration); headersDecor = new StickyRecyclerHeadersDecoration(rarAdapter); listView.addItemDecoration(headersDecor); addheader = false; } final FastScroller fastScroller=(FastScroller)rootView.findViewById(R.id.fastscroll); fastScroller.setRecyclerView(listView,1); fastScroller.setPressedHandleColor(mainActivity.getColorPreference().getColor(ColorUsage.ACCENT)); ((AppBarLayout)mToolbarContainer).addOnOffsetChangedListener(new AppBarLayout.OnOffsetChangedListener() { @Override public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { fastScroller.updateHandlePosition(verticalOffset,112); } }); listView.stopScroll(); zipViewer.current = dir; zipViewer.bbar(); swipeRefreshLayout.setRefreshing(false); } public void loadlist(String path) { new ZipHelperTask(this, "").execute(path); } }