From 2e9900201e3768b6fd04910b93b5eac7c8fd19dd Mon Sep 17 00:00:00 2001 From: lunaticbum <> Date: Fri, 30 Aug 2024 14:43:42 +0900 Subject: [PATCH] ... --- app/src/main/AndroidManifest.xml | 6 +- .../rasel/lunar/launcher/LauncherActivity.kt | 260 +++++++++- .../rasel/lunar/launcher/feeds/Feeds.kt | 166 +++--- .../rasel/lunar/launcher/feeds/SystemStats.kt | 2 +- .../lunar/launcher/feeds/rss/RssAdapter.kt | 102 ++-- .../rasel/lunar/launcher/home/LauncherHome.kt | 483 ++++-------------- .../lunar/launcher/todos/RssItemAdapter.kt | 57 ++- .../rasel/lunar/launcher/todos/YoutubeData.kt | 77 ++- .../rasel/lunar/launcher/utils/DataManager.kt | 160 +++--- app/src/main/res/layout/launcher_activity.xml | 11 +- app/src/main/res/layout/launcher_home.xml | 36 +- app/src/main/res/layout/list_item_with.xml | 26 +- .../main/res/layout/text_inpu_password.xml | 27 + 13 files changed, 795 insertions(+), 618 deletions(-) create mode 100644 app/src/main/res/layout/text_inpu_password.xml diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index df1ca47f..70a20eb8 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -62,6 +62,8 @@ android:name=".LauncherActivity" android:theme="@style/Theme.LunarLauncher.Starting" android:launchMode="singleInstance" + android:screenOrientation="portrait" + android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection" android:windowSoftInputMode="adjustResize" android:exported="true"> @@ -131,13 +133,13 @@ - - diff --git a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt index 16dd64a0..d4812357 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/LauncherActivity.kt @@ -20,19 +20,31 @@ package rasel.lunar.launcher import android.Manifest import android.appwidget.AppWidgetManager +import android.content.BroadcastReceiver +import android.content.Context import android.content.Intent import android.content.SharedPreferences import android.content.pm.PackageManager +import android.graphics.Bitmap import android.graphics.Color import android.net.Uri +import android.net.http.SslError import android.os.Build import android.os.Bundle import android.provider.CallLog import android.provider.ContactsContract import android.provider.Settings +import android.telephony.TelephonyManager import android.util.Log +import android.view.View import android.view.WindowInsets 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.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatDelegate @@ -44,8 +56,13 @@ import androidx.core.view.WindowInsetsCompat import androidx.core.view.updatePadding import androidx.recyclerview.widget.RecyclerView 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.dialog.MaterialAlertDialogBuilder +import org.jsoup.Jsoup +import org.jsoup.nodes.Document import rasel.lunar.launcher.apps.AppDrawer import rasel.lunar.launcher.apps.DismissCalback 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.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.RssItem +import rasel.lunar.launcher.home.RssTagItem 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.Locale +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit internal class LauncherActivity : AppCompatActivity() { @@ -74,15 +103,69 @@ internal class LauncherActivity : AppCompatActivity() { companion object { val TEST_PAG = "https://jav.guru/" - + private var mWorkManager: WorkManager? = null 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 appWidgetManager: AppWidgetManager? = 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(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(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(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?) { installSplashScreen() + mWorkManager = WorkManager.getInstance(this) DynamicColors.applyToActivityIfAvailable(this) settingsPrefs = getSharedPreferences(PREFS_SETTINGS, 0) @@ -105,6 +188,9 @@ internal class LauncherActivity : AppCompatActivity() { /* handle navigation back events */ handleBackPress() + refreshSms() + refreshCalls() + refreshFeeds() } override fun onDestroy() { @@ -274,5 +360,175 @@ internal class LauncherActivity : AppCompatActivity() { 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") + } + + } +} -} \ No newline at end of file diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt index 66eccb20..5abe94c3 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/Feeds.kt @@ -22,41 +22,36 @@ import android.R.attr.* import android.app.Activity.RESULT_CANCELED import android.app.Activity.RESULT_OK import android.appwidget.AppWidgetManager +import android.content.DialogInterface import android.content.Intent import android.content.SharedPreferences import android.os.* import android.view.* +import android.widget.EditText import androidx.activity.result.contract.ActivityResultContracts +import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.LinearLayoutCompat.LayoutParams import androidx.appcompat.widget.PopupMenu -import androidx.core.app.JobIntentService.enqueueWork import androidx.fragment.app.Fragment import androidx.lifecycle.Lifecycle import androidx.lifecycle.lifecycleScope import androidx.lifecycle.repeatOnLifecycle import com.google.android.material.button.MaterialButtonToggleGroup import kotlinx.coroutines.* +import rasel.lunar.launcher.LauncherActivity.Companion.TEST_PAG import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetHost import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetManager import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.R 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.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_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.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.requestCreateWidget import rasel.lunar.launcher.helpers.Constants.Companion.requestPickWidget -import rasel.lunar.launcher.helpers.Constants.Companion.rssJobId -import rasel.lunar.launcher.helpers.UniUtils.Companion.isNetworkAvailable +import rasel.lunar.launcher.home.LauncherHome.Companion.listItem import java.util.* @@ -64,18 +59,18 @@ internal class Feeds : Fragment() { private lateinit var binding: FeedsBinding private val requestCodeString = "requestCode" - + var mRssAdapter : RssAdapter? = null override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { binding = FeedsBinding.inflate(inflater, container, false) - + mRssAdapter = RssAdapter(listItem, requireContext()) + binding.feedsRss.rss.adapter = mRssAdapter updateWidgets() - return binding.root } override fun onViewCreated(view: View, savedInstanceState: Bundle?) { super.onViewCreated(view, savedInstanceState) - binding.feedsRss.rss.adapter = RssAdapter(arrayListOf(), requireContext()) + expandCollapse() systemInfo() } @@ -88,6 +83,8 @@ internal class Feeds : Fragment() { override fun onPause() { super.onPause() unregisterForContextMenu(binding.widgetContainer) + if (binding.expandRss.isChecked) + binding.expandRss.isChecked = false } 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() { - 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) + binding.feedsRss.rss.visibility = View.GONE + binding.feedsRss.loading.visibility = View.VISIBLE + binding.feedsRss.refresh.visibility = View.VISIBLE + val builder: AlertDialog.Builder = AlertDialog.Builder(requireContext()) + builder.setTitle("Title") + val viewInflated: View = LayoutInflater.from(context) + .inflate(R.layout.text_inpu_password, view as ViewGroup?, false) + val input = viewInflated.findViewById(R.id.input) as EditText + builder.setView(viewInflated) + builder.setPositiveButton(android.R.string.ok, + DialogInterface.OnClickListener { dialog, which -> + 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 + } + } + } + } + } + } } - } - 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) + "jJTag"-> { +// lActivity?.doWebPare(TEST_PAG.plus("tags")) } - } - else -> resumeService() - } + else -> { + 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() { binding.feedsRss.apply { rss.visibility = View.GONE loading.visibility = View.GONE refresh.visibility = View.VISIBLE - refresh.setOnClickListener { startService() } + refresh.setOnClickListener { + mRssAdapter?.notifyDataSetChanged() + } } } - /* rss service's result receiver */ + /* rss service's result receiver */ @Suppress("UNCHECKED_CAST") private val resultReceiver: ResultReceiver = object : ResultReceiver(Handler(Looper.getMainLooper())) { - override fun onReceiveResult(resultCode: Int, resultData: Bundle) { - when (val items = resultData.getSerializable(RSS_ITEMS) as List?) { - null -> resumeService() - else -> { - binding.feedsRss.apply { - if(rss.adapter != null) { - (rss.adapter as RssAdapter).items.addAll(items) - } - refresh.visibility = View.GONE - loading.visibility = View.GONE - rss.visibility = View.VISIBLE - } - } - } - } +// override fun onReceiveResult(resultCode: Int, resultData: Bundle) { +// when (val items = resultData.getSerializable(RSS_ITEMS) as List?) { +// null -> resumeService() +// else -> { +// binding.feedsRss.apply { +// if(rss.adapter != null) { +// (rss.adapter as RssAdapter).items.addAll(items) +// } +// refresh.visibility = View.GONE +// loading.visibility = View.GONE +// rss.visibility = View.VISIBLE +// } +// } +// } +// } } private fun systemInfo() { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/SystemStats.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/SystemStats.kt index de4de5b2..e954a5cf 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/SystemStats.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/SystemStats.kt @@ -225,7 +225,7 @@ internal class SystemStats { currentFreq = curFreq.toDouble() / 1000 readerCurFreq.close() currentFReq = currentFreq.toInt() - println("$currentFReq----------------------------------------------------") +// println("$currentFReq----------------------------------------------------") } catch (ex: java.lang.Exception) { ex.printStackTrace() } diff --git a/app/src/main/kotlin/rasel/lunar/launcher/feeds/rss/RssAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/feeds/rss/RssAdapter.kt index 839cccfe..ec8260bc 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/feeds/rss/RssAdapter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/feeds/rss/RssAdapter.kt @@ -23,63 +23,103 @@ import android.view.ViewGroup import android.view.LayoutInflater import android.annotation.SuppressLint import android.content.Context +import android.content.Intent import android.view.Gravity import androidx.core.content.ContextCompat import android.graphics.Typeface import android.util.TypedValue import android.content.res.ColorStateList import android.net.Uri +import android.view.View 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.ListItemWithBinding 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 = arrayListOf(), private val context: Context) : +internal class RssAdapter(var items: ArrayList = arrayListOf(), private val context: Context) : RecyclerView.Adapter() { 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) } override fun getItemCount(): Int = items.size - + val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd") @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: RssViewHolder, position: Int) { + val item = items[position] /* customize the first item */ - if (position == 0) { - holder.view.itemText.apply { - text = "\u22B6 " + items[position].title + " \u22B7" - gravity = Gravity.CENTER - setTextColor(ContextCompat.getColor(context, - getColorResId(context, com.google.android.material.R.attr.colorPrimary))) - setTypeface(null, Typeface.BOLD) - textSize = 20f - } - /* reset customization for rest */ - } else { - holder.view.itemText.apply { - text = items[position].title - gravity = holder.gravity - setTextColor(holder.color) - typeface = holder.typeface - setTextSize(TypedValue.COMPLEX_UNIT_PX, holder.size) - } +// if (position == 0) { + holder.view.title.apply { + text = item.title + } + holder.view.date.text = dateFormat.format(Date(item.date)) + holder.view.desc.text = item.tags.plus("\n").plus(item.model) + holder.view.circlePreview.visibility = View.GONE + /* reset customization for rest */ +// } else { +// holder.view.desc.apply { +// text = items[position].title +//// gravity = holder.gravity +//// setTextColor(holder.color) +//// 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 */ - holder.view.itemText.setOnClickListener { - val customTabsIntent = CustomTabsIntent.Builder().setUrlBarHidingEnabled(true).build() - customTabsIntent.launchUrl(context, Uri.parse(items[position].link)) + holder.view.root.setOnLongClickListener { + openOpera("https://cili.site/search?q=${URLEncoder.encode(item.model, Charset.defaultCharset().name())}") + openOpera(item.pageLink) + true } } - inner class RssViewHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) { - /* store previous styles for resetting */ - var gravity: Int = view.itemText.gravity - var color: ColorStateList = view.itemText.textColors - var typeface: Typeface = view.itemText.typeface - var size: Float = view.itemText.textSize + fun openOpera(schemeString : String) { + val gmmIntentUri = Uri.parse(schemeString) + val mapIntent = Intent(Intent.ACTION_VIEW, gmmIntentUri) + mapIntent.setPackage("com.opera.browser") + lActivity?.startActivity(mapIntent) + } + + fun updateData(newList: List) { + DiffUtil.calculateDiff(RssItemDiffUtil(items, newList)).dispatchUpdatesTo(this) + } + inner class RssViewHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root) { + } } + + +internal class RssItemDiffUtil( + private val oldList: List, private val 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].pageLink == newList[newItemPosition].pageLink + + override fun areContentsTheSame(oldItemPosition: Int, newItemPosition: Int): Boolean = + oldList[oldItemPosition].pageLink == newList[newItemPosition].pageLink +} \ No newline at end of file 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 6ae75dc8..f5813917 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/home/LauncherHome.kt @@ -48,6 +48,7 @@ import androidx.core.content.ContextCompat.RECEIVER_EXPORTED import androidx.core.content.ContextCompat.registerReceiver import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager +import androidx.recyclerview.widget.LinearLayoutManager import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.PeriodicWorkRequestBuilder import androidx.work.WorkManager @@ -59,8 +60,12 @@ import org.jsoup.Jsoup import org.jsoup.nodes.Document import org.xmlpull.v1.XmlPullParser 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.lActivity +import rasel.lunar.launcher.LauncherActivity.Companion.workmanager import rasel.lunar.launcher.R import rasel.lunar.launcher.databinding.LauncherHomeBinding 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.expandNotificationPanel 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.qaccess.QuickAccess 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.utils.BLog import rasel.lunar.launcher.utils.MissedCallGetter +import rasel.lunar.launcher.utils.NewsFeedsGetter import rasel.lunar.launcher.utils.RecentSmsGetter import rasel.lunar.launcher.utils.RecentSmsLog import rasel.lunar.launcher.utils.RssList import rasel.lunar.launcher.utils.SimpleFingerGestures +import rasel.lunar.launcher.utils.beforeDay import java.io.ByteArrayInputStream import java.io.InputStream import java.nio.charset.Charset @@ -113,10 +118,8 @@ internal class LauncherHome : Fragment() { private lateinit var batteryReceiver: BatteryReceiver private var shouldResume = true companion object { - val SMS_WORK_TAG = "RecentSmsGetter" - val CALL_WORK_TAG = "MissedCallGetter" var lastedFinishedPageUrl : String = "" - private var mWorkManager: WorkManager? = null + var missedCalls = hashMapOf() var callList = arrayListOf() @@ -124,44 +127,44 @@ internal class LauncherHome : Fragment() { var listTags = arrayListOf() var listItem = arrayListOf() var rssSet = hashMapOf() - var rssUrls = arrayListOf() - var feddsUrls = arrayListOf() + var rssList = arrayListOf() - fun refreshSms() { - Executors.newSingleThreadScheduledExecutor().schedule({ - mWorkManager?.cancelAllWorkByTag(SMS_WORK_TAG) - mWorkManager?.enqueue(PeriodicWorkRequestBuilder(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(30, TimeUnit.MINUTES).addTag("MissedCallGetter").build()) - }, 2, TimeUnit.SECONDS) - } + } private var nReceiver: NotificationReceiver? = null class NotificationReceiver : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent) { -// val temp = """ -// ${intent.getStringExtra("notification_event")} -//// ${txtView.getText()} -// """.trimIndent() -// txtView.setText(temp) + BLog.LOGE("NotificationReceiver >>>> ${intent.extras?.keySet()}") } } - fun workmanager() : WorkManager? { - if (mWorkManager == null) { - mWorkManager = WorkManager.getInstance(requireContext()) - } - return mWorkManager - } + + val UPDATE_DELAY = 500L + val commandHandler = Handler(Looper.getMainLooper()) + + 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 { - mWorkManager = WorkManager.getInstance(requireContext()) + binding = LauncherHomeBinding.inflate(inflater, container, false) fragManager = lActivity!!.supportFragmentManager settingsPrefs = requireContext().getSharedPreferences(PREFS_SETTINGS, 0) @@ -169,35 +172,45 @@ internal class LauncherHome : Fragment() { mMissedCallsAdapter = MissedCallsAdapter(callList, requireContext()) mSmsLogsAdapter = SmsLogsAdapter(smsList, requireContext()) mRssAdapter = RssItemAdapter(rssList, requireContext()) - binding.favAppsGroup.visibility = View.GONE - binding.mainList.layoutManager = LinearLayoutManagerWrapper(requireContext()) + binding.mainList.adapter = mMissedCallsAdapter + 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 { - binding.recentSms.text = "최근 문자 [${smsList.size}]" - if (binding.recentSms.isChecked) chooseAdpater() - else if (binding.missedCalls.isChecked && missedCalls.size == 0) { - binding.recentSms.isChecked = true - chooseAdpater() - } - BLog.LOGE("smsList.size >>> ${smsList.size}") + commandHandler.removeCallbacks(smsUpdate) + commandHandler.postDelayed(smsUpdate,UPDATE_DELAY) it.clear() } workmanager()?.getWorkInfosByTagLiveData(CALL_WORK_TAG)?.observeForever { - binding.missedCalls.text = "최근 통화 [${missedCalls.size}]" - if (binding.recentSms.isChecked && missedCalls.size > 0) binding.missedCalls.isChecked = true - if (binding.missedCalls.isChecked) chooseAdpater() + commandHandler.removeCallbacks(callUpdate) + commandHandler.postDelayed(callUpdate,UPDATE_DELAY) it.clear() } + + workmanager()?.getWorkInfosByTagLiveData(FEDDS_WORK_TAG)?.observeForever { + commandHandler.removeCallbacks(infoUpdate) + commandHandler.postDelayed(infoUpdate,UPDATE_DELAY) + it.clear() + } + + + nReceiver = NotificationReceiver() val filter = IntentFilter() // filter.addAction("com.kpbird.nlsexample.NOTIFICATION_LISTENER_EXAMPLE") registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED) BLog.LOGE("onCreateView()") - refreshSms() - refreshCalls() + return binding.root } @@ -238,178 +251,42 @@ internal class LauncherHome : Fragment() { chooseAdpater() } binding.otherCheck.setOnClickListener { - if(rssSet.size < 10) { - rssSet.clear() - 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.isChecked = true + chooseAdpater() } binding.otherCheck.setOnLongClickListener { listItem.clear() - doWebPare(TEST_PAG) + lActivity?.doWebPare(TEST_PAG, null) 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}") +// 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}") } - 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 () { + binding.mainList.visibility = View.GONE + binding.smsList.visibility = View.GONE + binding.infoList.visibility = View.GONE if (binding.missedCalls.isChecked) { if (missedCalls.size > 0 && isAdded && isResumed && isVisible) { try { callList.clear() - if(binding.mainList.adapter is MissedCallsAdapter){ - }else { - binding.mainList.adapter = mMissedCallsAdapter - } missedCalls.forEach { t, u -> callList.add(u) }.apply { 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) { } @@ -417,17 +294,32 @@ internal class LauncherHome : Fragment() { } else if(binding.recentSms.isChecked){ if (smsList.size > 0 && isAdded && isResumed && isVisible) { try { - if(binding.mainList.adapter is SmsLogsAdapter){ - - }else { - binding.mainList.adapter = mSmsLogsAdapter - } 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) { } } + } 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() { @@ -448,7 +340,6 @@ internal class LauncherHome : Fragment() { } /* show 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) { 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("")[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 { diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt index 2f231c76..f6cf3c67 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/RssItemAdapter.kt @@ -25,6 +25,7 @@ import android.content.Context import android.content.Intent import android.net.Uri import android.text.Html +import android.view.Gravity import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -61,24 +62,47 @@ internal class RssItemAdapter ( } val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd") + @SuppressLint("SetTextI18n") override fun onBindViewHolder(holder: RssTag, position: Int) { val todo = smsList[position] - BLog.LOGE("rssitem >>>> ${Gson().toJson(todo)}") holder.view.title.text = "${todo.title()}" - holder.view.desc.text = Html.fromHtml("${todo.description()}") holder.view.date.text = "${dateFormat.format(Date(todo.pubDate()))}" - if(todo.thumbnailUrl()?.length ?: 0 > 6) { - Picasso.get().load(todo.thumbnailUrl().toUri()).into(holder.view.circlePreview) - holder.view.circlePreview.visibility = View.VISIBLE - } else { - holder.view.circlePreview.visibility = View.GONE + holder.view.desc.visibility = View.GONE + holder.view.circlePreview.visibility = View.GONE + when(todo.category()) { + RssDataType.YOUTUBE -> { + 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 { - val clipBoard = - lActivity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager - clipBoard.setPrimaryClip(ClipData.newPlainText("", todo.thumbnailUrl())) + when(todo.category()) { + RssDataType.YOUTUBE -> {} + RssDataType.NewsFeed -> { + openNews(todo.originPage()) + } + RssDataType.NO_DATA -> {} + } +// val clipBoard = +// lActivity!!.getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager +// clipBoard.setPrimaryClip(ClipData.newPlainText("", todo.thumbnailUrl())) true } @@ -87,7 +111,20 @@ internal class RssItemAdapter ( fun updateData(newList: List) { 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) diff --git a/app/src/main/kotlin/rasel/lunar/launcher/todos/YoutubeData.kt b/app/src/main/kotlin/rasel/lunar/launcher/todos/YoutubeData.kt index 2c0b2847..74db5790 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/todos/YoutubeData.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/todos/YoutubeData.kt @@ -503,13 +503,13 @@ class GridChannelRenderer { } class GridVideoRenderer : VideoRenderer() { -// var videoId: String? = null + // var videoId: String? = null // var thumbnail: Thumbnail? = null // var title: Title? = null // var publishedTimeText: PublishedTimeText? = null // var navigationEndpoint: NavigationEndpoint? = null var badges: ArrayList? = null -// var ownerBadges: ArrayList? = null + // var ownerBadges: ArrayList? = null // var trackingParams: String? = null // var menu: Menu? = null // var thumbnailOverlays: ArrayList? = null @@ -1117,11 +1117,11 @@ class RichThumbnail { } class Root { -// var responseContext: ResponseContext? = null + // var responseContext: ResponseContext? = null var contents: Content14? = null var header: Header? = null var metadata: Metadata? = null -// var trackingParams: String? = null + // var trackingParams: String? = null // var topbar: Topbar? = null var microformat: Microformat? = null // var onResponseReceivedActions: ArrayList? = null @@ -1584,7 +1584,7 @@ open class VideoRenderer : RssDataItem { var thumbnailOverlays: ArrayList? = null var avatar: Avatar? = null 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 { @@ -1602,43 +1602,40 @@ open class VideoRenderer : RssDataItem { } override fun description(): String { - return "" + return title?.accessibility?.accessibilityData?.label ?: "" } override fun pubDate(): Long { var date = Date() var dateTime = date.time var before = 0 - try { - var targetDate = publishedTimeText?.simpleText ?: publishedTimeText?.runs?.first()?.text ?: "" - if (targetDate?.length ?: 0 > 1) { - BLog.LOGE("targetDate >>>> ${targetDate}") - var dateDesc = targetDate -// dateDesc = dateDesc!!.replace("스트리밍 시간:","").trim() - dateDesc = dateDesc!!.split(" 전")[0].trim() - val dayString = dateDesc.replace("[^0-9]".toRegex(), "") - before = dayString.toInt() - BLog.LOGE("targetDate >>>> ${before}") - if (dateDesc.contains("년")) { - before = 365 * before - dateTime = beforeDay(date, before) - } else if (dateDesc.contains("월")) { - before = 30 * before - dateTime = beforeDay(date, before) - } else if (dateDesc.contains("주")) { - before = 7 * before - dateTime = beforeDay(date, before) - } else if (dateDesc.contains("일")) { - dateTime = beforeDay(date, before) - } else if (dateDesc.contains("시간")) { - dateTime = dateTime.minus(before.times(1000L * 60L * 60L)) - } else if (dateDesc.contains("분")) { - dateTime = dateTime.minus(before.times(1000L * 60L)) - } + try { + var targetDate = publishedTimeText?.simpleText ?: publishedTimeText?.runs?.first()?.text ?: "" + if (targetDate?.length ?: 0 > 1) { + var dateDesc = targetDate + dateDesc = dateDesc!!.split(" 전")[0].trim() + val dayString = dateDesc.replace("[^0-9]".toRegex(), "") + before = dayString.toInt() + if (dateDesc.contains("년")) { + before = 365 * before + dateTime = beforeDay(date, before) + } else if (dateDesc.contains("월")) { + before = 30 * before + dateTime = beforeDay(date, before) + } else if (dateDesc.contains("주")) { + before = 7 * before + dateTime = beforeDay(date, before) + } else if (dateDesc.contains("일")) { + dateTime = beforeDay(date, before) + } else if (dateDesc.contains("시간")) { + 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 @@ -1739,13 +1736,13 @@ class YtConfigData { } class YoutubeData { - // var responseContext: ResponseContext? = null - var contents: JSONObject? = null - var header: JSONObject? = null - var metadata: JSONObject? = null - // var trackingParams: String? = null + // var responseContext: ResponseContext? = null + var contents: JSONObject? = null + var header: JSONObject? = null + var metadata: JSONObject? = null + // var trackingParams: String? = null // var topbar: Topbar? = null - var microformat: JSONObject? = null + var microformat: JSONObject? = null // var onResponseReceivedActions: ArrayList? = null // var frameworkUpdates: FrameworkUpdates? = null diff --git a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt index d82a2f53..ef17daad 100644 --- a/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt +++ b/app/src/main/kotlin/rasel/lunar/launcher/utils/DataManager.kt @@ -7,14 +7,24 @@ import android.database.Cursor import android.net.Uri import android.provider.CallLog import android.provider.ContactsContract.PhoneLookup +import android.provider.Settings.Global import android.provider.Telephony import androidx.work.Worker import androidx.work.WorkerParameters 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.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.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.IOException import java.io.InputStream @@ -22,6 +32,8 @@ import java.io.InputStreamReader import java.text.SimpleDateFormat import java.util.Calendar import java.util.Date +import java.util.concurrent.Executors +import java.util.concurrent.TimeUnit class MissedCallGetter : Worker { @@ -468,83 +480,101 @@ fun getContactId(contentResolver: ContentResolver, phoneNumber: String?): String class NewsFeedsGetter : Worker { - + var feddsUrls = arrayListOf() + var rssUrls = arrayListOf() constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) { } - - - @SuppressLint("RestrictedApi") override fun doWork(): Result { - BLog.LOGE("phNumber == onStart") - var dateParam = beforeDay(Date(),3).toString() - val managedCursor = lActivity?.contentResolver?.query( - Telephony.Sms.CONTENT_URI, arrayOf( - Telephony.Sms.THREAD_ID, - Telephony.Sms.ADDRESS, - Telephony.Sms.TYPE, - Telephony.Sms.DATE, - Telephony.Sms.DATE_SENT, - Telephony.Sms.BODY, - Telephony.Sms.PERSON, - ), 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"} + feddsUrls.clear() + feddsUrls.addAll(RssList.newsFeeds) + rssUrls.clear() + rssUrls.addAll(RssList.youtubeUrls) + var limitDateTime = beforeDay(Date(),3) + BLog.LOGE("getFeeds it >> NewsFeedsGetter doWork Start") + for(url in feddsUrls) { + GlobalScope.async { + for (it in RssFeedsParser.getFeeds(url)) { + if (it.pubDate() >= limitDateTime) { + rssSet.put(it.originPage(), it) } - 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) { - TestQueryHelper(lActivity?.contentResolver!!).query() + BLog.LOGE("getFeeds it >> NewsFeedsGetter doWork before Yt") + for (url in rssUrls) { + GlobalScope.async { + ytChannel(Jsoup.connect(url).get()) + } } + + BLog.LOGE("getFeeds it >> NewsFeedsGetter Result") 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("")[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) { + + } + } } + diff --git a/app/src/main/res/layout/launcher_activity.xml b/app/src/main/res/layout/launcher_activity.xml index 2349793c..13de10fc 100644 --- a/app/src/main/res/layout/launcher_activity.xml +++ b/app/src/main/res/layout/launcher_activity.xml @@ -1,12 +1,19 @@ - + + - - + + + - + android:layout_width="120dp" + android:layout_height="120dp"/> diff --git a/app/src/main/res/layout/text_inpu_password.xml b/app/src/main/res/layout/text_inpu_password.xml new file mode 100644 index 00000000..834bbc01 --- /dev/null +++ b/app/src/main/res/layout/text_inpu_password.xml @@ -0,0 +1,27 @@ + + + + + + + + + \ No newline at end of file