This commit is contained in:
lunaticbum 2024-08-22 16:00:05 +09:00
parent bdb6a57a55
commit 74c64c7617
12 changed files with 464 additions and 120 deletions

View File

@ -44,6 +44,8 @@ import androidx.viewpager2.widget.ViewPager2
import com.google.android.material.color.DynamicColors import com.google.android.material.color.DynamicColors
import com.google.android.material.dialog.MaterialAlertDialogBuilder import com.google.android.material.dialog.MaterialAlertDialogBuilder
import rasel.lunar.launcher.apps.AppDrawer 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.databinding.LauncherActivityBinding
import rasel.lunar.launcher.feeds.Feeds import rasel.lunar.launcher.feeds.Feeds
import rasel.lunar.launcher.feeds.WidgetHost import rasel.lunar.launcher.feeds.WidgetHost
@ -150,13 +152,16 @@ internal class LauncherActivity : AppCompatActivity() {
/* set up viewpager2 */ /* set up viewpager2 */
private fun setupView() { private fun setupView() {
viewPager = binding.viewPager.apply { viewPager = binding.viewPager.apply {
adapter = ViewPagerAdapter( adapter = ViewPagerAdapter(
supportFragmentManager, mutableListOf(Feeds(), LauncherHome(), AppDrawer()), lifecycle) supportFragmentManager,
offscreenPageLimit = 1 mutableListOf(Feeds(), LauncherHome(), AppDrawer()),
setCurrentItem(1, false) lifecycle
reduceDragSensitivity() )
} offscreenPageLimit = 1
setCurrentItem(1, false)
reduceDragSensitivity()
}
} }
private fun setBgColor() { private fun setBgColor() {
@ -227,4 +232,7 @@ internal class LauncherActivity : AppCompatActivity() {
} }
} }
fun openSearchMenus(keyword : String, dismissCalback: DismissCalback) {
SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()}
}
} }

View File

@ -32,7 +32,7 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.provider.ContactsContract import android.provider.ContactsContract
import android.util.Log import android.util.Log
import android.view.Gravity import android.view.KeyEvent.ACTION_UP
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.View.GONE import android.view.View.GONE
@ -44,16 +44,12 @@ import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.GridLayoutManager
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import rasel.lunar.launcher.BuildConfig import rasel.lunar.launcher.BuildConfig
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.databinding.AppDrawerBinding 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_COUNT
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPS_LAYOUT 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_APP_NAMES
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
@ -65,7 +61,7 @@ internal class AppDrawer : Fragment() {
private lateinit var binding: AppDrawerBinding private lateinit var binding: AppDrawerBinding
private var layoutType: Int = 0 private var layoutType: Int = 0
private var isSearchShown: Boolean = false // private var isSearchShown: Boolean = false
private var isKeyboardShowing: Boolean = false private var isKeyboardShowing: Boolean = false
companion object { companion object {
@ -155,7 +151,30 @@ internal class AppDrawer : Fragment() {
openSearchApps("coupang://search?q=${getInputText()}","com.coupang.mobile") openSearchApps("coupang://search?q=${getInputText()}","com.coupang.mobile")
} }
binding.reset.setOnClickListener { filterAppsList("") }
binding.searchInput.setOnKeyListener { v, keyCode, event ->
BLog.LOGE("v == ${v}, keyCode == ${keyCode}, event == ${event}")
BLog.LOGE("isAdded == ${isAdded}, isResumed == ${isResumed}, isVisible == ${isVisible}")
clearCancelSearch()
if (v.equals(binding.searchInput) && keyCode == 66 && isAdded && isResumed && isVisible && lActivity?.hasWindowFocus() == true && event.action == ACTION_UP) {
try {
if (lastSearchString.length > 0) {
checkResult(binding.searchInput.text.toString())
}
return@setOnKeyListener true
} catch (e :Exception) {
e.printStackTrace()
}
}
return@setOnKeyListener false
}
binding.searchInput.doOnTextChanged { inputText, _, _, _ ->
clearCancelSearch()
binding.searchInput.text?.let { binding.searchInput.setSelection(it.length) }
filterAppsList(inputText.toString())
}
setLayout() setLayout()
return binding.root return binding.root
@ -202,6 +221,7 @@ internal class AppDrawer : Fragment() {
} }
fun openSearchApps(schemeString : String, pakage : String? = null) { fun openSearchApps(schemeString : String, pakage : String? = null) {
val gmmIntentUri = Uri.parse(schemeString) val gmmIntentUri = Uri.parse(schemeString)
val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
@ -215,108 +235,133 @@ internal class AppDrawer : Fragment() {
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) 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 ->
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() { fun checkResult(keyword: String) {
if (lastSearchString.length > 0 && packageList.size == 1) {
var dialog = AlertDialog.Builder(requireContext()) if(!isAdded || !isResumed || keyword.length < 1) return
dialog.setTitle("앱 실행 확인") var dialog : AlertDialog.Builder? = null
dialog.setMessage("${lastSearchString} 검색 결과 '${packageList[0].appName}' 준비됨") var filted = packageList.filter { it.appName.equals(keyword) }
dialog.setCancelable(false) BLog.LOGE("filted >> ${filted.size}")
dialog.setNegativeButton("취소") { s,d-> var filtedContact = contactList.filter { it.name.equals(keyword) }
s.dismiss() 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.setPositiveButton("실행") { s, d -> dialog?.setCancelable(false)
startActivity(packageManager?.getLaunchIntentForPackage(packageList[0].packageName)) dialog?.setNegativeButton("취소") { s, d ->
s.dismiss() runonUi { s.dismiss() }
} }
dialog.show() dialog?.setOnDismissListener { registCancelSearch() }
} else if (packageList.size == 0 && contactList.size == 1) { dialog?.show()
var dialog = AlertDialog.Builder(requireContext()) } else if (contactList.size == 1 || filtedContact.size > 0) {
dialog.setTitle("연락처 실행 확인") dialog = AlertDialog.Builder(requireContext())
dialog.setMessage("${lastSearchString} 검색 결과 '${contactList[0].name}' 준비됨") dialog?.setTitle("연락처 실행 확인")
dialog.setCancelable(false) dialog?.setCancelable(false)
dialog.setNegativeButton("취소") { s,d-> dialog?.setNegativeButton("취소") { s, d ->
s.dismiss() runonUi { s.dismiss() }
} }
dialog.setPositiveButton("실행") { s, d -> if (contactList.size == 1) {
ContactMenu().show(childFragmentManager, contactList[0].id.toString()) dialog?.setMessage("${keyword} 검색 결과 '${contactList[0].name}' 준비됨")
s.dismiss() 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.show() dialog?.setOnDismissListener { registCancelSearch() }
dialog?.show()
} else { } else {
var dialog = AlertDialog.Builder(requireContext()) lActivity?.openSearchMenus(keyword) {
dialog.setTitle("검색 실행 확인") registCancelSearch()
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()
} }
} }
fun runonUi(invoke : () -> Unit) {
Handler(Looper.getMainLooper()).run {
try {
invoke.invoke()
}catch (e : Exception) {
e.printStackTrace()
}
}
}
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
BLog.LOGE("onResume")
fetchApps() fetchApps()
GetContact() GetContact()
setKeyboardPadding() setKeyboardPadding()
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))
}
contactAdapter?.updateData(contactList) contactAdapter?.updateData(contactList)
/* pop up the keyboard */ /* pop up the keyboard */
openSearch() openSearch()
registCancelSearch()
chechHandler.postDelayed(cancelSearch, 3000L) BLog.LOGE("onResume after chechHandler.postDelayed(cancelSearch, 3000L)")
} }
val chechHandler = Handler(Looper.getMainLooper()) val chechHandler = Handler(Looper.getMainLooper())
val cancelSearch = Runnable { timerCheck() } val cancelSearch = Runnable { timerCheck() }
private fun timerCheck() { fun registCancelSearch() {
BLog.LOGE("Called registCancelSearch")
chechHandler.removeCallbacks(cancelSearch)
chechHandler.postDelayed(cancelSearch, 3000L)
}
fun clearCancelSearch() {
chechHandler.removeCallbacks(cancelSearch)
}
private fun timerCheck() {
lActivity?.onBackPressed() lActivity?.onBackPressed()
} }
@ -396,7 +441,6 @@ internal class AppDrawer : Fragment() {
var lastSearchStringLength = 0 var lastSearchStringLength = 0
var lastSearchString : String = "" var lastSearchString : String = ""
private fun filterAppsList(searchString: String) { private fun filterAppsList(searchString: String) {
chechHandler.removeCallbacks(cancelSearch)
/* check each app name and add if it matches the search string */ /* check each app name and add if it matches the search string */
if (searchString.length > 0 && (lastSearchStringLength != searchString.length || lastSearchString.equals(searchString) == false)) { if (searchString.length > 0 && (lastSearchStringLength != searchString.length || lastSearchString.equals(searchString) == false)) {
BLog.LOGE("START FILTER") BLog.LOGE("START FILTER")
@ -410,7 +454,7 @@ internal class AppDrawer : Fragment() {
packageList.sortBy { it.appName } packageList.sortBy { it.appName }
BLog.LOGE("MIDDLE FILTER") BLog.LOGE("MIDDLE FILTER")
appsAdapter?.updateData(packageList) appsAdapter?.updateData(packageList)
contactList.clear() contactList.clear()
for (item in originContactList) { for (item in originContactList) {
@ -426,7 +470,7 @@ internal class AppDrawer : Fragment() {
} }
lastSearchString = searchString lastSearchString = searchString
lastSearchStringLength = searchString.length lastSearchStringLength = searchString.length
chechHandler.postDelayed(cancelSearch, 3000L) registCancelSearch()
} }
private fun afterClearSearch() { private fun afterClearSearch() {
@ -452,26 +496,21 @@ internal class AppDrawer : Fragment() {
} }
private fun openSearch() { private fun openSearch() {
isSearchShown = true
binding.searchInput.apply { binding.searchInput.apply {
visibility = VISIBLE visibility = VISIBLE
requestFocus() requestFocus()
let { let {
(lActivity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) (lActivity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
.showSoftInput(it, InputMethodManager.SHOW_IMPLICIT)
} }
} }
} }
/* clear search string, hide keyboard and search box */ /* clear search string, hide keyboard and search box */
private fun closeSearch() { private fun closeSearch() {
isSearchShown = false
binding.searchInput.apply { binding.searchInput.apply {
text?.clear()
visibility = GONE
let { let {
(lActivity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager) text?.clear()
.hideSoftInputFromWindow(it.windowToken, 0) (lActivity?.getSystemService(Context.INPUT_METHOD_SERVICE) as? InputMethodManager)?.hideSoftInputFromWindow(it.windowToken, 0)
} }
} }
} }

View File

@ -47,7 +47,7 @@ internal class AppsAdapter(
private val appsCount: TextView) : RecyclerView.Adapter<AppsAdapter.AppsViewHolder>() { private val appsCount: TextView) : RecyclerView.Adapter<AppsAdapter.AppsViewHolder>() {
private var oldList = mutableListOf<Packages>() private var oldList = mutableListOf<Packages>()
private var appGravity: Int = Gravity.CENTER // private var appGravity: Int = Gravity.CENTER
companion object { companion object {
@JvmStatic var appsSize: Int? = null @JvmStatic var appsSize: Int? = null
@ -106,21 +106,6 @@ internal class AppsAdapter(
appsSize = it 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 ( data class Packages (

View 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

View File

@ -67,7 +67,7 @@ internal class Constants {
const val KEY_LOCK_METHOD = "lock_method" 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_SIZE = 44
const val DEFAULT_ICON_PACK = "default_icon_pack" const val DEFAULT_ICON_PACK = "default_icon_pack"
const val DEFAULT_GRID_COLUMNS = 4 const val DEFAULT_GRID_COLUMNS = 4

View File

@ -105,6 +105,8 @@ internal class LauncherHome : Fragment() {
requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
/* time and date */ /* time and date */
binding.time.textLocale = Locale.US
binding.date.textLocale = Locale.US
if (DateFormat.is24HourFormat(requireContext())) { if (DateFormat.is24HourFormat(requireContext())) {
binding.time.format24Hour = timeFormat binding.time.format24Hour = timeFormat
binding.date.format24Hour = dateFormat binding.date.format24Hour = dateFormat
@ -390,9 +392,9 @@ internal class LauncherHome : Fragment() {
0 -> return if (DateFormat.is24HourFormat(requireContext())) { 0 -> return if (DateFormat.is24HourFormat(requireContext())) {
"kk:mm" "kk:mm"
} else { } else {
"h:mm a" "HH:mm a"
} }
1 -> return "h:mm a" 1 -> return "HH:mm a"
2 -> return "kk:mm" 2 -> return "kk:mm"
} }
return null return null

View File

@ -5,7 +5,7 @@ import rasel.lunar.launcher.BuildConfig
import java.lang.Exception import java.lang.Exception
object BLog { object BLog {
val DEFAULT_TAG = "MyEBook_TAG" val DEFAULT_TAG = "Lunatic"
enum class BLogType { enum class BLogType {
D,I,E D,I,E
} }

View File

@ -38,6 +38,7 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
private val mShaderMatrix: Matrix = Matrix() private val mShaderMatrix: Matrix = Matrix()
private val mBitmapPaint: Paint = Paint() private val mBitmapPaint: Paint = Paint()
private val mBorderPaint: Paint = Paint() private val mBorderPaint: Paint = Paint()
private val mLabelPaint: Paint = Paint()
private val mCircleBackgroundPaint: Paint = Paint() private val mCircleBackgroundPaint: Paint = Paint()
private var mBorderColor = DEFAULT_BORDER_COLOR private var mBorderColor = DEFAULT_BORDER_COLOR
@ -60,6 +61,7 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
private var mBorderOverlay = false private var mBorderOverlay = false
private var mDisableCircularTransformation = false private var mDisableCircularTransformation = false
private var label : String = ""
constructor(context: Context) : super(context) { constructor(context: Context) : super(context) {
init() init()
} }
@ -85,6 +87,8 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
DEFAULT_CIRCLE_BACKGROUND_COLOR DEFAULT_CIRCLE_BACKGROUND_COLOR
) )
label = a.getString(R.styleable.CircleImageView_civ_label) ?: ""
a.recycle() a.recycle()
init() init()
@ -110,6 +114,9 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
mCircleBackgroundPaint.setAntiAlias(true) mCircleBackgroundPaint.setAntiAlias(true)
mCircleBackgroundPaint.setColor(mCircleBackgroundColor) mCircleBackgroundPaint.setColor(mCircleBackgroundColor)
mLabelPaint.color = Color.WHITE
mLabelPaint.isFakeBoldText = true
mLabelPaint.textAlign = Paint.Align.CENTER
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
outlineProvider = OutlineProvider() outlineProvider = OutlineProvider()
} }
@ -175,6 +182,10 @@ class CircleImageView : androidx.appcompat.widget.AppCompatImageView {
mBorderPaint mBorderPaint
) )
} }
if (label.length > 0) {
canvas.drawText(label.toUpperCase(),mBorderRect.centerX(),mBorderRect.height() * 0.98f, mLabelPaint)
}
} }
override fun invalidateDrawable(@NonNull dr: Drawable) { 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) { override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh) super.onSizeChanged(w, h, oldw, oldh)
updateDimensions() updateDimensions()
mLabelPaint.textSize = h * 0.2f
invalidate() invalidate()
} }

View File

@ -2,6 +2,7 @@
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
@ -29,11 +30,13 @@
android:textIsSelectable="false" android:textIsSelectable="false"
android:textSize="@dimen/clockText" android:textSize="@dimen/clockText"
android:textStyle="bold" android:textStyle="bold"
android:textLocale="en_US"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress" app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress" app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
app:layout_constraintStart_toStartOf="@+id/batteryProgress" app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintTop_toTopOf="@+id/batteryProgress" app:layout_constraintTop_toTopOf="@+id/batteryProgress"
app:layout_constraintVertical_bias="0.450" /> app:layout_constraintVertical_bias="0.450"
tools:ignore="UnusedAttribute" />
<TextClock <TextClock
android:id="@+id/date" android:id="@+id/date"
@ -41,12 +44,14 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:maxLines="1" android:maxLines="1"
android:textLocale="en_US"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress" app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress" app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
app:layout_constraintStart_toStartOf="@+id/batteryProgress" app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintTop_toBottomOf="@+id/time" 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 <com.google.android.material.textview.MaterialTextView
android:id="@+id/weather" android:id="@+id/weather"

View 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>

View File

@ -5,5 +5,6 @@
<attr name="civ_border_color" format="color" /> <attr name="civ_border_color" format="color" />
<attr name="civ_border_overlay" format="boolean" /> <attr name="civ_border_overlay" format="boolean" />
<attr name="civ_circle_background_color" format="color" /> <attr name="civ_circle_background_color" format="color" />
<attr name="civ_label" format="string" />
</declare-styleable> </declare-styleable>
</resources> </resources>

View File

@ -34,4 +34,28 @@
<item name="civ_border_color">#000000</item> <item name="civ_border_color">#000000</item>
</style> </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> </resources>