Przeglądaj źródła

Add popup menu for apps in the drawer (#134)

Nidhish Chadive 2 lat temu
rodzic
commit
b9a5a15cae

+ 1 - 1
app/src/main/AndroidManifest.xml

@@ -5,10 +5,10 @@
     <uses-permission android:name="com.android.alarm.permission.SET_ALARM" />
     <uses-permission android:name="android.permission.QUERY_ALL_PACKAGES"
         tools:ignore="QueryAllPackagesPermission" />
+    <uses-permission android:name="android.permission.REQUEST_DELETE_PACKAGES" />
     <uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
     <uses-permission android:name="android.permission.SET_WALLPAPER"/>
 
-
     <application
         android:name=".App"
         android:allowBackup="false"

+ 22 - 2
app/src/main/java/com/sduduzog/slimlauncher/MainActivity.kt

@@ -3,6 +3,7 @@ package com.sduduzog.slimlauncher
 import android.annotation.SuppressLint
 import android.content.SharedPreferences
 import android.content.res.Resources
+import android.graphics.Rect
 import android.os.Bundle
 import android.util.Log
 import android.view.GestureDetector
@@ -14,6 +15,7 @@ import androidx.appcompat.app.AppCompatActivity
 import androidx.constraintlayout.motion.widget.MotionLayout
 import androidx.navigation.NavController
 import androidx.navigation.Navigation.findNavController
+import androidx.recyclerview.widget.RecyclerView
 import com.sduduzog.slimlauncher.utils.*
 import dagger.hilt.android.AndroidEntryPoint
 import java.lang.reflect.Method
@@ -147,12 +149,30 @@ class MainActivity : AppCompatActivity(),
         super.onBackPressed()
     }
 
+    private fun isVisible(view: View): Boolean {
+        if (!view.isShown) {
+            return false
+        }
+
+        val actualPosition = Rect()
+        view.getGlobalVisibleRect(actualPosition)
+        val screen = Rect(0, 0, Resources.getSystem().displayMetrics.widthPixels, Resources.getSystem().displayMetrics.heightPixels)
+        return actualPosition.intersect(screen)
+    }
+
     private val gestureDetector = GestureDetector(baseContext, object : SimpleOnGestureListener() {
         override fun onLongPress(e: MotionEvent) {
             // Open Options
+            val recyclerView = findViewById<RecyclerView>(R.id.app_drawer_fragment_list)
             val homeView = findViewById<View>(R.id.home_fragment)
-            if(homeView != null) {
-                findNavController(homeView).navigate(R.id.action_homeFragment_to_optionsFragment, null)
+
+            if(homeView != null && recyclerView != null)
+            {
+                if(isVisible(recyclerView))
+                   recyclerView.performLongClick()
+                else // we are in the homeFragment
+                    findNavController(homeView).navigate(R.id.action_homeFragment_to_optionsFragment, null)
+
             }
         }
 

+ 3 - 1
app/src/main/java/com/sduduzog/slimlauncher/adapters/AppDrawerAdapter.kt

@@ -20,7 +20,6 @@ class AppDrawerAdapter(
     appsRepo: UnlauncherAppsRepository
 ) : RecyclerView.Adapter<AppDrawerAdapter.ViewHolder>() {
     private val regex = Regex("[!@#\$%^&*()_+\\-=\\[\\]{};':\"\\\\|,.<>/? ]")
-
     private var apps: List<UnlauncherApp> = listOf()
     private var filteredApps: List<UnlauncherApp> = listOf()
     private var filterQuery = ""
@@ -40,6 +39,9 @@ class AppDrawerAdapter(
         holder.itemView.setOnClickListener {
             listener.onAppClicked(item)
         }
+        holder.itemView.setOnLongClickListener {
+            listener.onAppLongClicked(item, it)
+        }
     }
 
     override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {

+ 19 - 0
app/src/main/java/com/sduduzog/slimlauncher/datasource/apps/UnlauncherAppsRepository.kt

@@ -123,6 +123,25 @@ class UnlauncherAppsRepository(
         }
     }
 
+    fun updateDisplayName(appToUpdate: UnlauncherApp, displayName: String) {
+        lifecycleScope.launch {
+            unlauncherAppsStore.updateData { currentApps ->
+                val builder = currentApps.toBuilder()
+                val index = builder.appsList.indexOf(appToUpdate)
+                if (index >= 0) {
+                    builder.setApps(
+                        index,
+                        appToUpdate.toBuilder().setDisplayName(displayName)
+                    )
+                }
+
+                sortAppsAlphabetically(builder)
+                builder.build()
+            }
+        }
+    }
+
+
     fun updateDisplayInDrawer(appToUpdate: UnlauncherApp, displayInDrawer: Boolean) {
         lifecycleScope.launch {
             unlauncherAppsStore.updateData { currentApps ->

+ 57 - 0
app/src/main/java/com/sduduzog/slimlauncher/ui/dialogs/RenameAppDisplayNameDialog.kt

@@ -0,0 +1,57 @@
+package com.sduduzog.slimlauncher.ui.dialogs
+
+import android.app.Dialog
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.widget.EditText
+import android.widget.Toast
+import androidx.appcompat.app.AlertDialog
+import androidx.fragment.app.DialogFragment
+import com.jkuester.unlauncher.datastore.UnlauncherApp
+import com.sduduzog.slimlauncher.R
+import com.sduduzog.slimlauncher.datasource.apps.UnlauncherAppsRepository
+import kotlinx.android.synthetic.main.customise_apps_fragment.*
+
+class RenameAppDisplayNameDialog : DialogFragment() {
+    private lateinit var app: UnlauncherApp
+    private lateinit var unlauncherAppsRepo: UnlauncherAppsRepository
+
+    override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
+        val view = LayoutInflater.from(context).inflate(R.layout.rename_dialog_edit_text, customise_apps_fragment, false)
+        val editText: EditText = view.findViewById(R.id.rename_editText)
+        val appName: String = app.displayName
+        editText.text.append(appName)
+        val builder = AlertDialog.Builder(requireContext())
+        builder.setTitle("Rename $appName")
+        builder.setView(view)
+        builder.setPositiveButton("DONE") { _, _ ->
+            val name = editText.text.toString()
+            updateApp(name)
+        }
+        editText.setOnEditorActionListener { v, _, _ ->
+            val name = v.text.toString()
+            updateApp(name)
+            this@RenameAppDisplayNameDialog.dismiss()
+            true
+        }
+
+        return builder.create()
+    }
+
+    private fun updateApp(newName: String) {
+        if (newName.isNotEmpty()) {
+            unlauncherAppsRepo.updateDisplayName(app, newName)
+        } else {
+            Toast.makeText(context, "Couldn't save, App name shouldn't be empty", Toast.LENGTH_LONG).show()
+        }
+    }
+
+    companion object {
+        fun getInstance(app: UnlauncherApp, unlauncherAppsRepo : UnlauncherAppsRepository) : RenameAppDisplayNameDialog {
+            return RenameAppDisplayNameDialog().apply {
+                this.app = app
+                this.unlauncherAppsRepo = unlauncherAppsRepo
+            }
+        }
+    }
+}

+ 52 - 0
app/src/main/java/com/sduduzog/slimlauncher/ui/main/HomeFragment.kt

@@ -3,15 +3,20 @@ package com.sduduzog.slimlauncher.ui.main
 import android.app.Activity
 import android.content.*
 import android.content.pm.LauncherApps
+import android.net.Uri
 import android.os.Bundle
 import android.os.UserManager
 import android.provider.AlarmClock
 import android.provider.CalendarContract
 import android.provider.MediaStore
+import android.provider.Settings
 import android.view.LayoutInflater
+import android.view.MenuItem
 import android.view.View
 import android.view.ViewGroup
 import android.view.inputmethod.InputMethodManager
+import android.widget.PopupMenu
+import android.widget.Toast
 import androidx.constraintlayout.motion.widget.MotionLayout
 import androidx.constraintlayout.motion.widget.MotionLayout.TransitionListener
 import androidx.fragment.app.viewModels
@@ -26,6 +31,7 @@ import com.sduduzog.slimlauncher.datasource.UnlauncherDataSource
 import com.sduduzog.slimlauncher.datasource.quickbuttonprefs.QuickButtonPreferencesRepository
 import com.sduduzog.slimlauncher.models.HomeApp
 import com.sduduzog.slimlauncher.models.MainViewModel
+import com.sduduzog.slimlauncher.ui.dialogs.RenameAppDisplayNameDialog
 import com.sduduzog.slimlauncher.utils.BaseFragment
 import com.sduduzog.slimlauncher.utils.OnLaunchAppListener
 import dagger.hilt.android.AndroidEntryPoint
@@ -37,6 +43,7 @@ import java.text.SimpleDateFormat
 import java.util.*
 import javax.inject.Inject
 
+
 @AndroidEntryPoint
 class HomeFragment : BaseFragment(), OnLaunchAppListener {
     @Inject
@@ -281,6 +288,51 @@ class HomeFragment : BaseFragment(), OnLaunchAppListener {
     }
 
     inner class AppDrawerListener {
+        fun onAppLongClicked(app : UnlauncherApp, view: View) : Boolean {
+            val popupMenu = PopupMenu(context, view)
+            popupMenu.inflate(R.menu.app_long_press_menu)
+
+            popupMenu.setOnMenuItemClickListener { item: MenuItem? ->
+
+                when (item!!.itemId) {
+                    R.id.open -> {
+                        onAppClicked(app)
+                    }
+                    R.id.info -> {
+                        val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
+                        intent.addCategory(Intent.CATEGORY_DEFAULT)
+                        intent.data = Uri.parse("package:" + app.packageName)
+                        startActivity(intent)
+                    }
+                    R.id.hide -> {
+                        unlauncherDataSource.unlauncherAppsRepo.updateDisplayInDrawer(app, false)
+                        Toast.makeText(context, "Unhide under Unlauncher's Options > Customize Drawer > Visible Apps", Toast.LENGTH_LONG).show()
+                    }
+                    R.id.rename -> {
+                        RenameAppDisplayNameDialog.getInstance(app, unlauncherDataSource.unlauncherAppsRepo).show(childFragmentManager, "AppListAdapter")
+                    }
+                    R.id.uninstall -> {
+                        val intent = Intent(Intent.ACTION_DELETE)
+                        intent.data = Uri.parse("package:" + app.packageName)
+                        startActivity(intent)
+                        //appDrawerAdapter.notifyDataSetChanged()
+                        // TODO: Handle the case when this is done for system apps
+                    }
+                }
+                true
+            }
+
+            val fieldMPopup = PopupMenu::class.java.getDeclaredField("mPopup")
+            fieldMPopup.isAccessible = true
+            val mPopup = fieldMPopup.get(popupMenu)
+            mPopup.javaClass
+                .getDeclaredMethod("setForceShowIcon", Boolean::class.java)
+                .invoke(mPopup, true)
+
+            popupMenu.show()
+            return true
+        }
+
         fun onAppClicked(app: UnlauncherApp) {
             launchApp(app.packageName, app.className, app.userSerial)
             home_fragment.transitionToStart()

+ 9 - 0
app/src/main/res/drawable/ic_app_info.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="?attr/colorAccent"
+        android:pathData="M11,7h2v2h-2zM11,11h2v6h-2zM12,2C6.48,2 2,6.48 2,12s4.48,10 10,10 10,-4.48 10,-10S17.52,2 12,2zM12,20c-4.41,0 -8,-3.59 -8,-8s3.59,-8 8,-8 8,3.59 8,8 -3.59,8 -8,8z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_hide_app.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <path
+        android:fillColor="?attr/colorAccent"
+        android:pathData="m31.45,27.05 l-2.2,-2.2q1.3,-3.55 -1.35,-5.9 -2.65,-2.35 -5.75,-1.2l-2.2,-2.2q0.85,-0.55 1.9,-0.8 1.05,-0.25 2.15,-0.25 3.55,0 6.025,2.475Q32.5,19.45 32.5,23q0,1.1 -0.275,2.175 -0.275,1.075 -0.775,1.875ZM37.9,33.5 L35.9,31.5q2.45,-1.8 4.275,-4.025Q42,25.25 42.85,23q-2.5,-5.55 -7.5,-8.775Q30.35,11 24.5,11q-2.1,0 -4.3,0.4 -2.2,0.4 -3.45,0.95L14.45,10q1.75,-0.8 4.475,-1.4Q21.65,8 24.25,8q7.15,0 13.075,4.075Q43.25,16.15 46,23q-1.3,3.2 -3.35,5.85 -2.05,2.65 -4.75,4.65ZM40.8,44.8 L32.4,36.55q-1.75,0.7 -3.95,1.075T24,38q-7.3,0 -13.25,-4.075T2,23q1,-2.6 2.775,-5.075T9.1,13.2L2.8,6.9l2.1,-2.15L42.75,42.6ZM11.15,15.3q-1.85,1.35 -3.575,3.55Q5.85,21.05 5.1,23q2.55,5.55 7.675,8.775Q17.9,35 24.4,35q1.65,0 3.25,-0.2t2.4,-0.6l-3.2,-3.2q-0.55,0.25 -1.35,0.375T24,31.5q-3.5,0 -6,-2.45T15.5,23q0,-0.75 0.125,-1.5T16,20.15ZM26.4,22.4ZM20.6,25.3Z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_open_app.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="24"
+    android:viewportHeight="24">
+    <path
+        android:fillColor="?attr/colorAccent"
+        android:pathData="M19,19H5V5h7V3H5c-1.11,0 -2,0.9 -2,2v14c0,1.1 0.89,2 2,2h14c1.1,0 2,-0.9 2,-2v-7h-2v7zM14,3v2h3.59l-9.83,9.83 1.41,1.41L19,6.41V10h2V3h-7z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_rename_app.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <path
+        android:fillColor="?attr/colorAccent"
+        android:pathData="M9,39h2.2l22.15,-22.15 -2.2,-2.2L9,36.8ZM39.7,14.7 L33.3,8.3 35.4,6.2q0.85,-0.85 2.1,-0.85t2.1,0.85l2.2,2.2q0.85,0.85 0.85,2.1t-0.85,2.1ZM37.6,16.8L12.4,42L6,42v-6.4l25.2,-25.2ZM32.25,15.75 L31.15,14.65 33.35,16.85Z"/>
+</vector>

+ 9 - 0
app/src/main/res/drawable/ic_uninstall_app.xml

@@ -0,0 +1,9 @@
+<vector xmlns:android="http://schemas.android.com/apk/res/android"
+    android:width="24dp"
+    android:height="24dp"
+    android:viewportWidth="48"
+    android:viewportHeight="48">
+    <path
+        android:fillColor="?attr/colorAccent"
+        android:pathData="M13.05,42q-1.25,0 -2.125,-0.875T10.05,39L10.05,10.5L8,10.5v-3h9.4L17.4,6h13.2v1.5L40,7.5v3h-2.05L37.95,39q0,1.2 -0.9,2.1 -0.9,0.9 -2.1,0.9ZM34.95,10.5h-21.9L13.05,39h21.9ZM18.35,34.7h3L21.35,14.75h-3ZM26.65,34.7h3L29.65,14.75h-3ZM13.05,10.5L13.05,39Z"/>
+</vector>

+ 23 - 0
app/src/main/res/menu/app_long_press_menu.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item
+        android:id="@+id/open"
+        android:title="@string/open_app"
+        android:icon="@drawable/ic_open_app"/>
+    <item
+        android:id="@+id/info"
+        android:title="@string/app_info"
+        android:icon="@drawable/ic_app_info"/>
+    <item
+        android:id="@+id/hide"
+        android:title="@string/hide_app"
+        android:icon="@drawable/ic_hide_app" />
+    <item
+        android:id="@+id/rename"
+        android:title="@string/rename_app"
+        android:icon="@drawable/ic_rename_app" />
+    <item
+        android:id="@+id/uninstall"
+        android:title="@string/uninstall"
+        android:icon="@drawable/ic_uninstall_app" />
+</menu>

+ 5 - 0
app/src/main/res/values/strings.xml

@@ -57,5 +57,10 @@
     <string name="remove_all_apps_dialog_title" translatable="false">Remove All Apps</string>
     <string name="remove_all_apps_dialog_message" translatable="false">"This action will not uninstall your apps."
     "It is just to confirm if you're clearing this list on purpose"</string>
+    <string name="open_app">Open App</string>
+    <string name="app_info">App Info</string>
+    <string name="hide_app">Hide App</string>
+    <string name="rename_app">Rename App</string>
+    <string name="uninstall">Uninstall</string>
 
 </resources>