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 9570740..8f149af 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt @@ -28,6 +28,8 @@ import android.content.pm.ResolveInfo import android.net.Uri import android.os.Build import android.os.Bundle +import android.os.Handler +import android.os.Looper import android.provider.ContactsContract import android.util.Log import android.view.Gravity @@ -148,6 +150,12 @@ internal class AppDrawer : Fragment() { binding.searchTranslate.setOnClickListener { openSearchApps("https://translate.google.com/?hl=ko&sl=ko&tl=en&text=${getInputText()}&op=translate","com.android.chrome") } + + binding.searchCoupang.setOnClickListener { + openSearchApps("coupang://search?q=${getInputText()}","com.coupang.mobile") + } + + setLayout() return binding.root @@ -223,13 +231,65 @@ internal class AppDrawer : Fragment() { // false -> openSearch() // } // } - + binding.searchInput.setOnKeyListener { v, keyCode, event -> + BLog.LOGE("v == ${v}, keyCode == ${keyCode}, event == ${event}") + if (keyCode==66) { checkResult() } + return@setOnKeyListener true + } binding.searchInput.doOnTextChanged { inputText, _, _, _ -> binding.searchInput.text?.let { binding.searchInput.setSelection(it.length) } filterAppsList(inputText.toString()) } } + fun checkResult() { + if (lastSearchString.length > 0 && packageList.size == 1) { + var dialog = AlertDialog.Builder(requireContext()) + dialog.setTitle("앱 실행 확인") + dialog.setMessage("${lastSearchString} 검색 결과 '${packageList[0].appName}' 준비됨") + dialog.setCancelable(false) + dialog.setNegativeButton("취소") { s,d-> + s.dismiss() + } + dialog.setPositiveButton("실행") { s, d -> + startActivity(packageManager?.getLaunchIntentForPackage(packageList[0].packageName)) + s.dismiss() + } + dialog.show() + } else if (packageList.size == 0 && contactList.size == 1) { + var dialog = AlertDialog.Builder(requireContext()) + dialog.setTitle("연락처 실행 확인") + dialog.setMessage("${lastSearchString} 검색 결과 '${contactList[0].name}' 준비됨") + dialog.setCancelable(false) + dialog.setNegativeButton("취소") { s,d-> + s.dismiss() + } + dialog.setPositiveButton("실행") { s, d -> + ContactMenu().show(childFragmentManager, contactList[0].id.toString()) + s.dismiss() + } + dialog.show() + } else { + var dialog = AlertDialog.Builder(requireContext()) + dialog.setTitle("검색 실행 확인") + dialog.setMessage("${lastSearchString} 검색 준비됨") + dialog.setCancelable(true) + dialog.setNegativeButton("네이버 지도 검색") { s,d-> + s.dismiss() + binding.searchNmap.performClick() + } + dialog.setNeutralButton("쿠팡 검색") { s,d-> + s.dismiss() + binding.searchCoupang.performClick() + } + dialog.setPositiveButton("구글 검색") { s, d -> + s.dismiss() + binding.searchGoogle.performClick() + + } + dialog.show() + } + } override fun onResume() { super.onResume() @@ -246,7 +306,18 @@ internal class AppDrawer : Fragment() { contactAdapter?.updateData(contactList) /* pop up the keyboard */ - if (settingsPrefs!!.getBoolean(KEY_KEYBOARD_SEARCH, false)) openSearch() + openSearch() + + + chechHandler.postDelayed(cancelSearch, 3000L) + } + + val chechHandler = Handler(Looper.getMainLooper()) + val cancelSearch = Runnable { timerCheck() } + + private fun timerCheck() { + + lActivity?.onBackPressed() } override fun onPause() { @@ -271,62 +342,30 @@ internal class AppDrawer : Fragment() { /* update app list with app and package name */ fun fetchApps() { - if (oringinPackageList.size > 0) { - packageList.clear() - for(pkg in oringinPackageList) { - packageList.add(pkg) - } - } else { - packageList.clear() - oringinPackageList.clear() - 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) } - - forEach { - oringinPackageList.add( - Packages( - it.activityInfo.packageName, - appName(it), - getCategory(it.activityInfo.applicationInfo.category) - ) - ) - packageList.add( - Packages( - it.activityInfo.packageName, - appName(it), - getCategory(it.activityInfo.applicationInfo.category) - ) - ) - } - }!! - } - /* add package and app names to the list */ - -// var edit = appNamesPrefs?.edit() -// for (resolver in packageInfoList) { -// packageList.add(Packages(resolver.activityInfo.packageName, appName(resolver))) -// } + packageList.clear() + oringinPackageList.clear() + 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) } + forEach { oringinPackageList.add(Packages(it.activityInfo.packageName, normalize(appName(it)), getCategory(it.activityInfo.applicationInfo.category))) } + oringinPackageList.sortBy { it.appName } + packageList.addAll( + oringinPackageList + ) + binding.appsList.post { if (packageList.size > 0) { + appsAdapter?.updateData(packageList) + } } + }!! } -// when { -// packageList.size < 1 -> return -// else -> { - if (packageList.size > 0) { - MainScope().launch { - appsAdapter?.updateData(packageList) - } - } -// } - } private fun getAlphabetItems() { @@ -357,8 +396,9 @@ internal class AppDrawer : Fragment() { var lastSearchStringLength = 0 var lastSearchString : String = "" private fun filterAppsList(searchString: String) { + chechHandler.removeCallbacks(cancelSearch) /* check each app name and add if it matches the search string */ - if (lastSearchStringLength > 0 && (lastSearchStringLength != searchString.length || lastSearchString.equals(searchString) == false)) { + if (searchString.length > 0 && (lastSearchStringLength != searchString.length || lastSearchString.equals(searchString) == false)) { BLog.LOGE("START FILTER") packageList.clear() for (pkg in oringinPackageList) { @@ -367,51 +407,41 @@ internal class AppDrawer : Fragment() { packageList.add(pkg) } } + packageList.sortBy { it.appName } 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) - } + contactList.clear() for (item in originContactList) { if (item.name.contains(searchString) || item.phoneNumber.contains(searchString)) { contactList.add(item) } } + contactList.sortBy { it.name } contactAdapter?.updateData(contactList) BLog.LOGE("END FILTER") - } else if(lastSearchStringLength == 0){ - contactList.clear() - for (item in originContactList) { - contactList.add(item) - } - packageList.clear() - for (resolver in oringinPackageList) { - packageList.add(resolver) - } - appsAdapter?.updateData(packageList) - contactAdapter?.updateData(contactList) + } else { + afterClearSearch() } lastSearchString = searchString lastSearchStringLength = searchString.length + chechHandler.postDelayed(cancelSearch, 3000L) + } + + private fun afterClearSearch() { + contactList.clear() + packageList.clear() + for (item in originContactList) { + contactList.add(item) + } + for (resolver in oringinPackageList) { + packageList.add(resolver) + } + packageList.sortBy { it.appName } + contactList.sortBy { it.name } + appsAdapter?.updateData(packageList) + contactAdapter?.updateData(contactList) } private fun normalize(str: String): String { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactAdapter.kt index ba93ddc..37ac76c 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactAdapter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactAdapter.kt @@ -70,7 +70,7 @@ internal class ContactAdapter ( holder.view.root.apply { /* on click - open app */ setOnClickListener { - context.startActivity(Intent(Intent.ACTION_DIAL, Uri.parse("tel://${item.phoneNumber}"))) + ContactMenu().show(fragmentManager, item.id.toString()) } /* on long click - open app menu */ diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt index 233f46f..8fd934a 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/ContactMenu.kt @@ -58,6 +58,7 @@ import rasel.lunar.launcher.apps.AppDrawer.Companion.appNamesPrefs import rasel.lunar.launcher.databinding.ActivityBrowserDialogBinding import rasel.lunar.launcher.databinding.AppInfoDialogBinding import rasel.lunar.launcher.databinding.AppMenuBinding +import rasel.lunar.launcher.databinding.ContactMenuBinding import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APP_NO_ import rasel.lunar.launcher.helpers.Constants.Companion.MAX_FAVORITE_APPS import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_FAVORITE_APPS @@ -74,14 +75,15 @@ import java.util.* internal class ContactMenu : BottomSheetDialogFragment() { - private lateinit var binding: AppMenuBinding + private lateinit var binding: ContactMenuBinding private lateinit var packageName: String private lateinit var packageManager: PackageManager private lateinit var appInfo: ApplicationInfo private lateinit var defAppName: String - + var contactName : String = "" + var contactPhoneNumber : String = "" override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { - binding = AppMenuBinding.inflate(inflater, container, false) + binding = ContactMenuBinding.inflate(inflater, container, false) /* get package name from fragment's tag */ packageName = tag.toString() @@ -96,14 +98,12 @@ internal class ContactMenu : BottomSheetDialogFragment() { val cursor = resolver.query(phoneUri, projection, ContactsContract.CommonDataKinds.Phone.CONTACT_ID + " = " + packageName, null , null) if (cursor != null) { while (cursor.moveToNext()) { -// val idx =cursor.getColumnIndex(projection[0]) val nameIndex = cursor.getColumnIndex(projection[0]) val numberIndex = cursor.getColumnIndex(projection[1]) -// var contactId = cursor.getInt(idx) - val name = cursor.getString(nameIndex) + contactName = cursor.getString(nameIndex) var number = cursor.getString(numberIndex) - number = number.replace("-", "") - BLog.LOGE("GetContact", "이름 : $name 번호 : $number ") + contactPhoneNumber = number.replace("-", "") + BLog.LOGE("GetContact", "이름 : $contactName 번호 : $contactPhoneNumber ") } } // 데이터 계열은 반드시 닫아줘야 한다. @@ -124,8 +124,8 @@ internal class ContactMenu : BottomSheetDialogFragment() { // copyToClipboard(requireContext(), packageName) // } // -// appName() -// binding.detailedInfo.setOnClickListener { detailedInfo() } + appName() + binding.detailedInfo.setOnClickListener { detailedInfo() } // binding.activityBrowser.setOnClickListener { activityBrowser() } // binding.appStore.setOnClickListener { appStore() } // binding.appFreeform.setOnClickListener { freeform() } @@ -165,7 +165,7 @@ internal class ContactMenu : BottomSheetDialogFragment() { /* listen on clicks */ binding.favGroup.addOnButtonCheckedListener { _: MaterialButtonToggleGroup?, - checkedId: Int, isChecked: Boolean -> + checkedId: Int, isChecked: Boolean -> try { if (checkedId == button.id) { if (isChecked) { @@ -186,66 +186,17 @@ internal class ContactMenu : BottomSheetDialogFragment() { } private fun appName() { - binding.appName.setOnFocusChangeListener { _, hasFocus -> - if (hasFocus) binding.appName.minWidth = resources.getDimensionPixelOffset(R.dimen.twoSeventySix) - else { - (requireContext().getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) - .hideSoftInputFromWindow(binding.appName.windowToken, 0) - - binding.appName.apply { - minWidth = resources.getDimensionPixelOffset(R.dimen.zero) - - if (text!!.isBlank()) setText(defAppName) - else setText(text!!.trim()) - - if (text.toString() == defAppName) appNamesPrefs?.edit()!!.remove(packageName).apply() - else appNamesPrefs?.edit()!!.putString(packageName, text.toString()).apply() - - (requireParentFragment() as AppDrawer).fetchApps() - } - } - } - - binding.appName.setOnKeyListener { _, keyCode, event -> - if (event.action == KeyEvent.ACTION_DOWN) { - if (keyCode == KeyEvent.KEYCODE_ENTER || keyCode == KeyEvent.KEYCODE_BACK) { - binding.appName.clearFocus() - return@setOnKeyListener true - } - } - false - } + binding.appName.text = contactName + binding.phoneNumber.text = contactPhoneNumber } /* detailed info dialog */ @SuppressLint("SetTextI18n") private fun detailedInfo() { - val dialogBinding = AppInfoDialogBinding.inflate(lActivity!!.layoutInflater) - MaterialAlertDialogBuilder(lActivity!!) - .setView(dialogBinding.root) - .setPositiveButton(android.R.string.cancel, null) - .show() + var intent = Intent(Intent.ACTION_VIEW); + intent.setData(Uri.parse(ContactsContract.Contacts.CONTENT_URI.toString() + "/" + packageName)); + startActivity(intent); - /* show app name */ - dialogBinding.appName.text = packageManager.getApplicationLabel(appInfo) - - /* get package info */ - val packageInfo = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) { - packageManager.getPackageInfo(packageName, PackageManager.PackageInfoFlags.of(0)) - } else { - packageManager.getPackageInfo(packageName, 0) - } - - /* show infos */ - dialogBinding.mixed.text = - "${resources.getString(R.string.version)}: ${packageInfo.versionName} (${PackageInfoCompat.getLongVersionCode(packageInfo).toInt()})\n" + - "${resources.getString(R.string.sdk)}: ${appInfo.minSdkVersion} ~ ${appInfo.targetSdkVersion}\n" + - "${resources.getString(R.string.uid)}: ${appInfo.uid}\n" + - "${resources.getString(R.string.first_install)}: ${dateTimeFormat(packageInfo.firstInstallTime)}\n" + - "${resources.getString(R.string.last_update)}: ${dateTimeFormat(packageInfo.lastUpdateTime)}" - - /* show permissions */ - dialogBinding.permissions.text = permissionsList } /* activity browser dialog */ diff --git a/app/src/main/res/drawable/coupang.png b/app/src/main/res/drawable/coupang.png new file mode 100644 index 0000000..3ca44f4 Binary files /dev/null and b/app/src/main/res/drawable/coupang.png differ diff --git a/app/src/main/res/layout/app_drawer.xml b/app/src/main/res/layout/app_drawer.xml index e200984..d4ad6d2 100644 --- a/app/src/main/res/layout/app_drawer.xml +++ b/app/src/main/res/layout/app_drawer.xml @@ -95,11 +95,23 @@ style="@style/SearchIcons" android:id="@+id/search_translate"/> + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file