diff --git a/app/build.gradle.kts b/app/build.gradle.kts
index ff34894f..39458454 100644
--- a/app/build.gradle.kts
+++ b/app/build.gradle.kts
@@ -70,4 +70,5 @@ dependencies {
implementation ("com.google.android.material:material:1.10.0")
implementation (kotlin("stdlib", version = kotlinVersion))
implementation ("com.github.cachapa:ExpandableLayout:2.9.2")
+ implementation ("com.squareup.picasso:picasso:2.8")
}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 099a1213..e30947b0 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -19,6 +19,9 @@
+
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/AlphabetScrollbar.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/AlphabetScrollbar.kt
index 043aab8d..ba8d350c 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AlphabetScrollbar.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AlphabetScrollbar.kt
@@ -1,118 +1,112 @@
-/*
- * Lunar Launcher
- * Copyright (C) 2022 Md Rasel Hossain
- *
- * 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 .
- */
-
-package rasel.lunar.launcher.apps
-
-import android.annotation.SuppressLint
-import android.content.Context
-import android.graphics.Canvas
-import android.graphics.Paint
-import android.util.AttributeSet
-import android.util.TypedValue
-import android.view.MotionEvent
-import android.view.View
-import androidx.core.content.ContextCompat
-import rasel.lunar.launcher.apps.AppDrawer.Companion.alphabetList
-import rasel.lunar.launcher.apps.AppDrawer.Companion.letterPreview
-import rasel.lunar.launcher.apps.AppDrawer.Companion.listenScroll
-import rasel.lunar.launcher.apps.AppDrawer.Companion.settingsPrefs
-import rasel.lunar.launcher.apps.AppsAdapter.Companion.appsSize
-import rasel.lunar.launcher.helpers.Constants
-
-
-internal class AlphabetScrollbar : View {
-
- private var paint: Paint? = null
- private var selectedIndex = -1
- private val alphabet get() = alphabetList.distinct()
-
- constructor(context: Context?) : super(context) {
- init()
- }
-
- constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
- init()
- }
-
- constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
- init()
- }
-
- @SuppressLint("ResourceType")
- private fun init() {
- paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
- color = defaultTextColor
- textSize = 16f
- }
- }
-
- override fun onDraw(canvas: Canvas) {
- super.onDraw(canvas)
- val width = width
- val height = height
- val letterHeight: Int = height / alphabet.count()
- alphabet.indices.forEach { i: Int ->
- val x = width / 2f - paint!!.measureText(alphabet[i]) / 2f
- val y = i * letterHeight + letterHeight / 2f
- when (i) {
- selectedIndex -> paint!!.textSize = 20f
- else -> paint!!.textSize = 16f
- }
- canvas.drawText(alphabet[i], x, y, paint!!)
- }
- }
-
- @SuppressLint("ClickableViewAccessibility")
- override fun onTouchEvent(event: MotionEvent): Boolean {
- when (event.action) {
- MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
- val y = event.y
- val index = (y / height * alphabet.count()).toInt()
- if (index != selectedIndex) {
- selectedIndex = index
- invalidate()
- }
-
- if (!settingsPrefs!!.getBoolean(Constants.KEY_APPS_COUNT, true)) letterPreview?.visibility = VISIBLE
- try { letterPreview?.text = alphabet[selectedIndex] }
- catch (exception: Exception) { exception.printStackTrace() }
- }
-
- MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
- when {
- selectedIndex < 0 -> listenScroll(alphabet[0])
- selectedIndex > alphabet.count() - 1 -> listenScroll(alphabet[alphabet.count() - 1])
- else -> listenScroll(alphabet[selectedIndex])
- }
-
- selectedIndex = -1
- invalidate()
- if (settingsPrefs!!.getBoolean(Constants.KEY_APPS_COUNT, true)) letterPreview?.text = appsSize.toString()
- else letterPreview?.visibility = GONE
- }
- }
- return true
- }
-
- private val defaultTextColor: Int get() {
- val resolvedAttr = TypedValue()
- context.theme.resolveAttribute(android.R.attr.textColorPrimary, resolvedAttr, true)
- val colorRes = resolvedAttr.run { if (resourceId != 0) resourceId else data }
- return ContextCompat.getColor(context, colorRes)
- }
-}
\ No newline at end of file
+///*
+// * Lunar Launcher
+// * Copyright (C) 2022 Md Rasel Hossain
+// *
+// * 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 .
+// */
+//
+//package rasel.lunar.launcher.apps
+//
+//import android.annotation.SuppressLint
+//import android.content.Context
+//import android.graphics.Canvas
+//import android.graphics.Paint
+//import android.util.AttributeSet
+//import android.util.TypedValue
+//import android.view.MotionEvent
+//import android.view.View
+//import androidx.core.content.ContextCompat
+//
+//
+//internal class AlphabetScrollbar : View {
+//
+// private var paint: Paint? = null
+// private var selectedIndex = -1
+//// private val alphabet get() = alphabetList.distinct()
+//
+// constructor(context: Context?) : super(context) {
+// init()
+// }
+//
+// constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) {
+// init()
+// }
+//
+// constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
+// init()
+// }
+//
+// @SuppressLint("ResourceType")
+// private fun init() {
+// paint = Paint(Paint.ANTI_ALIAS_FLAG).apply {
+// color = defaultTextColor
+// textSize = 16f
+// }
+// }
+//
+// override fun onDraw(canvas: Canvas) {
+// super.onDraw(canvas)
+// val width = width
+// val height = height
+// val letterHeight: Int = height / alphabet.count()
+// alphabet.indices.forEach { i: Int ->
+// val x = width / 2f - paint!!.measureText(alphabet[i]) / 2f
+// val y = i * letterHeight + letterHeight / 2f
+// when (i) {
+// selectedIndex -> paint!!.textSize = 20f
+// else -> paint!!.textSize = 16f
+// }
+// canvas.drawText(alphabet[i], x, y, paint!!)
+// }
+// }
+//
+// @SuppressLint("ClickableViewAccessibility")
+// override fun onTouchEvent(event: MotionEvent): Boolean {
+//// when (event.action) {
+//// MotionEvent.ACTION_DOWN, MotionEvent.ACTION_MOVE -> {
+//// val y = event.y
+//// val index = (y / height * alphabet.count()).toInt()
+//// if (index != selectedIndex) {
+//// selectedIndex = index
+//// invalidate()
+//// }
+////
+//// if (!settingsPrefs!!.getBoolean(Constants.KEY_APPS_COUNT, true)) letterPreview?.visibility = VISIBLE
+//// try { letterPreview?.text = alphabet[selectedIndex] }
+//// catch (exception: Exception) { exception.printStackTrace() }
+//// }
+////
+//// MotionEvent.ACTION_UP, MotionEvent.ACTION_CANCEL -> {
+//// when {
+//// selectedIndex < 0 -> listenScroll(alphabet[0])
+//// selectedIndex > alphabet.count() - 1 -> listenScroll(alphabet[alphabet.count() - 1])
+//// else -> listenScroll(alphabet[selectedIndex])
+//// }
+////
+//// selectedIndex = -1
+//// invalidate()
+//// if (settingsPrefs!!.getBoolean(Constants.KEY_APPS_COUNT, true)) letterPreview?.text = appsSize.toString()
+//// else letterPreview?.visibility = GONE
+//// }
+//// }
+// return true
+// }
+//
+// private val defaultTextColor: Int get() {
+// val resolvedAttr = TypedValue()
+// context.theme.resolveAttribute(android.R.attr.textColorPrimary, resolvedAttr, true)
+// val colorRes = resolvedAttr.run { if (resourceId != 0) resourceId else data }
+// return ContextCompat.getColor(context, colorRes)
+// }
+//}
\ No newline at end of file
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt
index 59024fa1..23b0cc4e 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt
@@ -27,6 +27,7 @@ import android.content.pm.ResolveInfo
import android.graphics.Rect
import android.os.Build
import android.os.Bundle
+import android.provider.Settings.Global
import android.view.Gravity
import android.view.LayoutInflater
import android.view.View
@@ -41,6 +42,9 @@ import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.android.material.textview.MaterialTextView
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.launch
import rasel.lunar.launcher.BuildConfig
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R
@@ -75,42 +79,25 @@ internal class AppDrawer : Fragment() {
private var appsAdapter: AppsAdapter? = null
private var packageInfoList: MutableList = mutableListOf()
private var packageList = mutableListOf()
- private var packageListClone = mutableListOf()
- private val numberPattern = Pattern.compile("[0-9]")
- private val alphabetPattern = Pattern.compile("[A-Z]")
+
+ // private val numberPattern = Pattern.compile("[0-9]")
+// private val alphabetPattern = Pattern.compile("[A-Z]")
@JvmStatic var settingsPrefs: SharedPreferences? = null
@JvmStatic var appNamesPrefs: SharedPreferences? = null
- @JvmStatic var alphabetList = mutableListOf()
+ // @JvmStatic var alphabetList = mutableListOf()
@JvmStatic var letterPreview: MaterialTextView? = null
private fun appName(resolver: ResolveInfo): String {
- return appNamesPrefs?.getString(resolver.activityInfo.packageName, resolver.loadLabel(packageManager).toString())!!
+ if(appNamesPrefs?.contains(resolver.activityInfo.packageName) != null && appNamesPrefs?.getString(resolver.activityInfo.packageName,"")?.length ?: 0 > 0) {
+ return appNamesPrefs?.getString(resolver.activityInfo.packageName,"") ?: ""
+ } else {
+ return resolver.loadLabel(packageManager).toString().apply {
+ appNamesPrefs?.edit()?.putString(resolver.activityInfo.packageName, this)?.apply()
+ }
+ }
+
}
- fun listenScroll(letter: String) {
-// packageListClone.clear()
-// for (resolver in packageInfoList) {
-// when {
-// letter == "#" -> {
-// if (numberPattern.matcher(appName(resolver).first().uppercase()).matches()) {
-// packageListClone.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
-// }
-// }
-// alphabetPattern.matcher(letter).matches() -> {
-// if (appName(resolver).first().uppercase() == letter) {
-// packageListClone.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
-// }
-// }
-// letter == "⠶" -> {
-// if (!numberPattern.matcher(appName(resolver).first().uppercase()).matches() &&
-// !alphabetPattern.matcher(appName(resolver).first().uppercase()).matches()) {
-// packageListClone.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
-// }
-// }
-// }
-// }
-// appsAdapter?.updateData(packageListClone.sortedBy { it.appName.lowercase() })
- }
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
@@ -126,9 +113,7 @@ internal class AppDrawer : Fragment() {
binding.appsCount.visibility = if (settingsPrefs!!.getBoolean(KEY_APPS_COUNT, true)) VISIBLE else GONE
setLayout()
- fetchApps()
- getAlphabetItems()
- setKeyboardPadding()
+
return binding.root
}
@@ -140,7 +125,7 @@ internal class AppDrawer : Fragment() {
binding.reset.setOnClickListener { onResume() }
binding.moveDown.setOnClickListener {
- binding.appsList.smoothScrollToPosition(packageListClone.size - 1)
+ binding.appsList.smoothScrollToPosition(packageList.size - 1)
}
binding.moveUp.setOnClickListener {
@@ -163,7 +148,7 @@ internal class AppDrawer : Fragment() {
override fun onResume() {
super.onResume()
fetchApps()
- getAlphabetItems()
+ setKeyboardPadding()
binding.appsCount.visibility = if (settingsPrefs!!.getBoolean(KEY_APPS_COUNT, true)) VISIBLE else GONE
@@ -186,7 +171,7 @@ internal class AppDrawer : Fragment() {
binding.appsList.layoutManager = LinearLayoutManager(requireContext())
appsAdapter!!.updateGravity(settingsPrefs!!.getInt(KEY_DRAW_ALIGN, Gravity.CENTER))
}
- 2 -> binding.appsList.layoutManager = GridLayoutManager(requireContext(), settingsPrefs!!.getInt(KEY_GRID_COLUMNS, DEFAULT_GRID_COLUMNS))
+ 2 -> binding.appsList.layoutManager = GridLayoutManager(requireContext(), Math.min(settingsPrefs!!.getInt(KEY_GRID_COLUMNS, DEFAULT_GRID_COLUMNS), 4))
}
/* initialize apps list adapter */
@@ -195,30 +180,39 @@ internal class AppDrawer : Fragment() {
/* update app list with app and package name */
fun fetchApps() {
- packageInfoList = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
- packageManager?.queryIntentActivities(
- Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER),
- PackageManager.ResolveInfoFlags.of(0)
- )
- } else {
- (packageManager?.queryIntentActivities(
- Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER), 0))
- })?.apply {
- removeIf { it.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID) }
- sortWith(ResolveInfo.DisplayNameComparator(packageManager))
- }!!
+ GlobalScope.launch {
+ packageInfoList = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
+ packageManager?.queryIntentActivities(
+ Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER),
+ PackageManager.ResolveInfoFlags.of(0)
+ )
+ } else {
+ (packageManager?.queryIntentActivities(
+ Intent(Intent.ACTION_MAIN, null).addCategory(Intent.CATEGORY_LAUNCHER), 0
+ ))
+ })?.apply {
+ removeIf { it.activityInfo.packageName.equals(BuildConfig.APPLICATION_ID) }
+ sortedBy {
+ appName(it)
+ }
+ }!!
- /* add package and app names to the list */
- packageList.clear()
- packageListClone.clear()
- for (resolver in packageInfoList) {
- packageList.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
- packageListClone.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
- }
+ /* add package and app names to the list */
+ packageList.clear()
+ var edit = appNamesPrefs?.edit()
+ for (resolver in packageInfoList) {
+ packageList.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
+ }
- when {
- packageListClone.size < 1 -> return
- else -> appsAdapter?.updateData(packageListClone.sortedBy { it.appName.lowercase() })
+// when {
+// packageList.size < 1 -> return
+// else -> {
+ if (packageList.size > 0) {
+ MainScope().launch {
+ appsAdapter?.updateData(packageList)
+ }
+ }
+// }
}
}
@@ -247,43 +241,63 @@ internal class AppDrawer : Fragment() {
// }
}
+ var lastSearchStringLength = 0
+ var lastSearchString : String = ""
private fun filterAppsList(searchString: String) {
/* check each app name and add if it matches the search string */
- packageListClone.clear()
- for (resolver in packageInfoList) {
- appName(resolver).let {
- BLog.LOGE("searchString >>> ${searchString} , normalize(it) ${normalize(it)} ${normalize(it).contains(searchString)}")
- if (normalize(it).contains(searchString)) {
- packageListClone.add(Packages(resolver.activityInfo.packageName, it))
+ if (lastSearchStringLength > 0 && (lastSearchStringLength != searchString.length || lastSearchString.equals(searchString) == false)) {
+ BLog.LOGE("START FILTER")
+ packageList.clear()
+ for (resolver in packageInfoList) {
+ appName(resolver).let {
+// BLog.LOGE("searchString >>> ${searchString} , normalize(it) ${normalize(it)} ${normalize(it).contains(normalize(searchString), false)}")
+ if (normalize(it).contains(normalize(searchString), false)) {
+ packageList.add(Packages(resolver.activityInfo.packageName, it))
+ } else {
+
+ }
}
}
- }
-
- if (searchString.length > 2 && packageListClone.size == 1 && settingsPrefs!!.getBoolean(KEY_QUICK_LAUNCH, true)) {
- var dialog = AlertDialog.Builder(requireContext())
- dialog.setTitle("앱 실행 확인")
- dialog.setMessage("${searchString} 검색 결과 '${packageListClone[0].appName}' 준비됨")
- dialog.setCancelable(false)
- dialog.setOnCancelListener {
- binding.searchInput.setText("")
- it.dismiss()
+ BLog.LOGE("MIDDLE FILTER")
+ if (searchString.length > 2 && packageList.size == 1 && settingsPrefs!!.getBoolean(
+ KEY_QUICK_LAUNCH,
+ true
+ )
+ ) {
+ var dialog = AlertDialog.Builder(requireContext())
+ dialog.setTitle("앱 실행 확인")
+ dialog.setMessage("${searchString} 검색 결과 '${packageList[0].appName}' 준비됨")
+ dialog.setCancelable(false)
+ dialog.setNegativeButton("취소") { s,d->
+ binding.searchInput.setText("")
+ s.dismiss()
+ }
+ dialog.setPositiveButton("실행") { s, d ->
+ startActivity(packageManager?.getLaunchIntentForPackage(packageList[0].packageName))
+ s.dismiss()
+ binding.searchInput.setText("")
+ }
+ dialog.show()
+ } else {
+ appsAdapter?.updateData(packageList)
}
- dialog.setPositiveButton("실행") { s,d ->
- startActivity(packageManager?.getLaunchIntentForPackage(packageListClone[0].packageName))
- s.dismiss()
- binding.searchInput.setText("")
+ BLog.LOGE("END FILTER")
+ } else if(lastSearchStringLength == 0){
+ packageList.clear()
+ for (resolver in packageInfoList) {
+ packageList.add(Packages(resolver.activityInfo.packageName, appName(resolver)))
}
- dialog.show()
+ appsAdapter?.updateData(packageList)
}
- else appsAdapter?.updateData(packageListClone.sortedBy { it.appName.lowercase() })
-
+ lastSearchString = searchString
+ lastSearchStringLength = searchString.length
}
private fun normalize(str: String): String {
val normalizedString =
- Normalizer.normalize(str.replace("\\W".toRegex(), ""), Normalizer.Form.NFD)
+ Normalizer.normalize(str.replace("\\W".toRegex(), ""), Normalizer.Form.NFC)
val pattern = Pattern.compile("\\p{InCombiningDiacriticalMarks}+")
- return pattern.matcher(normalizedString).replaceAll("").lowercase()
+ return pattern.matcher(normalizedString).replaceAll("").toLowerCase()
}
private fun openSearch() {
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppsAdapter.kt
index 9072c000..7da00b1a 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppsAdapter.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppsAdapter.kt
@@ -30,6 +30,8 @@ import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.android.material.textview.MaterialTextView
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.async
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R
import rasel.lunar.launcher.apps.IconPackManager.Companion.getDrawableIconForPackage
@@ -75,7 +77,13 @@ internal class AppsAdapter(
}
1 -> {
appIcon.visibility = View.GONE
- appIconTwo.setImageDrawable(getDrawableIconForPackage(item.packageName, packageManager.getApplicationIcon(item.packageName)))
+ appIconTwo.visibility = View.VISIBLE
+
+ MainScope().async {
+ getDrawableIconForPackage(item.packageName, packageManager.getApplicationIcon(item.packageName)) {
+ appIconTwo.post { appIconTwo.setImageDrawable(it) }
+ } }
+
childTextview.apply {
gravity = appGravity or Gravity.CENTER_VERTICAL
setTextSize(TypedValue.COMPLEX_UNIT_PX, lActivity!!.resources.getDimension(R.dimen.twenty))
@@ -85,7 +93,15 @@ internal class AppsAdapter(
}
2 -> {
appIconTwo.visibility = View.GONE
- appIcon.setImageDrawable(getDrawableIconForPackage(item.packageName, packageManager.getApplicationIcon(item.packageName)))
+ appIcon.visibility = View.VISIBLE
+ MainScope().async {
+ getDrawableIconForPackage(
+ item.packageName,
+ packageManager.getApplicationIcon(item.packageName)
+ ) {
+ appIcon.post { appIcon.setImageDrawable(it) }
+ }
+ }
childTextview.apply {
gravity = Gravity.CENTER
setTextSize(TypedValue.COMPLEX_UNIT_PX, lActivity!!.resources.getDimension(R.dimen.twelve))
@@ -125,7 +141,6 @@ internal class AppsAdapter(
appsCount.text = it.toString()
appsSize = it
}
- this.notifyDataSetChanged()
}
/* update text gravity (alignment) */
@@ -138,6 +153,10 @@ internal class AppsAdapter(
notifyDataSetChanged()
}
}
+
+ fun hideItem(idx: Int) {
+
+ }
}
internal data class Packages (
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/IconPackManager.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/IconPackManager.kt
index d967b4a2..6087eb23 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/apps/IconPackManager.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/IconPackManager.kt
@@ -25,7 +25,13 @@ import android.graphics.Bitmap
import android.graphics.drawable.BitmapDrawable
import android.graphics.drawable.Drawable
import android.util.Log
+import androidx.collection.LruCache
import androidx.core.content.res.ResourcesCompat
+import com.squareup.picasso.Picasso
+import kotlinx.coroutines.GlobalScope
+import kotlinx.coroutines.MainScope
+import kotlinx.coroutines.async
+import kotlinx.coroutines.launch
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import org.xmlpull.v1.XmlPullParserFactory
@@ -47,12 +53,14 @@ internal class IconPackManager {
private val packageName = settingsPrefs.getString(KEY_ICON_PACK, DEFAULT_ICON_PACK)
private var loaded = false
private val packagesDrawables = HashMap()
+ private val packagesConponentNames = HashMap()
private val backImages: MutableList = ArrayList()
private var maskImage: Bitmap? = null
private var frontImage: Bitmap? = null
private var factor = 1.0f
private var totalIcons = 0
private var iconPackRes: Resources? = null
+ private var appPackageIconDrawables : HashMap = hashMapOf()
private fun load() {
/* load appfilter.xml from the icon pack package */
@@ -62,11 +70,14 @@ internal class IconPackManager {
val appFilterId = iconPackRes!!.getIdentifier("appfilter", "xml", packageName)
if (appFilterId > 0) {
xpp = iconPackRes!!.getXml(appFilterId)
+ BLog.LOGE("packageName >>> ${packageName}")
} else {
- /* no resource found, try to open it from assets folder */
try {
xpp = XmlPullParserFactory.newInstance().apply { isNamespaceAware = true }
- .newPullParser().apply { setInput(iconPackRes!!.assets.open("appfilter.xml"), "utf-8") }
+ .newPullParser().apply {
+ BLog.LOGE("packageName >>> ${packageName}")
+ setInput(iconPackRes!!.assets.open("appfilter.xml"), "utf-8")
+ }
} catch (e: IOException) {
e.printStackTrace()
BLog.w("", "Couldn't find the appfilter.xml file")
@@ -78,36 +89,24 @@ internal class IconPackManager {
if (eventType == XmlPullParser.START_TAG) {
when (xpp.name) {
"iconback" -> {
- for (i in 0 until xpp.attributeCount) {
- if (xpp.getAttributeName(i).startsWith("img")) {
- loadBitmap(xpp.getAttributeValue(i))?.let { backImages.add(it) }
- }
- }
+ for (i in 0 until xpp.attributeCount) { if (xpp.getAttributeName(i).startsWith("img")) { loadBitmap(xpp.getAttributeValue(i))?.let { backImages.add(it) }}}
}
"iconmask" -> {
- if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "img1") {
- maskImage = loadBitmap(xpp.getAttributeValue(0))
- }
+ if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "img1") { maskImage = loadBitmap(xpp.getAttributeValue(0)) }
}
"iconupon" -> {
- if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "img1") {
- frontImage = loadBitmap(xpp.getAttributeValue(0))
- }
+ if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "img1") { frontImage = loadBitmap(xpp.getAttributeValue(0)) }
}
"scale" -> {
- if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "factor") {
- factor = java.lang.Float.valueOf(xpp.getAttributeValue(0))
- }
+ if (xpp.attributeCount > 0 && xpp.getAttributeName(0) == "factor") { factor = java.lang.Float.valueOf(xpp.getAttributeValue(0)) }
}
"item" -> {
var componentName: String? = null
var drawableName: String? = null
- for (i in 0 until xpp.attributeCount) {
- when (xpp.getAttributeName(i)) {
- "component" -> componentName = xpp.getAttributeValue(i)
- "drawable" -> drawableName = xpp.getAttributeValue(i)
- }
- }
+ for (i in 0 until xpp.attributeCount) { when (xpp.getAttributeName(i)) {
+ "component" -> componentName = xpp.getAttributeValue(i)
+ "drawable" -> drawableName = xpp.getAttributeValue(i)
+ } }
if (!packagesDrawables.containsKey(componentName)) {
packagesDrawables[componentName] = drawableName
totalIcons += 1
@@ -127,12 +126,30 @@ internal class IconPackManager {
e.printStackTrace()
}
}
+ val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
+ val cacheSize = maxMemory / 8
+ val bitmapCache = object : LruCache(cacheSize) {
+ fun sizeOf(key: String?, value: Bitmap?): Int {
+ return if(value?.byteCount?.toInt() ?: 0 > 1024) {
+ value?.byteCount!!.div(1024)
+ } else { 0 }
+ }
+ }
private fun loadBitmap(drawableName: String): Bitmap? {
+ if (packageName != null && packageName.length > 0) {
+ var bm = bitmapCache.get(packageName)
+ if (bm != null) return bm
+ }
iconPackRes!!.getIdentifier(drawableName, "drawable", packageName).let { id ->
if (id > 0) {
ResourcesCompat.getDrawable(iconPackRes!!, id, null).let {
- if (it is BitmapDrawable) return it.bitmap
+ if (it is BitmapDrawable) {
+ if (packageName != null && packageName.length > 0) {
+ bitmapCache.put(packageName, it.bitmap)
+ }
+ return it.bitmap
+ }
}
}
}
@@ -146,35 +163,69 @@ internal class IconPackManager {
}
}
- fun getDrawableIconForPackage(appPackageName: String?, defaultDrawable: Drawable?): Drawable? {
- when (packageName) {
- DEFAULT_ICON_PACK -> return defaultDrawable
- else -> {
- if (!loaded) load()
- var componentName: String? = null
- if (lActivity!!.packageManager.getLaunchIntentForPackage(appPackageName!!) != null) {
- componentName = lActivity!!.packageManager.getLaunchIntentForPackage(appPackageName)!!.component.toString()
- }
- var drawable = packagesDrawables[componentName]
- if (!drawable.isNullOrEmpty()) return loadDrawable(drawable)
- else {
- /* try to get a resource with the component filename */
- if (!componentName.isNullOrEmpty()) {
- val start = componentName.indexOf("{") + 1
- val end = componentName.indexOf("}", start)
- if (end > start) {
- drawable = componentName.substring(start, end).lowercase(Locale.getDefault()).replace(".", "_").replace("/", "_")
- try {
- if (iconPackRes!!.getIdentifier(drawable, "drawable", packageName) > 0) return loadDrawable(drawable)
- } catch (e: NullPointerException) {
- settingsPrefs.edit().putString(KEY_ICON_PACK, DEFAULT_ICON_PACK).apply()
+ fun putAfterReturn(packages: String, drawable : Drawable?) : Drawable? {
+ if (drawable != null) {
+ appPackageIconDrawables.put(packages, drawable)
+ }
+ return drawable
+ }
+
+ fun getDrawableIconForPackage(appPackageName: String?, defaultDrawable: Drawable?, onComplete : (Drawable?)->Unit) {
+ var ddd = if (appPackageIconDrawables.containsKey(appPackageName)) appPackageIconDrawables.get(appPackageName) else null
+ if (ddd != null) {
+ onComplete(ddd)
+ } else {
+ when (packageName) {
+ DEFAULT_ICON_PACK -> onComplete.invoke(defaultDrawable)
+ else -> {
+ if (!loaded) load()
+ var componentName: String? = null
+ componentName = packagesConponentNames.get(appPackageName!!)
+ if (componentName == null || componentName.length ?: 0 <= 0 ) {
+ BLog.LOGE("it's compo ${appPackageName}")
+ var pkgIntent =
+ lActivity!!.packageManager.getLaunchIntentForPackage(
+ appPackageName!!
+ )
+ if (pkgIntent != null) {
+ componentName = pkgIntent!!.component.toString()
+ }
+ }
+ var drawable = packagesDrawables[componentName]
+ if (!drawable.isNullOrEmpty()) onComplete.invoke(
+ putAfterReturn(
+ appPackageName,
+ loadDrawable(drawable)
+ )
+ )
+ else {
+ if (!componentName.isNullOrEmpty()) {
+ val start = componentName.indexOf("{") + 1
+ val end = componentName.indexOf("}", start)
+ if (end > start) {
+ drawable = componentName.substring(start, end)
+ .lowercase(Locale.getDefault()).replace(".", "_")
+ .replace("/", "_")
+ try {
+ if (iconPackRes!!.getIdentifier(
+ drawable,
+ "drawable",
+ packageName
+ ) > 0
+ ) onComplete.invoke(putAfterReturn(appPackageName, loadDrawable(drawable)))
+ } catch (e: NullPointerException) {
+ settingsPrefs.edit()
+ .putString(KEY_ICON_PACK, DEFAULT_ICON_PACK).apply()
+ }
}
+ } else {
+ onComplete.invoke(defaultDrawable)
}
}
}
- return defaultDrawable
}
}
+
}
}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHost.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHost.kt
index cf9fe9de..402955b9 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHost.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHost.kt
@@ -32,4 +32,5 @@ internal class WidgetHost(context: Context, hostId: Int) : AppWidgetHost(context
clearViews()
}
+
}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHostView.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHostView.kt
index 847f2d69..b71497a4 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHostView.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/WidgetHostView.kt
@@ -36,7 +36,6 @@ internal class WidgetHostView(context: Context) : AppWidgetHostView(context) {
hasPerformedLongPress = false
return true
}
-
// Watch for long press events at this level to make sure
// users can always pick up this widget
when (ev.action) {
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/helpers/UniUtils.kt b/app/src/main/kotlin/rasel/lunar/launcher/helpers/UniUtils.kt
index e6d785af..ba1ecf32 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/helpers/UniUtils.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/helpers/UniUtils.kt
@@ -212,11 +212,11 @@ internal class UniUtils {
(iconSize * resources.displayMetrics.density).toInt(), 1F)
}.let { sImageView ->
context.packageManager.getApplicationIcon(packageName).let { defaultIcon ->
- sImageView.setImageDrawable(
if (context.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_APPS_LAYOUT, 0) != 0)
- getDrawableIconForPackage(packageName, defaultIcon)
- else defaultIcon
- )
+ getDrawableIconForPackage(packageName, defaultIcon) {
+ sImageView.setImageDrawable(it ?: defaultIcon)
+ }
+ else sImageView.setImageDrawable(defaultIcon)
}
sImageView.setOnClickListener {
context.startActivity(context.packageManager.getLaunchIntentForPackage(packageName))
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/BatteryReceiver.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/BatteryReceiver.kt
index 0ff32f5b..a24b1fa4 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/home/BatteryReceiver.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/home/BatteryReceiver.kt
@@ -26,6 +26,7 @@ import android.provider.Settings
import android.view.animation.AnimationUtils
import com.google.android.material.progressindicator.CircularProgressIndicator
import rasel.lunar.launcher.R
+import rasel.lunar.launcher.utils.BLog
internal class BatteryReceiver(private val progressBar: CircularProgressIndicator) : BroadcastReceiver() {
@@ -42,7 +43,14 @@ internal class BatteryReceiver(private val progressBar: CircularProgressIndicato
override fun onReceive(context: Context?, intent: Intent?) {
val animationDuration = try {
- Settings.Global.getFloat(context?.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE)
+ intent?.extras?.keySet()?.let {
+ it.iterator().forEach {
+ BLog.LOGE("intent key >> ${it}")
+ }
+ }
+ BLog.LOGE("intent >> ${intent}")
+
+ Settings.Global.getFloat(context?.contentResolver, Settings.Global.ANIMATOR_DURATION_SCALE, 1.0f)
} catch (e: Settings.SettingNotFoundException) {
e.printStackTrace()
}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt
index 1d678cd2..d9f838f2 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt
@@ -134,12 +134,7 @@ internal class LauncherHome : Fragment() {
gestureDistance: Double
): Boolean {
when(fingers) {
- 1 ->
- if (targetView?.equals(binding.batteryProgress) ?: false) {
- QuickAccess().show(fragManager, BOTTOM_SHEET_TAG)
- } else {
- QuickAccess().show(fragManager, BOTTOM_SHEET_TAG)
- }
+ 3 -> QuickAccess().show(fragManager, BOTTOM_SHEET_TAG)
2->{
var startIntene = Intent(Intent.ACTION_MAIN)
startIntene.setComponent(ComponentName("com.mime.dualscreenview","com.mime.dualscreenview.activity.Intro"))
@@ -215,11 +210,7 @@ internal class LauncherHome : Fragment() {
override fun onDoubleTap(targetView: View,fingers: Int): Boolean {
when(fingers) {
- 1 -> if (targetView?.equals(binding.batteryProgress) ?: false) {
- lockMethod(settingsPrefs.getInt(KEY_LOCK_METHOD, 0), requireContext(), binding.favAppsGroup)
- } else {
- lockMethod(settingsPrefs.getInt(KEY_LOCK_METHOD, 0), requireContext(), binding.favAppsGroup)
- }
+ 1 -> lockMethod(settingsPrefs.getInt(KEY_LOCK_METHOD, 0), requireContext(), binding.favAppsGroup)
else -> {}
}
return false
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/weather/WeatherExecutor.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/weather/WeatherExecutor.kt
index 657fbedc..9e597e9c 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/home/weather/WeatherExecutor.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/home/weather/WeatherExecutor.kt
@@ -35,6 +35,10 @@ import java.util.concurrent.Executors
internal class WeatherExecutor(sharedPreferences: SharedPreferences) {
+ companion object {
+ var lastedCheckTime = 0L
+ }
+
private val cityName: String
private val owmApi: String
private val weatherUrl: String
@@ -44,10 +48,9 @@ internal class WeatherExecutor(sharedPreferences: SharedPreferences) {
@SuppressLint("SetTextI18n")
fun generateWeatherString(materialTextView: MaterialTextView) {
materialTextView.visibility = View.GONE
-
/* run the executor if network is available,
and city name and owm api values are not empty */
- if (isNetworkAvailable && cityName.isNotEmpty() && owmApi.isNotEmpty()) {
+ if (System.currentTimeMillis() - lastedCheckTime > (1000 * 60 * 15) && isNetworkAvailable && cityName.isNotEmpty() && owmApi.isNotEmpty()) {
try {
Executors.newSingleThreadExecutor().execute {
var weather: Weather? = null
@@ -70,6 +73,7 @@ internal class WeatherExecutor(sharedPreferences: SharedPreferences) {
exception.printStackTrace()
}
}
+ lastedCheckTime = System.currentTimeMillis()
}
init {
@@ -77,7 +81,7 @@ internal class WeatherExecutor(sharedPreferences: SharedPreferences) {
owmApi = sharedPreferences.getString(KEY_OWM_API, "").toString()
tempUnit = sharedPreferences.getInt(KEY_TEMP_UNIT, 0)
showCity = sharedPreferences.getBoolean(KEY_SHOW_CITY, false)
- weatherUrl = URLEncoder.encode("https://api.openweathermap.org/data/2.5/weather?q=$cityName&APPID=$owmApi&units=" + if (tempUnit == 0) "metric" else "imperial","utf-8")
+ weatherUrl = "https://api.openweathermap.org/data/2.5/weather?q=$cityName&APPID=$owmApi&units=" + if (tempUnit == 0) "metric" else "imperial"
}
}
diff --git a/app/src/main/kotlin/rasel/lunar/launcher/settings/childs/Apps.kt b/app/src/main/kotlin/rasel/lunar/launcher/settings/childs/Apps.kt
index 6ffad637..653848db 100644
--- a/app/src/main/kotlin/rasel/lunar/launcher/settings/childs/Apps.kt
+++ b/app/src/main/kotlin/rasel/lunar/launcher/settings/childs/Apps.kt
@@ -127,7 +127,7 @@ internal class Apps : BottomSheetDialogFragment() {
Gravity.RIGHT -> binding.appAlignmentRight.isChecked = true
}
- binding.columnsCount.value = settingsPrefs!!.getInt(KEY_GRID_COLUMNS, DEFAULT_GRID_COLUMNS).toFloat()
+ binding.columnsCount.value = Math.min(settingsPrefs!!.getInt(KEY_GRID_COLUMNS, DEFAULT_GRID_COLUMNS).toFloat(), 4f)
binding.scrollbarHeight.value = settingsPrefs!!.getInt(KEY_SCROLLBAR_HEIGHT, DEFAULT_SCROLLBAR_HEIGHT).toFloat()
return binding.root
diff --git a/app/src/main/res/layout/app_drawer.xml b/app/src/main/res/layout/app_drawer.xml
index 947afeac..e85e2c93 100644
--- a/app/src/main/res/layout/app_drawer.xml
+++ b/app/src/main/res/layout/app_drawer.xml
@@ -7,37 +7,39 @@
-
+
+
+
+
+
+
+
+
+
+ app:layout_constraintLeft_toLeftOf="parent"
+ app:layout_constraintRight_toRightOf="parent"/>
diff --git a/app/src/main/res/layout/apps_child.xml b/app/src/main/res/layout/apps_child.xml
index dca3e351..25c3e256 100644
--- a/app/src/main/res/layout/apps_child.xml
+++ b/app/src/main/res/layout/apps_child.xml
@@ -1,30 +1,40 @@
-
-
+
+
+ android:layout_marginBottom="@dimen/four"
+ android:layout_height="match_parent" />
-
-
-
-
-
\ No newline at end of file
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/settings_apps.xml b/app/src/main/res/layout/settings_apps.xml
index bd40b197..435512ef 100644
--- a/app/src/main/res/layout/settings_apps.xml
+++ b/app/src/main/res/layout/settings_apps.xml
@@ -231,8 +231,8 @@
android:id="@+id/columnsCount"
android:layout_width="@dimen/zero"
android:layout_height="wrap_content"
- android:valueFrom="3"
- android:valueTo="7"
+ android:valueFrom="2"
+ android:valueTo="5"
android:stepSize="1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"