Merge branch 'main' of https://dev.lunaticbum.kr/lun_admin/lun_launcher
# Conflicts: # app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt
This commit is contained in:
commit
ed24af2d41
@ -18,6 +18,7 @@
|
||||
<uses-permission android:name="com.android.alarm.permission.SET_ALARM"/>
|
||||
<uses-permission android:name="android.permission.READ_CONTACTS" />
|
||||
|
||||
<uses-permission android:name="android.permission.READ_CALL_LOG"/>
|
||||
<!-- api 33+ -->
|
||||
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
|
||||
<uses-permission
|
||||
|
||||
@ -27,7 +27,10 @@ import android.graphics.Color
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.CallLog
|
||||
import android.provider.ContactsContract
|
||||
import android.provider.Settings
|
||||
import android.util.Log
|
||||
import android.view.WindowInsets
|
||||
import android.view.WindowManager
|
||||
import androidx.activity.OnBackPressedCallback
|
||||
@ -44,11 +47,12 @@ import androidx.viewpager2.widget.ViewPager2
|
||||
import com.google.android.material.color.DynamicColors
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import rasel.lunar.launcher.apps.AppDrawer
|
||||
import rasel.lunar.launcher.apps.DismissCalback
|
||||
import rasel.lunar.launcher.apps.SearchMenu
|
||||
import rasel.lunar.launcher.databinding.LauncherActivityBinding
|
||||
import rasel.lunar.launcher.feeds.Feeds
|
||||
import rasel.lunar.launcher.feeds.WidgetHost
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_BACK_HOME
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_FIRST_LAUNCH
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_STATUS_BAR
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WINDOW_BACKGROUND
|
||||
@ -59,6 +63,7 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId
|
||||
import rasel.lunar.launcher.helpers.ViewPagerAdapter
|
||||
import rasel.lunar.launcher.home.LauncherHome
|
||||
import rasel.lunar.launcher.utils.BLog
|
||||
import java.util.Date
|
||||
|
||||
|
||||
internal class LauncherActivity : AppCompatActivity() {
|
||||
@ -152,7 +157,10 @@ internal class LauncherActivity : AppCompatActivity() {
|
||||
private fun setupView() {
|
||||
viewPager = binding.viewPager.apply {
|
||||
adapter = ViewPagerAdapter(
|
||||
supportFragmentManager, mutableListOf(Feeds(), LauncherHome(), AppDrawer()), lifecycle)
|
||||
supportFragmentManager,
|
||||
mutableListOf(Feeds(), LauncherHome(), AppDrawer()),
|
||||
lifecycle
|
||||
)
|
||||
offscreenPageLimit = 1
|
||||
setCurrentItem(1, false)
|
||||
reduceDragSensitivity()
|
||||
@ -227,4 +235,9 @@ internal class LauncherActivity : AppCompatActivity() {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
fun openSearchMenus(keyword : String, dismissCalback: DismissCalback) {
|
||||
SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@ -28,9 +28,11 @@ 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
|
||||
import android.view.KeyEvent.ACTION_UP
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.View.GONE
|
||||
@ -42,16 +44,12 @@ import androidx.core.widget.doOnTextChanged
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.recyclerview.widget.GridLayoutManager
|
||||
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.databinding.AppDrawerBinding
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPS_COUNT
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPS_LAYOUT
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_DRAW_ALIGN
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_KEYBOARD_SEARCH
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_QUICK_LAUNCH
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_APP_NAMES
|
||||
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS
|
||||
import rasel.lunar.launcher.utils.BLog
|
||||
@ -63,7 +61,7 @@ internal class AppDrawer : Fragment() {
|
||||
|
||||
private lateinit var binding: AppDrawerBinding
|
||||
private var layoutType: Int = 0
|
||||
private var isSearchShown: Boolean = false
|
||||
// private var isSearchShown: Boolean = false
|
||||
private var isKeyboardShowing: Boolean = false
|
||||
|
||||
companion object {
|
||||
@ -226,6 +224,7 @@ internal class AppDrawer : Fragment() {
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun openSearchApps(schemeString : String, pakage : String? = null) {
|
||||
val gmmIntentUri = Uri.parse(schemeString)
|
||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||
@ -238,52 +237,158 @@ internal class AppDrawer : Fragment() {
|
||||
@SuppressLint("ClickableViewAccessibility")
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
|
||||
binding.reset.setOnClickListener { filterAppsList("") }
|
||||
|
||||
// binding.moveDown.setOnClickListener {
|
||||
// binding.appsList.smoothScrollToPosition(packageList.size - 1)
|
||||
// }
|
||||
//
|
||||
// binding.moveUp.setOnClickListener {
|
||||
// binding.appsList.smoothScrollToPosition(0)
|
||||
// }
|
||||
|
||||
// binding.search.setOnClickListener {
|
||||
// when (isSearchShown) {
|
||||
// true -> closeSearch()
|
||||
// false -> openSearch()
|
||||
// }
|
||||
// }
|
||||
|
||||
binding.searchInput.setOnKeyListener { v, keyCode, event ->
|
||||
if (keyCode == 66 && contactList.size < 1 && packageList.size < 1) {
|
||||
binding.searchGoogle.performClick()
|
||||
true
|
||||
true
|
||||
}else {
|
||||
false
|
||||
}
|
||||
}
|
||||
binding.searchInput.doOnTextChanged { inputText, _, _, _ ->
|
||||
binding.searchInput.doOnTextChanged{ inputText, _, _, _ ->
|
||||
binding.searchInput.text?.let { binding.searchInput.setSelection(it.length) }
|
||||
filterAppsList(inputText.toString())
|
||||
}
|
||||
}
|
||||
|
||||
fun checkResult(keyword: String) {
|
||||
|
||||
if(!isAdded || !isResumed || keyword.length < 1) return
|
||||
var dialog : AlertDialog.Builder? = null
|
||||
var filted = packageList.filter { it.appName.equals(keyword) }
|
||||
BLog.LOGE("filted >> ${filted.size}")
|
||||
var filtedContact = contactList.filter { it.name.equals(keyword) }
|
||||
BLog.LOGE("filtedContact >> ${filtedContact.size}")
|
||||
if (keyword.length > 0 && (packageList.size == 1 || filted.size > 0)) {
|
||||
dialog = AlertDialog.Builder(requireContext())
|
||||
dialog?.setTitle("앱 실행 확인")
|
||||
if (packageList.size == 1) {
|
||||
dialog?.setMessage("${keyword} 검색 결과 '${packageList[0].appName}' 준비됨")
|
||||
dialog?.setPositiveButton("실행") { s, d ->
|
||||
runonUi {
|
||||
startActivity(packageManager?.getLaunchIntentForPackage(packageList[0].packageName))
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
} else if (filted.size > 0) {
|
||||
dialog?.setMessage("${keyword} 검색 결과 '${filted[0].appName}' 준비됨")
|
||||
dialog?.setPositiveButton("${filted[0].appName} 실행") { s, d ->
|
||||
runonUi {
|
||||
startActivity(packageManager?.getLaunchIntentForPackage(filted[0].packageName))
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
if(filted.size > 1) {
|
||||
dialog?.setNeutralButton("${filted[1].appName} 실행") { s, d ->
|
||||
runonUi {
|
||||
startActivity(packageManager?.getLaunchIntentForPackage(filted[1].packageName))
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dialog?.setCancelable(false)
|
||||
dialog?.setNegativeButton("취소") { s, d ->
|
||||
runonUi { s.dismiss() }
|
||||
}
|
||||
dialog?.setOnDismissListener { registCancelSearch() }
|
||||
dialog?.show()
|
||||
} else if (contactList.size == 1 || filtedContact.size > 0) {
|
||||
dialog = AlertDialog.Builder(requireContext())
|
||||
dialog?.setTitle("연락처 실행 확인")
|
||||
dialog?.setCancelable(false)
|
||||
dialog?.setNegativeButton("취소") { s, d ->
|
||||
runonUi { s.dismiss() }
|
||||
}
|
||||
if (contactList.size == 1) {
|
||||
dialog?.setMessage("${keyword} 검색 결과 '${contactList[0].name}' 준비됨")
|
||||
dialog?.setPositiveButton("자세히 보기") { s, d ->
|
||||
runonUi {
|
||||
ContactMenu().show(childFragmentManager, contactList[0].id.toString())
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
} else if(filtedContact.size > 0) {
|
||||
dialog?.setMessage("${keyword} 검색 결과 '${filtedContact[0].name}' 준비됨")
|
||||
dialog?.setPositiveButton("'${filtedContact[0].name},\n${filtedContact[0].phoneNumber}'\n자세히 보기") { s, d ->
|
||||
runonUi {
|
||||
ContactMenu().show(childFragmentManager, filtedContact[0].id.toString())
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
if (filtedContact.size > 1) {
|
||||
dialog?.setNeutralButton("'${filtedContact[1].name},\n${filtedContact[1].phoneNumber}'\n자세히 보기") { s, d ->
|
||||
runonUi {
|
||||
ContactMenu().show(childFragmentManager, filtedContact[1].id.toString())
|
||||
s.dismiss()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dialog?.setOnDismissListener { registCancelSearch() }
|
||||
dialog?.show()
|
||||
} else {
|
||||
lActivity?.openSearchMenus(keyword) {
|
||||
registCancelSearch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
fun runonUi(invoke : () -> Unit) {
|
||||
Handler(Looper.getMainLooper()).run {
|
||||
try {
|
||||
invoke.invoke()
|
||||
}catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
override fun onResume() {
|
||||
super.onResume()
|
||||
BLog.LOGE("onResume")
|
||||
fetchApps()
|
||||
GetContact()
|
||||
|
||||
binding.appsCount.visibility = if (settingsPrefs!!.getBoolean(KEY_APPS_COUNT, true)) VISIBLE else GONE
|
||||
|
||||
if (settingsPrefs!!.getInt(KEY_APPS_LAYOUT, 0) in 0..1) {
|
||||
appsAdapter?.updateGravity(settingsPrefs!!.getInt(KEY_DRAW_ALIGN, Gravity.CENTER))
|
||||
}
|
||||
// if (settingsPrefs!!.getInt(KEY_APPS_LAYOUT, 0) in 0..1) {
|
||||
// appsAdapter?.updateGravity(settingsPrefs!!.getInt(KEY_DRAW_ALIGN, Gravity.CENTER))
|
||||
// }
|
||||
|
||||
contactAdapter?.updateData(contactList)
|
||||
|
||||
openSearch()
|
||||
setKeyboardPadding()
|
||||
|
||||
contactAdapter?.updateData(contactList)
|
||||
|
||||
/* pop up the keyboard */
|
||||
openSearch()
|
||||
|
||||
registCancelSearch()
|
||||
BLog.LOGE("onResume after chechHandler.postDelayed(cancelSearch, 3000L)")
|
||||
}
|
||||
|
||||
val chechHandler = Handler(Looper.getMainLooper())
|
||||
|
||||
val cancelSearch = Runnable { timerCheck() }
|
||||
|
||||
fun registCancelSearch() {
|
||||
BLog.LOGE("Called registCancelSearch")
|
||||
chechHandler.removeCallbacks(cancelSearch)
|
||||
chechHandler.postDelayed(cancelSearch, 3000L)
|
||||
}
|
||||
|
||||
fun clearCancelSearch() {
|
||||
chechHandler.removeCallbacks(cancelSearch)
|
||||
}
|
||||
|
||||
private fun timerCheck() {
|
||||
lActivity?.onBackPressed()
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
@ -308,62 +413,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() {
|
||||
@ -395,7 +468,7 @@ internal class AppDrawer : Fragment() {
|
||||
var lastSearchString : String = ""
|
||||
private fun filterAppsList(searchString: String) {
|
||||
/* 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) {
|
||||
@ -404,38 +477,22 @@ 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)
|
||||
}
|
||||
|
||||
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) {
|
||||
@ -447,9 +504,28 @@ internal class AppDrawer : Fragment() {
|
||||
}
|
||||
appsAdapter?.updateData(packageList)
|
||||
contactAdapter?.updateData(contactList)
|
||||
} else {
|
||||
afterClearSearch()
|
||||
|
||||
}
|
||||
lastSearchString = searchString
|
||||
lastSearchStringLength = searchString.length
|
||||
registCancelSearch()
|
||||
}
|
||||
|
||||
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 {
|
||||
@ -460,26 +536,21 @@ internal class AppDrawer : Fragment() {
|
||||
}
|
||||
|
||||
private fun openSearch() {
|
||||
isSearchShown = true
|
||||
binding.searchInput.apply {
|
||||
visibility = VISIBLE
|
||||
requestFocus()
|
||||
let {
|
||||
(lActivity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
|
||||
.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
|
||||
(lActivity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* clear search string, hide keyboard and search box */
|
||||
private fun closeSearch() {
|
||||
isSearchShown = false
|
||||
binding.searchInput.apply {
|
||||
text?.clear()
|
||||
visibility = GONE
|
||||
let {
|
||||
(lActivity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager)
|
||||
.hideSoftInputFromWindow(it.windowToken, 0)
|
||||
text?.clear()
|
||||
(lActivity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.hideSoftInputFromWindow(it.windowToken, 0)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -47,7 +47,7 @@ internal class AppsAdapter(
|
||||
private val appsCount: TextView) : RecyclerView.Adapter<AppsAdapter.AppsViewHolder>() {
|
||||
|
||||
private var oldList = mutableListOf<Packages>()
|
||||
private var appGravity: Int = Gravity.CENTER
|
||||
// private var appGravity: Int = Gravity.CENTER
|
||||
|
||||
companion object {
|
||||
@JvmStatic var appsSize: Int? = null
|
||||
@ -106,21 +106,6 @@ internal class AppsAdapter(
|
||||
appsSize = it
|
||||
}
|
||||
}
|
||||
|
||||
/* update text gravity (alignment) */
|
||||
@SuppressLint("RtlHardcoded", "NotifyDataSetChanged")
|
||||
fun updateGravity(gravity: Int){
|
||||
/* the first check is to avoid calling notifyDataSetChanged() everytime */
|
||||
if (gravity != appGravity &&
|
||||
(gravity == Gravity.LEFT || gravity == Gravity.CENTER || gravity == Gravity.RIGHT)) {
|
||||
appGravity = gravity
|
||||
notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
|
||||
fun hideItem(idx: Int) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
data class Packages (
|
||||
|
||||
@ -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 */
|
||||
|
||||
@ -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 */
|
||||
|
||||
179
app/src/main/kotlin/rasel/lunar/launcher/apps/SearchMenu.kt
Normal file
179
app/src/main/kotlin/rasel/lunar/launcher/apps/SearchMenu.kt
Normal file
@ -0,0 +1,179 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package rasel.lunar.launcher.apps
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.app.ActivityOptions
|
||||
import android.content.ActivityNotFoundException
|
||||
import android.content.ComponentName
|
||||
import android.content.DialogInterface
|
||||
import android.content.Intent
|
||||
import android.content.pm.ApplicationInfo
|
||||
import android.content.pm.PackageManager
|
||||
import android.content.res.ColorStateList
|
||||
import android.graphics.Rect
|
||||
import android.icu.text.SimpleDateFormat
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.provider.ContactsContract
|
||||
import android.provider.Settings
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.AdapterView
|
||||
import android.widget.ArrayAdapter
|
||||
import android.widget.Toast
|
||||
import androidx.appcompat.widget.LinearLayoutCompat
|
||||
import androidx.core.content.FileProvider
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import androidx.fragment.app.FragmentTransaction
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
|
||||
import com.google.android.material.button.MaterialButton
|
||||
import com.google.android.material.button.MaterialButtonToggleGroup
|
||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||
import rasel.lunar.launcher.BuildConfig
|
||||
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
|
||||
import rasel.lunar.launcher.R
|
||||
import rasel.lunar.launcher.databinding.ActivityBrowserDialogBinding
|
||||
import rasel.lunar.launcher.databinding.ContactMenuBinding
|
||||
import rasel.lunar.launcher.databinding.SearchMenuBinding
|
||||
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
|
||||
import rasel.lunar.launcher.helpers.UniUtils.Companion.screenHeight
|
||||
import rasel.lunar.launcher.helpers.UniUtils.Companion.screenWidth
|
||||
import rasel.lunar.launcher.utils.BLog
|
||||
import java.io.File
|
||||
import java.io.FileInputStream
|
||||
import java.io.FileOutputStream
|
||||
import java.io.IOException
|
||||
import java.util.*
|
||||
|
||||
|
||||
internal class SearchMenu : BottomSheetDialogFragment() {
|
||||
|
||||
private lateinit var binding: SearchMenuBinding
|
||||
private lateinit var searchWord: String
|
||||
private lateinit var packageManager: PackageManager
|
||||
private lateinit var appInfo: ApplicationInfo
|
||||
|
||||
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
|
||||
binding = SearchMenuBinding.inflate(inflater, container, false)
|
||||
|
||||
/* get package name from fragment's tag */
|
||||
searchWord = tag.toString()
|
||||
|
||||
return binding.root
|
||||
}
|
||||
|
||||
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||
super.onViewCreated(view, savedInstanceState)
|
||||
(requireDialog() as BottomSheetDialog).dismissWithAnimation = true
|
||||
|
||||
/* copy package name */
|
||||
// binding.appPackage.setOnClickListener {
|
||||
// copyToClipboard(requireContext(), packageName)
|
||||
// }
|
||||
//
|
||||
appName()
|
||||
// binding.detailedInfo.setOnClickListener { detailedInfo() }
|
||||
// binding.activityBrowser.setOnClickListener { activityBrowser() }
|
||||
// binding.appStore.setOnClickListener { appStore() }
|
||||
// binding.appFreeform.setOnClickListener { freeform() }
|
||||
// binding.appInfo.setOnClickListener { appInfo() }
|
||||
// binding.appShare.setOnClickListener { share() }
|
||||
// binding.appUninstall.setOnClickListener { uninstall() }
|
||||
binding.searchNmap.setOnClickListener {
|
||||
openSearchApps("nmap://search?query=${searchWord}&appname=${BuildConfig.APPLICATION_ID}","com.nhn.android.nmap")
|
||||
}
|
||||
binding.searchGoogleMap.setOnClickListener {
|
||||
openSearchApps("geo:0,0?q=${searchWord}","com.google.android.apps.maps")
|
||||
}
|
||||
binding.searchGoogle.setOnClickListener {
|
||||
openSearchApps("https://www.google.com/search?q=${searchWord}","com.android.chrome")
|
||||
}
|
||||
binding.searchTmap.setOnClickListener {
|
||||
openSearchApps("tmap://search?name=${searchWord}","com.skt.tmap.ku")
|
||||
|
||||
}
|
||||
binding.searchNaver.setOnClickListener {
|
||||
openSearchApps("https://search.naver.com/search.naver?where=nexearch&query=${searchWord}", "com.nhn.android.search")
|
||||
}
|
||||
binding.searchDuckduckgo.setOnClickListener {
|
||||
openSearchApps("https://duckduckgo.com/?t=h_&q=${searchWord}","com.duckduckgo.mobile.android")
|
||||
}
|
||||
binding.searchNamuwiki.setOnClickListener {
|
||||
openSearchApps("https://namu.wiki/Search?q=${searchWord}")
|
||||
}
|
||||
|
||||
binding.searchTranslate.setOnClickListener {
|
||||
openSearchApps("https://translate.google.com/?hl=ko&sl=ko&tl=en&text=${searchWord}&op=translate","com.android.chrome")
|
||||
}
|
||||
|
||||
binding.searchCoupang.setOnClickListener {
|
||||
openSearchApps("coupang://search?q=${searchWord}","com.coupang.mobile")
|
||||
}
|
||||
}
|
||||
|
||||
fun openSearchApps(schemeString : String, pakage : String? = null) {
|
||||
val gmmIntentUri = Uri.parse(schemeString)
|
||||
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
|
||||
pakage?.let {
|
||||
mapIntent.setPackage(pakage)
|
||||
}
|
||||
startActivity(mapIntent)
|
||||
try {
|
||||
dismiss()
|
||||
} catch (e : Exception) {
|
||||
e.printStackTrace()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private fun appName() {
|
||||
binding.keyworkd.text = searchWord
|
||||
}
|
||||
|
||||
var mDismissCalback : DismissCalback? = null
|
||||
|
||||
fun show(manager: FragmentManager, tag: String? , dismissCalback : DismissCalback?) {
|
||||
this.mDismissCalback = dismissCalback
|
||||
this.show(manager, tag)
|
||||
}
|
||||
|
||||
override fun show(manager: FragmentManager, tag: String?) {
|
||||
super.show(manager, tag)
|
||||
}
|
||||
|
||||
override fun dismiss() {
|
||||
BLog.LOGE("dismiss()")
|
||||
mDismissCalback?.invoke()
|
||||
super.dismiss()
|
||||
}
|
||||
|
||||
override fun onDismiss(dialog: DialogInterface) {
|
||||
BLog.LOGE("onDismiss(dialog: DialogInterface)")
|
||||
mDismissCalback?.invoke()
|
||||
super.onDismiss(dialog)
|
||||
}
|
||||
}
|
||||
|
||||
typealias DismissCalback = ()->Unit
|
||||
@ -67,7 +67,7 @@ internal class Constants {
|
||||
const val KEY_LOCK_METHOD = "lock_method"
|
||||
|
||||
/* --- */
|
||||
const val DEFAULT_DATE_FORMAT = "EEE dx MMM, yyyy"
|
||||
const val DEFAULT_DATE_FORMAT = "EEE, dd, MM, yyyy"
|
||||
const val DEFAULT_ICON_SIZE = 44
|
||||
const val DEFAULT_ICON_PACK = "default_icon_pack"
|
||||
const val DEFAULT_GRID_COLUMNS = 4
|
||||
|
||||
@ -25,14 +25,23 @@ import android.content.IntentFilter
|
||||
import android.content.SharedPreferences
|
||||
import android.os.Bundle
|
||||
import android.provider.AlarmClock
|
||||
import android.provider.CallLog
|
||||
import android.text.format.DateFormat
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import android.widget.RadioButton
|
||||
import android.widget.Toast
|
||||
import androidx.biometric.BiometricPrompt
|
||||
import androidx.core.view.get
|
||||
import androidx.fragment.app.Fragment
|
||||
import androidx.fragment.app.FragmentManager
|
||||
import kotlinx.coroutines.CoroutineScope
|
||||
import kotlinx.coroutines.DelicateCoroutinesApi
|
||||
import kotlinx.coroutines.GlobalScope
|
||||
import kotlinx.coroutines.MainScope
|
||||
import kotlinx.coroutines.async
|
||||
import kotlinx.coroutines.launch
|
||||
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
|
||||
import rasel.lunar.launcher.R
|
||||
import rasel.lunar.launcher.databinding.LauncherHomeBinding
|
||||
@ -51,10 +60,12 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod
|
||||
import rasel.lunar.launcher.home.weather.WeatherExecutor
|
||||
import rasel.lunar.launcher.qaccess.QuickAccess
|
||||
import rasel.lunar.launcher.settings.SettingsActivity
|
||||
import rasel.lunar.launcher.todos.MissedCallsAdapter
|
||||
import rasel.lunar.launcher.todos.TodoAdapter
|
||||
import rasel.lunar.launcher.todos.TodoManager
|
||||
import rasel.lunar.launcher.utils.BLog
|
||||
import rasel.lunar.launcher.utils.SimpleFingerGestures
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
|
||||
|
||||
@ -74,7 +85,9 @@ internal class LauncherHome : Fragment() {
|
||||
batteryReceiver = BatteryReceiver(binding.batteryProgress)
|
||||
|
||||
binding.favAppsGroup.visibility = View.GONE
|
||||
|
||||
Thread("CALLED").run {
|
||||
getCallDetails()
|
||||
}
|
||||
return binding.root
|
||||
}
|
||||
|
||||
@ -105,6 +118,8 @@ internal class LauncherHome : Fragment() {
|
||||
requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
|
||||
|
||||
/* time and date */
|
||||
binding.time.textLocale = Locale.US
|
||||
binding.date.textLocale = Locale.US
|
||||
if (DateFormat.is24HourFormat(requireContext())) {
|
||||
binding.time.format24Hour = timeFormat
|
||||
binding.date.format24Hour = dateFormat
|
||||
@ -120,6 +135,79 @@ internal class LauncherHome : Fragment() {
|
||||
}
|
||||
}
|
||||
|
||||
var callList = arrayListOf<MissedCall>()
|
||||
|
||||
|
||||
private fun getCallDetails() {
|
||||
var dateParam = Date(System.currentTimeMillis() - (1000 * 60 * 60 * 24 * 3)).time.toString()
|
||||
val managedCursor = lActivity!!.managedQuery(
|
||||
CallLog.Calls.CONTENT_URI, arrayOf(
|
||||
CallLog.Calls.NUMBER,
|
||||
CallLog.Calls.TYPE,
|
||||
CallLog.Calls.DATE,
|
||||
CallLog.Calls.DURATION,
|
||||
CallLog.Calls.CACHED_NAME,
|
||||
), CallLog.Calls.DATE + "> ? AND " + CallLog.Calls.TYPE + " > ?", arrayOf<String>(dateParam, "2"), CallLog.Calls.DATE + " desc")
|
||||
val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
|
||||
val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
|
||||
val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
|
||||
val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
|
||||
val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
|
||||
var missedCalls = hashMapOf<String, MissedCall>()
|
||||
if (missedCalls.size != callList.size) {
|
||||
while (managedCursor.moveToNext()) {
|
||||
val phNumber = managedCursor.getString(number) // mobile number
|
||||
val callType = managedCursor.getString(type) // call type
|
||||
val callDate = managedCursor.getString(date) // call date
|
||||
val callDayTime: Date = Date(callDate.toLong())
|
||||
val callDuration = managedCursor.getString(duration)
|
||||
val callerName = managedCursor.getString(name)
|
||||
|
||||
var dir: String = ""
|
||||
val dircode = callType.toInt()
|
||||
when (dircode) {
|
||||
CallLog.Calls.INCOMING_TYPE -> {
|
||||
dir = "INCOMING_TYPE"
|
||||
}
|
||||
CallLog.Calls.OUTGOING_TYPE -> {
|
||||
dir = "OUTGOING_TYPE"
|
||||
}
|
||||
CallLog.Calls.MISSED_TYPE -> {
|
||||
dir = "MISSED_TYPE"
|
||||
}
|
||||
CallLog.Calls.VOICEMAIL_TYPE -> {
|
||||
dir = "VOICEMAIL_TYPE"
|
||||
}
|
||||
CallLog.Calls.REJECTED_TYPE -> {
|
||||
dir = "REJECTED_TYPE"
|
||||
}
|
||||
CallLog.Calls.BLOCKED_TYPE -> {
|
||||
dir = "BLOCKED_TYPE"
|
||||
}
|
||||
CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> {
|
||||
dir = "ANSWERED_EXTERNALLY_TYPE"
|
||||
}
|
||||
}
|
||||
var missed: MissedCall = if (missedCalls.containsKey(phNumber)) {
|
||||
missedCalls.get(phNumber)!!.apply {
|
||||
count = count + 1
|
||||
}
|
||||
} else {
|
||||
MissedCall(1,callerName,phNumber, dircode, dir, SimpleDateFormat("yyy/MM/dd-HH:mm:ss").format(callDayTime))
|
||||
}
|
||||
missedCalls.put(phNumber, missed)
|
||||
}
|
||||
}
|
||||
managedCursor.close()
|
||||
if (callList.size == missedCalls.size) {
|
||||
} else {
|
||||
callList.clear()
|
||||
missedCalls.forEach { t, u ->
|
||||
callList.add(u)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPause() {
|
||||
super.onPause()
|
||||
/* unregister battery changes */
|
||||
@ -380,8 +468,18 @@ internal class LauncherHome : Fragment() {
|
||||
}
|
||||
|
||||
/* to-do list */
|
||||
@SuppressLint("NotifyDataSetChanged")
|
||||
private fun showTodoList() {
|
||||
binding.notes.adapter = TodoAdapter(null, requireContext())
|
||||
if (binding.missedCalls.isChecked == true) {
|
||||
if (callList.size > 0) {
|
||||
BLog.LOGE("callList >>> ${callList.size}")
|
||||
binding.notes.adapter = MissedCallsAdapter(callList, requireContext())?.apply {
|
||||
this.notifyDataSetChanged()
|
||||
}
|
||||
}
|
||||
} else {
|
||||
binding.notes.adapter = TodoAdapter(null, requireContext())
|
||||
}
|
||||
}
|
||||
|
||||
/* get time format string */
|
||||
@ -390,9 +488,9 @@ internal class LauncherHome : Fragment() {
|
||||
0 -> return if (DateFormat.is24HourFormat(requireContext())) {
|
||||
"kk:mm"
|
||||
} else {
|
||||
"h:mm a"
|
||||
"HH:mm a"
|
||||
}
|
||||
1 -> return "h:mm a"
|
||||
1 -> return "HH:mm a"
|
||||
2 -> return "kk:mm"
|
||||
}
|
||||
return null
|
||||
@ -420,3 +518,22 @@ internal class LauncherHome : Fragment() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
class MissedCall {
|
||||
constructor(count: Int, name: String?, number: String, type: Int, typeString: String, date : String) {
|
||||
this.count = count
|
||||
this.name = name ?: "unknown"
|
||||
this.number = number
|
||||
this.type = type
|
||||
this.typeString = typeString
|
||||
this.date = date
|
||||
}
|
||||
|
||||
var count : Int = 1
|
||||
var name : String = "how"
|
||||
var number : String = ""
|
||||
var type : Int = 0
|
||||
var typeString : String = ""
|
||||
var date : String = ""
|
||||
}
|
||||
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package rasel.lunar.launcher.todos
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.view.LayoutInflater
|
||||
import android.view.View
|
||||
import android.view.ViewGroup
|
||||
import androidx.core.content.ContextCompat
|
||||
import androidx.recyclerview.widget.RecyclerView
|
||||
import com.google.android.material.bottomsheet.BottomSheetDialog
|
||||
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
|
||||
import rasel.lunar.launcher.R
|
||||
import rasel.lunar.launcher.databinding.ListItemBinding
|
||||
import rasel.lunar.launcher.databinding.TodoDialogBinding
|
||||
import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard
|
||||
import rasel.lunar.launcher.home.MissedCall
|
||||
import rasel.lunar.launcher.utils.BLog
|
||||
import java.util.*
|
||||
import kotlin.collections.ArrayList
|
||||
|
||||
|
||||
internal class MissedCallsAdapter(
|
||||
private val callList: ArrayList<MissedCall>,
|
||||
private val context: Context) : RecyclerView.Adapter<MissedCallsAdapter.MissedCallsHolder>() {
|
||||
|
||||
private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
|
||||
|
||||
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): MissedCallsHolder {
|
||||
val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
|
||||
return MissedCallsHolder(binding)
|
||||
}
|
||||
|
||||
override fun getItemCount(): Int {
|
||||
// BLog.LOGE("callList.size >>> ${callList.size}")
|
||||
return callList.size
|
||||
}
|
||||
|
||||
@SuppressLint("SetTextI18n")
|
||||
override fun onBindViewHolder(holder: MissedCallsHolder, position: Int) {
|
||||
val todo = callList[position]
|
||||
BLog.LOGE("callList >>> ${callList[position]}")
|
||||
holder.view.itemText.text = "\u25CF ${if(todo.name.equals("unknown")) todo.number else { todo.name}} , ${todo.typeString} : ${todo.count} : ${todo.date}"
|
||||
|
||||
/* multiline texts are enabled for TodoManager */
|
||||
holder.view.itemText.isSingleLine = false
|
||||
/* launch edit or update dialog on item click */
|
||||
holder.view.itemText.setOnClickListener { updateDialog(position) }
|
||||
/* copy texts on long click */
|
||||
holder.view.itemText.setOnLongClickListener {
|
||||
copyToClipboard(context, todo.name)
|
||||
true
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
inner class MissedCallsHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
|
||||
|
||||
/* update dialog */
|
||||
private fun updateDialog(position: Int) {
|
||||
val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
|
||||
val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
|
||||
bottomSheetDialog.setContentView(dialogBinding.root)
|
||||
bottomSheetDialog.show()
|
||||
bottomSheetDialog.dismissWithAnimation = true
|
||||
|
||||
val databaseHandler = DatabaseHandler(context)
|
||||
val todo = databaseHandler.todos[position]
|
||||
|
||||
dialogBinding.apply {
|
||||
deleteAllConfirmation.visibility = View.GONE
|
||||
todoInput.setText(todo.name)
|
||||
todoCancel.text = context.getString(R.string.delete)
|
||||
todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
|
||||
todoOk.text = context.getString(R.string.update)
|
||||
}
|
||||
|
||||
/* delete the item */
|
||||
dialogBinding.todoCancel.setOnClickListener {
|
||||
|
||||
}
|
||||
|
||||
/* update the item */
|
||||
dialogBinding.todoOk.setOnClickListener {
|
||||
val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
|
||||
if (updatedTodoString.isNotEmpty()) {
|
||||
todo.name = updatedTodoString
|
||||
databaseHandler.updateTodo(todo)
|
||||
bottomSheetDialog.dismiss()
|
||||
} else {
|
||||
dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@ -5,7 +5,7 @@ import rasel.lunar.launcher.BuildConfig
|
||||
import java.lang.Exception
|
||||
|
||||
object BLog {
|
||||
val DEFAULT_TAG = "MyEBook_TAG"
|
||||
val DEFAULT_TAG = "Lunatic"
|
||||
enum class BLogType {
|
||||
D,I,E
|
||||
}
|
||||
|
||||
@ -38,6 +38,7 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
private val mShaderMatrix: Matrix = Matrix()
|
||||
private val mBitmapPaint: Paint = Paint()
|
||||
private val mBorderPaint: Paint = Paint()
|
||||
private val mLabelPaint: Paint = Paint()
|
||||
private val mCircleBackgroundPaint: Paint = Paint()
|
||||
|
||||
private var mBorderColor = DEFAULT_BORDER_COLOR
|
||||
@ -60,6 +61,7 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
private var mBorderOverlay = false
|
||||
private var mDisableCircularTransformation = false
|
||||
|
||||
private var label : String = ""
|
||||
constructor(context: Context) : super(context) {
|
||||
init()
|
||||
}
|
||||
@ -85,6 +87,8 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
DEFAULT_CIRCLE_BACKGROUND_COLOR
|
||||
)
|
||||
|
||||
label = a.getString(R.styleable.CircleImageView_civ_label) ?: ""
|
||||
|
||||
a.recycle()
|
||||
|
||||
init()
|
||||
@ -110,6 +114,9 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
mCircleBackgroundPaint.setAntiAlias(true)
|
||||
mCircleBackgroundPaint.setColor(mCircleBackgroundColor)
|
||||
|
||||
mLabelPaint.color = Color.WHITE
|
||||
mLabelPaint.isFakeBoldText = true
|
||||
mLabelPaint.textAlign = Paint.Align.CENTER
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
|
||||
outlineProvider = OutlineProvider()
|
||||
}
|
||||
@ -175,6 +182,10 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
mBorderPaint
|
||||
)
|
||||
}
|
||||
|
||||
if (label.length > 0) {
|
||||
canvas.drawText(label.toUpperCase(),mBorderRect.centerX(),mBorderRect.height() * 0.98f, mLabelPaint)
|
||||
}
|
||||
}
|
||||
|
||||
override fun invalidateDrawable(@NonNull dr: Drawable) {
|
||||
@ -185,6 +196,7 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
|
||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
||||
super.onSizeChanged(w, h, oldw, oldh)
|
||||
updateDimensions()
|
||||
mLabelPaint.textSize = h * 0.2f
|
||||
invalidate()
|
||||
}
|
||||
|
||||
|
||||
BIN
app/src/main/res/drawable/coupang.png
Normal file
BIN
app/src/main/res/drawable/coupang.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 12 KiB |
@ -110,6 +110,7 @@
|
||||
style="@style/SearchIcons"
|
||||
android:id="@+id/search_store"/>
|
||||
</LinearLayout>
|
||||
|
||||
<TextView
|
||||
android:layout_marginTop="10dp"
|
||||
android:layout_marginBottom="10dp"
|
||||
|
||||
144
app/src/main/res/layout/contact_menu.xml
Normal file
144
app/src/main/res/layout/contact_menu.xml
Normal file
@ -0,0 +1,144 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:padding="@dimen/twelve"
|
||||
android:clickable="true"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/appName"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="@dimen/zero"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/eight"
|
||||
android:inputType="textNoSuggestions"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/phoneNumber"
|
||||
style="@style/Widget.Material3.Button.TextButton"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/appName" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/activityBrowser"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_activity"
|
||||
android:tooltipText="@string/activity_browser"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/detailedInfo"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneNumber" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/detailedInfo"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:layout_marginEnd="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_info"
|
||||
android:tooltipText="@string/detailed_info"
|
||||
app:layout_constraintEnd_toStartOf="@id/activityBrowser"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/phoneNumber" />
|
||||
|
||||
<com.google.android.material.button.MaterialButtonToggleGroup
|
||||
android:id="@+id/favGroup"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/detailedInfo"
|
||||
app:singleSelection="true" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/appInfo"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:layout_marginEnd="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_info2"
|
||||
android:tooltipText="@string/app_info"
|
||||
app:layout_constraintEnd_toStartOf="@id/appFreeform"
|
||||
app:layout_constraintHorizontal_chainStyle="packed"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/favGroup" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/appFreeform"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:layout_marginEnd="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_pip"
|
||||
android:tooltipText="@string/freeform"
|
||||
app:layout_constraintEnd_toStartOf="@id/appStore"
|
||||
app:layout_constraintStart_toEndOf="@id/appInfo"
|
||||
app:layout_constraintTop_toBottomOf="@+id/favGroup" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/appStore"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:layout_marginEnd="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_store"
|
||||
android:tooltipText="@string/app_store"
|
||||
app:layout_constraintEnd_toStartOf="@id/appShare"
|
||||
app:layout_constraintStart_toEndOf="@id/appFreeform"
|
||||
app:layout_constraintTop_toBottomOf="@+id/favGroup" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/appShare"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:layout_marginEnd="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_share"
|
||||
android:tooltipText="@string/share"
|
||||
app:layout_constraintEnd_toStartOf="@id/appUninstall"
|
||||
app:layout_constraintStart_toEndOf="@id/appStore"
|
||||
app:layout_constraintTop_toBottomOf="@+id/favGroup" />
|
||||
|
||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||
android:id="@+id/appUninstall"
|
||||
style="@style/Widget.Material3.ExtendedFloatingActionButton.Surface"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="@dimen/eight"
|
||||
android:contentDescription="@null"
|
||||
android:src="@drawable/ic_delete"
|
||||
android:tooltipText="@string/uninstall"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toEndOf="@id/appShare"
|
||||
app:layout_constraintTop_toBottomOf="@+id/favGroup"
|
||||
app:tint="@android:color/holo_red_light" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -2,6 +2,7 @@
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
@ -29,11 +30,13 @@
|
||||
android:textIsSelectable="false"
|
||||
android:textSize="@dimen/clockText"
|
||||
android:textStyle="bold"
|
||||
android:textLocale="en_US"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
|
||||
app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
|
||||
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
|
||||
app:layout_constraintTop_toTopOf="@+id/batteryProgress"
|
||||
app:layout_constraintVertical_bias="0.450" />
|
||||
app:layout_constraintVertical_bias="0.450"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<TextClock
|
||||
android:id="@+id/date"
|
||||
@ -41,12 +44,14 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:gravity="center"
|
||||
android:maxLines="1"
|
||||
android:textLocale="en_US"
|
||||
android:textIsSelectable="false"
|
||||
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
|
||||
app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
|
||||
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
|
||||
app:layout_constraintTop_toBottomOf="@+id/time"
|
||||
app:layout_constraintVertical_bias="0.075" />
|
||||
app:layout_constraintVertical_bias="0.075"
|
||||
tools:ignore="UnusedAttribute" />
|
||||
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/weather"
|
||||
@ -61,18 +66,54 @@
|
||||
app:layout_constraintTop_toBottomOf="@+id/date"
|
||||
app:layout_constraintVertical_bias="0.100" />
|
||||
|
||||
<RadioGroup
|
||||
android:id="@+id/summaryChoose"
|
||||
android:layout_width="0dp"
|
||||
android:gravity="center"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
|
||||
>
|
||||
<RadioButton
|
||||
android:id="@+id/missedCalls"
|
||||
android:button="@null"
|
||||
android:gravity="center"
|
||||
android:text="전화"
|
||||
android:checked="true"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<RadioButton
|
||||
android:gravity="center"
|
||||
android:button="@null"
|
||||
android:text="투두"
|
||||
android:checked="false"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
<RadioButton
|
||||
android:gravity="center"
|
||||
android:button="@null"
|
||||
android:text="문자"
|
||||
android:checked="false"
|
||||
android:layout_weight="1"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"/>
|
||||
</RadioGroup>
|
||||
<androidx.recyclerview.widget.RecyclerView
|
||||
android:id="@+id/notes"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="@dimen/zero"
|
||||
android:layout_height="200dp"
|
||||
android:overScrollMode="never"
|
||||
android:padding="@dimen/fortyEight"
|
||||
android:padding="20dp"
|
||||
android:scrollbars="none"
|
||||
app:layoutManager="LinearLayoutManager"
|
||||
app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/batteryProgress" />
|
||||
|
||||
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" />
|
||||
|
||||
<androidx.appcompat.widget.LinearLayoutCompat
|
||||
android:id="@+id/favAppsGroup"
|
||||
|
||||
@ -7,7 +7,7 @@
|
||||
<com.google.android.material.textview.MaterialTextView
|
||||
android:id="@+id/itemText"
|
||||
android:layout_width="@dimen/zero"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_height="40dp"
|
||||
android:padding="@dimen/twelve"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
||||
89
app/src/main/res/layout/search_menu.xml
Normal file
89
app/src/main/res/layout/search_menu.xml
Normal file
@ -0,0 +1,89 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:clipToPadding="false"
|
||||
android:padding="@dimen/twelve"
|
||||
android:clickable="true"
|
||||
android:focusableInTouchMode="true">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/keyworkd"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
android:layout_width="wrap_content"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:minWidth="@dimen/zero"
|
||||
android:textSize="24dp"
|
||||
android:gravity="center"
|
||||
android:padding="@dimen/eight"
|
||||
android:inputType="textNoSuggestions"
|
||||
/>
|
||||
|
||||
|
||||
<LinearLayout
|
||||
style="@style/SearchMenus"
|
||||
android:id="@+id/quickSearch"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/keyworkd">
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
android:src="@drawable/google"
|
||||
android:id="@+id/search_google"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
android:src="@drawable/naver"
|
||||
android:id="@+id/search_naver"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
app:civ_label="DDuckGo"
|
||||
android:src="@drawable/duckduckgo"
|
||||
android:id="@+id/search_duckduckgo"/>
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:id="@+id/quickSearch2"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/quickSearch"
|
||||
style="@style/SearchMenus">
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
android:src="@drawable/namuwiki"
|
||||
android:id="@+id/search_namuwiki"
|
||||
style="@style/SearchMenuItem"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
android:src="@drawable/gmap"
|
||||
android:id="@+id/search_googleMap"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
android:src="@drawable/navermap"
|
||||
android:id="@+id/search_nmap"/>
|
||||
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
<LinearLayout
|
||||
android:id="@+id/quickSearch3"
|
||||
android:orientation="horizontal"
|
||||
app:layout_constraintTop_toBottomOf="@id/quickSearch2"
|
||||
style="@style/SearchMenus">
|
||||
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
style="@style/SearchMenuItem"
|
||||
android:src="@drawable/coupang"
|
||||
android:id="@+id/search_coupang"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
android:src="@drawable/tmap"
|
||||
style="@style/SearchMenuItem"
|
||||
android:id="@+id/search_tmap"/>
|
||||
<rasel.lunar.launcher.view.CircleImageView
|
||||
android:src="@drawable/translate"
|
||||
style="@style/SearchMenuItem"
|
||||
android:id="@+id/search_translate"/>
|
||||
</LinearLayout>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
@ -5,5 +5,6 @@
|
||||
<attr name="civ_border_color" format="color" />
|
||||
<attr name="civ_border_overlay" format="boolean" />
|
||||
<attr name="civ_circle_background_color" format="color" />
|
||||
<attr name="civ_label" format="string" />
|
||||
</declare-styleable>
|
||||
</resources>
|
||||
@ -37,4 +37,28 @@
|
||||
<item name="civ_border_color">#000000</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="SearchMenuItem">
|
||||
<item name="android:layout_margin">5dp</item>
|
||||
<item name="android:adjustViewBounds">true</item>
|
||||
<item name="android:scaleType">fitCenter</item>
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">wrap_content</item>
|
||||
<item name="android:layout_weight">1</item>
|
||||
<item name="civ_border_width">1dp</item>
|
||||
<item name="civ_border_color">#000000</item>
|
||||
</style>
|
||||
|
||||
|
||||
<style name="SearchMenus">
|
||||
<item name="layout_constraintLeft_toLeftOf">parent</item>
|
||||
<item name="layout_constraintRight_toRightOf">parent</item>
|
||||
<item name="android:orientation">horizontal</item>
|
||||
<item name="android:background">@null</item>
|
||||
<item name="android:layout_width">0dp</item>
|
||||
<item name="android:layout_height">80dp</item>
|
||||
</style>
|
||||
|
||||
|
||||
</resources>
|
||||
Loading…
x
Reference in New Issue
Block a user