From 72fb8256d1b73816e1ce09ef0c3f4a77fe581a4a Mon Sep 17 00:00:00 2001 From: tibbi Date: Sun, 22 Oct 2017 21:17:26 +0200 Subject: [PATCH] keep updating a single fragment instead of creating new ones --- .../filemanager/activities/MainActivity.kt | 137 ++++--------- .../filemanager/adapters/ItemsAdapter.kt | 32 ++- .../filemanager/fragments/ItemsFragment.kt | 192 ++++++++++-------- app/src/main/res/layout/activity_main.xml | 12 +- app/src/main/res/layout/items_fragment.xml | 7 + 5 files changed, 172 insertions(+), 208 deletions(-) diff --git a/app/src/main/kotlin/com/simplemobiletools/filemanager/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/filemanager/activities/MainActivity.kt index 3752a6fb..f9b3767b 100644 --- a/app/src/main/kotlin/com/simplemobiletools/filemanager/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/filemanager/activities/MainActivity.kt @@ -3,74 +3,66 @@ package com.simplemobiletools.filemanager.activities import android.content.Intent import android.os.Bundle import android.os.Handler -import android.os.Parcelable import android.view.Menu import android.view.MenuItem import com.simplemobiletools.commons.dialogs.RadioGroupDialog -import com.simplemobiletools.commons.dialogs.StoragePickerDialog -import com.simplemobiletools.commons.extensions.* +import com.simplemobiletools.commons.extensions.checkWhatsNew +import com.simplemobiletools.commons.extensions.handleHiddenFolderPasswordProtection +import com.simplemobiletools.commons.extensions.storeStoragePaths +import com.simplemobiletools.commons.extensions.toast import com.simplemobiletools.commons.helpers.LICENSE_KOTLIN import com.simplemobiletools.commons.helpers.LICENSE_MULTISELECT +import com.simplemobiletools.commons.helpers.LICENSE_PATTERN import com.simplemobiletools.commons.helpers.PERMISSION_WRITE_STORAGE -import com.simplemobiletools.commons.models.FileDirItem import com.simplemobiletools.commons.models.RadioItem import com.simplemobiletools.commons.models.Release -import com.simplemobiletools.commons.views.Breadcrumbs import com.simplemobiletools.filemanager.BuildConfig -import com.simplemobiletools.filemanager.PATH import com.simplemobiletools.filemanager.R -import com.simplemobiletools.filemanager.SCROLL_STATE import com.simplemobiletools.filemanager.dialogs.ChangeSortingDialog import com.simplemobiletools.filemanager.extensions.config import com.simplemobiletools.filemanager.fragments.ItemsFragment import com.simplemobiletools.filemanager.helpers.RootHelpers import com.stericson.RootTools.RootTools import kotlinx.android.synthetic.main.activity_main.* +import kotlinx.android.synthetic.main.items_fragment.* import java.util.* -class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Breadcrumbs.BreadcrumbsListener { +class MainActivity : SimpleActivity() { private val BACK_PRESS_TIMEOUT = 5000 - - private var latestFragment: ItemsFragment? = null - private var scrollStates = HashMap() - private var storedTextColor = 0 - private var currentPath = "" private var wasBackJustPressed = false + private lateinit var fragment: ItemsFragment + override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) storeStoragePaths() - storeConfigVariables() - breadcrumbs.listener = this + + fragment = fragment_holder as ItemsFragment tryInitFileManager() checkWhatsNewDialog() checkIfRootAvailable() } - override fun onResume() { - super.onResume() - updateTextColors(main_screen) - if (storedTextColor != config.textColor) { - storedTextColor = config.textColor - breadcrumbs.textColor = storedTextColor - openPath(currentPath) - } - invalidateOptionsMenu() - } - - override fun onPause() { - super.onPause() - storeConfigVariables() - } - override fun onDestroy() { super.onDestroy() config.temporarilyShowHidden = false } - private fun storeConfigVariables() { - storedTextColor = config.textColor + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.menu, menu) + + val favorites = config.favorites + menu.apply { + findItem(R.id.add_favorite).isVisible = !favorites.contains(fragment.currentPath) + findItem(R.id.remove_favorite).isVisible = favorites.contains(fragment.currentPath) + findItem(R.id.go_to_favorite).isVisible = favorites.isNotEmpty() + + findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden + findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden + } + + return true } private fun tryInitFileManager() { @@ -89,44 +81,10 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br } private fun openPath(path: String) { - val realPath = if (path.length > 1) path.trimEnd('/') else path - breadcrumbs.setBreadcrumb(realPath) - val bundle = Bundle() - bundle.putString(PATH, realPath) - - if (scrollStates.containsKey(realPath)) { - bundle.putParcelable(SCROLL_STATE, scrollStates[realPath]) - } - - if (latestFragment != null) { - scrollStates.put(latestFragment!!.mPath.trimEnd('/'), latestFragment!!.getScrollState()) - } - - latestFragment = ItemsFragment().apply { - arguments = bundle - setListener(this@MainActivity) - supportFragmentManager.beginTransaction().replace(R.id.fragment_holder, this).addToBackStack(realPath).commitAllowingStateLoss() - } - currentPath = realPath + (fragment_holder as ItemsFragment).openPath(path) invalidateOptionsMenu() } - override fun onCreateOptionsMenu(menu: Menu): Boolean { - menuInflater.inflate(R.menu.menu, menu) - - val favorites = config.favorites - menu.apply { - findItem(R.id.add_favorite).isVisible = !favorites.contains(currentPath) - findItem(R.id.remove_favorite).isVisible = favorites.contains(currentPath) - findItem(R.id.go_to_favorite).isVisible = favorites.isNotEmpty() - - findItem(R.id.temporarily_show_hidden).isVisible = !config.shouldShowHidden - findItem(R.id.stop_showing_hidden).isVisible = config.temporarilyShowHidden - } - - return true - } - override fun onOptionsItemSelected(item: MenuItem): Boolean { when (item.itemId) { R.id.go_home -> goHome() @@ -145,27 +103,23 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br } private fun goHome() { - if (config.homeFolder != currentPath) + if (config.homeFolder != fragment.currentPath) openPath(config.homeFolder) } private fun showSortingDialog() { - ChangeSortingDialog(this, currentPath) { - if (latestFragment != null) { - latestFragment!!.fillItems() - } else { - openPath(currentPath) - } + ChangeSortingDialog(this, fragment.currentPath) { + fragment.refreshItems() } } private fun addFavorite() { - config.addFavorite(currentPath) + config.addFavorite(fragment.currentPath) invalidateOptionsMenu() } private fun removeFavorite() { - config.removeFavorite(currentPath) + config.removeFavorite(fragment.currentPath) invalidateOptionsMenu() } @@ -176,7 +130,7 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br favorites.forEachIndexed { index, path -> items.add(RadioItem(index, path, path)) - if (path == currentPath) { + if (path == fragment.currentPath) { currFavoriteIndex = index } } @@ -187,7 +141,7 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br } private fun setAsHome() { - config.homeFolder = currentPath + config.homeFolder = fragment.currentPath toast(R.string.home_folder_updated) } @@ -203,16 +157,16 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br private fun toggleTemporarilyShowHidden(show: Boolean) { config.temporarilyShowHidden = show - openPath(currentPath) + openPath(fragment.currentPath) invalidateOptionsMenu() } private fun launchAbout() { - startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT, BuildConfig.VERSION_NAME) + startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT or LICENSE_PATTERN, BuildConfig.VERSION_NAME) } override fun onBackPressed() { - if (breadcrumbs.childCount <= 1) { + if (fragment.breadcrumbs.childCount <= 1) { if (!wasBackJustPressed) { wasBackJustPressed = true toast(R.string.press_back_again) @@ -221,23 +175,8 @@ class MainActivity : SimpleActivity(), ItemsFragment.ItemInteractionListener, Br finish() } } else { - breadcrumbs.removeBreadcrumb() - openPath(breadcrumbs.lastItem.path) - } - } - - override fun itemClicked(item: FileDirItem) { - openPath(item.path) - } - - override fun breadcrumbClicked(id: Int) { - if (id == 0) { - StoragePickerDialog(this@MainActivity, currentPath) { - openPath(it) - } - } else { - val item = breadcrumbs.getChildAt(id).tag as FileDirItem - openPath(item.path) + fragment.breadcrumbs.removeBreadcrumb() + openPath(fragment.breadcrumbs.lastItem.path) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/filemanager/adapters/ItemsAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/filemanager/adapters/ItemsAdapter.kt index 20d6b528..a2cdfc17 100644 --- a/app/src/main/kotlin/com/simplemobiletools/filemanager/adapters/ItemsAdapter.kt +++ b/app/src/main/kotlin/com/simplemobiletools/filemanager/adapters/ItemsAdapter.kt @@ -40,25 +40,26 @@ import java.util.zip.ZipOutputStream class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList, val listener: ItemOperationsListener?, val itemClick: (FileDirItem) -> Unit) : RecyclerView.Adapter() { - val multiSelector = MultiSelector() - val config = activity.config + private var textColor = activity.config.textColor - var actMode: ActionMode? = null - var itemViews = SparseArray() - val selectedPositions = HashSet() + private val multiSelector = MultiSelector() + private val config = activity.config - var textColor = activity.config.textColor + private var actMode: ActionMode? = null + private var itemViews = SparseArray() + private val selectedPositions = HashSet() - private val folderDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_folder, textColor) - private val fileDrawable = activity.resources.getColoredDrawableWithColor(R.drawable.ic_file, textColor) + lateinit private var folderDrawable: Drawable + lateinit private var fileDrawable: Drawable fun toggleItemSelection(select: Boolean, pos: Int) { itemViews[pos]?.item_frame?.isSelected = select - if (select) + if (select) { selectedPositions.add(pos) - else + } else { selectedPositions.remove(pos) + } if (selectedPositions.isEmpty()) { actMode?.finish() @@ -74,6 +75,17 @@ class ItemsAdapter(val activity: SimpleActivity, var mItems: MutableList() - private var fragmentView: View? = null +class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener, Breadcrumbs.BreadcrumbsListener { + var currentPath = "" - var mPath = "" + private var storedTextColor = 0 + private var showHidden = false + private var storedItems = ArrayList() + private var scrollStates = HashMap() + + private lateinit var mView: View override fun onCreateView(inflater: LayoutInflater?, container: ViewGroup?, savedInstanceState: Bundle?): View { - fragmentView = inflater!!.inflate(R.layout.items_fragment, container, false)!! + mView = inflater!!.inflate(R.layout.items_fragment, container, false)!! storeConfigVariables() - return fragmentView!! + return mView } override fun onViewCreated(view: View?, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - fillItems() - - items_swipe_refresh.setOnRefreshListener({ fillItems() }) - items_fab.setOnClickListener { createNewItem() } + mView.apply { + items_swipe_refresh.setOnRefreshListener({ refreshItems() }) + items_fab.setOnClickListener { createNewItem() } + breadcrumbs.listener = this@ItemsFragment + } } override fun onResume() { super.onResume() val config = context.config - if (mShowHidden != config.shouldShowHidden) { - mShowHidden = !mShowHidden - fillItems() + if (showHidden != config.shouldShowHidden) { + showHidden = !showHidden + refreshItems() } - context.updateTextColors(items_holder) - if (mStoredTextColor != config.textColor) { - mItems = ArrayList() - fillItems() - mStoredTextColor = config.textColor + + if (storedTextColor != config.textColor) { + storedItems = ArrayList() + (items_list.adapter as ItemsAdapter).updateTextColor(config.textColor) + refreshItems() + storedTextColor = config.textColor } } @@ -75,64 +81,72 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { } private fun storeConfigVariables() { - mShowHidden = context.config.shouldShowHidden - mStoredTextColor = context.config.textColor + showHidden = context.config.shouldShowHidden + storedTextColor = context.config.textColor } - fun fillItems() { - if (activity == null || (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 && activity.isDestroyed)) - return + fun openPath(path: String) { + var realPath = path.trimEnd('/') + if (realPath.isEmpty()) + realPath = "/" - mPath = arguments.getString(PATH) - getItems(mPath) { + scrollStates.put(currentPath, getScrollState()) + currentPath = realPath + showHidden = context.config.shouldShowHidden + getItems(currentPath) { if (!isAdded) return@getItems - val newItems = it - FileDirItem.sorting = context.config.getFolderSorting(mPath) - newItems.sort() + FileDirItem.sorting = context.config.getFolderSorting(currentPath) + it.sort() + activity.runOnUiThread { + addItems(it) + } + } + } - fragmentView.apply { - activity?.runOnUiThread { - items_swipe_refresh?.isRefreshing = false - if (newItems.hashCode() == mItems.hashCode()) { - return@runOnUiThread - } + private fun addItems(items: ArrayList) { + mView.apply { + activity?.runOnUiThread { + items_swipe_refresh?.isRefreshing = false + if (items.hashCode() == storedItems.hashCode()) { + return@runOnUiThread + } - mItems = newItems - - val currAdapter = items_list.adapter - if (currAdapter == null) { - items_list.apply { - this.adapter = ItemsAdapter(activity as SimpleActivity, mItems, this@ItemsFragment) { - itemClicked(it) - } - - DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply { - setDrawable(context.resources.getDrawable(com.simplemobiletools.commons.R.drawable.divider)) - addItemDecoration(this) - } - - isDragSelectionEnabled = true + mView.breadcrumbs.setBreadcrumb(currentPath) + storedItems = items + val currAdapter = items_list.adapter + if (currAdapter == null) { + items_list.apply { + this.adapter = ItemsAdapter(activity as SimpleActivity, storedItems, this@ItemsFragment) { + itemClicked(it) } - items_fastscroller.setViews(items_list, items_swipe_refresh) - setupRecyclerViewListener() - } else { - val state = (items_list.layoutManager as LinearLayoutManager).onSaveInstanceState() - (currAdapter as ItemsAdapter).updateItems(mItems) - (items_list.layoutManager as LinearLayoutManager).onRestoreInstanceState(state) - } - getRecyclerLayoutManager().onRestoreInstanceState(arguments.getParcelable(SCROLL_STATE)) + DividerItemDecoration(context, DividerItemDecoration.VERTICAL).apply { + setDrawable(context.resources.getDrawable(com.simplemobiletools.commons.R.drawable.divider)) + addItemDecoration(this) + } + + isDragSelectionEnabled = true + } + items_fastscroller.setViews(items_list, items_swipe_refresh) + setupRecyclerViewListener() + } else { + (currAdapter as ItemsAdapter).updateItems(storedItems) + + val savedState = scrollStates[currentPath] + if (savedState != null) { + getRecyclerLayoutManager().onRestoreInstanceState(savedState) + } else { + getRecyclerLayoutManager().scrollToPosition(0) + } } } } } - private fun getRecyclerLayoutManager() = (fragmentView?.items_list?.layoutManager as LinearLayoutManager) - private fun setupRecyclerViewListener() { - fragmentView?.items_list?.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener { + mView.items_list?.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener { override fun zoomIn() { } @@ -155,16 +169,14 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { fun getScrollState() = getRecyclerLayoutManager().onSaveInstanceState() - fun setListener(listener: ItemInteractionListener) { - mListener = listener - } + private fun getRecyclerLayoutManager() = (mView.items_list.layoutManager as LinearLayoutManager) private fun getItems(path: String, callback: (items: ArrayList) -> Unit) { Thread({ if (!context.config.enableRootAccess || !context.isPathOnRoot(path)) { getRegularItemsOf(path, callback) } else { - getRootItemsOf(path, callback) + RootHelpers().getFiles(activity as SimpleActivity, path, callback) } }).start() } @@ -176,7 +188,7 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { for (file in files) { val curPath = file.absolutePath val curName = curPath.getFilenameFromPath() - if (!mShowHidden && curName.startsWith(".")) + if (!showHidden && curName.startsWith(".")) continue val children = getChildren(file) @@ -188,18 +200,11 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { callback(items) } - private fun getRootItemsOf(path: String, callback: (items: ArrayList) -> Unit) { - var wantedPath = path.trimEnd('/') - if (wantedPath.isEmpty()) - wantedPath = "/" - RootHelpers().getFiles(activity as SimpleActivity, wantedPath, callback) - } - private fun getChildren(file: File): Int { val fileList: Array? = file.list() ?: return 0 if (file.isDirectory) { - return if (mShowHidden) { + return if (showHidden) { fileList!!.size } else { fileList!!.count { fileName -> fileName[0] != '.' } @@ -208,9 +213,9 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { return 0 } - fun itemClicked(item: FileDirItem) { + private fun itemClicked(item: FileDirItem) { if (item.isDirectory) { - mListener?.itemClicked(item) + openPath(item.path) } else { val path = item.path val file = File(path) @@ -244,9 +249,9 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { } private fun createNewItem() { - CreateNewItemDialog(activity as SimpleActivity, mPath) { + CreateNewItemDialog(activity as SimpleActivity, currentPath) { if (it) { - fillItems() + refreshItems() } } } @@ -259,8 +264,19 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { return "$type/*" } + override fun breadcrumbClicked(id: Int) { + if (id == 0) { + StoragePickerDialog(activity, currentPath) { + openPath(it) + } + } else { + val item = breadcrumbs.getChildAt(id).tag as FileDirItem + openPath(item.path) + } + } + override fun refreshItems() { - fillItems() + openPath(currentPath) } override fun deleteFiles(files: ArrayList) { @@ -283,8 +299,4 @@ class ItemsFragment : Fragment(), ItemsAdapter.ItemOperationsListener { override fun itemLongClicked(position: Int) { items_list.setDragSelectActive(position) } - - interface ItemInteractionListener { - fun itemClicked(item: FileDirItem) - } } diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml index 2cefcfc5..2b86ecae 100644 --- a/app/src/main/res/layout/activity_main.xml +++ b/app/src/main/res/layout/activity_main.xml @@ -5,16 +5,10 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - - - + android:layout_height="match_parent"/> diff --git a/app/src/main/res/layout/items_fragment.xml b/app/src/main/res/layout/items_fragment.xml index 62f34496..57f561c3 100644 --- a/app/src/main/res/layout/items_fragment.xml +++ b/app/src/main/res/layout/items_fragment.xml @@ -16,10 +16,17 @@ android:layout_width="match_parent" android:layout_height="wrap_content"> + +