diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index bb8c208..6a6582d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -32,7 +32,7 @@ - + diff --git a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt index 1724eb3..a574b3a 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt @@ -18,9 +18,12 @@ package rasel.lunar.launcher +//import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet import android.Manifest +import android.app.NotificationManager import android.appwidget.AppWidgetManager import android.content.BroadcastReceiver +import android.content.ComponentName import android.content.Context import android.content.Intent import android.content.SharedPreferences @@ -46,6 +49,7 @@ import android.webkit.WebView import android.webkit.WebViewClient import android.widget.Toast import androidx.activity.OnBackPressedCallback +import androidx.annotation.RequiresApi import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM @@ -54,6 +58,7 @@ import androidx.core.view.ViewCompat import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePadding +import androidx.lifecycle.ReportFragment.Companion.reportFragment import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 import androidx.work.ExistingPeriodicWorkPolicy @@ -72,27 +77,23 @@ import rasel.lunar.launcher.feeds.WidgetHost import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME 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 import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_FIRST_LAUNCH import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS import rasel.lunar.launcher.helpers.Constants.Companion.widgetHostId -import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId import rasel.lunar.launcher.helpers.ViewPagerAdapter import rasel.lunar.launcher.home.LauncherHome import rasel.lunar.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl -import rasel.lunar.launcher.home.LauncherHome.Companion.listItem import rasel.lunar.launcher.home.LauncherHome.Companion.listTags -//import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet -import rasel.lunar.launcher.model.RssItem -import rasel.lunar.launcher.model.RssTagItem import rasel.lunar.launcher.model.RssData -import rasel.lunar.launcher.model.getT import rasel.lunar.launcher.model.RssDataInterface import rasel.lunar.launcher.model.RssDataType +import rasel.lunar.launcher.model.RssItem +import rasel.lunar.launcher.model.RssTagItem import rasel.lunar.launcher.model.getRssData +import rasel.lunar.launcher.model.getT import rasel.lunar.launcher.utils.BLog +import rasel.lunar.launcher.utils.NLService import rasel.lunar.launcher.utils.RssList.jGuruMain -import rasel.lunar.launcher.utils.RssList.jGuruRanks import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.make0H import rasel.lunar.launcher.workers.ArcaGetter @@ -128,7 +129,7 @@ internal class LauncherActivity : AppCompatActivity() { val COMIC_WORK_TAG = "ComicGetter" val COMIC2_WORK_TAG = "ComicGetter2" val REDDIT_WORK_TAG = "RedditGetter" - val shortTimePeriod = 15L + val shortTimePeriod = 20L val longTimePeriod = 60L val midTimePeriod = 30L var isOpendFold = false @@ -302,6 +303,11 @@ internal class LauncherActivity : AppCompatActivity() { refreshYoutube() refreshReddit() refreshComics() +// if (listItem.size < 2) { +// lActivity?.doWebParseStart(jGuruRanks) { +// +// } +// } } override fun onDestroy() { @@ -314,16 +320,19 @@ internal class LauncherActivity : AppCompatActivity() { BLog.LOGE("LauncherActivity onStart()") statusBarView() setBgColor() - - if (listItem.size < 2) { - lActivity?.doWebParseStart(jGuruRanks) { - - } - } } + + @RequiresApi(Build.VERSION_CODES.O_MR1) override fun onResume() { super.onResume() BLog.LOGE("LauncherActivity onResume") + val cn: ComponentName = ComponentName(this, NLService::class.java) + val n = applicationContext.getSystemService(NOTIFICATION_SERVICE) as NotificationManager + if (n.isNotificationListenerAccessGranted(cn)) { + } else { + val intent = Intent(Settings.ACTION_NOTIFICATION_LISTENER_SETTINGS) + startActivity(intent) + } } @@ -405,9 +414,7 @@ internal class LauncherActivity : AppCompatActivity() { } private fun setBgColor() { - binding.root.setBackgroundColor(Color.parseColor("#${ - settingsPrefs.getString(KEY_WINDOW_BACKGROUND, getString(getColorResId(this, android.R.attr.colorBackground)) - .replace("#", ""))}")) + binding.root.setBackgroundColor(Color.parseColor("#22000000")) } private fun statusBarView() { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt index 0b11aef..ef2d064 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppDrawer.kt @@ -54,6 +54,7 @@ import rasel.lunar.launcher.helpers.Constants.Companion.KEY_APPS_LAYOUT 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 +import java.net.URLEncoder import java.text.Normalizer import java.util.regex.Pattern @@ -162,6 +163,12 @@ internal class AppDrawer : Fragment() { binding.runKatalk.setOnClickListener { sendMsg(pkg = "com.kakao.talk") } + + binding.runKatalkT.setOnClickListener{ + openSearchApps("kakaot://taxi?dest_lat=${URLEncoder.encode("37.467696")}&dest_lng=${URLEncoder.encode("127.101063")}","com.kakao.taxi") +// openSearchApps("kakaot://taxi?${URLEncoder.encode("세곡동 557")}","com.kakao.taxi") +// openSearchApps("kakaot://taxi?dest_addr=${URLEncoder.encode("세곡동 557")}","com.kakao.taxi") + } setLayout() return binding.root diff --git a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppMenu.kt b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppMenu.kt index bebc63d..b08bbe5 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/apps/AppMenu.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/apps/AppMenu.kt @@ -49,6 +49,7 @@ 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 com.google.gson.Gson import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.R import rasel.lunar.launcher.apps.AppDrawer.Companion.appNamesPrefs @@ -62,6 +63,7 @@ import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_FAVORITE_APPS import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard 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 @@ -261,12 +263,15 @@ internal class AppMenu : BottomSheetDialogFragment() { } else { packageManager.getPackageInfo(packageName, PackageManager.GET_ACTIVITIES) } - + BLog.LOGE("activity. >>>>> ${Gson().toJson(activityInfo)}") /* show activity list */ val activityAdapter: ArrayAdapter = ArrayAdapter(requireContext(), R.layout.list_item, R.id.itemText, ArrayList()) if (activityInfo.activities.isNotEmpty()) { for (activity in activityInfo.activities) { + if (packageName.contains("com.kakao") == true) { + BLog.LOGE("activity. >>>>> ${Gson().toJson(activity)}") + } activityAdapter.add( activity.toString().split(" ").toTypedArray()[1].replace("}", "") ) diff --git a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt index 5fe6208..47274b2 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt @@ -29,7 +29,6 @@ import android.os.Bundle import android.os.Handler import android.os.Looper import android.provider.AlarmClock -import android.text.format.DateFormat import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -40,6 +39,7 @@ import androidx.core.content.ContextCompat.registerReceiver import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.DividerItemDecoration +import androidx.recyclerview.widget.GridLayoutManager import androidx.recyclerview.widget.LinearLayoutManager import io.realm.kotlin.ext.query import io.realm.kotlin.notifications.ResultsChange @@ -48,9 +48,11 @@ import io.realm.kotlin.query.RealmResults import io.realm.kotlin.query.Sort import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.Job import kotlinx.coroutines.launch import org.json.JSONArray import org.json.JSONObject +import org.jsoup.Jsoup import rasel.lunar.launcher.LauncherActivity.Companion.CALL_WORK_TAG import rasel.lunar.launcher.LauncherActivity.Companion.FEDDS_WORK_TAG import rasel.lunar.launcher.LauncherActivity.Companion.SMS_WORK_TAG @@ -74,11 +76,13 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.canAuthenticate import rasel.lunar.launcher.helpers.UniUtils.Companion.expandNotificationPanel import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod import rasel.lunar.launcher.home.weather.WeatherExecutor +import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.RssData import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.todos.MissedCallsAdapter import rasel.lunar.launcher.model.RssDataInterface +import rasel.lunar.launcher.todos.NotificationItemAdapter import rasel.lunar.launcher.todos.RssItemAdapter import rasel.lunar.launcher.todos.SmsLogsAdapter import rasel.lunar.launcher.utils.BLog @@ -119,7 +123,7 @@ internal class LauncherHome : Fragment() { } } - val UPDATE_DELAY = 3000L + val UPDATE_DELAY = 1000L val commandHandler = Handler(Looper.getMainLooper()) val smsUpdate = Runnable { @@ -136,16 +140,20 @@ internal class LauncherHome : Fragment() { val infoUpdate = Runnable { chooseAdpater() - if (lasted?.size ?: 0 > 0) { + } + + val notiUpdate = Runnable { + if (lastedNoti?.size ?: 0 > 0) { binding.otherCheck.text = "최근 정보[${lasted!!.size}]" mRssAdapter.updateData(lasted!!) binding.infoList.smoothScrollToPosition(0) - binding.infoList.visibility = View.VISIBLE } } var lasted : RealmResults? = null + var lastedNoti : RealmResults? = null + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { @@ -155,24 +163,30 @@ internal class LauncherHome : Fragment() { batteryReceiver = BatteryReceiver(binding.batteryProgress) mMissedCallsAdapter = MissedCallsAdapter(callList, requireContext()) mSmsLogsAdapter = SmsLogsAdapter(smsList, requireContext()) + mNotiAdapter = NotificationItemAdapter(requireContext()) mRssAdapter = RssItemAdapter(requireContext()) - binding.mainList.adapter = mMissedCallsAdapter - binding.smsList.adapter = mSmsLogsAdapter - binding.infoList.adapter = mRssAdapter + val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) binding.mainList.addItemDecoration(decoration) - binding.smsList.addItemDecoration(decoration) + binding.notiList.addItemDecoration(decoration) binding.infoList.addItemDecoration(decoration) - binding.missedCalls.isChecked = true + binding.missedCalls.isSelected = true binding.smsList.visibility = View.GONE binding.infoList.visibility = View.GONE // binding.favAppsGroup.visibility = View.GONE + binding.notiList.layoutManager = LinearLayoutManager(requireContext()) binding.mainList.layoutManager = LinearLayoutManager(requireContext()) - binding.smsList.layoutManager = LinearLayoutManager(requireContext()) + binding.smsList.layoutManager = GridLayoutManager(requireContext(),2) binding.infoList.layoutManager = LinearLayoutManager(requireContext()) + binding.mainList.adapter = mMissedCallsAdapter + binding.smsList.adapter = mSmsLogsAdapter + binding.infoList.adapter = mRssAdapter + binding.notiList.adapter = mNotiAdapter + + workmanager()?.getWorkInfosByTagLiveData(SMS_WORK_TAG)?.observeForever { commandHandler.removeCallbacks(smsUpdate) commandHandler.postDelayed(smsUpdate,UPDATE_DELAY) @@ -213,22 +227,14 @@ internal class LauncherHome : Fragment() { BLog.LOGE("onCreateView()") mRssDataResult = WorkersDb.getRealm().query().query("pubDate > $0",beforeDay(Date(),3)).sort("pubDate ", Sort.DESCENDING).find() - val job = CoroutineScope(Dispatchers.Default).launch { - // create a Flow from that collection, then add a listener to the Flow + mNotificationResult = WorkersDb.getRealm().query().find() + job = CoroutineScope(Dispatchers.Default).launch { mRssDataResult.asFlow().collect { changes: ResultsChange -> when (changes) { // UpdatedResults means this change represents an update/insert/delete operation is UpdatedResults -> { - -// changes.insertions // indexes of inserted objects -// changes.insertionRanges // ranges of inserted objects -// changes.changes // indexes of modified objects -// changes.changeRanges // ranges of modified objects -// changes.deletions // indexes of deleted objects -// changes.deletionRanges // ranges of deleted objects -// changes.list // the full collection of objects - if (lasted?.size != changes.list.size) { - BLog.LOGE("ResultsChange") + if (mRssAdapter.itemCount != changes.list.size) { +// BLog.LOGE("ResultsChange") lasted = changes.list commandHandler.removeCallbacks(infoUpdate) commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) @@ -242,17 +248,45 @@ internal class LauncherHome : Fragment() { } } } + } -// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) job.start() + CoroutineScope(Dispatchers.Default).launch { + mNotificationResult.asFlow().collect { changes: ResultsChange -> + BLog.LOGE("changes >>> ${changes}") + when (changes) { + // UpdatedResults means this change represents an update/insert/delete operation + is UpdatedResults -> { +// if (lasted?.size != changes.list.size) { + BLog.LOGE("ResultsChange onNotificationPosted") + lastedNoti = changes.list + commandHandler.removeCallbacks(infoUpdate) + commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) + +// } +// WorkersDb.getRealm().apply { write { +// delete(query().query("pubDate < $0",beforeDay(Date(),3)).find()) +// }} + } + + else -> { + // types other than UpdatedResults are not changes -- ignore them + } + } + } + }.start() + mNotiAdapter?.updateData(mNotificationResult) + mRssAdapter?.updateData(mRssDataResult) return binding.root } + lateinit var job : Job lateinit var mMissedCallsAdapter : MissedCallsAdapter lateinit var mSmsLogsAdapter : SmsLogsAdapter lateinit var mRssAdapter : RssItemAdapter + lateinit var mNotiAdapter : NotificationItemAdapter lateinit var mRssDataResult : RealmResults - + lateinit var mNotificationResult : RealmResults override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) @@ -276,57 +310,96 @@ internal class LauncherHome : Fragment() { } binding.mainList.setHasFixedSize(true) binding.mainList.setItemViewCacheSize(10) - binding.missedCalls.setOnClickListener { - binding.missedCalls.isChecked = true - chooseAdpater() - } - binding.recentSms.setOnClickListener { - binding.recentSms.isChecked = true - chooseAdpater() - } - binding.otherCheck.setOnClickListener { - binding.otherCheck.isChecked = true - commandHandler.removeCallbacks(infoUpdate) - commandHandler.post(infoUpdate) + + + var checkListner = object : View.OnClickListener { + + + override fun onClick(v: View?) { + var views = arrayListOf(binding.mainList, binding.smsList, binding.infoList, binding.notiList) + var chechboxs = arrayListOf(binding.missedCalls, + binding.recentSms, + binding.otherCheck, + binding.notice) + chechboxs.remove(v) + when (v) { + binding.missedCalls -> { + if (binding.missedCalls.isSelected ) { + binding.missedCalls.isSelected = false + + } else { + binding.missedCalls.isSelected = true + views.remove(binding.mainList) + binding.mainList.visibility = View.VISIBLE + } + } + binding.recentSms -> { + if (binding.recentSms.isSelected ) { + binding.recentSms.isSelected = false + + } else { + binding.recentSms.isSelected = true + views.remove(binding.smsList) + binding.smsList.visibility = View.VISIBLE + } + } + binding.otherCheck -> { + if (binding.otherCheck.isSelected ) { + binding.otherCheck.isSelected = false + + } else { + binding.otherCheck.isSelected = true + views.remove(binding.infoList) + binding.infoList.visibility = View.VISIBLE + } + } + binding.notice -> { + if (binding.notice.isSelected ) { + binding.notice.isSelected = false + } else { + binding.notice.isSelected = true + views.remove(binding.notiList) + binding.notiList.visibility = View.VISIBLE + } + } + } + chechboxs.forEach { it.isSelected = false } + views.forEach { it.visibility = View.GONE } + + chooseAdpater() + } } + binding.otherCheck.setOnClickListener(checkListner) + binding.recentSms.setOnClickListener(checkListner) + binding.missedCalls.setOnClickListener(checkListner) + binding.notice.setOnClickListener(checkListner) + binding.otherCheck.setOnLongClickListener { -// synchronized(rssSet) { -// val now = Date() -// var keys = arrayListOf() -// rssSet.forEach { t, u -> -// if (u.pubDate() <= beforeDay(now,3)) { -// keys.add(t) -// } -// }.apply { -// keys.forEach { rssSet.remove(it) } -// }.apply { refreshYoutube() refreshComics() refreshFeeds() refreshReddit() -// } -// } true } -// binding.summaryChoose.setOnCheckedChangeListener { group, checkedId -> -// chooseAdpater() -// } -//// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE") -//// i.putExtra("command", "list") -//// lActivity?.sendBroadcast(i) -//// BLog.LOGE("intent >>> ${i.action}") } // https://www.youtube.com/results?search_query=sds + fun showAl() { + binding.alcholKatalkT.visibility = View.VISIBLE + } + + fun hideAl() { + binding.alcholKatalkT.visibility = View.GONE + } fun chooseAdpater () { - if (binding.missedCalls.isChecked == false) binding.mainList.visibility = View.GONE else binding.mainList.visibility = View.VISIBLE - if (binding.recentSms.isChecked == false) binding.smsList.visibility = View.GONE else binding.smsList.visibility = View.VISIBLE - if (binding.otherCheck.isChecked == false) binding.infoList.visibility = View.GONE else binding.infoList.visibility = View.VISIBLE - - if (binding.missedCalls.isChecked) { + binding.mainList.visibility = View.GONE + binding.smsList.visibility = View.GONE + binding.infoList.visibility = View.GONE + binding.notiList.visibility = View.GONE + if (binding.missedCalls.isSelected) { if (recentCalls.size > 0 && isAdded && isResumed && isVisible) { try { callList.clear() @@ -337,12 +410,16 @@ internal class LauncherHome : Fragment() { Handler(Looper.getMainLooper()).post { binding.mainList.visibility = View.VISIBLE mMissedCallsAdapter.updateData(callList) + binding.recentSms.isSelected = false + binding.otherCheck.isSelected = false + binding.notice.isSelected = false } } } catch (e : Exception) { + } } - } else if(binding.recentSms.isChecked){ + } else if(binding.recentSms.isSelected){ if (smsList.size > 0 && isAdded && isResumed && isVisible) { try { smsList.sortByDescending { it.rcvDate } @@ -350,36 +427,39 @@ internal class LauncherHome : Fragment() { Handler(Looper.getMainLooper()).post { binding.smsList.visibility = View.VISIBLE mSmsLogsAdapter.updateData(smsList) + binding.missedCalls.isSelected = false + binding.otherCheck.isSelected = false + binding.notice.isSelected = false } } catch (e : Exception) { } } - } else if(binding.otherCheck.isChecked) { -// try { -// GlobalScope.launch { -// (rssSet.clone() as? HashMap)?.let { temMap -> -// synchronized(binding.infoList) { -// var tempList = arrayListOf() -// temMap.forEach { k,v -> -// if(v.pubDate() > beforeDay(Date(),3)) { -// tempList.add(v) -// } else { -// -// } -// }.apply { -// tempList.sortByDescending { it.pubDate() } -// rssList.clear() -// rssList.addAll(tempList) -// Handler(Looper.getMainLooper()).post { -// binding.infoList.visibility = View.VISIBLE -// mRssAdapter.updateData(rssList) -// } -// } -// } -// } -// } -// }catch (e : Exception){} + } else if(binding.otherCheck.isSelected) { + Handler(Looper.getMainLooper()).post { + binding.missedCalls.isSelected = false + binding.recentSms.isSelected = false + binding.notice.isSelected = false + binding.infoList.visibility = View.VISIBLE + if (lasted?.size ?: 0 > 0) { + binding.otherCheck.text = "최근 정보[${lasted!!.size}]" + mRssAdapter.updateData(lasted!!) + binding.infoList.smoothScrollToPosition(0) + } + } + } + else if(binding.notice.isSelected) { + Handler(Looper.getMainLooper()).post { + binding.missedCalls.isSelected = false + binding.recentSms.isSelected = false + binding.otherCheck.isSelected = false + binding.notiList.visibility = View.VISIBLE + if (lastedNoti?.size ?: 0 > 0) { + binding.otherCheck.text = "알림 센터[${lastedNoti!!.size}]" + mNotiAdapter.updateData(lastedNoti!!) + binding.notiList.smoothScrollToPosition(0) + } + } } } override fun onResume() { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/model/NotificationItem.kt b/app/src/main/kotlin/rasel/lunar/launcher/model/NotificationItem.kt new file mode 100644 index 0000000..4de1a38 --- /dev/null +++ b/app/src/main/kotlin/rasel/lunar/launcher/model/NotificationItem.kt @@ -0,0 +1,11 @@ +package rasel.lunar.launcher.model + +import io.realm.kotlin.types.RealmObject + +class NotificationItem : RealmObject{ + var notiId : Int = 0 + var pkgName : String? = null + var tikerMsg : String? = null + var postTime : Long = 0L + var uniq_id : String? = null +} \ No newline at end of file diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/NotificationItemAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/NotificationItemAdapter.kt new file mode 100644 index 0000000..a013022 --- /dev/null +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/NotificationItemAdapter.kt @@ -0,0 +1,142 @@ +/* + * Lunar Launcher + * Copyright (C) 2022 Md Rasel Hossain + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package rasel.lunar.launcher.todos + +import android.annotation.SuppressLint +import android.content.Context +import android.content.Intent +import android.content.pm.PackageManager +import android.graphics.drawable.Drawable +import android.net.Uri +import android.view.LayoutInflater +import android.view.ViewGroup +import androidx.recyclerview.widget.DiffUtil +import androidx.recyclerview.widget.RecyclerView +import rasel.lunar.launcher.LauncherActivity.Companion.lActivity +import rasel.lunar.launcher.databinding.ListItemWithBinding +import rasel.lunar.launcher.model.NotificationItem +import rasel.lunar.launcher.utils.BLog +import java.text.SimpleDateFormat +import java.util.Date + + +internal class NotificationItemAdapter ( + private val context: Context) : RecyclerView.Adapter() { + private var notiItems: ArrayList = arrayListOf() + override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): NotiHolder { + val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + return NotiHolder(binding) + } + + override fun getItemCount(): Int { + return notiItems.size + } + + val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd") + + @SuppressLint("SetTextI18n") + override fun onBindViewHolder(holder: NotiHolder, position: Int) { + val todo = notiItems[position] + try { + val d: Drawable = context.packageManager.getApplicationIcon(todo.pkgName!!) + holder.view.circlePreview.setImageDrawable(d) + holder.view.title.text = todo.tikerMsg + holder.view.desc.text = todo.pkgName + holder.view.date.text = dateFormat.format(Date(todo.postTime)) + } catch (e: PackageManager.NameNotFoundException) { + return + } + + } + + fun openOpera(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS) + mapIntent.setPackage("com.opera.browser") + lActivity?.startActivity(mapIntent) + } + + + fun updateData(newList: List) { + try { + BLog.LOGE("NotificationItem newList >> ${newList}") + DiffUtil.calculateDiff(NotiItemDiffUtil(notiItems, newList)).apply { + + }.dispatchUpdatesTo(this).apply { +// notifyItemRangeChanged(0,10) + } + notiItems.clear() + notiItems.addAll(newList) + }catch ( e : Exception) { + e.printStackTrace() + } + } + fun openNews(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.setPackage("com.android.chrome") + lActivity?.startActivity(mapIntent) + } + + + fun openYouTube(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.setPackage("com.google.android.youtube") + lActivity?.startActivity(mapIntent) + } + + fun openReddit(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.setPackage("com.reddit.frontpage") + lActivity?.startActivity(mapIntent) + } + + fun openDotax(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW) + mapIntent.setPackage("net.daum.android.cafe") + mapIntent.setData(gmmIntentUri) + lActivity?.startActivity(mapIntent) + } +} + +//fun dp2px(dp: Float): Float { +// val resources: Resources = this.getResources() +// val metrics = resources.displayMetrics +// val px = dp * (metrics.densityDpi.toFloat() / DisplayMetrics.DENSITY_DEFAULT) +// return px +//} + +internal class NotiHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root) +internal class NotiItemDiffUtil( + var oldList: List, var newList: List +) : DiffUtil.Callback() { + + override fun getOldListSize(): Int = oldList.size + override fun getNewListSize(): Int = newList.size + + override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else "" + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + oldList[oldItemPosition].uniq_id == if (newList.size > newItemPosition) newList[newItemPosition].uniq_id else "" +} diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt index bf47d4b..390f2ed 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/SmsLogsAdapter.kt @@ -30,6 +30,7 @@ import androidx.recyclerview.widget.RecyclerView import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.R import rasel.lunar.launcher.databinding.ListItemBinding +import rasel.lunar.launcher.databinding.SmsItemBinding import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.workers.RecentSms import java.text.SimpleDateFormat @@ -43,7 +44,7 @@ internal class SmsLogsAdapter( private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer) override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): SmsLogHolder { - val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) + val binding = SmsItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) return SmsLogHolder(binding) } @@ -57,7 +58,7 @@ internal class SmsLogsAdapter( if(todo.isMms) { var body = todo.mmsContents.get("text")?.joinToString("\n")?.replace("\n"," ") body = if (body?.length ?: 0 > 60) body?.substring(0,60).plus("...") else body - holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${body} : ${ + holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} : ${ SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format( Date( Math.max( @@ -67,8 +68,9 @@ internal class SmsLogsAdapter( ) ) } : ${todo.type}" + holder.view.contents.text = "${body}" } else { - holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} , ${todo.body} : ${ + holder.view.itemText.text = "\u25CF ${todo.person} ${todo.addr} : ${ SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format( Date( Math.max( @@ -78,7 +80,9 @@ internal class SmsLogsAdapter( ) ) } : ${todo.type}" + holder.view.contents.text = "${todo.body}" } + /* multiline texts are enabled for TodoManager */ // holder.view.itemText.isSingleLine = false /* launch edit or update dialog on item click */ @@ -140,7 +144,7 @@ internal class SmsLogsAdapter( } } -class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) +class SmsLogHolder(var view: SmsItemBinding) : RecyclerView.ViewHolder(view.root) internal class SmsDiffUtil( private val oldList: List, private val newList: List ) : DiffUtil.Callback() { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt b/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt index c3e7dc9..e562af9 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/NLService.kt @@ -4,9 +4,17 @@ import android.content.BroadcastReceiver import android.content.Context import android.content.Intent import android.content.IntentFilter +import android.content.pm.PackageManager +import android.graphics.drawable.Drawable +import android.os.Build import android.service.notification.NotificationListenerService import android.service.notification.StatusBarNotification +import androidx.annotation.RequiresApi import com.google.gson.Gson +import io.realm.kotlin.ext.query +import rasel.lunar.launcher.model.NotificationItem +import rasel.lunar.launcher.workers.WorkersDb +import java.security.AccessController.getContext class NLService : NotificationListenerService() { @@ -26,26 +34,52 @@ class NLService : NotificationListenerService() { unregisterReceiver(nlservicereciver) } + val skips = arrayListOf("com.wssyncmldm") + @RequiresApi(Build.VERSION_CODES.S) override fun onNotificationPosted(sbn: StatusBarNotification) { - BLog.LOGE( "********** onNotificationPosted") - BLog.LOGE("ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName) - val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") - i.putExtra("notification_event", "onNotificationPosted :" + sbn.packageName + "\n") - sendBroadcast(i) + BLog.LOGE( "NLService********** onNotificationPosted") + BLog.LOGE("NLServiceID :" + sbn.id + "\t${sbn.notification.tickerText}\t" + sbn.packageName) + + if (sbn.notification.actions != null && sbn.notification.actions.size > 0 && sbn.id > 0 && (sbn.packageName.contains(".") || sbn.packageName.contains("android")) && sbn.packageName.length > 0) { + NotificationItem().apply { + notiId = sbn.id + pkgName = sbn.packageName + tikerMsg = sbn.notification?.tickerText?.toString() ?: "" + postTime = sbn.postTime + uniq_id = "${sbn.id}_${sbn.packageName}" + }.apply { + if (skips.contains(pkgName)) { + + } else { + WorkersDb.insertNoti(this) + BLog.LOGE("NLService********** onNotificationPosted ${Gson().toJson(this)}") + } + } + } +// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") +// i.putExtra("notification_event", "onNotificationPosted :" + sbn.packageName + "\n") +// sendBroadcast(i) } override fun onNotificationRemoved(sbn: StatusBarNotification) { - BLog.LOGE(TAG, "********** onNOtificationRemoved") - BLog.LOGE( "ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName) - val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") - i.putExtra("notification_event", "onNotificationRemoved :" + sbn.packageName + "\n") - - sendBroadcast(i) + BLog.LOGE( "NLService********** onNOtificationRemoved") + BLog.LOGE( "NLService ID :" + sbn.id + "\t" + sbn.notification.tickerText + "\t" + sbn.packageName) + var uniq_id = "${sbn.id}_${sbn.packageName}" + try { + WorkersDb.getRealm()?.apply { + this.writeBlocking { + delete(query().query("pkgName == $0", sbn.packageName).find()) + } + } + }catch (e : Exception){e.printStackTrace()} +// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") +// i.putExtra("notification_event", "onNotificationRemoved :" + sbn.packageName + "\n") +// sendBroadcast(i) } internal inner class NLServiceReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent) { - BLog.LOGE("intent >>> ${intent.action}") + BLog.LOGE("NLService intent >>> ${intent.action}") if (intent.getStringExtra("command") == "clearall") { this@NLService.cancelAllNotifications() } else if (intent.getStringExtra("command") == "list") { @@ -54,7 +88,7 @@ class NLService : NotificationListenerService() { // sendBroadcast(i1) var i = 1 for (sbn in this@NLService.activeNotifications) { - BLog.LOGE("sbn >>> ${sbn.packageName} , ${Gson().toJson(sbn.notification.extras.keySet())}") + BLog.LOGE("NLService sbn >>> ${sbn.packageName} , ${Gson().toJson(sbn.notification.extras.keySet())}") // val i2 = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") // i2.putExtra("notification_event", i.toString() + " " + sbn.packageName + "\n") // sendBroadcast(i2) diff --git a/app/src/main/kotlin/rasel/lunar/launcher/workers/ArcaGetter.kt b/app/src/main/kotlin/rasel/lunar/launcher/workers/ArcaGetter.kt index b7a30fb..25a2282 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/workers/ArcaGetter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/workers/ArcaGetter.kt @@ -23,12 +23,12 @@ class ArcaGetter : BaseGetter { try { val urls = arrayListOf( "https://arca.live/b/singbung?mode=best", - "https://arca.live/b/headline", - "https://arca.live/b/live", +// "https://arca.live/b/headline", +// "https://arca.live/b/live", "https://arca.live/b/namuhotnow", "https://arca.live/b/society", - "https://arca.live/b/replay", - "https://arca.live/b/breaking" +// "https://arca.live/b/replay", +// "https://arca.live/b/breaking" ) urls.forEach { Jsoup.connect(it) diff --git a/app/src/main/kotlin/rasel/lunar/launcher/workers/WorkersDb.kt b/app/src/main/kotlin/rasel/lunar/launcher/workers/WorkersDb.kt index 1549c11..0dc12d9 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/workers/WorkersDb.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/workers/WorkersDb.kt @@ -5,6 +5,7 @@ import io.realm.kotlin.RealmConfiguration import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.types.BaseRealmObject import io.realm.kotlin.types.TypedRealmObject +import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.RssData import rasel.lunar.launcher.model.RssDataInterface import rasel.lunar.launcher.model.getRssData @@ -12,7 +13,7 @@ import kotlin.reflect.KClass object WorkersDb { - val clazz : Set> = setOf(RssData::class) + val clazz : Set> = setOf(RssData::class, NotificationItem::class) val schemaVersion : Long = 0L private var pRealm : Realm? = null @@ -35,7 +36,6 @@ object WorkersDb { } fun insertBulkData(rssDatas: Collection) { - rssDatas.forEach { try { getRealm().writeBlocking { @@ -45,6 +45,7 @@ object WorkersDb { } } } + fun insertBulkInteface(rssInterfaceDatas: Collection) { rssInterfaceDatas.forEach { @@ -61,4 +62,14 @@ object WorkersDb { } } } + + fun insertNoti(data: NotificationItem) { + getRealm().apply { + this.writeBlocking { + this.copyToRealm(data, UpdatePolicy.ALL) + } + } + } + + } \ No newline at end of file diff --git a/app/src/main/res/color/tabs.xml b/app/src/main/res/color/tabs.xml index 9bc9773..86f780a 100644 --- a/app/src/main/res/color/tabs.xml +++ b/app/src/main/res/color/tabs.xml @@ -1,5 +1,5 @@ - + \ No newline at end of file diff --git a/app/src/main/res/drawable/base_bg.xml b/app/src/main/res/drawable/base_bg.xml new file mode 100644 index 0000000..bc7b745 --- /dev/null +++ b/app/src/main/res/drawable/base_bg.xml @@ -0,0 +1,9 @@ + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/drawable/kakaot.png b/app/src/main/res/drawable/kakaot.png new file mode 100644 index 0000000..7c37097 Binary files /dev/null and b/app/src/main/res/drawable/kakaot.png differ diff --git a/app/src/main/res/drawable/sms_bg.xml b/app/src/main/res/drawable/sms_bg.xml new file mode 100644 index 0000000..6945c6a --- /dev/null +++ b/app/src/main/res/drawable/sms_bg.xml @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/app_drawer.xml b/app/src/main/res/layout/app_drawer.xml index ed5d1fd..0b6f503 100644 --- a/app/src/main/res/layout/app_drawer.xml +++ b/app/src/main/res/layout/app_drawer.xml @@ -14,11 +14,13 @@ app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:layout_width="0dp" + android:layout_margin="10dp" android:layout_height="0dp"> + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + @@ -190,21 +199,24 @@ android:layout_height="wrap_content" android:background="@drawable/rounded_bg" android:padding="@dimen/eight" - android:layout_marginBottom="@dimen/four" - app:layout_constraintRight_toRightOf="parent" - app:layout_constraintTop_toTopOf="parent" + android:layout_margin="5dp" + app:layout_constraintBottom_toBottomOf="@id/searchInput" + app:layout_constraintRight_toRightOf="@id/searchInput" + app:layout_constraintTop_toTopOf="@id/searchInput" app:srcCompat="@drawable/ic_refresh" /> + app:layout_constraintRight_toRightOf="parent"/> diff --git a/app/src/main/res/layout/feeds.xml b/app/src/main/res/layout/feeds.xml index d083b91..8d52552 100644 --- a/app/src/main/res/layout/feeds.xml +++ b/app/src/main/res/layout/feeds.xml @@ -11,41 +11,47 @@ android:layout_width="match_parent" android:layout_height="wrap_content" app:singleSelection="true" - android:layout_margin="@dimen/eight"> + android:layout_margin="10dp" + > + style="@style/asdda" + /> + style="@style/asdda" + /> + android:layout_margin="10dp"> - @@ -15,6 +16,7 @@ android:layout_height="match_parent"/> + + - - - - - - - - - - - - - - + + + + + + + + + + + + + + - - - - - - - - - - - - - + + + + + + + + + + + + + - - - - - - - - + + + + > + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/layout/sms_item.xml b/app/src/main/res/layout/sms_item.xml new file mode 100644 index 0000000..3b0c946 --- /dev/null +++ b/app/src/main/res/layout/sms_item.xml @@ -0,0 +1,31 @@ + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml index 033f631..bed158c 100644 --- a/app/src/main/res/values/styles.xml +++ b/app/src/main/res/values/styles.xml @@ -36,7 +36,12 @@ 1dp #000000 - +