This commit is contained in:
lunaticbum 2024-08-30 14:43:42 +09:00
parent e9dff17966
commit 2e9900201e
13 changed files with 795 additions and 618 deletions

View File

@ -62,6 +62,8 @@
android:name=".LauncherActivity" android:name=".LauncherActivity"
android:theme="@style/Theme.LunarLauncher.Starting" android:theme="@style/Theme.LunarLauncher.Starting"
android:launchMode="singleInstance" android:launchMode="singleInstance"
android:screenOrientation="portrait"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection"
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
@ -131,13 +133,13 @@
<action android:name="android.service.notification.NotificationListenerService" /> <action android:name="android.service.notification.NotificationListenerService" />
</intent-filter> </intent-filter>
</service> </service>
<receiver android:name=".home.EndCallReceiver" <receiver android:name=".LauncherActivity$EndCallReceiver"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.PHONE_STATE" /> <action android:name="android.intent.action.PHONE_STATE" />
</intent-filter> </intent-filter>
</receiver> </receiver>
<receiver android:name=".home.SMSReceiver" <receiver android:name=".LauncherActivity$SMSReceiver"
android:exported="true" android:exported="true"
android:permission="android.permission.BROADCAST_SMS"> android:permission="android.permission.BROADCAST_SMS">
<intent-filter> <intent-filter>

View File

@ -20,19 +20,31 @@ package rasel.lunar.launcher
import android.Manifest import android.Manifest
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.content.pm.PackageManager import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.graphics.Color import android.graphics.Color
import android.net.Uri import android.net.Uri
import android.net.http.SslError
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
import android.provider.CallLog import android.provider.CallLog
import android.provider.ContactsContract import android.provider.ContactsContract
import android.provider.Settings import android.provider.Settings
import android.telephony.TelephonyManager
import android.util.Log import android.util.Log
import android.view.View
import android.view.WindowInsets import android.view.WindowInsets
import android.view.WindowManager import android.view.WindowManager
import android.webkit.JavascriptInterface
import android.webkit.SslErrorHandler
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
import android.widget.Toast
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.app.AppCompatDelegate import androidx.appcompat.app.AppCompatDelegate
@ -44,8 +56,13 @@ import androidx.core.view.WindowInsetsCompat
import androidx.core.view.updatePadding import androidx.core.view.updatePadding
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.viewpager2.widget.ViewPager2 import androidx.viewpager2.widget.ViewPager2
import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager
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 org.jsoup.Jsoup
import org.jsoup.nodes.Document
import rasel.lunar.launcher.apps.AppDrawer import rasel.lunar.launcher.apps.AppDrawer
import rasel.lunar.launcher.apps.DismissCalback import rasel.lunar.launcher.apps.DismissCalback
import rasel.lunar.launcher.apps.SearchMenu import rasel.lunar.launcher.apps.SearchMenu
@ -62,8 +79,20 @@ import rasel.lunar.launcher.helpers.Constants.Companion.widgetHostId
import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId
import rasel.lunar.launcher.helpers.ViewPagerAdapter import rasel.lunar.launcher.helpers.ViewPagerAdapter
import rasel.lunar.launcher.home.LauncherHome 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.RssItem
import rasel.lunar.launcher.home.RssTagItem
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.MissedCallGetter
import rasel.lunar.launcher.utils.NewsFeedsGetter
import rasel.lunar.launcher.utils.RecentSmsGetter
import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
internal class LauncherActivity : AppCompatActivity() { internal class LauncherActivity : AppCompatActivity() {
@ -74,15 +103,69 @@ internal class LauncherActivity : AppCompatActivity() {
companion object { companion object {
val TEST_PAG = "https://jav.guru/" val TEST_PAG = "https://jav.guru/"
private var mWorkManager: WorkManager? = null
val TEST_PAG2 = "https://torrentsee246.com/topic/index?category1=129&category2=132" val TEST_PAG2 = "https://torrentsee246.com/topic/index?category1=129&category2=132"
val SMS_WORK_TAG = "RecentSmsGetter"
val CALL_WORK_TAG = "MissedCallGetter"
val FEDDS_WORK_TAG = "NewsFeedsGetter"
@JvmStatic var lActivity: LauncherActivity? = null @JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null @JvmStatic var appWidgetManager: AppWidgetManager? = null
@JvmStatic var appWidgetHost: WidgetHost? = null @JvmStatic var appWidgetHost: WidgetHost? = null
fun refreshSms() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(
SMS_WORK_TAG,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<RecentSmsGetter>(30, TimeUnit.MINUTES)
.addTag(SMS_WORK_TAG)
.build())
}, 2, TimeUnit.SECONDS)
}
fun refreshCalls() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(CALL_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(
CALL_WORK_TAG,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<MissedCallGetter>(30, TimeUnit.MINUTES)
.addTag(CALL_WORK_TAG)
.build())
}, 2, TimeUnit.SECONDS)
}
fun refreshFeeds() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(FEDDS_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(
FEDDS_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<NewsFeedsGetter>(30, TimeUnit.MINUTES)
.addTag(FEDDS_WORK_TAG)
.build())
}, 2, TimeUnit.SECONDS)
}
fun workmanager() : WorkManager? {
if (mWorkManager == null && lActivity != null) {
mWorkManager = WorkManager.getInstance(lActivity!!)
}
return mWorkManager
}
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
binding.viewPager.invalidate()
binding.viewPager.post {
binding.viewPager?.adapter?.notifyDataSetChanged()
}
} }
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
installSplashScreen() installSplashScreen()
mWorkManager = WorkManager.getInstance(this)
DynamicColors.applyToActivityIfAvailable(this) DynamicColors.applyToActivityIfAvailable(this)
settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0) settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0)
@ -105,6 +188,9 @@ internal class LauncherActivity : AppCompatActivity() {
/* handle navigation back events */ /* handle navigation back events */
handleBackPress() handleBackPress()
refreshSms()
refreshCalls()
refreshFeeds()
} }
override fun onDestroy() { override fun onDestroy() {
@ -274,5 +360,175 @@ internal class LauncherActivity : AppCompatActivity() {
SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()} SearchMenu().show(supportFragmentManager,keyword) {dismissCalback?.invoke()}
} }
class EndCallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
BLog.LOGE("EndCallReceiver >>> ${intent}")
val phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE) ?: return
if (phoneState == TelephonyManager.EXTRA_STATE_IDLE) {
refreshCalls()
}
}
}
class SMSReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
BLog.LOGE("SMSReceiver >>> ${intent}")
refreshSms()
}
}
fun doWebPare(url : String, callBack : (()->Unit)?) {
BLog.LOGE("binding.otherCheck before ThreadRun")
binding.searcher01.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
super.onPageStarted(view, url, favicon)
}
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) {
handler?.proceed()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
lastedFinishedPageUrl = url ?: ""
BLog.LOGE("binding.otherCheck searcher01 in onPageFinished ${url}")
if (url?.contains("youtube", false) == true) {
view?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
}
} else {
view?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
}
}
callBack?.invoke()
}
}
WebView.setWebContentsDebuggingEnabled(false)
binding.searcher01.apply {
this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface")
setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
try {
settings.apply {
javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
useWideViewPort = true // 화면에 맞게 페이지 확대/축소
domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
setSupportMultipleWindows(true)
javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
textZoom = 100 // system 에 의한 글꼴 변형 방지
defaultTextEncodingName = "UTF-8" // 인코딩 설정
allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
}
} catch (ignore: NoSuchMethodError) {}
loadUrl(url) // 웹페이지 연결
}
}
var maxDate : Long = Long.MIN_VALUE
var minDate : Long = Long.MAX_VALUE
val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US)
fun jGuruMain(doc: Document) {
BLog.LOGE("do default parsing")
BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy", Locale.US).format(Date())}")
val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
BLog.LOGE("doc.getElementsByClass(prev).get(0).html() ${prevUrl}")
doc.getElementsByClass("column").forEach {
var title = it.getElementsByAttribute("title").get(0).text()
var model = title.replace("[","").split("]")[0]
var pageLink = it.getElementsByClass("imgg").get(0).getElementsByAttribute("href").get(0).attr("href")
var imgg = it.getElementsByClass("imgg").get(0).getElementsByAttribute("src").get(0).attr("src")
var tags = it.getElementsByClass("tags").get(0).text()
var date = it.getElementsByClass("date").get(0).text()
var regDate = simpldateFormat.parse(date).time
minDate = Math.min(minDate,regDate)
maxDate = Math.max(maxDate,regDate)
listItem.add(RssItem(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = simpldateFormat.parse(date).time))
}.apply {
BLog.LOGE("listItem.size >>> ${listItem.size}")
if (prevUrl!=null && prevUrl.length > TEST_PAG.length && prevUrl.contains("/page/") && (maxDate - minDate) < (1000L * 60L * 60L * 24L * 3L)) {
BLog.LOGE("listItem.size >>> ${listItem.size} do next ")
BLog.LOGE("saving data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}")
binding.searcher01.postDelayed({binding.searcher01.loadUrl(prevUrl)}, 5000L)
} else {
listItem.sortByDescending { it.date }
BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}")
Toast.makeText(this@LauncherActivity,
"Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}]", Toast.LENGTH_LONG).show()
}
}
}
fun jGuruTag(doc: Document) {
listTags.clear()
doc.getElementsByTag("ul").forEach {
it.children().forEach {
if (it.tag().name.contains("li")) {
listTags.add(
RssTagItem(
tagTitle = it.getElementsByTag("a").get(0).text(),
link = it.getElementsByTag("a").get(0).attr("href")
)
)
}
}
}.apply {
listTags.sortByDescending { it.count }
Toast.makeText(this@LauncherActivity,
"Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show()
}
}
inner class MyJavaScriptInterface(val webView: WebView) {
@JavascriptInterface
fun sendValueFromHtml(result: String) {
if (lastedFinishedPageUrl.contains(TEST_PAG)) {
var htmlString = result.replace("\\u003","<")
val doc: Document = Jsoup.parse(htmlString)
if (lastedFinishedPageUrl?.contains("page") == true || lastedFinishedPageUrl?.equals(
TEST_PAG
) == true
) {
jGuruMain(doc)
} else if (lastedFinishedPageUrl?.contains("/tags/") == true) {
jGuruTag(doc)
}
} else if (lastedFinishedPageUrl?.contains("youtube") == true) {
// val doc: Document = Jsoup.parse(result)
// ytChannel(doc)
}
BLog.LOGE("binding.otherCheck after ThreadRun")
}
}
}
}

View File

@ -22,41 +22,36 @@ import android.R.attr.*
import android.app.Activity.RESULT_CANCELED import android.app.Activity.RESULT_CANCELED
import android.app.Activity.RESULT_OK import android.app.Activity.RESULT_OK
import android.appwidget.AppWidgetManager import android.appwidget.AppWidgetManager
import android.content.DialogInterface
import android.content.Intent import android.content.Intent
import android.content.SharedPreferences import android.content.SharedPreferences
import android.os.* import android.os.*
import android.view.* import android.view.*
import android.widget.EditText
import androidx.activity.result.contract.ActivityResultContracts import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.LinearLayoutCompat.LayoutParams import androidx.appcompat.widget.LinearLayoutCompat.LayoutParams
import androidx.appcompat.widget.PopupMenu import androidx.appcompat.widget.PopupMenu
import androidx.core.app.JobIntentService.enqueueWork
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import com.google.android.material.button.MaterialButtonToggleGroup import com.google.android.material.button.MaterialButtonToggleGroup
import kotlinx.coroutines.* import kotlinx.coroutines.*
import rasel.lunar.launcher.LauncherActivity.Companion.TEST_PAG
import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetHost import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetHost
import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetManager import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetManager
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.FeedsBinding import rasel.lunar.launcher.databinding.FeedsBinding
import rasel.lunar.launcher.feeds.rss.Rss
import rasel.lunar.launcher.feeds.rss.RssAdapter import rasel.lunar.launcher.feeds.rss.RssAdapter
import rasel.lunar.launcher.feeds.rss.RssService
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_RSS_URL
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_RSS_URL2
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WIDGET_HEIGHTS import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WIDGET_HEIGHTS
import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WIDGET_IDS import rasel.lunar.launcher.helpers.Constants.Companion.KEY_WIDGET_IDS
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS
import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_WIDGETS import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_WIDGETS
import rasel.lunar.launcher.helpers.Constants.Companion.RSS_ITEMS
import rasel.lunar.launcher.helpers.Constants.Companion.RSS_RECEIVER
import rasel.lunar.launcher.helpers.Constants.Companion.SEPARATOR import rasel.lunar.launcher.helpers.Constants.Companion.SEPARATOR
import rasel.lunar.launcher.helpers.Constants.Companion.requestCreateWidget import rasel.lunar.launcher.helpers.Constants.Companion.requestCreateWidget
import rasel.lunar.launcher.helpers.Constants.Companion.requestPickWidget import rasel.lunar.launcher.helpers.Constants.Companion.requestPickWidget
import rasel.lunar.launcher.helpers.Constants.Companion.rssJobId import rasel.lunar.launcher.home.LauncherHome.Companion.listItem
import rasel.lunar.launcher.helpers.UniUtils.Companion.isNetworkAvailable
import java.util.* import java.util.*
@ -64,18 +59,18 @@ internal class Feeds : Fragment() {
private lateinit var binding: FeedsBinding private lateinit var binding: FeedsBinding
private val requestCodeString = "requestCode" private val requestCodeString = "requestCode"
var mRssAdapter : RssAdapter? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FeedsBinding.inflate(inflater, container, false) binding = FeedsBinding.inflate(inflater, container, false)
mRssAdapter = RssAdapter(listItem, requireContext())
binding.feedsRss.rss.adapter = mRssAdapter
updateWidgets() updateWidgets()
return binding.root return binding.root
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
binding.feedsRss.rss.adapter = RssAdapter(arrayListOf(), requireContext())
expandCollapse() expandCollapse()
systemInfo() systemInfo()
} }
@ -88,6 +83,8 @@ internal class Feeds : Fragment() {
override fun onPause() { override fun onPause() {
super.onPause() super.onPause()
unregisterForContextMenu(binding.widgetContainer) unregisterForContextMenu(binding.widgetContainer)
if (binding.expandRss.isChecked)
binding.expandRss.isChecked = false
} }
override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) { override fun onCreateContextMenu(menu: ContextMenu, v: View, menuInfo: ContextMenu.ContextMenuInfo?) {
@ -125,65 +122,118 @@ internal class Feeds : Fragment() {
} }
} }
/* start rss service if network is active and rss url is not empty */ /* start rss service if network is active and rss url is not empty */
private fun startService() { private fun startService() {
binding.feedsRss.apply { binding.feedsRss.rss.visibility = View.GONE
if(rss.adapter != null) { binding.feedsRss.loading.visibility = View.VISIBLE
(rss.adapter as RssAdapter).items.clear() binding.feedsRss.refresh.visibility = View.VISIBLE
} val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext())
} builder.setTitle("Title")
val rssUrl = lActivity!!.getSharedPreferences(PREFS_SETTINGS, 0) val viewInflated: View = LayoutInflater.from(context)
.getString(KEY_RSS_URL, "") .inflate(R.layout.text_inpu_password, view as ViewGroup?, false)
when { val input = viewInflated.findViewById<View>(R.id.input) as EditText
isNetworkAvailable && !rssUrl.isNullOrEmpty() -> { builder.setView(viewInflated)
Intent(lActivity!!, RssService::class.java) builder.setPositiveButton(android.R.string.ok,
.putExtra(RSS_RECEIVER, resultReceiver).let { DialogInterface.OnClickListener { dialog, which ->
enqueueWork(lActivity!!, RssService::class.java, rssJobId, it) dialog.dismiss()
when(input.text.toString()) {
"jJguru","vVioPup*383v" -> {
mRssAdapter?.updateData(listItem)
binding.feedsRss.apply {
loading.visibility = View.VISIBLE
if (listItem.size > 0) {
rss.visibility = View.VISIBLE
loading.visibility = View.GONE
} else {
refresh.visibility = View.VISIBLE
rss.visibility = View.GONE
refresh.setOnClickListener {
lActivity?.doWebPare(TEST_PAG) {
if (listItem.size > 0) {
mRssAdapter?.updateData(listItem)
rss?.post {
loading.visibility = View.GONE
refresh.visibility = View.GONE
rss.visibility = View.VISIBLE
}
}
}
}
}
}
} }
} "jJTag"-> {
else -> resumeService() // lActivity?.doWebPare(TEST_PAG.plus("tags"))
}
val rssUrl2 = lActivity!!.getSharedPreferences(PREFS_SETTINGS, 0)
.getString(KEY_RSS_URL2, "")
when {
isNetworkAvailable && !rssUrl2.isNullOrEmpty() -> {
Intent(lActivity!!, RssService::class.java)
.putExtra(RSS_RECEIVER, resultReceiver).let {
enqueueWork(lActivity!!, RssService::class.java, rssJobId, it)
} }
} else -> {
else -> resumeService() binding.expandRss.isChecked = false
} }
}
})
builder.setNegativeButton(android.R.string.cancel,
DialogInterface.OnClickListener { dialog, which -> dialog.cancel() })
builder.show()
// binding.feedsRss.apply {
// if(rss.adapter != null) {
// (rss.adapter as RssAdapter).items.clear()
// }
// }
// val rssUrl = lActivity!!.getSharedPreferences(PREFS_SETTINGS, 0)
// .getString(KEY_RSS_URL, "")
// when {
// isNetworkAvailable && !rssUrl.isNullOrEmpty() -> {
//// Intent(lActivity!!, RssService::class.java)
//// .putExtra(RSS_RECEIVER, resultReceiver).let {
//// enqueueWork(lActivity!!, RssService::class.java, rssJobId, it)
//// }
// }
// else -> resumeService()
// }
// val rssUrl2 = lActivity!!.getSharedPreferences(PREFS_SETTINGS, 0)
// .getString(KEY_RSS_URL2, "")
// when {
// isNetworkAvailable && !rssUrl2.isNullOrEmpty() -> {
// Intent(lActivity!!, RssService::class.java)
// .putExtra(RSS_RECEIVER, resultReceiver).let {
// enqueueWork(lActivity!!, RssService::class.java, rssJobId, it)
// }
// }
// else -> resumeService()
// }
} }
/* retry to start rss service */ /* retry to start rss service */
private fun resumeService() { private fun resumeService() {
binding.feedsRss.apply { binding.feedsRss.apply {
rss.visibility = View.GONE rss.visibility = View.GONE
loading.visibility = View.GONE loading.visibility = View.GONE
refresh.visibility = View.VISIBLE refresh.visibility = View.VISIBLE
refresh.setOnClickListener { startService() } refresh.setOnClickListener {
mRssAdapter?.notifyDataSetChanged()
}
} }
} }
/* rss service's result receiver */ /* rss service's result receiver */
@Suppress("UNCHECKED_CAST") @Suppress("UNCHECKED_CAST")
private val resultReceiver: ResultReceiver = object : ResultReceiver(Handler(Looper.getMainLooper())) { private val resultReceiver: ResultReceiver = object : ResultReceiver(Handler(Looper.getMainLooper())) {
override fun onReceiveResult(resultCode: Int, resultData: Bundle) { // override fun onReceiveResult(resultCode: Int, resultData: Bundle) {
when (val items = resultData.getSerializable(RSS_ITEMS) as List<Rss>?) { // when (val items = resultData.getSerializable(RSS_ITEMS) as List<Rss>?) {
null -> resumeService() // null -> resumeService()
else -> { // else -> {
binding.feedsRss.apply { // binding.feedsRss.apply {
if(rss.adapter != null) { // if(rss.adapter != null) {
(rss.adapter as RssAdapter).items.addAll(items) // (rss.adapter as RssAdapter).items.addAll(items)
} // }
refresh.visibility = View.GONE // refresh.visibility = View.GONE
loading.visibility = View.GONE // loading.visibility = View.GONE
rss.visibility = View.VISIBLE // rss.visibility = View.VISIBLE
} // }
} // }
} // }
} // }
} }
private fun systemInfo() { private fun systemInfo() {

View File

@ -225,7 +225,7 @@ internal class SystemStats {
currentFreq = curFreq.toDouble() / 1000 currentFreq = curFreq.toDouble() / 1000
readerCurFreq.close() readerCurFreq.close()
currentFReq = currentFreq.toInt() currentFReq = currentFreq.toInt()
println("$currentFReq----------------------------------------------------") // println("$currentFReq----------------------------------------------------")
} catch (ex: java.lang.Exception) { } catch (ex: java.lang.Exception) {
ex.printStackTrace() ex.printStackTrace()
} }

View File

@ -23,63 +23,103 @@ import android.view.ViewGroup
import android.view.LayoutInflater import android.view.LayoutInflater
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.view.Gravity import android.view.Gravity
import androidx.core.content.ContextCompat import androidx.core.content.ContextCompat
import android.graphics.Typeface import android.graphics.Typeface
import android.util.TypedValue import android.util.TypedValue
import android.content.res.ColorStateList import android.content.res.ColorStateList
import android.net.Uri import android.net.Uri
import android.view.View
import androidx.browser.customtabs.CustomTabsIntent import androidx.browser.customtabs.CustomTabsIntent
import androidx.recyclerview.widget.DiffUtil
import com.squareup.picasso.Picasso
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.databinding.ListItemBinding import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.databinding.ListItemWithBinding
import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId
import rasel.lunar.launcher.home.RssItem
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssItemDiffUtil
import java.net.URLEncoder
import java.nio.charset.Charset
import java.text.SimpleDateFormat
import java.util.Date
internal class RssAdapter(var items: ArrayList<Rss> = arrayListOf(), private val context: Context) : internal class RssAdapter(var items: ArrayList<RssItem> = arrayListOf(), private val context: Context) :
RecyclerView.Adapter<RssAdapter.RssViewHolder>() { RecyclerView.Adapter<RssAdapter.RssViewHolder>() {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RssViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RssViewHolder {
val binding = ListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false) val binding = ListItemWithBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return RssViewHolder(binding) return RssViewHolder(binding)
} }
override fun getItemCount(): Int = items.size override fun getItemCount(): Int = items.size
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: RssViewHolder, position: Int) { override fun onBindViewHolder(holder: RssViewHolder, position: Int) {
val item = items[position]
/* customize the first item */ /* customize the first item */
if (position == 0) { // if (position == 0) {
holder.view.itemText.apply { holder.view.title.apply {
text = "\u22B6 " + items[position].title + " \u22B7" text = item.title
gravity = Gravity.CENTER }
setTextColor(ContextCompat.getColor(context, holder.view.date.text = dateFormat.format(Date(item.date))
getColorResId(context, com.google.android.material.R.attr.colorPrimary))) holder.view.desc.text = item.tags.plus("\n").plus(item.model)
setTypeface(null, Typeface.BOLD) holder.view.circlePreview.visibility = View.GONE
textSize = 20f /* reset customization for rest */
} // } else {
/* reset customization for rest */ // holder.view.desc.apply {
} else { // text = items[position].title
holder.view.itemText.apply { //// gravity = holder.gravity
text = items[position].title //// setTextColor(holder.color)
gravity = holder.gravity //// typeface = holder.typeface
setTextColor(holder.color) //// setTextSize(TypedValue.COMPLEX_UNIT_PX, holder.size)
typeface = holder.typeface // }
setTextSize(TypedValue.COMPLEX_UNIT_PX, holder.size) // }
} Picasso.get().load(item.image).into(holder.view.circlePreview)
holder.view.root.setOnClickListener {
holder.view.circlePreview.visibility = View.VISIBLE
holder.view.circlePreview.postDelayed({
holder.view.circlePreview.visibility = View.GONE
},500L)
} }
/* on click - open in browser */ /* on click - open in browser */
holder.view.itemText.setOnClickListener { holder.view.root.setOnLongClickListener {
val customTabsIntent = CustomTabsIntent.Builder().setUrlBarHidingEnabled(true).build() openOpera("https://cili.site/search?q=${URLEncoder.encode(item.model, Charset.defaultCharset().name())}")
customTabsIntent.launchUrl(context, Uri.parse(items[position].link)) openOpera(item.pageLink)
true
} }
} }
inner class RssViewHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) { fun openOpera(schemeString : String) {
/* store previous styles for resetting */ val gmmIntentUri = Uri.parse(schemeString)
var gravity: Int = view.itemText.gravity val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri)
var color: ColorStateList = view.itemText.textColors mapIntent.setPackage("com.opera.browser")
var typeface: Typeface = view.itemText.typeface lActivity?.startActivity(mapIntent)
var size: Float = view.itemText.textSize }
fun updateData(newList: List<RssItem>) {
DiffUtil.calculateDiff(RssItemDiffUtil(items, newList)).dispatchUpdatesTo(this)
}
inner class RssViewHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root) {
} }
} }
internal class RssItemDiffUtil(
private val oldList: List<RssItem>, private val newList: List<RssItem>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size
override fun getNewListSize(): Int = newList.size
override fun areItemsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].pageLink == newList[newItemPosition].pageLink
override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean =
oldList[oldItemPosition].pageLink == newList[newItemPosition].pageLink
}

View File

@ -48,6 +48,7 @@ import androidx.core.content.ContextCompat.RECEIVER_EXPORTED
import androidx.core.content.ContextCompat.registerReceiver import androidx.core.content.ContextCompat.registerReceiver
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.ExistingPeriodicWorkPolicy
import androidx.work.PeriodicWorkRequestBuilder import androidx.work.PeriodicWorkRequestBuilder
import androidx.work.WorkManager import androidx.work.WorkManager
@ -59,8 +60,12 @@ import org.jsoup.Jsoup
import org.jsoup.nodes.Document import org.jsoup.nodes.Document
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserFactory import org.xmlpull.v1.XmlPullParserFactory
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
import rasel.lunar.launcher.LauncherActivity.Companion.TEST_PAG import rasel.lunar.launcher.LauncherActivity.Companion.TEST_PAG
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.LauncherActivity.Companion.workmanager
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.LauncherHomeBinding import rasel.lunar.launcher.databinding.LauncherHomeBinding
import rasel.lunar.launcher.helpers.Constants.Companion.BOTTOM_SHEET_TAG import rasel.lunar.launcher.helpers.Constants.Companion.BOTTOM_SHEET_TAG
@ -74,8 +79,6 @@ import rasel.lunar.launcher.helpers.UniUtils.Companion.biometricPromptInfo
import rasel.lunar.launcher.helpers.UniUtils.Companion.canAuthenticate import rasel.lunar.launcher.helpers.UniUtils.Companion.canAuthenticate
import rasel.lunar.launcher.helpers.UniUtils.Companion.expandNotificationPanel import rasel.lunar.launcher.helpers.UniUtils.Companion.expandNotificationPanel
import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod import rasel.lunar.launcher.helpers.UniUtils.Companion.lockMethod
import rasel.lunar.launcher.home.LauncherHome.Companion.refreshCalls
import rasel.lunar.launcher.home.LauncherHome.Companion.refreshSms
import rasel.lunar.launcher.home.weather.WeatherExecutor import rasel.lunar.launcher.home.weather.WeatherExecutor
import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.qaccess.QuickAccess
import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.settings.SettingsActivity
@ -90,10 +93,12 @@ import rasel.lunar.launcher.todos.SmsLogsAdapter
import rasel.lunar.launcher.todos.TwoColumnBrowseResultsRenderer import rasel.lunar.launcher.todos.TwoColumnBrowseResultsRenderer
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.MissedCallGetter import rasel.lunar.launcher.utils.MissedCallGetter
import rasel.lunar.launcher.utils.NewsFeedsGetter
import rasel.lunar.launcher.utils.RecentSmsGetter import rasel.lunar.launcher.utils.RecentSmsGetter
import rasel.lunar.launcher.utils.RecentSmsLog import rasel.lunar.launcher.utils.RecentSmsLog
import rasel.lunar.launcher.utils.RssList import rasel.lunar.launcher.utils.RssList
import rasel.lunar.launcher.utils.SimpleFingerGestures import rasel.lunar.launcher.utils.SimpleFingerGestures
import rasel.lunar.launcher.utils.beforeDay
import java.io.ByteArrayInputStream import java.io.ByteArrayInputStream
import java.io.InputStream import java.io.InputStream
import java.nio.charset.Charset import java.nio.charset.Charset
@ -113,10 +118,8 @@ internal class LauncherHome : Fragment() {
private lateinit var batteryReceiver: BatteryReceiver private lateinit var batteryReceiver: BatteryReceiver
private var shouldResume = true private var shouldResume = true
companion object { companion object {
val SMS_WORK_TAG = "RecentSmsGetter"
val CALL_WORK_TAG = "MissedCallGetter"
var lastedFinishedPageUrl : String = "" var lastedFinishedPageUrl : String = ""
private var mWorkManager: WorkManager? = null
var missedCalls = hashMapOf<String, MissedCall>() var missedCalls = hashMapOf<String, MissedCall>()
var callList = arrayListOf<MissedCall>() var callList = arrayListOf<MissedCall>()
@ -124,44 +127,44 @@ internal class LauncherHome : Fragment() {
var listTags = arrayListOf<RssTagItem>() var listTags = arrayListOf<RssTagItem>()
var listItem = arrayListOf<RssItem>() var listItem = arrayListOf<RssItem>()
var rssSet = hashMapOf<String,RssDataItem>() var rssSet = hashMapOf<String,RssDataItem>()
var rssUrls = arrayListOf<String>()
var feddsUrls = arrayListOf<String>()
var rssList = arrayListOf<RssDataItem>() var rssList = arrayListOf<RssDataItem>()
fun refreshSms() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG)
mWorkManager?.enqueue(PeriodicWorkRequestBuilder<RecentSmsGetter>(30, TimeUnit.MINUTES).addTag(SMS_WORK_TAG).build())
}, 2, TimeUnit.SECONDS)
}
fun refreshCalls() {
Executors.newSingleThreadScheduledExecutor().schedule({
mWorkManager?.cancelAllWorkByTag(CALL_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(CALL_WORK_TAG,ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,PeriodicWorkRequestBuilder<MissedCallGetter>(30, TimeUnit.MINUTES).addTag("MissedCallGetter").build())
}, 2, TimeUnit.SECONDS)
}
} }
private var nReceiver: NotificationReceiver? = null private var nReceiver: NotificationReceiver? = null
class NotificationReceiver : BroadcastReceiver() { class NotificationReceiver : BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent) { override fun onReceive(context: Context?, intent: Intent) {
// val temp = """ BLog.LOGE("NotificationReceiver >>>> ${intent.extras?.keySet()}")
// ${intent.getStringExtra("notification_event")}
//// ${txtView.getText()}
// """.trimIndent()
// txtView.setText(temp)
} }
} }
fun workmanager() : WorkManager? {
if (mWorkManager == null) { val UPDATE_DELAY = 500L
mWorkManager = WorkManager.getInstance(requireContext()) val commandHandler = Handler(Looper.getMainLooper())
}
return mWorkManager val smsUpdate = Runnable {
} BLog.LOGE("observeForever smsList.size >>> ${smsList.size}")
binding.recentSms.text = "최근 문자 [${smsList.size}]"
chooseAdpater()
}
val callUpdate = Runnable {
binding.missedCalls.text = "최근 통화 [${missedCalls.size}]"
BLog.LOGE("observeForever missedCalls.size >>> ${missedCalls.size}")
chooseAdpater()
}
val infoUpdate = Runnable {
binding.otherCheck.text = "최근 정보[${rssSet.size}]"
BLog.LOGE("observeForever rssSet.size >>> ${rssSet.size}")
chooseAdpater()
}
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
mWorkManager = WorkManager.getInstance(requireContext())
binding = LauncherHomeBinding.inflate(inflater, container, false) binding = LauncherHomeBinding.inflate(inflater, container, false)
fragManager = lActivity!!.supportFragmentManager fragManager = lActivity!!.supportFragmentManager
settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0) settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0)
@ -169,35 +172,45 @@ internal class LauncherHome : Fragment() {
mMissedCallsAdapter = MissedCallsAdapter(callList, requireContext()) mMissedCallsAdapter = MissedCallsAdapter(callList, requireContext())
mSmsLogsAdapter = SmsLogsAdapter(smsList, requireContext()) mSmsLogsAdapter = SmsLogsAdapter(smsList, requireContext())
mRssAdapter = RssItemAdapter(rssList, requireContext()) mRssAdapter = RssItemAdapter(rssList, requireContext())
binding.favAppsGroup.visibility = View.GONE binding.mainList.adapter = mMissedCallsAdapter
binding.mainList.layoutManager = LinearLayoutManagerWrapper(requireContext()) binding.smsList.adapter = mSmsLogsAdapter
binding.infoList.adapter = mRssAdapter
binding.missedCalls.isChecked = true
binding.smsList.visibility = View.GONE
binding.infoList.visibility = View.GONE
binding.favAppsGroup.visibility = View.GONE
binding.mainList.layoutManager = LinearLayoutManager(requireContext())
binding.smsList.layoutManager = LinearLayoutManager(requireContext())
binding.infoList.layoutManager = LinearLayoutManager(requireContext())
workmanager()?.getWorkInfosByTagLiveData(SMS_WORK_TAG)?.observeForever { workmanager()?.getWorkInfosByTagLiveData(SMS_WORK_TAG)?.observeForever {
binding.recentSms.text = "최근 문자 [${smsList.size}]" commandHandler.removeCallbacks(smsUpdate)
if (binding.recentSms.isChecked) chooseAdpater() commandHandler.postDelayed(smsUpdate,UPDATE_DELAY)
else if (binding.missedCalls.isChecked && missedCalls.size == 0) {
binding.recentSms.isChecked = true
chooseAdpater()
}
BLog.LOGE("smsList.size >>> ${smsList.size}")
it.clear() it.clear()
} }
workmanager()?.getWorkInfosByTagLiveData(CALL_WORK_TAG)?.observeForever { workmanager()?.getWorkInfosByTagLiveData(CALL_WORK_TAG)?.observeForever {
binding.missedCalls.text = "최근 통화 [${missedCalls.size}]" commandHandler.removeCallbacks(callUpdate)
if (binding.recentSms.isChecked && missedCalls.size > 0) binding.missedCalls.isChecked = true commandHandler.postDelayed(callUpdate,UPDATE_DELAY)
if (binding.missedCalls.isChecked) chooseAdpater()
it.clear() it.clear()
} }
workmanager()?.getWorkInfosByTagLiveData(FEDDS_WORK_TAG)?.observeForever {
commandHandler.removeCallbacks(infoUpdate)
commandHandler.postDelayed(infoUpdate,UPDATE_DELAY)
it.clear()
}
nReceiver = NotificationReceiver() nReceiver = NotificationReceiver()
val filter = IntentFilter() val filter = IntentFilter()
// filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") // filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE")
registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED) registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED)
BLog.LOGE("onCreateView()") BLog.LOGE("onCreateView()")
refreshSms()
refreshCalls()
return binding.root return binding.root
} }
@ -238,178 +251,42 @@ internal class LauncherHome : Fragment() {
chooseAdpater() chooseAdpater()
} }
binding.otherCheck.setOnClickListener { binding.otherCheck.setOnClickListener {
if(rssSet.size < 10) { binding.otherCheck.isChecked = true
rssSet.clear() chooseAdpater()
feddsUrls.clear()
feddsUrls.addAll(RssList.newsFeeds)
rssUrls.clear()
rssUrls.addAll(RssList.youtubeUrls)
binding.otherCheck.isChecked = true
rssList.clear()
rssList.add(object : RssDataItem {
override fun title(): String {
return "waiting for data"
}
override fun thumbnailUrl(): String {
return ""
}
override fun originPage(): String {
return "waiting for data"
}
override fun description(): String {
return "waiting for data"
}
override fun pubDate(): Long {
return 0L
}
override fun category(): RssDataType {
return RssDataType.NO_DATA
}
})
doWebPare(RssList.youtubeUrls.removeFirst())
getFeeds(feddsUrls.removeFirst())
}
binding.mainList.adapter = mRssAdapter
} }
binding.otherCheck.setOnLongClickListener { binding.otherCheck.setOnLongClickListener {
listItem.clear() listItem.clear()
doWebPare(TEST_PAG) lActivity?.doWebPare(TEST_PAG, null)
true true
} }
binding.summaryChoose.setOnCheckedChangeListener { group, checkedId -> // binding.summaryChoose.setOnCheckedChangeListener { group, checkedId ->
chooseAdpater() // chooseAdpater()
} // }
// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE") //// val i = Intent("com.kpbird.nlsexample.NOTIFICATION_LISTENER_SERVICE_EXAMPLE")
// i.putExtra("command", "list") //// i.putExtra("command", "list")
// lActivity?.sendBroadcast(i) //// lActivity?.sendBroadcast(i)
// BLog.LOGE("intent >>> ${i.action}") //// BLog.LOGE("intent >>> ${i.action}")
} }
fun getFeeds(url : String) {
Executors.newSingleThreadScheduledExecutor().schedule( {
RssFeedsParser.getFeeds(url).apply {
}.filter { it.pubDate() >= (System.currentTimeMillis() - 1000L * 60L * 60L * 24 * 3)
}.forEach {
BLog.LOGE("getFeeds it >> ${Gson().toJson(it)}")
rssSet.put(it.originPage(), it)
}.apply {
if (feddsUrls.size > 0) {
getFeeds(feddsUrls.removeFirst())
}
if(rssUrls.size < 1 && feddsUrls.size < 1) {
rssList.clear()
rssSet.forEach { t, u ->
rssList.add(u)
}
rssList.sortByDescending { it.pubDate() }
Handler(Looper.getMainLooper()).post {
mRssAdapter.updateData(rssList)
}
}
}
},1,TimeUnit.SECONDS)
}
fun doWebPare(url : String) {
if (url.contains("youtube")) {
Executors.newSingleThreadScheduledExecutor().schedule( {
Jsoup.connect(url).get()?.apply {
ytChannel(this)
}
},1,TimeUnit.SECONDS)
return
}
BLog.LOGE("binding.otherCheck before ThreadRun")
binding.searcher01.webViewClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
BLog.LOGE("binding.otherCheck searcher01 in onPageStarted ${url}")
super.onPageStarted(view, url, favicon)
}
override fun onReceivedSslError(
view: WebView?,
handler: SslErrorHandler?,
error: SslError?
) {
handler?.proceed()
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
lastedFinishedPageUrl = url ?: ""
BLog.LOGE("binding.otherCheck searcher01 in onPageFinished ${url}")
if (url?.contains("youtube", false) == true) {
view?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
}
} else {
view?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
}
}
}
}
WebView.setWebContentsDebuggingEnabled(false)
binding.searcher01.apply {
this.addJavascriptInterface(MyJavaScriptInterface(this),"MyJavaScriptInterface")
setBackgroundColor(Color.WHITE) // 백그라운드 색상 설정
setLayerType(View.LAYER_TYPE_SOFTWARE, null) // 랜더링 이슈 해결
try {
settings.apply {
javaScriptEnabled = true // 자바스크립트 사용 가능하도록 설정
loadWithOverviewMode = true // 전체 웹페이지를 화면에 맞게 로드
useWideViewPort = true // 화면에 맞게 페이지 확대/축소
domStorageEnabled = true // DOM 저장소 사용 가능하도록 설정
setSupportMultipleWindows(true)
javaScriptCanOpenWindowsAutomatically = true // 팝업창 차단 해제
cacheMode = WebSettings.LOAD_CACHE_ELSE_NETWORK
textZoom = 100 // system 에 의한 글꼴 변형 방지
defaultTextEncodingName = "UTF-8" // 인코딩 설정
allowContentAccess = true // 웹뷰를 통해 content url에 접근할지 여부
layoutAlgorithm = WebSettings.LayoutAlgorithm.TEXT_AUTOSIZING // 웹페이지의 레이아웃을 화면에 맞게 자동으로 조정
}
} catch (ignore: NoSuchMethodError) {}
loadUrl(url) // 웹페이지 연결
}
}
fun chooseAdpater () { fun chooseAdpater () {
binding.mainList.visibility = View.GONE
binding.smsList.visibility = View.GONE
binding.infoList.visibility = View.GONE
if (binding.missedCalls.isChecked) { if (binding.missedCalls.isChecked) {
if (missedCalls.size > 0 && isAdded && isResumed && isVisible) { if (missedCalls.size > 0 && isAdded && isResumed && isVisible) {
try { try {
callList.clear() callList.clear()
if(binding.mainList.adapter is MissedCallsAdapter){
}else {
binding.mainList.adapter = mMissedCallsAdapter
}
missedCalls.forEach { t, u -> missedCalls.forEach { t, u ->
callList.add(u) callList.add(u)
}.apply { }.apply {
callList.sortByDescending { it.date } callList.sortByDescending { it.date }
Handler(Looper.getMainLooper()).post {mMissedCallsAdapter.updateData(callList)} Handler(Looper.getMainLooper()).post {
mMissedCallsAdapter.updateData(callList)
binding.mainList.visibility = View.VISIBLE
}
} }
} catch (e : Exception) { } catch (e : Exception) {
} }
@ -417,17 +294,32 @@ internal class LauncherHome : Fragment() {
} else if(binding.recentSms.isChecked){ } else if(binding.recentSms.isChecked){
if (smsList.size > 0 && isAdded && isResumed && isVisible) { if (smsList.size > 0 && isAdded && isResumed && isVisible) {
try { try {
if(binding.mainList.adapter is SmsLogsAdapter){
}else {
binding.mainList.adapter = mSmsLogsAdapter
}
smsList.sortByDescending { it.rcvDate } smsList.sortByDescending { it.rcvDate }
Handler(Looper.getMainLooper()).post {mSmsLogsAdapter.updateData(smsList)} binding.smsList.visibility = View.VISIBLE
Handler(Looper.getMainLooper()).post {
mSmsLogsAdapter.updateData(smsList)
binding.smsList.visibility = View.VISIBLE
}
} catch (e : Exception) { } catch (e : Exception) {
} }
} }
} else if(binding.otherCheck.isChecked) {
try {
rssList.clear()
rssSet.forEach { k,v ->
if(v.pubDate() > beforeDay(Date(),3)) {
rssList.add(v)
} else {
rssSet.remove(k,v)
}
}.apply {
Handler(Looper.getMainLooper()).post {
mRssAdapter.updateData(rssList)
binding.infoList.visibility = View.VISIBLE
}
}
}catch (e : Exception){}
} }
} }
override fun onResume() { override fun onResume() {
@ -448,7 +340,6 @@ internal class LauncherHome : Fragment() {
} }
/* show weather */ /* show weather */
WeatherExecutor(settingsPrefs).generateWeatherString(binding.weather) WeatherExecutor(settingsPrefs).generateWeatherString(binding.weather)
chooseAdpater()
} }
} }
@ -599,90 +490,7 @@ internal class LauncherHome : Fragment() {
} }
} }
var maxDate : Long = Long.MIN_VALUE
var minDate : Long = Long.MAX_VALUE
val simpldateFormat = SimpleDateFormat("d MMM, yy",Locale.US)
fun jGuruMain(doc:Document) {
BLog.LOGE("do default parsing")
BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy",Locale.US).format(Date())}")
val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
BLog.LOGE("doc.getElementsByClass(prev).get(0).html() ${prevUrl}")
doc.getElementsByClass("column").forEach {
var title = it.getElementsByAttribute("title").get(0).text()
var model = title.replace("[","").split("]")[0]
var pageLink = it.getElementsByClass("imgg").get(0).getElementsByAttribute("href").get(0).attr("href")
var imgg = it.getElementsByClass("imgg").get(0).getElementsByAttribute("src").get(0).attr("src")
var tags = it.getElementsByClass("tags").get(0).text()
var date = it.getElementsByClass("date").get(0).text()
var regDate = simpldateFormat.parse(date).time
minDate = Math.min(minDate,regDate)
maxDate = Math.max(maxDate,regDate)
listItem.add(RssItem(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = simpldateFormat.parse(date).time))
}.apply {
BLog.LOGE("listItem.size >>> ${listItem.size}")
if (prevUrl!=null && prevUrl.length > TEST_PAG.length && prevUrl.contains("/page/") && (maxDate - minDate) < (1000L * 60L * 60L * 24L * 3L)) {
BLog.LOGE("listItem.size >>> ${listItem.size} do next ")
BLog.LOGE("saving data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}")
binding.searcher01.postDelayed({binding.searcher01.loadUrl(prevUrl)}, 5000L)
} else {
listItem.sortByDescending { it.date }
BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}")
Toast.makeText(requireContext(),
"Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}]", Toast.LENGTH_LONG).show()
}
}
}
fun jGuruTag(doc: Document) {
listTags.clear()
doc.getElementsByTag("ul").forEach {
it.children().forEach {
if (it.tag().name.contains("li")) {
listTags.add(
RssTagItem(
tagTitle = it.getElementsByTag("a").get(0).text(),
link = it.getElementsByTag("a").get(0).attr("href")
)
)
}
}
}.apply {
listTags.sortByDescending { it.count }
Toast.makeText(requireContext(),
"Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show()
}
}
inner class MyJavaScriptInterface(val webView: WebView) {
@JavascriptInterface
fun sendValueFromHtml(result: String) {
if (lastedFinishedPageUrl.contains(TEST_PAG)) {
var htmlString = result.replace("\\u003","<")
val doc: Document = Jsoup.parse(htmlString)
if (lastedFinishedPageUrl?.contains("page") == true || lastedFinishedPageUrl?.equals(
TEST_PAG
) == true
) {
jGuruMain(doc)
} else if (lastedFinishedPageUrl?.contains("/tags/") == true) {
jGuruTag(doc)
}
} else if (lastedFinishedPageUrl?.contains("youtube") == true) {
val doc: Document = Jsoup.parse(result)
ytChannel(doc)
}
BLog.LOGE("binding.otherCheck after ThreadRun")
}
}
fun jsonObjLog(pkey : String ,key : String, jsonObject: JSONObject) { fun jsonObjLog(pkey : String ,key : String, jsonObject: JSONObject) {
if (jsonObject?.has(key) == true && jsonObject?.get(key) is String) { if (jsonObject?.has(key) == true && jsonObject?.get(key) is String) {
@ -717,91 +525,7 @@ internal class LauncherHome : Fragment() {
fun ytChannel(doc: Document) {
BLog.LOGE("ytChannel >>>>> doc${doc.title()}")
try {
doc.getElementsByTag("script").forEach {
// BLog.LOGE("ytChannel >>>>> doc ${doc.title()} find script ${it}")
if(it.html().contains("var ytInitialData", false)) {/**/
BLog.LOGE("ytChannel >>>>> doc${doc.title()} find ytInitialData ${it} ")
var ytInitialData = it.html().split("var ytInitialData = ")[1].split("</script>")[0].toString()
// ytInitialData = ytInitialData.replace("\\x22", "\"")
// .replace("\\x7b", "{")
// .replace("\\x7d", "}")
// .replace("\\x5b", "[")
// .replace("\\x5d", "]")
BLog.LOGE("ytChannel >>>>> doc${doc.title()} find ytInitialData ${ytInitialData} ")
var tempJSONObject : JSONObject? = null
JSONObject(ytInitialData).apply{
tempJSONObject = this
val root = Gson().fromJson(tempJSONObject.toString(), Root::class.java)
BLog.LOGE("ytChannel >>>>> doc root ${Gson().toJson(root)} apply ")
(if (root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.size ?: 0 > 0) {
BLog.LOGE("ytChannel >>>>> doc singleColumnBrowseResultsRenderer apply ")
root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
BLog.LOGE("ytChannel >>>>> doc sectionListRenderer?.contents ${Gson().toJson(it)} apply ")
it.shelfRenderer?.content?.verticalListRenderer?.items?.forEach {
BLog.LOGE("ytChannel >>>>> doc verticalListRenderer?.items ${Gson().toJson(it)} apply ")
(it.compactVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() >= (System.currentTimeMillis() - 1000L * 60L * 60L * 24 * 3)) {
rssSet.put(it.originPage(), it)
BLog.LOGE("ytChannel >>>>> doc RssDataItem ${Gson().toJson(it)} apply ")
}
}
}
}
}
} else {
BLog.LOGE("ytChannel >>>>> doc twoColumnBrowseResultsRenderer apply ")
root?.contents?.twoColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
BLog.LOGE("ytChannel >>>>> doc sectionListRenderer?.contents ${Gson().toJson(it)} apply ")
it.itemSectionRenderer?.contents?.forEach {
BLog.LOGE("ytChannel >>>>> doc itemSectionRenderer?.items ${Gson().toJson(it)} apply ")
it.shelfRenderer?.content?.horizontalListRenderer?.items?.forEach {
(it.gridVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() >= (System.currentTimeMillis() - 1000L * 60L * 60L * 24 * 3)) {
rssSet.put(it.originPage(), it)
BLog.LOGE("ytChannel >>>>> doc RssDataItem ${Gson().toJson(it)} apply ")
}
}
}
}
}
}
}).apply {
BLog.LOGE("ytChannel >>>>> doc${doc.title()} apply ")
// rssList.clear()
// rssSet.forEach { k,v ->
// rssList.add(element = v)
// }.apply {
if(rssUrls.size > 0) {
try {
val dddd = rssUrls.removeFirst()
doWebPare(dddd)
} catch (e : Exception) { }
}
rssList.clear()
rssSet.forEach { k,v ->
rssList.add(element = v)
}
if(rssUrls.size < 1 && feddsUrls.size < 1) {
rssList.sortByDescending { it.pubDate() }
Handler(Looper.getMainLooper()).post {
mRssAdapter.updateData(rssList)
}
}
}
}
}
}
} catch(e: Exception) {
}
}
@ -907,21 +631,6 @@ class MissedCall {
} }
class EndCallReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
BLog.LOGE("EndCallReceiver >>> ${intent}")
val phoneState = intent.getStringExtra(TelephonyManager.EXTRA_STATE) ?: return
if (phoneState == TelephonyManager.EXTRA_STATE_IDLE) {
refreshCalls()
}
}
}
class SMSReceiver : BroadcastReceiver() {
override fun onReceive(context: Context, intent: Intent) {
BLog.LOGE("SMSReceiver >>> ${intent}")
refreshSms()
}
}
class RssTagItem { class RssTagItem {

View File

@ -25,6 +25,7 @@ import android.content.Context
import android.content.Intent import android.content.Intent
import android.net.Uri import android.net.Uri
import android.text.Html import android.text.Html
import android.view.Gravity
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
@ -61,24 +62,47 @@ internal class RssItemAdapter (
} }
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd") val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
@SuppressLint("SetTextI18n") @SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: RssTag, position: Int) { override fun onBindViewHolder(holder: RssTag, position: Int) {
val todo = smsList[position] val todo = smsList[position]
BLog.LOGE("rssitem >>>> ${Gson().toJson(todo)}")
holder.view.title.text = "${todo.title()}" holder.view.title.text = "${todo.title()}"
holder.view.desc.text = Html.fromHtml("${todo.description()}")
holder.view.date.text = "${dateFormat.format(Date(todo.pubDate()))}" holder.view.date.text = "${dateFormat.format(Date(todo.pubDate()))}"
if(todo.thumbnailUrl()?.length ?: 0 > 6) { holder.view.desc.visibility = View.GONE
Picasso.get().load(todo.thumbnailUrl().toUri()).into(holder.view.circlePreview) holder.view.circlePreview.visibility = View.GONE
holder.view.circlePreview.visibility = View.VISIBLE when(todo.category()) {
} else { RssDataType.YOUTUBE -> {
holder.view.circlePreview.visibility = View.GONE if(todo.thumbnailUrl()?.length ?: 0 > 6) {
Picasso.get().load(todo.thumbnailUrl().toUri()).into(holder.view.circlePreview)
holder.view.circlePreview.visibility = View.VISIBLE
}
holder.view.title.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.RIGHT)
holder.view.desc.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.RIGHT)
holder.view.date.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.RIGHT)
holder.view.desc.visibility = View.VISIBLE
holder.view.desc.text = if(todo.description().contains("게시자")) todo.description().split("게시자")[0] else todo.description()
holder.view.root.setOnClickListener { openYouTube(todo.originPage()) }
}
RssDataType.NewsFeed -> {
holder.view.title.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.LEFT)
holder.view.desc.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.LEFT)
holder.view.date.gravity = Gravity.CENTER_VERTICAL.plus(Gravity.RIGHT)
holder.view.root.setOnClickListener { openNews(todo.originPage()) }
}
RssDataType.NO_DATA -> {}
} }
holder.view.root.setOnLongClickListener { holder.view.root.setOnLongClickListener {
val clipBoard = when(todo.category()) {
lActivity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager RssDataType.YOUTUBE -> {}
clipBoard.setPrimaryClip(ClipData.newPlainText("", todo.thumbnailUrl())) RssDataType.NewsFeed -> {
openNews(todo.originPage())
}
RssDataType.NO_DATA -> {}
}
// val clipBoard =
// lActivity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
// clipBoard.setPrimaryClip(ClipData.newPlainText("", todo.thumbnailUrl()))
true true
} }
@ -87,7 +111,20 @@ internal class RssItemAdapter (
fun updateData(newList: List<RssDataItem>) { fun updateData(newList: List<RssDataItem>) {
DiffUtil.calculateDiff(RssItemDiffUtil(smsList, newList)).dispatchUpdatesTo(this) DiffUtil.calculateDiff(RssItemDiffUtil(smsList, newList)).dispatchUpdatesTo(this)
} }
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)
}
} }
class RssTag(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root) class RssTag(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root)

View File

@ -503,13 +503,13 @@ class GridChannelRenderer {
} }
class GridVideoRenderer : VideoRenderer() { class GridVideoRenderer : VideoRenderer() {
// var videoId: String? = null // var videoId: String? = null
// var thumbnail: Thumbnail? = null // var thumbnail: Thumbnail? = null
// var title: Title? = null // var title: Title? = null
// var publishedTimeText: PublishedTimeText? = null // var publishedTimeText: PublishedTimeText? = null
// var navigationEndpoint: NavigationEndpoint? = null // var navigationEndpoint: NavigationEndpoint? = null
var badges: ArrayList<Badge>? = null var badges: ArrayList<Badge>? = null
// var ownerBadges: ArrayList<OwnerBadge>? = null // var ownerBadges: ArrayList<OwnerBadge>? = null
// var trackingParams: String? = null // var trackingParams: String? = null
// var menu: Menu? = null // var menu: Menu? = null
// var thumbnailOverlays: ArrayList<ThumbnailOverlay>? = null // var thumbnailOverlays: ArrayList<ThumbnailOverlay>? = null
@ -1117,11 +1117,11 @@ class RichThumbnail {
} }
class Root { class Root {
// var responseContext: ResponseContext? = null // var responseContext: ResponseContext? = null
var contents: Content14? = null var contents: Content14? = null
var header: Header? = null var header: Header? = null
var metadata: Metadata? = null var metadata: Metadata? = null
// var trackingParams: String? = null // var trackingParams: String? = null
// var topbar: Topbar? = null // var topbar: Topbar? = null
var microformat: Microformat? = null var microformat: Microformat? = null
// var onResponseReceivedActions: ArrayList<OnResponseReceivedAction>? = null // var onResponseReceivedActions: ArrayList<OnResponseReceivedAction>? = null
@ -1584,7 +1584,7 @@ open class VideoRenderer : RssDataItem {
var thumbnailOverlays: ArrayList<ThumbnailOverlay>? = null var thumbnailOverlays: ArrayList<ThumbnailOverlay>? = null
var avatar: Avatar? = null var avatar: Avatar? = null
override fun title(): String { override fun title(): String {
return shortBylineText?.runs?.get(0)?.text ?: title?.runs?.get(0)?.text ?: title?.accessibility?.label ?: "" return shortBylineText?.runs?.get(0)?.text ?: title?.runs?.get(0)?.text ?: title?.accessibility?.label ?: title?.accessibility?.accessibilityData?.label ?: ""
} }
override fun thumbnailUrl(): String { override fun thumbnailUrl(): String {
@ -1602,43 +1602,40 @@ open class VideoRenderer : RssDataItem {
} }
override fun description(): String { override fun description(): String {
return "" return title?.accessibility?.accessibilityData?.label ?: ""
} }
override fun pubDate(): Long { override fun pubDate(): Long {
var date = Date() var date = Date()
var dateTime = date.time var dateTime = date.time
var before = 0 var before = 0
try { try {
var targetDate = publishedTimeText?.simpleText ?: publishedTimeText?.runs?.first()?.text ?: "" var targetDate = publishedTimeText?.simpleText ?: publishedTimeText?.runs?.first()?.text ?: ""
if (targetDate?.length ?: 0 > 1) { if (targetDate?.length ?: 0 > 1) {
BLog.LOGE("targetDate >>>> ${targetDate}") var dateDesc = targetDate
var dateDesc = targetDate dateDesc = dateDesc!!.split("")[0].trim()
// dateDesc = dateDesc!!.replace("스트리밍 시간:","").trim() val dayString = dateDesc.replace("[^0-9]".toRegex(), "")
dateDesc = dateDesc!!.split("")[0].trim() before = dayString.toInt()
val dayString = dateDesc.replace("[^0-9]".toRegex(), "") if (dateDesc.contains("")) {
before = dayString.toInt() before = 365 * before
BLog.LOGE("targetDate >>>> ${before}") dateTime = beforeDay(date, before)
if (dateDesc.contains("")) { } else if (dateDesc.contains("")) {
before = 365 * before before = 30 * before
dateTime = beforeDay(date, before) dateTime = beforeDay(date, before)
} else if (dateDesc.contains("")) { } else if (dateDesc.contains("")) {
before = 30 * before before = 7 * before
dateTime = beforeDay(date, before) dateTime = beforeDay(date, before)
} else if (dateDesc.contains("")) { } else if (dateDesc.contains("")) {
before = 7 * before dateTime = beforeDay(date, before)
dateTime = beforeDay(date, before) } else if (dateDesc.contains("시간")) {
} else if (dateDesc.contains("")) { dateTime = dateTime.minus(before.times(1000L * 60L * 60L))
dateTime = beforeDay(date, before) } else if (dateDesc.contains("")) {
} else if (dateDesc.contains("시간")) { dateTime = dateTime.minus(before.times(1000L * 60L))
dateTime = dateTime.minus(before.times(1000L * 60L * 60L))
} else if (dateDesc.contains("")) {
dateTime = dateTime.minus(before.times(1000L * 60L))
}
} }
}catch (e : Exception) {
} }
}catch (e : Exception) {
}
return dateTime return dateTime
@ -1739,13 +1736,13 @@ class YtConfigData {
} }
class YoutubeData { class YoutubeData {
// var responseContext: ResponseContext? = null // var responseContext: ResponseContext? = null
var contents: JSONObject? = null var contents: JSONObject? = null
var header: JSONObject? = null var header: JSONObject? = null
var metadata: JSONObject? = null var metadata: JSONObject? = null
// var trackingParams: String? = null // var trackingParams: String? = null
// var topbar: Topbar? = null // var topbar: Topbar? = null
var microformat: JSONObject? = null var microformat: JSONObject? = null
// var onResponseReceivedActions: ArrayList<OnResponseReceivedAction>? = null // var onResponseReceivedActions: ArrayList<OnResponseReceivedAction>? = null
// var frameworkUpdates: FrameworkUpdates? = null // var frameworkUpdates: FrameworkUpdates? = null

View File

@ -7,14 +7,24 @@ import android.database.Cursor
import android.net.Uri import android.net.Uri
import android.provider.CallLog import android.provider.CallLog
import android.provider.ContactsContract.PhoneLookup import android.provider.ContactsContract.PhoneLookup
import android.provider.Settings.Global
import android.provider.Telephony import android.provider.Telephony
import androidx.work.Worker import androidx.work.Worker
import androidx.work.WorkerParameters import androidx.work.WorkerParameters
import com.google.gson.Gson import com.google.gson.Gson
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.async
import org.json.JSONObject
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.home.LauncherHome.Companion.missedCalls import rasel.lunar.launcher.home.LauncherHome.Companion.missedCalls
import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import rasel.lunar.launcher.home.LauncherHome.Companion.smsList import rasel.lunar.launcher.home.LauncherHome.Companion.smsList
import rasel.lunar.launcher.home.MissedCall import rasel.lunar.launcher.home.MissedCall
import rasel.lunar.launcher.todos.Root
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssFeedsParser
import java.io.BufferedReader import java.io.BufferedReader
import java.io.IOException import java.io.IOException
import java.io.InputStream import java.io.InputStream
@ -22,6 +32,8 @@ import java.io.InputStreamReader
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
class MissedCallGetter : Worker { class MissedCallGetter : Worker {
@ -468,83 +480,101 @@ fun getContactId(contentResolver: ContentResolver, phoneNumber: String?): String
class NewsFeedsGetter : Worker { class NewsFeedsGetter : Worker {
var feddsUrls = arrayListOf<String>()
var rssUrls = arrayListOf<String>()
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) { constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
} }
@SuppressLint("RestrictedApi") @SuppressLint("RestrictedApi")
override fun doWork(): Result { override fun doWork(): Result {
BLog.LOGE("phNumber == onStart") feddsUrls.clear()
var dateParam = beforeDay(Date(),3).toString() feddsUrls.addAll(RssList.newsFeeds)
val managedCursor = lActivity?.contentResolver?.query( rssUrls.clear()
Telephony.Sms.CONTENT_URI, arrayOf( rssUrls.addAll(RssList.youtubeUrls)
Telephony.Sms.THREAD_ID, var limitDateTime = beforeDay(Date(),3)
Telephony.Sms.ADDRESS, BLog.LOGE("getFeeds it >> NewsFeedsGetter doWork Start")
Telephony.Sms.TYPE, for(url in feddsUrls) {
Telephony.Sms.DATE, GlobalScope.async {
Telephony.Sms.DATE_SENT, for (it in RssFeedsParser.getFeeds(url)) {
Telephony.Sms.BODY, if (it.pubDate() >= limitDateTime) {
Telephony.Sms.PERSON, rssSet.put(it.originPage(), it)
), Telephony.Sms.DATE + "> ${dateParam}", null, Telephony.Sms.DEFAULT_SORT_ORDER)
if (managedCursor != null && managedCursor.isClosed == false) {
try {
smsList.clear()
val tid = managedCursor.getColumnIndex(Telephony.Sms.THREAD_ID)
val address = managedCursor.getColumnIndex(Telephony.Sms.ADDRESS)
val type = managedCursor.getColumnIndex(Telephony.Sms.TYPE)
val date = managedCursor.getColumnIndex(Telephony.Sms.DATE)
val sendDate = managedCursor.getColumnIndex(Telephony.Sms.DATE_SENT)
val bodyIdx = managedCursor.getColumnIndex(Telephony.Sms.BODY)
val name = managedCursor.getColumnIndex(Telephony.Sms.PERSON)
while (managedCursor.moveToNext()) {
val id = managedCursor.getString(tid) // mobile number
val phNumber = managedCursor.getString(address) // mobile number
val callType = managedCursor.getString(type) // call type
val reciveDate = managedCursor.getString(date) // call date
val sendedDate = managedCursor.getString(sendDate) // call date
val smsBody = managedCursor.getString(bodyIdx).replace("\n"," ")
val callerName = managedCursor.getString(name)
var dir: String = ""
val dircode = callType.toInt()
when (dircode) {
Telephony.Sms.MESSAGE_TYPE_ALL -> {dir = "MESSAGE_TYPE_ALL"}
Telephony.Sms.MESSAGE_TYPE_INBOX -> {dir = "MESSAGE_TYPE_INBOX"}
Telephony.Sms.MESSAGE_TYPE_SENT -> {dir = "MESSAGE_TYPE_SENT"}
Telephony.Sms.MESSAGE_TYPE_DRAFT -> {dir = "MESSAGE_TYPE_DRAFT"}
Telephony.Sms.MESSAGE_TYPE_OUTBOX -> {dir = "MESSAGE_TYPE_OUTBOX"}
Telephony.Sms.MESSAGE_TYPE_FAILED -> {dir = "MESSAGE_TYPE_FAILED"}
Telephony.Sms.MESSAGE_TYPE_QUEUED -> {dir = "MESSAGE_TYPE_QUEUED"}
} }
var log = RecentSmsLog(
phNumber,
dir,
reciveDate,
sendedDate,
smsBody,
callerName ?: ""
)
log.id = id
log.isMms = false
// BLog.LOGE("RecentSmsGetter resultData put ${phNumber +"_"+ reciveDate} >>> ${log.toJson()}")
log.sender = getContactName(applicationContext.contentResolver,phNumber) ?: ""
smsList.add(log)
} }
} catch (e: Exception) {
} finally {
managedCursor.close()
} }
} }
if (lActivity?.contentResolver != null) { BLog.LOGE("getFeeds it >> NewsFeedsGetter doWork before Yt")
TestQueryHelper(lActivity?.contentResolver!!).query() for (url in rssUrls) {
GlobalScope.async {
ytChannel(Jsoup.connect(url).get())
}
} }
BLog.LOGE("getFeeds it >> NewsFeedsGetter Result")
return Result.success() return Result.success()
} }
fun ytChannel(doc: Document) {
BLog.LOGE("ytChannel >>>>> doc${doc.title()}")
try {
doc.getElementsByTag("script").forEach {
if(it.html().contains("var ytInitialData", false)) {/**/
var ytInitialData = it.html().split("var ytInitialData = ")[1].split("</script>")[0].toString()
var tempJSONObject : JSONObject? = null
JSONObject(ytInitialData).apply{
tempJSONObject = this
val root = Gson().fromJson(tempJSONObject.toString(), Root::class.java)
(if (root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.size ?: 0 > 0) {
BLog.LOGE("ytChannel >>>>> doc singleColumnBrowseResultsRenderer apply ")
root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
// BLog.LOGE("ytChannel >>>>> doc sectionListRenderer?.contents ${Gson().toJson(it)} apply ")
it.shelfRenderer?.content?.verticalListRenderer?.items?.forEach {
// BLog.LOGE("ytChannel >>>>> doc verticalListRenderer?.items ${Gson().toJson(it)} apply ")
(it.compactVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() >= (System.currentTimeMillis() - 1000L * 60L * 60L * 24 * 3)) {
rssSet.put(it.originPage(), it)
BLog.LOGE("ytChannel >>>>> doc RssDataItem ${Gson().toJson(it)} apply ")
}
}
}
}
}
} else {
BLog.LOGE("ytChannel >>>>> doc twoColumnBrowseResultsRenderer apply ")
root?.contents?.twoColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
// BLog.LOGE("ytChannel >>>>> doc sectionListRenderer?.contents ${Gson().toJson(it)} apply ")
it.itemSectionRenderer?.contents?.forEach {
// BLog.LOGE("ytChannel >>>>> doc itemSectionRenderer?.items ${Gson().toJson(it)} apply ")
it.shelfRenderer?.content?.horizontalListRenderer?.items?.forEach {
// BLog.LOGE("it.gridVideoRenderer >>>>> ${Gson().toJson(it)}")
// BLog.LOGE("it.gridVideoRenderer >>>>> ${Gson().toJson(it.gridVideoRenderer)}")
// BLog.LOGE("it.gridVideoRenderer?.title ${Gson().toJson(it.gridVideoRenderer?.title)}")
// BLog.LOGE("it.gridVideoRenderer?.thumbnail ${Gson().toJson(it.gridVideoRenderer?.thumbnail)}")
// BLog.LOGE("it.gridVideoRenderer?.navigationEndpoint ${Gson().toJson(it.gridVideoRenderer?.navigationEndpoint)}")
// BLog.LOGE("it.gridVideoRenderer?.longBylineText ${Gson().toJson(it.gridVideoRenderer?.longBylineText)}")
// BLog.LOGE("it.gridVideoRenderer?.descriptionSnippet ${Gson().toJson(it.gridVideoRenderer?.descriptionSnippet)}")
// BLog.LOGE("it.gridVideoRenderer?.lengthText ${Gson().toJson(it.gridVideoRenderer?.lengthText)}")
(it.gridVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() >= (System.currentTimeMillis() - 1000L * 60L * 60L * 24 * 3)) {
rssSet.put(it.originPage(), it)
BLog.LOGE("ytChannel >>>>> doc RssDataItem ${Gson().toJson(it)} apply ")
}
}
}
}
}
}
}).apply {
BLog.LOGE("ytChannel >>>>> doc${doc.title()} apply ")
}
}
}
}
} catch(e: Exception) {
}
}
} }

View File

@ -1,12 +1,19 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<FrameLayout <FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical" android:orientation="vertical"
android:id="@+id/mainFragmentsContainer" android:id="@+id/mainFragmentsContainer"
android:fitsSystemWindows="true"> android:fitsSystemWindows="true">
<WebView
android:layout_margin="30dp"
android:id="@+id/searcher_01"
android:layout_width="match_parent"
android:alpha="0"
android:layout_height="match_parent"/>
<androidx.viewpager2.widget.ViewPager2 <androidx.viewpager2.widget.ViewPager2
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"

View File

@ -5,17 +5,6 @@
xmlns:tools="http://schemas.android.com/tools" 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">
<WebView
android:layout_margin="30dp"
android:id="@+id/searcher_01"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
android:layout_width="0dp"
android:alpha="0.01"
android:layout_height="0dp"/>
<View <View
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -140,6 +129,31 @@
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
/> />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/smsList"
android:layout_width="0dp"
android:layout_height="0dp"
android:overScrollMode="never"
android:padding="20dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/infoList"
android:layout_width="0dp"
android:layout_height="0dp"
android:overScrollMode="never"
android:padding="20dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent"
/>
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/favAppsGroup" android:id="@+id/favAppsGroup"

View File

@ -5,29 +5,35 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<!--rasel.lunar.launcher.view.CircleImageView--> <!--rasel.lunar.launcher.view.CircleImageView-->
<rasel.lunar.launcher.view.CircleImageView <ImageView
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
android:id="@+id/circle_preview" android:id="@+id/circle_preview"
android:scaleType="fitCenter" android:scaleType="fitCenter"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:layout_width="90dp" android:layout_width="120dp"
android:layout_height="90dp"/> android:layout_height="120dp"/>
<TextView <TextView
android:id="@+id/title" android:id="@+id/title"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:layout_height="30dp" android:layout_height="wrap_content"
android:gravity="center_vertical|right" android:textSize="24sp"
android:maxLines="2"
android:includeFontPadding="false"
android:ellipsize="middle"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@id/circle_preview" app:layout_constraintLeft_toRightOf="@id/circle_preview"
app:layout_constraintRight_toRightOf="parent"/> app:layout_constraintRight_toRightOf="parent"/>
<TextView <TextView
android:id="@+id/desc" android:id="@+id/desc"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:layout_height="43dp" android:layout_height="wrap_content"
android:gravity="center_vertical|right" android:textSize="16sp"
android:maxLines="2"
android:includeFontPadding="false"
android:ellipsize="middle"
app:layout_constraintTop_toBottomOf="@id/title" app:layout_constraintTop_toBottomOf="@id/title"
app:layout_constraintBottom_toTopOf="@id/date" app:layout_constraintBottom_toTopOf="@id/date"
app:layout_constraintLeft_toRightOf="@id/circle_preview" app:layout_constraintLeft_toRightOf="@id/circle_preview"
@ -35,8 +41,10 @@
<TextView <TextView
android:id="@+id/date" android:id="@+id/date"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:layout_height="30dp" android:layout_height="wrap_content"
android:gravity="center_vertical|right" android:textSize="16sp"
android:lines="1"
android:includeFontPadding="false"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@id/circle_preview" app:layout_constraintLeft_toRightOf="@id/circle_preview"
app:layout_constraintRight_toRightOf="parent"/> app:layout_constraintRight_toRightOf="parent"/>

View File

@ -0,0 +1,27 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/colorInputLayout"
android:layout_width="@dimen/oneNinetySix"
android:layout_height="wrap_content"
android:hint="@string/argb"
app:boxBackgroundColor="?attr/colorSurface"
app:endIconMode="clear_text"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:imeOptions="actionDone"
android:inputType="textPassword" />
</com.google.android.material.textfield.TextInputLayout>
</androidx.constraintlayout.widget.ConstraintLayout>