diff --git a/app/build.gradle b/app/build.gradle index dbd08aa..b1c872c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -39,7 +39,7 @@ android { } dependencies { - implementation 'com.simplemobiletools:commons:3.0.3' + implementation 'com.simplemobiletools:commons:3.0.13' implementation 'com.facebook.stetho:stetho:1.5.0' implementation 'com.android.support:multidex:1.0.2' } diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt index 9089cfe..c562ba2 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/App.kt @@ -2,19 +2,12 @@ package com.simplemobiletools.applauncher import android.support.multidex.MultiDexApplication import com.facebook.stetho.Stetho -import com.simplemobiletools.applauncher.extensions.config -import java.util.* +import com.simplemobiletools.commons.extensions.checkUseEnglish class App : MultiDexApplication() { override fun onCreate() { super.onCreate() - - if (config.useEnglish) { - val conf = resources.configuration - conf.locale = Locale.ENGLISH - resources.updateConfiguration(conf, resources.displayMetrics) - } - + checkUseEnglish() Stetho.initializeWithDefaults(this) } } diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt index 7342760..d96a028 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/activities/MainActivity.kt @@ -7,23 +7,25 @@ import android.view.Menu import android.view.MenuItem import com.simplemobiletools.applauncher.BuildConfig import com.simplemobiletools.applauncher.R -import com.simplemobiletools.applauncher.adapters.RecyclerAdapter +import com.simplemobiletools.applauncher.adapters.LaunchersAdapter import com.simplemobiletools.applauncher.dialogs.AddAppLauncherDialog import com.simplemobiletools.applauncher.extensions.config import com.simplemobiletools.applauncher.extensions.dbHelper import com.simplemobiletools.applauncher.extensions.isAPredefinedApp import com.simplemobiletools.applauncher.models.AppLauncher +import com.simplemobiletools.commons.extensions.appLaunched import com.simplemobiletools.commons.extensions.checkWhatsNew import com.simplemobiletools.commons.extensions.restartActivity import com.simplemobiletools.commons.extensions.updateTextColors import com.simplemobiletools.commons.helpers.LICENSE_KOTLIN import com.simplemobiletools.commons.helpers.LICENSE_MULTISELECT import com.simplemobiletools.commons.helpers.LICENSE_STETHO +import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener import com.simplemobiletools.commons.models.Release import kotlinx.android.synthetic.main.activity_main.* import java.util.* -class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener { +class MainActivity : SimpleActivity(), RefreshRecyclerViewListener { private var launchers = ArrayList() private var mStoredPrimaryColor = 0 private var mStoredTextColor = 0 @@ -32,14 +34,14 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + appLaunched() setupLaunchers() checkWhatsNewDialog() - setupGridLayoutManager() storeStateVariables() fab.setOnClickListener { AddAppLauncherDialog(this, launchers) { - refreshLaunchers() + setupLaunchers() } } } @@ -89,30 +91,13 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener { startAboutActivity(R.string.app_name, LICENSE_KOTLIN or LICENSE_MULTISELECT or LICENSE_STETHO, BuildConfig.VERSION_NAME) } - private fun getGridAdapter() = launchers_grid.adapter as? RecyclerAdapter - - private fun setupGridLayoutManager() { - /*launchers_grid.isDragSelectionEnabled = true - launchers_grid.listener = object : MyScalableRecyclerView.MyScalableRecyclerViewListener { - override fun zoomIn() {} - - override fun zoomOut() {} - - override fun selectItem(position: Int) { - getGridAdapter()?.selectItem(position) - } - - override fun selectRange(initialSelection: Int, lastDraggedIndex: Int, minReached: Int, maxReached: Int) { - getGridAdapter()?.selectRange(initialSelection, lastDraggedIndex, minReached, maxReached) - } - }*/ - } + private fun getGridAdapter() = launchers_grid.adapter as? LaunchersAdapter private fun setupLaunchers() { launchers = dbHelper.getLaunchers() checkInvalidApps() - launchers_grid.adapter = RecyclerAdapter(this, launchers, this) { - val launchIntent = packageManager.getLaunchIntentForPackage(it.packageName) + val adapter = LaunchersAdapter(this, launchers, this, launchers_grid) { + val launchIntent = packageManager.getLaunchIntentForPackage((it as AppLauncher).packageName) if (launchIntent != null) { startActivity(launchIntent) finish() @@ -122,6 +107,8 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener { startActivity(intent) } } + adapter.setupDragListener(true) + launchers_grid.adapter = adapter } private fun checkInvalidApps() { @@ -144,14 +131,10 @@ class MainActivity : SimpleActivity(), RecyclerAdapter.AppLaunchersListener { } } - override fun refreshLaunchers() { + override fun refreshItems() { setupLaunchers() } - override fun itemLongClicked(position: Int) { - //launchers_grid.setDragSelectActive(position) - } - private fun checkWhatsNewDialog() { arrayListOf().apply { add(Release(7, R.string.release_7)) diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt new file mode 100644 index 0000000..5452e91 --- /dev/null +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/LaunchersAdapter.kt @@ -0,0 +1,99 @@ +package com.simplemobiletools.applauncher.adapters + +import android.view.Menu +import android.view.View +import android.view.ViewGroup +import com.simplemobiletools.applauncher.R +import com.simplemobiletools.applauncher.activities.SimpleActivity +import com.simplemobiletools.applauncher.dialogs.EditDialog +import com.simplemobiletools.applauncher.extensions.dbHelper +import com.simplemobiletools.applauncher.models.AppLauncher +import com.simplemobiletools.commons.adapters.MyRecyclerViewAdapter +import com.simplemobiletools.commons.dialogs.ConfirmationDialog +import com.simplemobiletools.commons.extensions.applyColorFilter +import com.simplemobiletools.commons.extensions.beVisibleIf +import com.simplemobiletools.commons.interfaces.RefreshRecyclerViewListener +import com.simplemobiletools.commons.views.MyRecyclerView +import kotlinx.android.synthetic.main.app_launcher_item.view.* +import java.util.* + +class LaunchersAdapter(activity: SimpleActivity, val launchers: MutableList, val listener: RefreshRecyclerViewListener?, + recyclerView: MyRecyclerView, itemClick: (Any) -> Unit) : MyRecyclerViewAdapter(activity, recyclerView, itemClick) { + + override fun getActionMenuId() = R.menu.cab + + override fun prepareItemSelection(view: View) { + view.launcher_check?.background?.applyColorFilter(primaryColor) + } + + override fun markItemSelection(select: Boolean, view: View?) { + view?.launcher_check?.beVisibleIf(select) + } + + override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int) = createViewHolder(R.layout.app_launcher_item, parent) + + override fun onBindViewHolder(holder: MyRecyclerViewAdapter.ViewHolder, position: Int) { + val launcher = launchers[position] + val view = holder.bindView(launcher) { itemView, layoutPosition -> + setupView(itemView, launcher) + } + bindViewHolder(holder, position, view) + } + + override fun getItemCount() = launchers.size + + override fun prepareActionMode(menu: Menu) { + menu.apply { + findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1 + } + } + + override fun actionItemPressed(id: Int) { + when (id) { + R.id.cab_edit -> showEditDialog() + R.id.cab_delete -> askConfirmDelete() + } + } + + override fun getSelectableItemCount() = launchers.size + + private fun showEditDialog() { + EditDialog(activity, launchers[selectedPositions.first()]) { + finishActMode() + listener?.refreshItems() + } + } + + private fun askConfirmDelete() { + ConfirmationDialog(activity, "", R.string.delete_explanation, R.string.ok, R.string.cancel) { + deleteItems() + } + } + + private fun deleteItems() { + val deleteIds = ArrayList(selectedPositions.size) + val removeLaunchers = ArrayList(selectedPositions.size) + selectedPositions.sortedDescending().forEach { + val launcher = launchers[it] + deleteIds.add(launcher.id.toString()) + removeLaunchers.add(launcher) + } + + launchers.removeAll(removeLaunchers) + activity.dbHelper.deleteLaunchers(deleteIds) + removeSelectedItems() + } + + fun updatePrimaryColor(primaryColor: Int) { + this.primaryColor = primaryColor + notifyDataSetChanged() + } + + private fun setupView(view: View, launcher: AppLauncher) { + view.apply { + launcher_label.text = launcher.name + launcher_label.setTextColor(textColor) + launcher_icon.setImageDrawable(launcher.drawable!!) + } + } +} diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/RecyclerAdapter.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/RecyclerAdapter.kt deleted file mode 100644 index 1480821..0000000 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/adapters/RecyclerAdapter.kt +++ /dev/null @@ -1,242 +0,0 @@ -package com.simplemobiletools.applauncher.adapters - -import android.support.v7.view.ActionMode -import android.support.v7.widget.RecyclerView -import android.util.SparseArray -import android.view.* -import com.bignerdranch.android.multiselector.ModalMultiSelectorCallback -import com.bignerdranch.android.multiselector.MultiSelector -import com.bignerdranch.android.multiselector.SwappingHolder -import com.simplemobiletools.applauncher.R -import com.simplemobiletools.applauncher.activities.SimpleActivity -import com.simplemobiletools.applauncher.dialogs.EditDialog -import com.simplemobiletools.applauncher.extensions.config -import com.simplemobiletools.applauncher.extensions.dbHelper -import com.simplemobiletools.applauncher.models.AppLauncher -import com.simplemobiletools.commons.dialogs.ConfirmationDialog -import com.simplemobiletools.commons.extensions.applyColorFilter -import com.simplemobiletools.commons.extensions.beGone -import com.simplemobiletools.commons.extensions.beVisibleIf -import com.simplemobiletools.commons.interfaces.MyAdapterListener -import kotlinx.android.synthetic.main.app_launcher_item.view.* -import java.util.* - -class RecyclerAdapter(val activity: SimpleActivity, val launchers: MutableList, val listener: AppLaunchersListener?, val itemClick: (AppLauncher) -> Unit) : - RecyclerView.Adapter() { - - private val config = activity.config - private var actMode: ActionMode? = null - private var primaryColor = config.primaryColor - - private val multiSelector = MultiSelector() - private var itemViews = SparseArray() - private val selectedPositions = HashSet() - private var textColor = config.textColor - - fun toggleItemSelection(select: Boolean, pos: Int) { - if (select) { - if (itemViews[pos] != null) { - itemViews[pos].launcher_check?.background?.applyColorFilter(primaryColor) - selectedPositions.add(pos) - } - } else { - selectedPositions.remove(pos) - } - - itemViews[pos]?.launcher_check?.beVisibleIf(select) - - if (selectedPositions.isEmpty()) { - actMode?.finish() - return - } - - updateTitle(selectedPositions.size) - } - - private fun updateTitle(cnt: Int) { - actMode?.title = "$cnt / ${launchers.size}" - actMode?.invalidate() - } - - private val adapterListener = object : MyAdapterListener { - override fun itemLongClicked(position: Int) { - } - - override fun toggleItemSelectionAdapter(select: Boolean, position: Int) { - toggleItemSelection(select, position) - } - - override fun getSelectedPositions(): HashSet = selectedPositions - } - - private val multiSelectorMode = object : ModalMultiSelectorCallback(multiSelector) { - override fun onActionItemClicked(mode: ActionMode?, item: MenuItem): Boolean { - when (item.itemId) { - R.id.cab_edit -> showEditDialog() - R.id.cab_delete -> askConfirmDelete() - else -> return false - } - return true - } - - override fun onCreateActionMode(actionMode: ActionMode?, menu: Menu?): Boolean { - super.onCreateActionMode(actionMode, menu) - actMode = actionMode - activity.menuInflater.inflate(R.menu.cab, menu) - return true - } - - override fun onPrepareActionMode(actionMode: ActionMode?, menu: Menu): Boolean { - menu.findItem(R.id.cab_edit).isVisible = selectedPositions.size == 1 - return true - } - - override fun onDestroyActionMode(actionMode: ActionMode?) { - super.onDestroyActionMode(actionMode) - selectedPositions.forEach { - itemViews[it]?.launcher_check?.beGone() - } - selectedPositions.clear() - actMode = null - } - } - - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - itemViews.put(position, holder.bindView(launchers[position], textColor)) - toggleItemSelection(selectedPositions.contains(position), position) - holder.itemView.tag = holder - } - - override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): ViewHolder { - val view = LayoutInflater.from(parent?.context).inflate(R.layout.app_launcher_item, parent, false) - return ViewHolder(view, adapterListener, activity, multiSelectorMode, multiSelector, listener, itemClick) - } - - override fun getItemCount() = launchers.count() - - private fun showEditDialog() { - EditDialog(activity, launchers[selectedPositions.first()]) { - actMode?.finish() - listener?.refreshLaunchers() - } - } - - private fun askConfirmDelete() { - ConfirmationDialog(activity, "", R.string.delete_explanation, R.string.ok, R.string.cancel) { - deleteItems() - } - } - - private fun deleteItems() { - val deleteIds = ArrayList(selectedPositions.size) - val removeLaunchers = ArrayList(selectedPositions.size) - selectedPositions.sortedDescending().forEach { - val launcher = launchers[it] - deleteIds.add(launcher.id.toString()) - removeLaunchers.add(launcher) - notifyItemRemoved(it) - itemViews.put(it, null) - } - - launchers.removeAll(removeLaunchers) - activity.dbHelper.deleteLaunchers(deleteIds) - - val newItems = SparseArray() - (0 until itemViews.size()) - .filter { itemViews[it] != null } - .forEachIndexed { curIndex, i -> newItems.put(curIndex, itemViews[i]) } - - itemViews = newItems - actMode?.finish() - } - - fun updateTextColor(textColor: Int) { - this.textColor = textColor - notifyDataSetChanged() - } - - fun updatePrimaryColor(primaryColor: Int) { - this.primaryColor = primaryColor - notifyDataSetChanged() - } - - fun selectItem(pos: Int) { - toggleItemSelection(true, pos) - } - - fun selectRange(from: Int, to: Int, min: Int, max: Int) { - if (from == to) { - (min..max).filter { it != from } - .forEach { toggleItemSelection(false, it) } - return - } - - if (to < from) { - for (i in to..from) - toggleItemSelection(true, i) - - if (min > -1 && min < to) { - (min until to).filter { it != from } - .forEach { toggleItemSelection(false, it) } - } - if (max > -1) { - for (i in from + 1..max) - toggleItemSelection(false, i) - } - } else { - for (i in from..to) - toggleItemSelection(true, i) - - if (max > -1 && max > to) { - (to + 1..max).filter { it != from } - .forEach { toggleItemSelection(false, it) } - } - - if (min > -1) { - for (i in min until from) - toggleItemSelection(false, i) - } - } - } - - class ViewHolder(view: View, val adapterListener: MyAdapterListener, val activity: SimpleActivity, val multiSelectorCallback: ModalMultiSelectorCallback, - val multiSelector: MultiSelector, val listener: AppLaunchersListener?, val itemClick: (AppLauncher) -> (Unit)) : SwappingHolder(view, MultiSelector()) { - fun bindView(launcher: AppLauncher, textColor: Int): View { - itemView.apply { - launcher_label.text = launcher.name - launcher_label.setTextColor(textColor) - launcher_icon.setImageDrawable(launcher.drawable!!) - - setOnClickListener { viewClicked(launcher) } - setOnLongClickListener { viewLongClicked(); true } - } - return itemView - } - - private fun viewClicked(appLauncher: AppLauncher) { - if (multiSelector.isSelectable) { - val isSelected = adapterListener.getSelectedPositions().contains(adapterPosition) - adapterListener.toggleItemSelectionAdapter(!isSelected, adapterPosition) - } else { - itemClick(appLauncher) - } - } - - private fun viewLongClicked() { - if (listener != null) { - if (!multiSelector.isSelectable) { - activity.startSupportActionMode(multiSelectorCallback) - adapterListener.toggleItemSelectionAdapter(true, adapterPosition) - } - - listener.itemLongClicked(adapterPosition) - } - } - } - - interface AppLaunchersListener { - fun refreshLaunchers() - - fun itemLongClicked(position: Int) - } -} diff --git a/app/src/main/kotlin/com/simplemobiletools/applauncher/models/AppLauncher.kt b/app/src/main/kotlin/com/simplemobiletools/applauncher/models/AppLauncher.kt index 7529061..134e9f3 100644 --- a/app/src/main/kotlin/com/simplemobiletools/applauncher/models/AppLauncher.kt +++ b/app/src/main/kotlin/com/simplemobiletools/applauncher/models/AppLauncher.kt @@ -3,7 +3,5 @@ package com.simplemobiletools.applauncher.models import android.graphics.drawable.Drawable data class AppLauncher(val id: Int, var name: String, val packageName: String, val drawable: Drawable? = null) { - override fun equals(other: Any?): Boolean { - return packageName.equals((other as AppLauncher).packageName, true) - } + override fun equals(other: Any?) = packageName.equals((other as AppLauncher).packageName, true) } diff --git a/app/src/main/res/layout/app_launcher_item.xml b/app/src/main/res/layout/app_launcher_item.xml index 2f75fc9..b947b38 100644 --- a/app/src/main/res/layout/app_launcher_item.xml +++ b/app/src/main/res/layout/app_launcher_item.xml @@ -5,6 +5,8 @@ android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="?attr/selectableItemBackground" + android:clickable="true" + android:focusable="true" android:paddingBottom="@dimen/small_margin" android:paddingLeft="@dimen/small_margin" android:paddingRight="@dimen/small_margin" @@ -32,6 +34,7 @@ android:layout_alignParentEnd="true" android:layout_alignParentRight="true" android:layout_alignParentTop="true" + android:layout_margin="@dimen/small_margin" android:background="@drawable/circle_background" android:padding="@dimen/tiny_margin" android:src="@drawable/ic_check"