This commit is contained in:
lunaticbum 2024-09-04 18:18:36 +09:00
parent 3708f094bd
commit cb3062153f
39 changed files with 3543 additions and 1728 deletions

View File

@ -74,7 +74,6 @@ android {
dependencies { dependencies {
val kotlinVersion: String? by extra val kotlinVersion: String? by extra
implementation ("androidx.appcompat:appcompat:1.7.0") implementation ("androidx.appcompat:appcompat:1.7.0")
implementation ("androidx.biometric:biometric-ktx:1.2.0-alpha05") implementation ("androidx.biometric:biometric-ktx:1.2.0-alpha05")
implementation ("androidx.browser:browser:1.8.0") implementation ("androidx.browser:browser:1.8.0")
@ -89,5 +88,5 @@ dependencies {
implementation ("com.google.code.gson:gson:2.11.0") implementation ("com.google.code.gson:gson:2.11.0")
implementation ("io.realm.kotlin:library-base:2.1.0") implementation ("io.realm.kotlin:library-base:2.1.0")
implementation ("org.jsoup:jsoup:1.18.1") implementation ("org.jsoup:jsoup:1.18.1")
implementation ("org.apache.commons:commons-text:1.10.0") implementation ("org.apache.commons:commons-text:1.12.0")
} }

View File

@ -82,23 +82,29 @@ import rasel.lunar.launcher.home.LauncherHome
import rasel.lunar.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl import rasel.lunar.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl
import rasel.lunar.launcher.home.LauncherHome.Companion.listItem import rasel.lunar.launcher.home.LauncherHome.Companion.listItem
import rasel.lunar.launcher.home.LauncherHome.Companion.listTags import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet //import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import rasel.lunar.launcher.home.RssItem import rasel.lunar.launcher.model.RssItem
import rasel.lunar.launcher.home.RssTagItem import rasel.lunar.launcher.model.RssTagItem
import rasel.lunar.launcher.model.ArcaGetter import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.DCGetter import rasel.lunar.launcher.model.getT
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.ComicsGetter
import rasel.lunar.launcher.utils.ComicsGetter2
import rasel.lunar.launcher.utils.MissedCallGetter
import rasel.lunar.launcher.utils.NewsFeedsGetter
import rasel.lunar.launcher.utils.RecentSmsGetter
import rasel.lunar.launcher.utils.RedditGetter
import rasel.lunar.launcher.utils.RssList.jGuruMain import rasel.lunar.launcher.utils.RssList.jGuruMain
import rasel.lunar.launcher.utils.RssList.jGuruRanks import rasel.lunar.launcher.utils.RssList.jGuruRanks
import rasel.lunar.launcher.utils.YoutubeGetter
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import rasel.lunar.launcher.utils.make0H import rasel.lunar.launcher.utils.make0H
import rasel.lunar.launcher.workers.ArcaGetter
import rasel.lunar.launcher.workers.DCGetter
import rasel.lunar.launcher.workers.DotaxGetter
import rasel.lunar.launcher.workers.FmKoreaGetter
import rasel.lunar.launcher.workers.NewsFeedsGetter
import rasel.lunar.launcher.workers.RecentCallGetter
import rasel.lunar.launcher.workers.RecentSmsGetter
import rasel.lunar.launcher.workers.RedditGetter
import rasel.lunar.launcher.workers.WorkersDb
import rasel.lunar.launcher.workers.YoutubeGetter
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
@ -115,7 +121,6 @@ internal class LauncherActivity : AppCompatActivity() {
companion object { companion object {
private var mWorkManager: WorkManager? = null private var mWorkManager: WorkManager? = null
val SMS_WORK_TAG = "RecentSmsGetter" val SMS_WORK_TAG = "RecentSmsGetter"
val CALL_WORK_TAG = "MissedCallGetter" val CALL_WORK_TAG = "MissedCallGetter"
val FEDDS_WORK_TAG = "NewsFeedsGetter" val FEDDS_WORK_TAG = "NewsFeedsGetter"
@ -127,7 +132,6 @@ internal class LauncherActivity : AppCompatActivity() {
val longTimePeriod = 60L val longTimePeriod = 60L
val midTimePeriod = 30L val midTimePeriod = 30L
var isOpendFold = false var isOpendFold = false
var rssSetTouchCount = 0
@JvmStatic var lActivity: LauncherActivity? = null @JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null @JvmStatic var appWidgetManager: AppWidgetManager? = null
@ -149,7 +153,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.enqueueUniquePeriodicWork( mWorkManager?.enqueueUniquePeriodicWork(
CALL_WORK_TAG, CALL_WORK_TAG,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<MissedCallGetter>(longTimePeriod, TimeUnit.MINUTES) PeriodicWorkRequestBuilder<RecentCallGetter>(longTimePeriod, TimeUnit.MINUTES)
.addTag(CALL_WORK_TAG) .addTag(CALL_WORK_TAG)
.build()) .build())
}, 2, TimeUnit.SECONDS) }, 2, TimeUnit.SECONDS)
@ -191,7 +195,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.cancelAllWorkByTag(COMIC_WORK_TAG) mWorkManager?.cancelAllWorkByTag(COMIC_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork( mWorkManager?.enqueueUniquePeriodicWork(
COMIC_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, COMIC_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<ComicsGetter>(midTimePeriod, TimeUnit.MINUTES) PeriodicWorkRequestBuilder<FmKoreaGetter>(midTimePeriod, TimeUnit.MINUTES)
.addTag(COMIC_WORK_TAG) .addTag(COMIC_WORK_TAG)
.build()) .build())
refreshComics2() refreshComics2()
@ -202,7 +206,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG) mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork( mWorkManager?.enqueueUniquePeriodicWork(
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<ComicsGetter2>(midTimePeriod, TimeUnit.MINUTES) PeriodicWorkRequestBuilder<DotaxGetter>(midTimePeriod, TimeUnit.MINUTES)
.addTag(COMIC2_WORK_TAG) .addTag(COMIC2_WORK_TAG)
.build()) .build())
}, 2, TimeUnit.SECONDS) }, 2, TimeUnit.SECONDS)
@ -247,8 +251,8 @@ internal class LauncherActivity : AppCompatActivity() {
BLog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}") BLog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
isOpendFold = (newConfig?.screenWidthDp?.toInt() ?: 0 > 700) == true isOpendFold = (newConfig?.screenWidthDp?.toInt() ?: 0 > 700) == true
binding.viewPager.invalidate() // binding.viewPager.invalidate()
binding.viewPager.currentItem = 1 // binding.viewPager.currentItem = 1
} }
override fun onNewIntent(intent: Intent?) { override fun onNewIntent(intent: Intent?) {
@ -592,6 +596,7 @@ internal class LauncherActivity : AppCompatActivity() {
val triple = 1000L * 60L * 60L * 24L * 2L val triple = 1000L * 60L * 60L * 24L * 2L
val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US) val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US)
fun jGuruToday(doc: Document) { fun jGuruToday(doc: Document) {
var temp = arrayListOf<RssData>()
doc.getElementsByTag("li").forEach { doc.getElementsByTag("li").forEach {
if (it.getElementsByTag("img").size > 0) { if (it.getElementsByTag("img").size > 0) {
var title = it.getElementsByTag("a").get(0).attr("title") var title = it.getElementsByTag("a").get(0).attr("title")
@ -600,7 +605,7 @@ internal class LauncherActivity : AppCompatActivity() {
var imgg = it.getElementsByTag("img").get(0).attr("src") var imgg = it.getElementsByTag("img").get(0).attr("src")
var actor = if (it.getElementsByClass("wpptax").size > 0 )it.getElementsByClass("wpptax").get(0).text() else "" var actor = if (it.getElementsByClass("wpptax").size > 0 )it.getElementsByClass("wpptax").get(0).text() else ""
if (pageLink.length > 0 && imgg.length > 0 && title.length > 0 && model.length > 0) { if (pageLink.length > 0 && imgg.length > 0 && title.length > 0 && model.length > 0) {
listItem.add( temp.add(
RssItem( RssItem(
model = model, model = model,
title = title, title = title,
@ -608,20 +613,13 @@ internal class LauncherActivity : AppCompatActivity() {
image = imgg, image = imgg,
tags = actor, tags = actor,
date = beforeDay(Date(),3) + 360000 date = beforeDay(Date(),3) + 360000
) ).getRssData()
) )
} }
} }
}.apply { }.apply {
this@LauncherActivity.callBack?.invoke() this@LauncherActivity.callBack?.invoke()
var idx = 0 WorkersDb.insertBulkInteface(temp)
listItem?.forEach {
if(it.date > beforeDay(Date(),3) && idx < 10) {
it.date = it.date + (10000L * idx)
rssSet.put(it.pageLink,it)
idx += 1
}
}
Toast.makeText(this@LauncherActivity, Toast.makeText(this@LauncherActivity,
"Stored rank data", Toast.LENGTH_LONG).show() "Stored rank data", Toast.LENGTH_LONG).show()
binding.searcher01?.post { binding.searcher01.loadUrl(jGuruMain) } binding.searcher01?.post { binding.searcher01.loadUrl(jGuruMain) }
@ -629,6 +627,7 @@ internal class LauncherActivity : AppCompatActivity() {
} }
fun jGuruMain(doc: Document) { fun jGuruMain(doc: Document) {
// BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy", Locale.US).format(Date())}") // BLog.LOGE("SimpleDateFormat D MM yy => ${SimpleDateFormat("d MMM yy", Locale.US).format(Date())}")
var temp = arrayListOf<RssData>()
val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href") val prevUrl = doc.getElementsByClass("prev").get(0).getElementsByAttribute("href").get(0).attr("href")
doc.getElementsByClass("column").forEach { doc.getElementsByClass("column").forEach {
var title = it.getElementsByAttribute("title").get(0).text() var title = it.getElementsByAttribute("title").get(0).text()
@ -641,23 +640,10 @@ internal class LauncherActivity : AppCompatActivity() {
minDate = Math.min(minDate,regDate) minDate = Math.min(minDate,regDate)
maxDate = Math.max(maxDate,regDate) maxDate = Math.max(maxDate,regDate)
listItem.add(RssItem(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = make0H(simpldateFormat.parse(date)))) temp.add(RssItem(model = model, title = title, pageLink = pageLink, image = imgg, tags = tags, date = make0H(simpldateFormat.parse(date))).getRssData())
}.apply { }.apply {
// if (prevUrl!=null && prevUrl.length > TEST_PAG.length && prevUrl.contains("/page/") && ((maxDate - minDate) < triple)) {
// listItem.sortByDescending { it.date }
// binding.searcher01.postDelayed({binding.searcher01.loadUrl(prevUrl)}, 5000L)
//// } else {
var itemC = 0 var itemC = 0
listItem.sortByDescending { it.date } WorkersDb.insertBulkInteface(temp)
listItem?.forEach {
if(it.date > beforeDay(Date(),1)) {
if (itemC < 10) {
it.date = it.date + (10000L * itemC)
rssSet.put(it.pageLink, it)
}
itemC = itemC + 1
}
}
BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}") BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}")
Toast.makeText(this@LauncherActivity, Toast.makeText(this@LauncherActivity,
"Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}] \n set in ${itemC}", Toast.LENGTH_LONG).show() "Stored data :: ${listItem.size} items :: [${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))}] \n set in ${itemC}", Toast.LENGTH_LONG).show()
@ -681,7 +667,7 @@ internal class LauncherActivity : AppCompatActivity() {
} }
} }
}.apply { }.apply {
listTags.sortByDescending { it.count } listTags.sortByDescending { it.pubDate() }
Toast.makeText(this@LauncherActivity, Toast.makeText(this@LauncherActivity,
"Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show() "Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show()
this@LauncherActivity.callBack?.invoke() this@LauncherActivity.callBack?.invoke()
@ -693,7 +679,7 @@ internal class LauncherActivity : AppCompatActivity() {
@JavascriptInterface @JavascriptInterface
fun sendValueFromHtml(result: String) { fun sendValueFromHtml(result: String) {
BLog.LOGE("binding.otherCheck start with ${result}") // BLog.LOGE("binding.otherCheck start with ${result}")
if (lastedFinishedPageUrl.contains(jGuruMain)) { if (lastedFinishedPageUrl.contains(jGuruMain)) {
var htmlString = result.replace("\\u003","<") var htmlString = result.replace("\\u003","<")
val doc: Document = Jsoup.parse(htmlString) val doc: Document = Jsoup.parse(htmlString)
@ -710,12 +696,31 @@ internal class LauncherActivity : AppCompatActivity() {
} else if (lastedFinishedPageUrl?.contains("youtube") == true) { } else if (lastedFinishedPageUrl?.contains("youtube") == true) {
// val doc: Document = Jsoup.parse(result) // val doc: Document = Jsoup.parse(result)
// ytChannel(doc) // ytChannel(doc)
} else if (lastedFinishedPageUrl?.contains("missjav")==true) { } else if (lastedFinishedPageUrl?.contains("missav")==true) {
val doc: Document = Jsoup.parse(result) val doc: Document = Jsoup.parse(result)
BLog.LOGE("missav >>> ${doc}") // BLog.LOGE("missav >>> ${doc}")
doc.getElementsByTag("li").forEach { miss_li -> var temp = arrayListOf<RssData>()
BLog.LOGE("miss_li >>>> ${miss_li}") doc.getElementsByClass("thumbnail group").forEach { miss_li ->
if (miss_li.getElementsByTag("img").size > 0 && miss_li.getElementsByTag("img").get(0).attr("data-src").length > 10 &&
miss_li.getElementsByTag("img").get(0).attr("data-src").startsWith("https") &&
miss_li.getElementsByTag("img").get(0).attr("data-src").endsWith("jpg")) {
var link = if(miss_li.getElementsByTag("a").size > 0) miss_li.getElementsByTag("a").get(0).attr("href") else ""
var title = miss_li.getElementsByClass("text-secondary group-hover:text-primary").getT()
var thumb = miss_li.getElementsByTag("img").get(0).attr("data-src")
var desc = miss_li.getElementsByTag("img").get(0).text()
MissD().apply {
this.link = link
this.title = title
this.thumb = thumb
this.desc = desc
temp.add(this.getRssData())
}
}
}.apply {
WorkersDb.insertBulkData(temp)
binding.searcher01?.post { binding.searcher01.loadData("<html></html>",null,null) }
} }
} }
BLog.LOGE("binding.otherCheck after ThreadRun") BLog.LOGE("binding.otherCheck after ThreadRun")
} }
@ -723,3 +728,36 @@ internal class LauncherActivity : AppCompatActivity() {
} }
} }
class MissD : RssDataInterface {
var link : String? = null
var title : String? = null
var thumb : String? = null
var desc : String? = null
override fun title(): String {
return title ?: ""
}
override fun thumbnailUrl(): String {
return thumb ?: ""
}
override fun originPage(): String {
return link ?: ""
}
override fun description(): String {
return desc ?: ""
}
override fun pubDate(): Long {
return beforeDay(Date(),3) + 36000L
}
override fun category(): RssDataType {
return RssDataType.GURU
}
}

View File

@ -36,6 +36,7 @@ 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 io.realm.kotlin.ext.query
import kotlinx.coroutines.* import kotlinx.coroutines.*
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
@ -55,9 +56,12 @@ 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.home.LauncherHome.Companion.listItem import rasel.lunar.launcher.home.LauncherHome.Companion.listItem
import rasel.lunar.launcher.home.LauncherHome.Companion.listTags import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
import rasel.lunar.launcher.home.RssItem import rasel.lunar.launcher.model.RssTagItem
import rasel.lunar.launcher.home.RssTagItem import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.utils.RssList.jGuruMain import rasel.lunar.launcher.utils.RssList.jGuruMain
import rasel.lunar.launcher.workers.WorkersDb
import java.util.* import java.util.*
@ -65,12 +69,12 @@ 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<RssItem>? = null var mRssAdapter : RssAdapter<RssDataInterface>? = null
var mRssAdapter2 : RssAdapter<RssTagItem>? = null var mRssAdapter2 : RssAdapter<RssTagItem>? = 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()) mRssAdapter = RssAdapter(requireContext())
mRssAdapter2 = RssAdapter(listTags, requireContext()) mRssAdapter2 = RssAdapter(requireContext())
binding.feedsRss.rss.adapter = mRssAdapter binding.feedsRss.rss.adapter = mRssAdapter
binding.feedsRss.rss2.adapter = mRssAdapter2 binding.feedsRss.rss2.adapter = mRssAdapter2
updateWidgets() updateWidgets()
@ -166,7 +170,11 @@ internal class Feeds : Fragment() {
rss.adapter = mRssAdapter rss.adapter = mRssAdapter
loading.visibility = View.VISIBLE loading.visibility = View.VISIBLE
if (listItem.size > 0) { if (listItem.size > 0) {
mRssAdapter?.updateData(listItem) listItem.sortByDescending { it.pubDate() }
WorkersDb.getRealm().query<RssData>("category == '$0'", RssDataType.GURU.name).find()?.apply {
mRssAdapter?.updateData(listItem)
}
rss.visibility = View.VISIBLE rss.visibility = View.VISIBLE
loading.visibility = View.GONE loading.visibility = View.GONE
refresh.visibility = View.GONE refresh.visibility = View.GONE
@ -177,6 +185,7 @@ internal class Feeds : Fragment() {
var call = { var call = {
if (listItem.size > 0) { if (listItem.size > 0) {
rss?.postDelayed( { rss?.postDelayed( {
listItem.sortByDescending { it.pubDate() }
mRssAdapter?.updateData(listItem) mRssAdapter?.updateData(listItem)
loading.visibility = View.GONE loading.visibility = View.GONE
refresh.visibility = View.GONE refresh.visibility = View.GONE
@ -192,7 +201,7 @@ internal class Feeds : Fragment() {
lActivity?.doWebParseStart("https://projectjav.com") {} lActivity?.doWebParseStart("https://projectjav.com") {}
} }
"jmiss" -> { "jmiss" -> {
lActivity?.doWebParseStart("https://missjav.com") {} lActivity?.doWebParseStart("https://missav.com/dm11/ko") {}
} }
"jreq" -> { "jreq" -> {
lActivity?.doWebParseStart(jGuruMain) {} lActivity?.doWebParseStart(jGuruMain) {}

View File

@ -25,25 +25,15 @@ import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent import android.content.Intent
import android.view.Gravity 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.net.Uri
import android.os.Handler
import android.os.Looper
import android.view.MotionEvent
import android.view.View import android.view.View
import androidx.browser.customtabs.CustomTabsIntent
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import com.squareup.picasso.Picasso import com.squareup.picasso.Picasso
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.databinding.ListItemWithBinding import rasel.lunar.launcher.databinding.ListItemWithBinding
import rasel.lunar.launcher.helpers.UniUtils.Companion.getColorResId import rasel.lunar.launcher.model.RssItem
import rasel.lunar.launcher.home.RssItem import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.todos.RssDataItem import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.todos.RssItemDiffUtil import rasel.lunar.launcher.todos.RssItemDiffUtil
import java.net.URLEncoder import java.net.URLEncoder
import java.nio.charset.Charset import java.nio.charset.Charset
@ -51,9 +41,9 @@ import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
internal class RssAdapter<T : RssDataItem>(var items: ArrayList<T> = arrayListOf<T>(), private val context: Context) : internal class RssAdapter<T : RssDataInterface>(private val context: Context) :
RecyclerView.Adapter<RssViewHolder>() { RecyclerView.Adapter<RssViewHolder>() {
var items: ArrayList<RssDataInterface> = arrayListOf<RssDataInterface>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RssViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RssViewHolder {
val binding = ListItemWithBinding.inflate(LayoutInflater.from(parent.context), parent, false) val binding = ListItemWithBinding.inflate(LayoutInflater.from(parent.context), parent, false)
return RssViewHolder(binding) return RssViewHolder(binding)
@ -128,8 +118,10 @@ internal class RssAdapter<T : RssDataItem>(var items: ArrayList<T> = arrayListOf
lActivity?.startActivity(mapIntent) lActivity?.startActivity(mapIntent)
} }
fun <T : RssDataItem>updateData(newList: List<T>) { fun updateData(newList: List<RssDataInterface>) {
DiffUtil.calculateDiff(RssItemDiffUtil(items, newList)).dispatchUpdatesTo(this) DiffUtil.calculateDiff(RssItemDiffUtil(items, newList)).dispatchUpdatesTo(this)
items.clear()
items.addAll(newList)
} }
} }
@ -138,7 +130,7 @@ class RssViewHolder(var view: ListItemWithBinding) : RecyclerView.ViewHolder(vie
} }
internal class RssItemDiffUtil( internal class RssItemDiffUtil(
private val oldList: List<RssDataItem>, private val newList: List<RssDataItem> private val oldList: List<RssDataInterface>, private val newList: List<RssDataInterface>
) : DiffUtil.Callback() { ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size override fun getOldListSize(): Int = oldList.size

View File

@ -193,43 +193,43 @@ internal class UniUtils {
/* favorite apps */ /* favorite apps */
private fun populateFavApps(context: Context, linearLayoutCompat: LinearLayoutCompat) { private fun populateFavApps(context: Context, linearLayoutCompat: LinearLayoutCompat) {
val prefsFavApps = context.getSharedPreferences(PREFS_FAVORITE_APPS, 0) // val prefsFavApps = context.getSharedPreferences(PREFS_FAVORITE_APPS, 0)
if (linearLayoutCompat.isVisible || prefsFavApps.all.toString().length < 3) { // if (linearLayoutCompat.isVisible || prefsFavApps.all.toString().length < 3) {
linearLayoutCompat.visibility = View.GONE // linearLayoutCompat.visibility = View.GONE
} else { // } else {
linearLayoutCompat.removeAllViews() // linearLayoutCompat.removeAllViews()
linearLayoutCompat.visibility = View.VISIBLE // linearLayoutCompat.visibility = View.VISIBLE
val iconSize = context.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_ICON_SIZE, DEFAULT_ICON_SIZE) // val iconSize = context.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_ICON_SIZE, DEFAULT_ICON_SIZE)
//
for (position in 1..MAX_FAVORITE_APPS) { // for (position in 1..MAX_FAVORITE_APPS) {
val packageName = prefsFavApps.getString(KEY_APP_NO_ + position.toString(), "").toString() // val packageName = prefsFavApps.getString(KEY_APP_NO_ + position.toString(), "").toString()
/* package name is not empty for a specific position */ // /* package name is not empty for a specific position */
if (packageName.isNotEmpty()) { // if (packageName.isNotEmpty()) {
try { // try {
ShapeableImageView(context).apply { // ShapeableImageView(context).apply {
layoutParams = LinearLayoutCompat.LayoutParams( // layoutParams = LinearLayoutCompat.LayoutParams(
(iconSize * resources.displayMetrics.density).toInt(), // (iconSize * resources.displayMetrics.density).toInt(),
(iconSize * resources.displayMetrics.density).toInt(), 1F) // (iconSize * resources.displayMetrics.density).toInt(), 1F)
}.let { sImageView -> // }.let { sImageView ->
context.packageManager.getApplicationIcon(packageName).let { defaultIcon -> // context.packageManager.getApplicationIcon(packageName).let { defaultIcon ->
if (context.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_APPS_LAYOUT, 0) != 0) // if (context.getSharedPreferences(PREFS_SETTINGS, 0).getInt(KEY_APPS_LAYOUT, 0) != 0)
getDrawableIconForPackage(packageName, defaultIcon) { // getDrawableIconForPackage(packageName, defaultIcon) {
sImageView.setImageDrawable(it ?: defaultIcon) // sImageView.setImageDrawable(it ?: defaultIcon)
} // }
else sImageView.setImageDrawable(defaultIcon) // else sImageView.setImageDrawable(defaultIcon)
} // }
sImageView.setOnClickListener { // sImageView.setOnClickListener {
context.startActivity(context.packageManager.getLaunchIntentForPackage(packageName)) // context.startActivity(context.packageManager.getLaunchIntentForPackage(packageName))
} // }
linearLayoutCompat.addView(sImageView) // linearLayoutCompat.addView(sImageView)
} // }
} catch (nameNotFoundException: PackageManager.NameNotFoundException) { // } catch (nameNotFoundException: PackageManager.NameNotFoundException) {
context.getSharedPreferences(PREFS_FAVORITE_APPS, 0) // context.getSharedPreferences(PREFS_FAVORITE_APPS, 0)
.edit().remove(KEY_APP_NO_ + position).apply() // .edit().remove(KEY_APP_NO_ + position).apply()
} // }
} // }
} // }
} // }
} }
/* lock screen using accessibility service */ /* lock screen using accessibility service */

View File

@ -24,12 +24,13 @@ import android.content.Intent
import android.os.BatteryManager import android.os.BatteryManager
import android.provider.Settings import android.provider.Settings
import android.view.animation.AnimationUtils import android.view.animation.AnimationUtils
import android.widget.TextView
import com.google.android.material.progressindicator.CircularProgressIndicator import com.google.android.material.progressindicator.CircularProgressIndicator
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
internal class BatteryReceiver(private val progressBar: CircularProgressIndicator) : BroadcastReceiver() { internal class BatteryReceiver(private val progressBar: TextView) : BroadcastReceiver() {
/* get current battery percentage */ /* get current battery percentage */
private fun batteryPercentage(intent: Intent): Int { private fun batteryPercentage(intent: Intent): Int {
@ -49,20 +50,20 @@ internal class BatteryReceiver(private val progressBar: CircularProgressIndicato
} }
/* set battery percentage value to the circular progress bar */ /* set battery percentage value to the circular progress bar */
progressBar.progress = batteryPercentage(intent!!) progressBar.text = "빠떼뤼 ~> ${batteryPercentage(intent!!)}%"
/* progress bar animation */ /* progress bar animation */
if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_CHARGING || // if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_CHARGING ||
chargingStatus(intent) == BatteryManager.BATTERY_STATUS_FULL) { // chargingStatus(intent) == BatteryManager.BATTERY_STATUS_FULL) {
if (progressBar.animation == null && animationDuration != 0f) { // if (progressBar.animation == null && animationDuration != 0f) {
progressBar.startAnimation( // progressBar.startAnimation(
AnimationUtils.loadAnimation(context, R.anim.rotate_clockwise) // AnimationUtils.loadAnimation(context, R.anim.rotate_clockwise)
) // )
} // }
} else if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_DISCHARGING || // } else if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_DISCHARGING ||
chargingStatus(intent) == BatteryManager.BATTERY_STATUS_NOT_CHARGING) { // chargingStatus(intent) == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
progressBar.clearAnimation() // progressBar.clearAnimation()
} // }
} }
} }

View File

@ -41,12 +41,16 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.Gson import io.realm.kotlin.ext.query
import kotlinx.coroutines.GlobalScope import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.notifications.UpdatedResults
import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import org.json.JSONArray import org.json.JSONArray
import org.json.JSONObject import org.json.JSONObject
import org.jsoup.Jsoup
import rasel.lunar.launcher.LauncherActivity.Companion.CALL_WORK_TAG import rasel.lunar.launcher.LauncherActivity.Companion.CALL_WORK_TAG
import rasel.lunar.launcher.LauncherActivity.Companion.FEDDS_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.SMS_WORK_TAG
@ -70,24 +74,25 @@ 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.weather.WeatherExecutor import rasel.lunar.launcher.home.weather.WeatherExecutor
import rasel.lunar.launcher.model.ArcaGetter import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.DCGetter
import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.qaccess.QuickAccess
import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.settings.SettingsActivity
import rasel.lunar.launcher.todos.MissedCallsAdapter import rasel.lunar.launcher.todos.MissedCallsAdapter
import rasel.lunar.launcher.todos.RssDataItem import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.todos.RssItemAdapter import rasel.lunar.launcher.todos.RssItemAdapter
import rasel.lunar.launcher.todos.SmsLogsAdapter import rasel.lunar.launcher.todos.SmsLogsAdapter
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import rasel.lunar.launcher.utils.SimpleFingerGestures import rasel.lunar.launcher.utils.SimpleFingerGestures
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import rasel.lunar.launcher.workers.ArcaGetter
import rasel.lunar.launcher.workers.DCGetter
import rasel.lunar.launcher.workers.RecentCall
import rasel.lunar.launcher.workers.RecentSms
import rasel.lunar.launcher.workers.WorkersDb
import java.text.SimpleDateFormat
import java.util.Calendar import java.util.Calendar
import java.util.Date import java.util.Date
import java.util.Locale import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
internal class LauncherHome : Fragment() { internal class LauncherHome : Fragment() {
@ -99,17 +104,11 @@ internal class LauncherHome : Fragment() {
private var shouldResume = true private var shouldResume = true
companion object { companion object {
var lastedFinishedPageUrl : String = "" var lastedFinishedPageUrl : String = ""
var recentCalls = hashMapOf<String, RecentCall>()
var callList = arrayListOf<RecentCall>()
var missedCalls = hashMapOf<String, MissedCall>() var smsList = arrayListOf<RecentSms>()
var callList = arrayListOf<MissedCall>() var listTags = arrayListOf<RssDataInterface>()
var smsList = arrayListOf<RecentSmsLog>() var listItem = arrayListOf<RssDataInterface>()
var listTags = arrayListOf<RssTagItem>()
var listItem = arrayListOf<RssItem>()
var rssSet = hashMapOf<String,RssDataItem>()
var rssList = arrayListOf<RssDataItem>()
} }
private var nReceiver: NotificationReceiver? = null private var nReceiver: NotificationReceiver? = null
@ -120,7 +119,7 @@ internal class LauncherHome : Fragment() {
} }
} }
val UPDATE_DELAY = 500L val UPDATE_DELAY = 3000L
val commandHandler = Handler(Looper.getMainLooper()) val commandHandler = Handler(Looper.getMainLooper())
val smsUpdate = Runnable { val smsUpdate = Runnable {
@ -130,18 +129,24 @@ internal class LauncherHome : Fragment() {
} }
val callUpdate = Runnable { val callUpdate = Runnable {
binding.missedCalls.text = "최근 통화 [${missedCalls.size}]" binding.missedCalls.text = "최근 통화 [${recentCalls.size}]"
BLog.LOGE("observeForever missedCalls.size >>> ${missedCalls.size}") BLog.LOGE("observeForever missedCalls.size >>> ${recentCalls.size}")
chooseAdpater() chooseAdpater()
} }
val infoUpdate = Runnable { val infoUpdate = Runnable {
binding.otherCheck.text = "최근 정보[${rssSet.size}]"
BLog.LOGE("observeForever rssSet.size >>> ${rssSet.size}")
chooseAdpater() chooseAdpater()
if (lasted?.size ?: 0 > 0) {
binding.otherCheck.text = "최근 정보[${lasted!!.size}]"
mRssAdapter.updateData(lasted!!)
binding.infoList.smoothScrollToPosition(0)
binding.infoList.visibility = View.VISIBLE
}
} }
var lasted : RealmResults<RssData>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = LauncherHomeBinding.inflate(inflater, container, false) binding = LauncherHomeBinding.inflate(inflater, container, false)
@ -162,7 +167,7 @@ internal class LauncherHome : Fragment() {
binding.smsList.visibility = View.GONE binding.smsList.visibility = View.GONE
binding.infoList.visibility = View.GONE binding.infoList.visibility = View.GONE
binding.favAppsGroup.visibility = View.GONE // binding.favAppsGroup.visibility = View.GONE
binding.mainList.layoutManager = LinearLayoutManager(requireContext()) binding.mainList.layoutManager = LinearLayoutManager(requireContext())
binding.smsList.layoutManager = LinearLayoutManager(requireContext()) binding.smsList.layoutManager = LinearLayoutManager(requireContext())
@ -207,14 +212,46 @@ internal class LauncherHome : Fragment() {
registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED) registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED)
BLog.LOGE("onCreateView()") BLog.LOGE("onCreateView()")
mRssDataResult = WorkersDb.getRealm().query<RssData>().query("pubDate > $0",beforeDay(Date(),3)).sort("pubDate ", Sort.DESCENDING).find()
val job = CoroutineScope(Dispatchers.Default).launch {
// create a Flow from that collection, then add a listener to the Flow
mRssDataResult.asFlow().collect { changes: ResultsChange<RssData> ->
when (changes) {
// UpdatedResults means this change represents an update/insert/delete operation
is UpdatedResults -> {
// changes.insertions // indexes of inserted objects
// changes.insertionRanges // ranges of inserted objects
// changes.changes // indexes of modified objects
// changes.changeRanges // ranges of modified objects
// changes.deletions // indexes of deleted objects
// changes.deletionRanges // ranges of deleted objects
// changes.list // the full collection of objects
if (lasted?.size != changes.list.size) {
BLog.LOGE("ResultsChange")
lasted = changes.list
commandHandler.removeCallbacks(infoUpdate)
commandHandler.postDelayed(infoUpdate, UPDATE_DELAY)
}
WorkersDb.getRealm().apply { write {
delete(query<RssData>().query("pubDate < $0",beforeDay(Date(),3)).find())
}}
}
else -> {
// types other than UpdatedResults are not changes -- ignore them
}
}
}
}
// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY)
job.start()
return binding.root return binding.root
} }
lateinit var mMissedCallsAdapter : MissedCallsAdapter lateinit var mMissedCallsAdapter : MissedCallsAdapter
lateinit var mSmsLogsAdapter : SmsLogsAdapter lateinit var mSmsLogsAdapter : SmsLogsAdapter
lateinit var mRssAdapter : RssItemAdapter lateinit var mRssAdapter : RssItemAdapter
lateinit var mRssDataResult : RealmResults<RssData>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -249,26 +286,27 @@ internal class LauncherHome : Fragment() {
} }
binding.otherCheck.setOnClickListener { binding.otherCheck.setOnClickListener {
binding.otherCheck.isChecked = true binding.otherCheck.isChecked = true
chooseAdpater() commandHandler.removeCallbacks(infoUpdate)
commandHandler.post(infoUpdate)
} }
binding.otherCheck.setOnLongClickListener { binding.otherCheck.setOnLongClickListener {
synchronized(rssSet) { // synchronized(rssSet) {
val now = Date() // val now = Date()
var keys = arrayListOf<String>() // var keys = arrayListOf<String>()
rssSet.forEach { t, u -> // rssSet.forEach { t, u ->
if (u.pubDate() <= beforeDay(now,3)) { // if (u.pubDate() <= beforeDay(now,3)) {
keys.add(t) // keys.add(t)
} // }
}.apply { // }.apply {
keys.forEach { rssSet.remove(it) } // keys.forEach { rssSet.remove(it) }
}.apply { // }.apply {
refreshYoutube() refreshYoutube()
refreshComics() refreshComics()
refreshFeeds() refreshFeeds()
refreshReddit() refreshReddit()
} // }
} // }
true true
} }
@ -284,14 +322,15 @@ internal class LauncherHome : Fragment() {
fun chooseAdpater () { fun chooseAdpater () {
binding.mainList.visibility = View.GONE if (binding.missedCalls.isChecked == false) binding.mainList.visibility = View.GONE else binding.mainList.visibility = View.VISIBLE
binding.smsList.visibility = View.GONE if (binding.recentSms.isChecked == false) binding.smsList.visibility = View.GONE else binding.smsList.visibility = View.VISIBLE
binding.infoList.visibility = View.GONE if (binding.otherCheck.isChecked == false) binding.infoList.visibility = View.GONE else binding.infoList.visibility = View.VISIBLE
if (binding.missedCalls.isChecked) { if (binding.missedCalls.isChecked) {
if (missedCalls.size > 0 && isAdded && isResumed && isVisible) { if (recentCalls.size > 0 && isAdded && isResumed && isVisible) {
try { try {
callList.clear() callList.clear()
missedCalls.forEach { t, u -> recentCalls.forEach { t, u ->
callList.add(u) callList.add(u)
}.apply { }.apply {
callList.sortByDescending { it.date } callList.sortByDescending { it.date }
@ -317,48 +356,50 @@ internal class LauncherHome : Fragment() {
} }
} }
} else if(binding.otherCheck.isChecked) { } else if(binding.otherCheck.isChecked) {
try { // try {
GlobalScope.launch { // GlobalScope.launch {
(rssSet.clone() as? HashMap<String,RssDataItem>)?.let { temMap -> // (rssSet.clone() as? HashMap<String,RssDataInterface>)?.let { temMap ->
synchronized(binding.infoList) { // synchronized(binding.infoList) {
var tempList = arrayListOf<RssDataItem>() // var tempList = arrayListOf<RssDataInterface>()
temMap.forEach { k,v -> // temMap.forEach { k,v ->
if(v.pubDate() > beforeDay(Date(),3)) { // if(v.pubDate() > beforeDay(Date(),3)) {
tempList.add(v) // tempList.add(v)
} else { // } else {
//
} // }
}.apply { // }.apply {
tempList.sortByDescending { it.pubDate() } // tempList.sortByDescending { it.pubDate() }
rssList.clear() // rssList.clear()
rssList.addAll(tempList) // rssList.addAll(tempList)
Handler(Looper.getMainLooper()).post { // Handler(Looper.getMainLooper()).post {
binding.infoList.visibility = View.VISIBLE // binding.infoList.visibility = View.VISIBLE
mRssAdapter.updateData(rssList) // mRssAdapter.updateData(rssList)
} // }
} // }
} // }
} // }
} // }
}catch (e : Exception){} // }catch (e : Exception){}
} }
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
BLog.LOGE("onResume()") BLog.LOGE("onResume()")
BLog.LOGE(SimpleDateFormat("yyyy년 M월 W주차, dd일 E요일").format(Date()))
if (shouldResume) { if (shouldResume) {
/* register battery changes */ /* register battery changes */
requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED)) requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
/* time and date */ /* time and date */
binding.time.textLocale = Locale.US // binding.time.textLocale = Locale.US
binding.date.textLocale = Locale.US // binding.date.textLocale = Locale.US
if (DateFormat.is24HourFormat(requireContext())) { // if (DateFormat.is24HourFormat(requireContext())) {
binding.time.format24Hour = timeFormat binding.time.format24Hour = timeFormat
binding.date.format24Hour = dateFormat binding.date.format24Hour = "yyyy년 M월 W주차, dd일 E요일"
} else { // } else {
binding.time.format12Hour = timeFormat // binding.time.format12Hour = timeFormat
binding.date.format12Hour = dateFormat // binding.date.format12Hour = dateFormat
} // }
/* show weather */ /* show weather */
WeatherExecutor(settingsPrefs).generateWeatherString(binding.weather) WeatherExecutor(settingsPrefs).generateWeatherString(binding.weather)
} }
@ -594,16 +635,16 @@ internal class LauncherHome : Fragment() {
/* get time format string */ /* get time format string */
private val timeFormat: String? get() { private val timeFormat: String? get() {
when (settingsPrefs.getInt(KEY_TIME_FORMAT, 0)) { // when (settingsPrefs.getInt(KEY_TIME_FORMAT, 0)) {
0 -> return if (DateFormat.is24HourFormat(requireContext())) { // 0 -> return if (DateFormat.is24HourFormat(requireContext())) {
"kk:mm" // "kk:mm"
} else { // } else {
"HH:mm a" // "HH:mm a"
} // }
1 -> return "HH:mm a" // 1 -> return "HH:mm a"
2 -> return "kk:mm" // 2 -> return "kk:mm"
} // }
return null return "a HH : mm"
} }
/* get date number suffix */ /* get date number suffix */
@ -618,127 +659,18 @@ internal class LauncherHome : Fragment() {
/* get date format string */ /* get date format string */
private val dateFormat: String get() { private val dateFormat: String get() {
settingsPrefs.getString(KEY_DATE_FORMAT, DEFAULT_DATE_FORMAT).let { // settingsPrefs.getString(KEY_DATE_FORMAT, DEFAULT_DATE_FORMAT).let {
return if (it!!.contains("x")) { // return if (it!!.contains("x")) {
it.replace("x", dateNumberSuffix) // it.replace("x", dateNumberSuffix)
} else { // } else {
it // it
} // }
} // }
} return "yyyy년 M월 W주차, dd일 E요일"
}
class MissedCall {
constructor(count: Int, name: String?, number: String, type: Int, typeString: String, date : String) {
this.count = count
this.name = name ?: "unknown"
this.number = number
this.type = type
this.typeString = typeString
this.date = date
}
var count : Int = 1
var name : String = "how"
var number : String = ""
var type : Int = 0
var typeString : String = ""
var date : String = ""
fun toJson() : String {
return Gson().toJson(this)
} }
} }
class RssTagItem : RssDataItem{
var link : String = ""
var tagTitle = ""
var count = 0
override fun title(): String {
return tagTitle
}
override fun thumbnailUrl(): String {
return ""
}
override fun originPage(): String {
return link
}
override fun description(): String {
return " "
}
override fun pubDate(): Long {
return 0L
}
override fun category(): RssDataType {
return RssDataType.TAGS
}
constructor(link: String, tagTitle: String) {
this.link = link
this.tagTitle = tagTitle
if (tagTitle.contains("(") && tagTitle.contains(")")) {
try {
count = tagTitle.split("(")[1].split(")")[0].toInt()
}catch (e : Exception) {}
}
}
}
class RssItem : RssDataItem {
var model : String = ""
var title : String = ""
var pageLink : String = ""
var image : String = ""
var tags : String = ""
var date : Long = 0L
constructor(
model: String,
title: String,
pageLink: String,
image: String,
tags: String,
date: Long
) {
this.model = model
this.title = title
this.pageLink = pageLink
this.image = image
this.tags = tags
this.date = date
}
override fun title(): String {
return title
}
override fun thumbnailUrl(): String {
return image
}
override fun originPage(): String {
return pageLink
}
override fun description(): String {
return tags.plus(model)
}
override fun pubDate(): Long {
return date
}
override fun category(): RssDataType {
return RssDataType.GURU
}
}

View File

@ -1,17 +1,9 @@
package rasel.lunar.launcher.model package rasel.lunar.launcher.model
import android.annotation.SuppressLint import io.realm.kotlin.types.RealmObject
import android.content.Context import io.realm.kotlin.types.annotations.PrimaryKey
import androidx.work.Worker
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import org.jsoup.select.Elements import org.jsoup.select.Elements
import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.USAGT
import rasel.lunar.launcher.utils.afterDay import rasel.lunar.launcher.utils.afterDay
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
@ -20,91 +12,17 @@ import java.util.Date
import java.util.TimeZone import java.util.TimeZone
class ArcaGetter : Worker {
companion object {
val TAG = "DCGetter"
}
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
override fun doWork(): Result {
var tempArray = arrayListOf<RssDataItem>()
try { fun Elements.getT() = if (size > 0) get(0).text() else ""
val urls = arrayListOf( val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
"https://arca.live/b/singbung?mode=best", class Arca : RssDataInterface {
"https://arca.live/b/headline",
"https://arca.live/b/live",
"https://arca.live/b/namuhotnow",
"https://arca.live/b/society",
"https://arca.live/b/replay",
"https://arca.live/b/breaking"
)
urls.forEach {
Jsoup.connect(it)
.userAgent(USAGT)
.get().let { arca ->
// BLog.LOGE("url >> ${it} >> ${arca}")
arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
if (araca_li.html().contains("title ") == true) {
parseArcaLi(araca_li).apply {
tempArray.addAll(this)
}
}
}
}
}
// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
// BLog.LOGE("projectj >>>>> ${projectj}")
// }
} catch (e:Exception){e.printStackTrace()}
return tempArray.forEach {
rssSet.put(it.originPage(),it)
}.run {
Result.success()
}
}
private fun parseArcaLi(aracaLi: Element) : ArrayList<RssDataItem> {
var tempArray = arrayListOf<RssDataItem>()
// BLog.LOGE("aracaLi >>> ${aracaLi}")
var title = aracaLi.getElementsByClass("title hybrid-title").getT()
var desc = aracaLi.getElementsByClass("badge").getT()
desc.plus(aracaLi.getElementsByClass("user-info ").getT())
var dateTime = aracaLi.getElementsByTag("time").attr("datetime")
var tumbnail = aracaLi.getElementsByTag("img").attr("src")
var link = "https://arca.live".plus(if(aracaLi.getElementsByClass("title hybrid-title").size > 0) aracaLi.getElementsByClass("title hybrid-title").get(0).attr("href") else if(aracaLi.getElementsByTag("a").size > 0) aracaLi.getElementsByTag("a").get(0).attr("href") else "")
if (title.length > 0 && link.length > 20) {
Arca().apply {
this.link = link
this.title = title
if (tumbnail.length > 0) {
this.thumbnail = "https:".plus(tumbnail)
//
// BLog.LOGE("Arca thumbnail >>> ${thumbnail}")
}
this.desc = desc
this.dateTiem = dateTime
}.apply {
// BLog.LOGE("parseArcaLi >>>> ${this}")
if(this.pubDate() > beforeDay(Date(),3)) {
tempArray.add(this)
}
}
}
return tempArray
}
fun Elements.getT() = if (size > 0) get(0).text() else ""
}
class Arca : RssDataItem {
var link : String? = null var link : String? = null
var title : String? = null var title : String? = null
var thumbnail : String? = null var thumbnail : String? = null
var desc : String? = null var desc : String? = null
var dateTiem : String? = null var dateTiem : String? = null
var updateDateTime : Long = 0L var updateDateTime : Long = 0L
override fun title(): String { override fun title(): String {
return title ?: "" return title ?: ""
} }
@ -120,18 +38,18 @@ var updateDateTime : Long = 0L
override fun description(): String { override fun description(): String {
return desc ?: "" return desc ?: ""
} }
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
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
if (updateDateTime == 0L) { if (updateDateTime == 0L) {
try { try {
BLog.LOGE("this.dateTiem >>> ${this.dateTiem}") // BLog.LOGE("this.dateTiem >>> ${this.dateTiem}")
val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'") val sdf = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'")
sdf.timeZone = TimeZone.getTimeZone("GMT") sdf.timeZone = TimeZone.getTimeZone("GMT")
updateDateTime = sdf.parse(this.dateTiem!!).time updateDateTime = sdf.parse(this.dateTiem!!).time
BLog.LOGE("updateDateTime >>>> ${dateFormat.format(Date(updateDateTime))}" ) // BLog.LOGE("updateDateTime >>>> ${dateFormat.format(Date(updateDateTime))}" )
// var targetDate = this.dateTiem ?: "" // var targetDate = this.dateTiem ?: ""
// if (targetDate?.length ?: 0 > 1) { // if (targetDate?.length ?: 0 > 1) {
// var dateDesc = targetDate // var dateDesc = targetDate
@ -176,7 +94,6 @@ var updateDateTime : Long = 0L
} else { } else {
dateTime = updateDateTime dateTime = updateDateTime
} }
return dateTime return dateTime
} }
@ -185,95 +102,13 @@ var updateDateTime : Long = 0L
} }
} }
class DCGetter : Worker {
companion object {
val TAG = "DCGetter"
}
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
fun parseDcLi(dc_li : org.jsoup.nodes.Element) : ArrayList<RssDataItem>{
var temp = arrayListOf<RssDataItem>()
if (dc_li.html().contains("<ul class=>") && dc_li.html().contains("con_list img")) {
dc_li.child(0).getElementsByTag("li").forEach {
parseDcLi(it)
}
} else {
var link = if (dc_li.getElementsByTag("a").size > 0) dc_li.getElementsByTag("a").get(0)
.attr("href") else ""
var title =
if (dc_li.getElementsByClass("box besttxt").size > 0) dc_li.getElementsByClass("box besttxt")
.get(0)
.text() else if (dc_li.getElementsByClass("tit").size > 0) dc_li.getElementsByClass(
"tit"
).get(0).text() else ""
var thumbnail =
if (dc_li.getElementsByTag("img").size > 0) dc_li.getElementsByTag("img").get(0)
.attr("src") else ""
var desc =
if (dc_li.getElementsByClass("box best_info").size > 0) dc_li.getElementsByClass("box best_info")
.get(0).text() else ""
var dateTiem =
if (dc_li.getElementsByClass("time").size > 0) dc_li.getElementsByClass("time")
.get(0).text() else ""
link = link.replace("&amp;","&")
thumbnail = thumbnail.replace("&amp;","&")
// BLog.LOGE("DC_LI >>>> link >>>> ${link}")
// BLog.LOGE("DC_LI >>>> title >>>> ${title}")
// BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}")
// BLog.LOGE("DC_LI >>>> desc >>>> ${desc}")
// BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}")
if (title.length > 0 && link.length > 0) {
DcInside().apply {
this.link = link
this.title = title
this.thumbnail = thumbnail
this.desc = desc
this.dateTiem = dateTiem
}.apply {
temp.add(this)
}
}
}
return temp
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
var tempArray = arrayListOf<RssDataItem>()
try {
val testUrl2 = "https://www.dcinside.com/"
Jsoup.connect(testUrl2)
.userAgent(USAGT)
.get().let { dc ->
// BLog.LOGE("test ${testUrl2} >> ${this}")
dc.getElementsByTag("li").forEach { dc_li ->
if (dc_li.html().contains("main_log") == true) {
parseDcLi(dc_li).apply {
tempArray.addAll(this)
}
}
}
}
} catch (e:Exception){e.printStackTrace()}
return tempArray.forEach {
rssSet.put(it.originPage(),it)
}.run {
Result.success()
}
}
}
class DcInside : RssDataItem {
class DcInside : RssDataInterface {
var link : String? = null var link : String? = null
var title : String? = null var title : String? = null
var thumbnail : String? = null var thumbnail : String? = null
@ -282,7 +117,6 @@ class DcInside : RssDataItem {
var dateTiemL : Long = 0L var dateTiemL : Long = 0L
val dateF = SimpleDateFormat("MM-dd") val dateF = SimpleDateFormat("MM-dd")
val timeF = SimpleDateFormat("HH:mm") val timeF = SimpleDateFormat("HH:mm")
override fun title(): String { override fun title(): String {
@ -332,4 +166,143 @@ class DcInside : RssDataItem {
return RssDataType.DcInside return RssDataType.DcInside
} }
}
class RssData : RealmObject, RssDataInterface {
@PrimaryKey
var originPage : String? = null
var title : String? = null
var description : String? = null
var thumbnail : String? = null
var pubDate : Long = 0L
var category : String? = null
override fun title(): String {
return title ?: ""
}
override fun thumbnailUrl(): String {
return thumbnail ?: ""
}
override fun originPage(): String {
return originPage ?: ""
}
override fun description(): String {
return description ?: ""
}
override fun pubDate(): Long {
return pubDate
}
override fun category(): RssDataType {
return RssDataType.valueOf(category!!)
}
}
open class Dotax(var pageLink : String,
var desc : String,
var dateTime : String,
var title : String,
var thumbnail : String) : RssDataInterface {
var updateDateTime = 0L
override fun title(): String {
return title
}
override fun thumbnailUrl(): String {
return thumbnail
}
override fun originPage(): String {
return "https://m.cafe.daum.net".plus(pageLink)
}
override fun description(): String {
return desc
}
override fun pubDate(): Long {
var date = Date()
var dateTime = date.time
var before = 0
if (updateDateTime == 0L) {
try {
var targetDate = this.dateTime ?: ""
if (targetDate?.length ?: 0 > 1) {
var dateDesc = targetDate
var isBefore = dateDesc.contains("")
val dayString = dateDesc.replace("[^0-9]".toRegex(), "")
before = dayString.toInt()
if (dateDesc.contains("")) {
before = 365 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
before = 30 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
before = 7 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("시간")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L * 60L * 60L)) else dateTime.plus(
before.times(1000L * 60L * 60L)
)
} else if (dateDesc.contains("")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L * 60L)) else dateTime.plus(
before.times(1000L * 60L)
)
}
else if (dateDesc.contains("")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L)) else dateTime.plus(
before.times(1000L)
)
}
}
} catch (e: Exception) {
} finally {
updateDateTime = dateTime
}
} else {
dateTime = updateDateTime
}
return dateTime
}
override fun category(): RssDataType {
return RssDataType.Dotax
}
}
data class FmKorea(var apageLink : String,
var adesc : String,
var adateTime : String,
var atitle : String,
var athumbnail : String) : Dotax(apageLink, adesc, adateTime, atitle, athumbnail) {
override fun originPage(): String {
return pageLink
}
override fun category(): RssDataType {
return RssDataType.FmKorae
}
}
fun RssDataInterface.getRssData() : RssData {
return RssData().apply {
title = this@getRssData.title()
description = this@getRssData.description()
originPage = this@getRssData.originPage()
thumbnail = this@getRssData.thumbnailUrl()
pubDate = this@getRssData.pubDate()
category = this@getRssData.category().name
}
} }

View File

@ -1,16 +1,9 @@
package rasel.lunar.launcher.model package rasel.lunar.launcher.model
import rasel.lunar.launcher.todos.Image import rasel.lunar.launcher.todos.Image
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.todos.Source import rasel.lunar.launcher.todos.Source
import rasel.lunar.launcher.utils.beforeDay
import java.sql.Date
class Reddit {
}
class Child { class Child {
var kind: String? = null var kind: String? = null
var data: Data? = null var data: Data? = null
@ -129,7 +122,7 @@ class CrosspostParentList {
var link_flair_template_id: String? = null var link_flair_template_id: String? = null
} }
class Data : RssDataItem { class Data : RssDataInterface {
var after: String? = null var after: String? = null
var dist: Int = 0 var dist: Int = 0
var modhash: String? = null var modhash: String? = null
@ -280,6 +273,7 @@ class Data : RssDataItem {
override fun category(): RssDataType { override fun category(): RssDataType {
return RssDataType.REDDIT return RssDataType.REDDIT
} }
} }
class Gif { class Gif {
@ -362,7 +356,7 @@ class Resolution {
var height: Int = 0 var height: Int = 0
} }
class Root { class Reddit {
var kind: String? = null var kind: String? = null
var data: Data? = null var data: Data? = null
} }

View File

@ -1,4 +1,4 @@
package rasel.lunar.launcher.todos package rasel.lunar.launcher.model
enum class RssDataType { enum class RssDataType {
NO_DATA, NO_DATA,
@ -13,7 +13,7 @@ enum class RssDataType {
Arca, Arca,
} }
interface RssDataItem { interface RssDataInterface {
fun title() : String fun title() : String
fun thumbnailUrl() : String fun thumbnailUrl() : String
fun originPage() : String fun originPage() : String

View File

@ -0,0 +1,50 @@
package rasel.lunar.launcher.model
class RssItem : RssDataInterface {
var model : String = ""
var title : String = ""
var pageLink : String = ""
var image : String = ""
var tags : String = ""
var date : Long = 0L
constructor(
model: String,
title: String,
pageLink: String,
image: String,
tags: String,
date: Long
) {
this.model = model
this.title = title
this.pageLink = pageLink
this.image = image
this.tags = tags
this.date = date
}
override fun title(): String {
return title
}
override fun thumbnailUrl(): String {
return image
}
override fun originPage(): String {
return pageLink
}
override fun description(): String {
return tags.plus(model)
}
override fun pubDate(): Long {
return date
}
override fun category(): RssDataType {
return RssDataType.GURU
}
}

View File

@ -0,0 +1,41 @@
package rasel.lunar.launcher.model
class RssTagItem : RssDataInterface {
var link : String = ""
var tagTitle = ""
var count = 0
override fun title(): String {
return tagTitle
}
override fun thumbnailUrl(): String {
return ""
}
override fun originPage(): String {
return link
}
override fun description(): String {
return " "
}
override fun pubDate(): Long {
return count.toLong()
}
override fun category(): RssDataType {
return RssDataType.TAGS
}
constructor(link: String, tagTitle: String) {
this.link = link
this.tagTitle = tagTitle
if (tagTitle.contains("(") && tagTitle.contains(")")) {
try {
count = tagTitle.split("(")[1].split(")")[0].toInt()
}catch (e : Exception) {}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -35,16 +35,15 @@ import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.ListItemBinding import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.databinding.TodoDialogBinding import rasel.lunar.launcher.databinding.TodoDialogBinding
import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard
import rasel.lunar.launcher.home.MissedCall
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import rasel.lunar.launcher.utils.getContactId import rasel.lunar.launcher.utils.getContactId
import rasel.lunar.launcher.workers.RecentCall
import java.util.* import java.util.*
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
internal class MissedCallsAdapter( internal class MissedCallsAdapter(
private val callList: ArrayList<MissedCall>, private val callList: ArrayList<RecentCall>,
private val context: Context) : RecyclerView.Adapter<MissedCallsAdapter.MissedCallsHolder>() { private val context: Context) : RecyclerView.Adapter<MissedCallsAdapter.MissedCallsHolder>() {
private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer) private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
@ -125,7 +124,7 @@ internal class MissedCallsAdapter(
// } // }
} }
fun updateData(newList: ArrayList<MissedCall>) { fun updateData(newList: ArrayList<RecentCall>) {
val diffUtilResult = DiffUtil.calculateDiff(MissedCallDiffUtil(callList, newList)) val diffUtilResult = DiffUtil.calculateDiff(MissedCallDiffUtil(callList, newList))
diffUtilResult.dispatchUpdatesTo(this) diffUtilResult.dispatchUpdatesTo(this)
// callList.clear() // callList.clear()
@ -135,7 +134,7 @@ internal class MissedCallsAdapter(
} }
internal class MissedCallDiffUtil( internal class MissedCallDiffUtil(
private val oldList: List<MissedCall>, private val newList: List<MissedCall> private val oldList: List<RecentCall>, private val newList: List<RecentCall>
) : DiffUtil.Callback() { ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size override fun getOldListSize(): Int = oldList.size

View File

@ -2,10 +2,10 @@ package rasel.lunar.launcher.todos
import android.util.Xml import android.util.Xml
import com.google.gson.Gson import com.google.gson.Gson
import com.google.gson.JsonParser
import org.xmlpull.v1.XmlPullParser import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException import org.xmlpull.v1.XmlPullParserException
import rasel.lunar.launcher.model.Root import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import java.io.IOException import java.io.IOException
@ -21,32 +21,28 @@ import java.util.Locale
object RssFeedsParser { object RssFeedsParser {
var parseDateFormat: SimpleDateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH) var parseDateFormat: SimpleDateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH)
var limitDateTime = beforeDay(Date(),3) var limitDateTime = beforeDay(Date(),3)
fun getFeeds(url : String) : List<RssDataItem> { fun getFeeds(url : String) : List<RssDataInterface> {
var returnList = mutableListOf<RssDataItem>() var returnList = mutableListOf<RssDataInterface>()
try { try {
returnList.addAll(parse(getInputStream(url)!!)) returnList.addAll(parse(getInputStream(url)!!))
BLog.LOGE("getInputStream >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${returnList.size}")
} catch (e : Exception) { } catch (e : Exception) {
e.printStackTrace() e.printStackTrace()
} }
return returnList return returnList
} }
fun getReddit(url : String): List<RssDataItem> { fun getReddit(url : String): List<RssDataInterface> {
var returnList = mutableListOf<RssDataItem>() var returnList = mutableListOf<RssDataInterface>()
var dateTime = beforeDay(Date(),3) var dateTime = beforeDay(Date(),3)
try { try {
var mRoot = Gson().fromJson(InputStreamReader(getInputStream(url)!!),rasel.lunar.launcher.model.Root::class.java) var mReddit = Gson().fromJson(InputStreamReader(getInputStream(url)!!),rasel.lunar.launcher.model.Reddit::class.java)
mRoot.data?.children?.forEach { mReddit.data?.children?.forEach {
// BLog.LOGE("getReddit >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${Gson().toJson(it)}")
if(((it.data?.created_utc ?: 0).toLong() * 1000L > dateTime)) { if(((it.data?.created_utc ?: 0).toLong() * 1000L > dateTime)) {
// BLog.LOGE("getReddit >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${Gson().toJson(it)}") (it.data as? RssDataInterface)?.let { rss ->
(it.data as? RssDataItem)?.let { rss ->
returnList.add(rss) returnList.add(rss)
} }
} }
} }
BLog.LOGE("getReddit >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${returnList.size}")
} catch (e : Exception) { } catch (e : Exception) {
e.printStackTrace() e.printStackTrace()
} }
@ -62,13 +58,12 @@ object RssFeedsParser {
ioException.printStackTrace() ioException.printStackTrace()
null null
}.apply { }.apply {
BLog.LOGE("getInputStream >>>>> link $link")
} }
} }
@Throws(XmlPullParserException::class, IOException::class) @Throws(XmlPullParserException::class, IOException::class)
private fun parse(inputStream: InputStream): List<RssDataItem> { private fun parse(inputStream: InputStream): List<RssDataInterface> {
return inputStream.use { stream -> return inputStream.use { stream ->
val parser = Xml.newPullParser() val parser = Xml.newPullParser()
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false) parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
@ -179,7 +174,7 @@ object RssFeedsParser {
} }
} }
class RssFeed : RssDataItem{ class RssFeed : RssDataInterface {
var title : String? = "" var title : String? = ""
var link : String? = "" var link : String? = ""

View File

@ -34,14 +34,16 @@ import com.squareup.picasso.Picasso
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.ListItemWithBinding import rasel.lunar.launcher.databinding.ListItemWithBinding
import rasel.lunar.launcher.home.RssItem import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.utils.BLog
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
internal class RssItemAdapter ( internal class RssItemAdapter (
private val context: Context) : RecyclerView.Adapter<RssTag>() { private val context: Context) : RecyclerView.Adapter<RssTag>() {
private var rssDataItemLis: ArrayList<RssDataItem> = arrayListOf() private var rssDataItemLis: ArrayList<RssDataInterface> = arrayListOf()
override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RssTag { override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): RssTag {
val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false) val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return RssTag(binding) return RssTag(binding)
@ -142,7 +144,7 @@ internal class RssItemAdapter (
holder.view.desc.text = todo.description().plus(" ").plus(todo.category().name) holder.view.desc.text = todo.description().plus(" ").plus(todo.category().name)
holder.view.desc.visibility = View.VISIBLE holder.view.desc.visibility = View.VISIBLE
holder.view.date.setOnClickListener { holder.view.date.setOnClickListener {
if (holder.view.desc.visibility == View.GONE) { if (holder.view.circlePreview.visibility == View.GONE) {
holder.view.circlePreview.visibility = View.VISIBLE holder.view.circlePreview.visibility = View.VISIBLE
holder.view.circlePreview.postDelayed({ holder.view.circlePreview.postDelayed({
holder.view.circlePreview.visibility = View.GONE holder.view.circlePreview.visibility = View.GONE
@ -168,7 +170,8 @@ internal class RssItemAdapter (
openReddit(todo.originPage()) openReddit(todo.originPage())
} else if( todo.category().equals(RssDataType.Dotax)) { } else if( todo.category().equals(RssDataType.Dotax)) {
openDotax(todo.originPage()) openDotax(todo.originPage())
}else if(todo.category().equals(RssDataType.FmKorae)|| todo.category().equals(RssDataType.DcInside)|| todo.category().equals(RssDataType.Arca)) { }else if(todo.category().equals(RssDataType.FmKorae)|| todo.category().equals(
RssDataType.DcInside)|| todo.category().equals(RssDataType.Arca)) {
openNews(todo.originPage()) openNews(todo.originPage())
} }
true true
@ -186,15 +189,17 @@ internal class RssItemAdapter (
} }
fun updateData(newList: List<RssDataItem>) { fun updateData(newList: List<RssDataInterface>) {
try { try {
BLog.LOGE("newList >> ${newList}")
DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply { DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
}.dispatchUpdatesTo(this).apply { }.dispatchUpdatesTo(this).apply {
notifyItemRangeChanged(0,10) // notifyItemRangeChanged(0,10)
} }
rssDataItemLis.clear() rssDataItemLis.clear()
rssDataItemLis.addAll(newList) rssDataItemLis.addAll(newList)
BLog.LOGE("rssDataItemLis >> ${rssDataItemLis}")
}catch ( e : Exception) { }catch ( e : Exception) {
e.printStackTrace() e.printStackTrace()
} }
@ -239,7 +244,7 @@ internal class RssItemAdapter (
internal class RssTag(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root) internal class RssTag(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root)
internal class RssItemDiffUtil( internal class RssItemDiffUtil(
var oldList: List<RssDataItem>, var newList: List<RssDataItem> var oldList: List<RssDataInterface>, var newList: List<RssDataInterface>
) : DiffUtil.Callback() { ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size override fun getOldListSize(): Int = oldList.size

View File

@ -20,23 +20,15 @@ package rasel.lunar.launcher.todos
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Context import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.DiffUtil import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson import com.google.gson.Gson
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.ListItemBinding import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.home.RssTagItem import rasel.lunar.launcher.model.RssTagItem
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import java.text.SimpleDateFormat
import java.util.Date
internal class RssTagAdapter( internal class RssTagAdapter(
private val smsList: ArrayList<RssTagItem>, private val smsList: ArrayList<RssTagItem>,
@ -58,7 +50,6 @@ internal class RssTagAdapter(
val todo = smsList[position] val todo = smsList[position]
holder.view.itemText.text = "\u25CF ${Gson().toJson(todo)}" holder.view.itemText.text = "\u25CF ${Gson().toJson(todo)}"
BLog.LOGE("holder.view.itemText.text >>> ${holder.view.itemText.text}")
/* multiline texts are enabled for TodoManager */ /* multiline texts are enabled for TodoManager */
// holder.view.itemText.isSingleLine = false // holder.view.itemText.isSingleLine = false
/* launch edit or update dialog on item click */ /* launch edit or update dialog on item click */

View File

@ -31,13 +31,13 @@ import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.ListItemBinding import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog import rasel.lunar.launcher.workers.RecentSms
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
internal class SmsLogsAdapter( internal class SmsLogsAdapter(
private val smsList: ArrayList<RecentSmsLog>, private val smsList: ArrayList<RecentSms>,
private val context: Context) : RecyclerView.Adapter<SmsLogHolder>() { private val context: Context) : RecyclerView.Adapter<SmsLogHolder>() {
private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer) private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
@ -95,7 +95,7 @@ internal class SmsLogsAdapter(
fun updateData(newList: List<RecentSmsLog>) { fun updateData(newList: List<RecentSms>) {
val diffUtilResult = DiffUtil.calculateDiff(SmsDiffUtil(smsList, newList)) val diffUtilResult = DiffUtil.calculateDiff(SmsDiffUtil(smsList, newList))
diffUtilResult.dispatchUpdatesTo(this) diffUtilResult.dispatchUpdatesTo(this)
// smsList.clear() // smsList.clear()
@ -142,7 +142,7 @@ internal class SmsLogsAdapter(
} }
class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root) class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
internal class SmsDiffUtil( internal class SmsDiffUtil(
private val oldList: List<RecentSmsLog>, private val newList: List<RecentSmsLog> private val oldList: List<RecentSms>, private val newList: List<RecentSms>
) : DiffUtil.Callback() { ) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size override fun getOldListSize(): Int = oldList.size

View File

@ -1,25 +0,0 @@
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package rasel.lunar.launcher.todos
//
//
//internal class Todo {
// var id: Long = -1
// var name = ""
//}

View File

@ -1,129 +0,0 @@
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package rasel.lunar.launcher.todos
//
//import android.annotation.SuppressLint
//import android.content.Context
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import androidx.core.content.ContextCompat
//import androidx.recyclerview.widget.RecyclerView
//import com.google.android.material.bottomsheet.BottomSheetDialog
//import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
//import rasel.lunar.launcher.R
//import rasel.lunar.launcher.databinding.ListItemBinding
//import rasel.lunar.launcher.databinding.TodoDialogBinding
//import rasel.lunar.launcher.helpers.Constants.Companion.KEY_TODO_COUNTS
//import rasel.lunar.launcher.helpers.Constants.Companion.PREFS_SETTINGS
//import rasel.lunar.launcher.helpers.UniUtils.Companion.copyToClipboard
//import java.util.*
//
//
//internal class TodoAdapter(
// private val todoManager: TodoManager?,
// private val context: Context) : RecyclerView.Adapter<TodoAdapter.TodoViewHolder>() {
//
// private val currentFragment = lActivity!!.supportFragmentManager.findFragmentById(R.id.mainFragmentsContainer)
//// private val todoList = DatabaseHandler(context).todos
//
// override fun onCreateViewHolder(viewGroup: ViewGroup, i: Int): TodoViewHolder {
// val binding = ListItemBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
// return TodoViewHolder(binding)
// }
//
// override fun getItemCount(): Int {
// /* if current fragment is LauncherHome,
// then return size following the settings value */
// val sharedPreferences = context.getSharedPreferences(PREFS_SETTINGS, 0)
// val numberOfTodos = sharedPreferences.getInt(KEY_TODO_COUNTS, 3)
// return if (currentFragment !is TodoManager) {
//// todoList.size.coerceAtMost(numberOfTodos)
// 0
// } else {
//// todoList.size
// 0
// }
// }
//
// @SuppressLint("SetTextI18n")
// override fun onBindViewHolder(holder: TodoViewHolder, position: Int) {
//// val todo = todoList[position]
//
//// holder.view.itemText.text = "\u25CF ${todo.name}"
////
//// if (currentFragment is TodoManager) {
//// /* multiline texts are enabled for TodoManager */
//// holder.view.itemText.isSingleLine = false
//// /* launch edit or update dialog on item click */
//// holder.view.itemText.setOnClickListener { updateDialog(position) }
//// /* copy texts on long click */
//// holder.view.itemText.setOnLongClickListener {
//// copyToClipboard(context, todo.name)
//// true
//// }
//// } else {
//// /* single line text for home screen */
//// holder.view.itemText.isSingleLine = true
//// }
// }
//
// inner class TodoViewHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
//
// /* update dialog */
// private fun updateDialog(position: Int) {
// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(context))
// bottomSheetDialog.setContentView(dialogBinding.root)
// bottomSheetDialog.show()
// bottomSheetDialog.dismissWithAnimation = true
//
// val databaseHandler = DatabaseHandler(context)
// val todo = databaseHandler.todos[position]
//
// dialogBinding.apply {
// deleteAllConfirmation.visibility = View.GONE
// todoInput.setText(todo.name)
// todoCancel.text = context.getString(R.string.delete)
// todoCancel.setTextColor(ContextCompat.getColor(context, android.R.color.holo_red_light))
// todoOk.text = context.getString(R.string.update)
// }
//
// /* delete the item */
// dialogBinding.todoCancel.setOnClickListener {
// databaseHandler.deleteTodo(todo.id)
// bottomSheetDialog.dismiss()
// todoManager?.refreshList()
// }
//
// /* update the item */
// dialogBinding.todoOk.setOnClickListener {
// val updatedTodoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
// if (updatedTodoString.isNotEmpty()) {
// todo.name = updatedTodoString
// databaseHandler.updateTodo(todo)
// bottomSheetDialog.dismiss()
// todoManager?.refreshList()
// } else {
// dialogBinding.todoInput.error = context.getString(R.string.empty_text_field)
// }
// }
// }
//
//}

View File

@ -1,129 +0,0 @@
///*
// * Lunar Launcher
// * Copyright (C) 2022 Md Rasel Hossain
// *
// * This program is free software: you can redistribute it and/or modify
// * it under the terms of the GNU General Public License as published by
// * the Free Software Foundation, either version 3 of the License, or
// * (at your option) any later version.
// *
// * This program is distributed in the hope that it will be useful,
// * but WITHOUT ANY WARRANTY; without even the implied warranty of
// * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// * GNU General Public License for more details.
// *
// * You should have received a copy of the GNU General Public License
// * along with this program. If not, see <http://www.gnu.org/licenses/>.
// */
//
//package rasel.lunar.launcher.todos
//
//import android.content.Context
//import android.os.Bundle
//import android.view.LayoutInflater
//import android.view.View
//import android.view.ViewGroup
//import android.view.inputmethod.InputMethodManager
//import androidx.core.content.ContextCompat
//import androidx.fragment.app.Fragment
//import com.google.android.material.bottomsheet.BottomSheetDialog
//import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
//import rasel.lunar.launcher.R
//import rasel.lunar.launcher.databinding.TodoDialogBinding
//import rasel.lunar.launcher.databinding.TodoManagerBinding
//import java.util.*
//
//
//internal class TodoManager : Fragment() {
//
// private lateinit var binding: TodoManagerBinding
// private lateinit var databaseHandler: DatabaseHandler
//
// override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
//
// binding = TodoManagerBinding.inflate(inflater, container, false)
// databaseHandler = DatabaseHandler(requireContext())
//
// return binding.root
// }
//
// override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
// super.onViewCreated(view, savedInstanceState)
// /* click listeners for add new and delete all buttons */
// binding.addNew.setOnClickListener { addNewDialog() }
// binding.deleteAll.setOnClickListener { deleteAllDialog() }
// }
//
// override fun onResume() {
// super.onResume()
// refreshList()
// lActivity!!.viewPager.isUserInputEnabled = false
// }
//
// override fun onPause() {
// super.onPause()
// lActivity!!.viewPager.isUserInputEnabled = true
// }
//
// fun refreshList() {
// binding.todos.adapter = TodoAdapter(this, requireContext())
// }
//
// /* add new dialog */
// private fun addNewDialog() {
// val bottomSheetDialog = BottomSheetDialog(lActivity!!, R.style.BottomSheetDialog)
// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(requireContext()))
// bottomSheetDialog.setContentView(dialogBinding.root)
// bottomSheetDialog.show()
// bottomSheetDialog.dismissWithAnimation = true
//
// dialogBinding.deleteAllConfirmation.visibility = View.GONE
// /* automatic keyboard popup */
// dialogBinding.todoInput.requestFocus()
// val inputMethodManager = lActivity!!.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager
// inputMethodManager.showSoftInput(dialogBinding.todoInput, InputMethodManager.SHOW_IMPLICIT)
//
// /* dismiss the dialog on cancel button click */
// dialogBinding.todoCancel.setOnClickListener { bottomSheetDialog.dismiss() }
// /* add new item to the database */
// dialogBinding.todoOk.setOnClickListener {
// val todo = Todo()
// val todoString = Objects.requireNonNull(dialogBinding.todoInput.text).toString().trim { it <= ' ' }
// if (todoString.isNotEmpty()) {
// todo.name = todoString
// databaseHandler.addTodo(todo)
// bottomSheetDialog.dismiss()
// refreshList()
// } else {
// dialogBinding.todoInput.error = getString(R.string.empty_text_field)
// }
// }
// }
//
// /* delete all dialog */
// private fun deleteAllDialog() {
// val bottomSheetDialog = BottomSheetDialog(lActivity!!)
// val dialogBinding = TodoDialogBinding.inflate(LayoutInflater.from(requireContext()))
// bottomSheetDialog.setContentView(dialogBinding.root)
// bottomSheetDialog.show()
// bottomSheetDialog.dismissWithAnimation = true
//
// /* if any item does not exist, then disable the ok button */
// if (!databaseHandler.isTodoExists) {
// dialogBinding.todoOk.isEnabled = false
// }
//
// dialogBinding.todoInput.visibility = View.GONE
// dialogBinding.todoOk.setTextColor(ContextCompat.getColor(requireContext(), android.R.color.holo_red_light))
//
// /* dismiss the dialog on cancel button click */
// dialogBinding.todoCancel.setOnClickListener { bottomSheetDialog.dismiss() }
// /* delete all the existing items from the database */
// dialogBinding.todoOk.setOnClickListener {
// databaseHandler.deleteAll()
// bottomSheetDialog.dismiss()
// refreshList()
// }
// }
//
//}

View File

@ -1,8 +1,10 @@
package rasel.lunar.launcher.todos package rasel.lunar.launcher.todos
import org.json.JSONObject import org.json.JSONObject
import rasel.lunar.launcher.model.Image import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.Source import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.model.YTBImage
import rasel.lunar.launcher.model.YTBSource
import rasel.lunar.launcher.utils.afterDay import rasel.lunar.launcher.utils.afterDay
import rasel.lunar.launcher.utils.beforeDay import rasel.lunar.launcher.utils.beforeDay
import java.util.Date import java.util.Date
@ -90,7 +92,7 @@ class Avatar {
} }
class AvatarViewModel { class AvatarViewModel {
var image: Image? = null var YTBImage: YTBImage? = null
var avatarImageSize: String? = null var avatarImageSize: String? = null
var loggingDirectives: LoggingDirectives? = null var loggingDirectives: LoggingDirectives? = null
} }
@ -589,19 +591,19 @@ class Identifier {
} }
class Image { class Image {
var sources: ArrayList<Source>? = null var sources: ArrayList<YTBSource>? = null
var decoratedAvatarViewModel: DecoratedAvatarViewModel? = null var decoratedAvatarViewModel: DecoratedAvatarViewModel? = null
var processor: Processor? = null var processor: Processor? = null
} }
class ImageBannerViewModel { class ImageBannerViewModel {
var image: Image? = null var YTBImage: YTBImage? = null
var style: String? = null var style: String? = null
var rendererContext: RendererContext? = null var rendererContext: RendererContext? = null
} }
class ImageType { class ImageType {
var image: Image? = null var YTBImage: YTBImage? = null
} }
class InlineContent { class InlineContent {
@ -653,7 +655,7 @@ class LayoutProperties {
} }
class LeadingImage { class LeadingImage {
var sources: ArrayList<Source>? = null var sources: ArrayList<YTBSource>? = null
} }
class Left { class Left {
@ -973,7 +975,7 @@ class PageHeaderRenderer {
class PageHeaderViewModel { class PageHeaderViewModel {
var title: Title? = null var title: Title? = null
var image: Image? = null var YTBImage: YTBImage? = null
var metadata: Metadata? = null var metadata: Metadata? = null
var actions: Action? = null var actions: Action? = null
var description: Description? = null var description: Description? = null
@ -1565,7 +1567,7 @@ class VideoCountText {
var runs: ArrayList<Run>? = null var runs: ArrayList<Run>? = null
} }
open class VideoRenderer : RssDataItem { open class VideoRenderer : RssDataInterface {
var videoId: String? = null var videoId: String? = null
var thumbnail: Thumbnail? = null var thumbnail: Thumbnail? = null
var title: Title? = null var title: Title? = null

View File

@ -1,830 +0,0 @@
package rasel.lunar.launcher.utils
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.CallLog
import android.provider.ContactsContract.PhoneLookup
import android.provider.Telephony
import androidx.work.Worker
import androidx.work.WorkerParameters
import com.google.gson.Gson
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.rssSetTouchCount
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.home.RssItem
import rasel.lunar.launcher.todos.Root
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.todos.RssFeedsParser
import rasel.lunar.launcher.utils.RssList.feedJsons
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.text.SimpleDateFormat
import java.util.Calendar
import java.util.Date
class MissedCallGetter : Worker {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
var dateParam = beforeDay(Date(),3).toString()
var managedCursor =lActivity?.contentResolver?.query(
CallLog.Calls.CONTENT_URI, arrayOf(
CallLog.Calls.NUMBER,
CallLog.Calls.TYPE,
CallLog.Calls.DATE,
CallLog.Calls.DURATION,
CallLog.Calls.CACHED_NAME,
), CallLog.Calls.DATE + " >= ? " , arrayOf<String>(dateParam), CallLog.Calls.DATE + " desc")
//+ CallLog.Calls.TYPE + " > ?"
//, "2"
if(managedCursor != null && managedCursor.isClosed == false) {
try {
val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
missedCalls.clear()
while (managedCursor.moveToNext()) {
val phNumber = managedCursor.getString(number) // mobile number
val callType = managedCursor.getString(type) // call type
val callDate = managedCursor.getString(date) // call date
val callDayTime: Date = Date(callDate.toLong())
val callDuration = managedCursor.getString(duration)
val callerName = managedCursor.getString(name)
var dir: String = ""
val dircode = callType.toInt()
when (dircode) {
CallLog.Calls.INCOMING_TYPE -> {
dir = "INCOMING_TYPE"
}
CallLog.Calls.OUTGOING_TYPE -> {
dir = "OUTGOING_TYPE"
}
CallLog.Calls.MISSED_TYPE -> {
dir = "MISSED_TYPE"
}
CallLog.Calls.VOICEMAIL_TYPE -> {
dir = "VOICEMAIL_TYPE"
}
CallLog.Calls.REJECTED_TYPE -> {
dir = "REJECTED_TYPE"
}
CallLog.Calls.BLOCKED_TYPE -> {
dir = "BLOCKED_TYPE"
}
CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> {
dir = "ANSWERED_EXTERNALLY_TYPE"
}
}
var missed: MissedCall = if (missedCalls.containsKey(phNumber)) {
missedCalls.get(phNumber)!!.apply {
count = count + 1
}
} else {
MissedCall(
1,
callerName,
phNumber,
dircode,
dir,
SimpleDateFormat("yyy/MM/dd-HH:mm:ss").format(callDayTime)
)
}
// BLog.LOGE("missed put >>> ${missed.toJson()}")
missedCalls.put(phNumber, missed)
}
} catch (e: Exception) {
} finally {
managedCursor.close()
}
}
return Result.success()
}
}
val USAGT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15"
fun before30Min(date: Date): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.MINUTE, -30)
return cal.timeInMillis
}
fun beforeDay(date: Date?, day: Int): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.DAY_OF_YEAR, Math.abs(day) * -1)
return cal.timeInMillis
}
fun make0H(date: Date?): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.set(Calendar.HOUR, 1)
return cal.timeInMillis
}
fun afterDay(date: Date?, day: Int): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.DAY_OF_YEAR, Math.abs(day) * 1)
return cal.timeInMillis
}
class RecentSmsGetter : Worker {
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.getLong(date) // call date
val sendedDate = managedCursor.getLong(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) {
TestQueryHelper(lActivity?.contentResolver!!).query()
}
return Result.success()
}
}
class RecentSmsLog {
var id : String = ""
var isMms : Boolean = false
var addr : String = ""
var type : String = ""
var rcvDate : Long = 0L
var pstDate : Long = 0L
var body : String = ""
var person : String = ""
var mmsContents : HashMap<String?,ArrayList<String>> = hashMapOf()
var sender : String = ""
constructor(
addr: String,
type: String,
rcvDate: Long,
pstDate: Long,
body: String,
person: String
) {
this.addr = addr
this.type = type
this.rcvDate = rcvDate
this.pstDate = pstDate
this.body = body
this.person = person
this.isMms = false
}
constructor(id: String, sender: String, date: Long, body: HashMap<String?,ArrayList<String>>) {
this.id = id
this.rcvDate = date
this.mmsContents = body
this.addr = sender
this.isMms = true
}
fun toJson() : String {
return Gson().toJson(this)
}
}
class TestQueryHelper(
private val _contentResolver: ContentResolver
) {
private val mmsUri: Uri = Telephony.Mms.CONTENT_URI
private val cursor: Cursor?
get() =
_contentResolver.query(
mmsUri,
null,
null,
null,
null
)
fun dataMapper(cursor: Cursor): RecentSmsLog {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Mms._ID))
val date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Mms.DATE)) * 1000
val sender : String = getSender(id) ?: throw NullPointerException("NotFound Sender For Mms")
val body = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
return RecentSmsLog(
id = id.toString(),
date = date,
body = body,
sender = sender
).apply {
isMms = true
this.sender = getContactName(_contentResolver,addr) ?: ""
}
}
private fun getSender(id: Int): String? {
_contentResolver.query(
Uri.parse("content://mms/$id/addr"),
null,
"${Telephony.Mms.Addr.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { senderAddressCursor ->
if (senderAddressCursor.moveToFirst()) {
do {
// 137 수신, 151 발신 타입 값이다. Telephony.Mms.Addr.Type 의 주석 참고.
val isSender = senderAddressCursor.getInt(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.TYPE)
) == 137
var sender = senderAddressCursor.getString(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.ADDRESS)
)
// BLog.LOGE("sender >> ${sender}")
if (isSender) {
return sender
}
} while (senderAddressCursor.moveToNext())
}
}
return null
}
private fun getMmsText(id: String): String {
val partURI = Uri.parse("content://mms/part/$id")
var `is`: InputStream? = null
val sb = StringBuilder()
try {
`is` = _contentResolver.openInputStream(partURI)
if (`is` != null) {
val isr = InputStreamReader(`is`, "UTF-8")
val reader = BufferedReader(isr)
var temp = reader.readLine()
while (temp != null) {
sb.append(temp)
temp = reader.readLine()
BLog.LOGE("temp >>> ${temp}")
}
}
} catch (e: IOException) {
} finally {
if (`is` != null) {
try {
`is`.close()
} catch (e: IOException) {
}
}
}
BLog.LOGE("sb >>> ${sb.toString()}")
return sb.toString()
}
private fun getBody(id: Int): HashMap<String?,ArrayList<String>> {
var returns = hashMapOf<String?,ArrayList<String>>()
val text = arrayListOf<String>()
val image = arrayListOf<String>()
val audio = arrayListOf<String>()
val projection = arrayOf("*")
val video = arrayListOf<String>()
_contentResolver.query(
Uri.parse("content://mms/part"),
projection,
"${Telephony.Mms.Part.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { partsCursor ->
if (partsCursor.moveToFirst()) {
do {
val partId: String = partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._ID))
val partContentType =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE))
// BLog.LOGE("partContentType >> ${partContentType}")
if(partContentType?.contains("text") == true) {
// BLog.LOGE("partContentType text >> ${partContentType} :: ${partId}")
val data =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA))
val textBody =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
if (data != null && data.length > 0) {
text.add(getMmsText(partId))
} else {
text.add(textBody)
}
}
else if(partContentType?.contains("image") == true) {
// BLog.LOGE("partContentType image >> ${partContentType}:: ${partId}")
image.add(partId)
}
else if(partContentType?.contains("audio") == true) {
// BLog.LOGE("partContentType audio >> ${partContentType}:: ${partId}")
audio.add(partId)
}
else if(partContentType?.contains("video") == true) {
// BLog.LOGE("partContentType video >> ${partContentType}:: ${partId}")
video.add(partId)
}
else {
// BLog.LOGE("partContentType >> ${partContentType}:: ${partId}")
}
// if (partContentType == "text/plain") {
// var textBody =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
//// .replace("\n\n", "\n").replace("\n", " ")
//// if (textBody.length > 60) {
//// textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
//// }
//// BLog.LOGE("textBody >>> ${textBody}")
// return Pair(textBody , partContentType)
// }
} while (partsCursor.moveToNext())
}
}
returns.put("text", text)
returns.put("image", image)
returns.put("audio", audio)
returns.put("video", video)
// BLog.LOGE("returns.get(text).join => ${text.size} :: ${text.joinToString("\n")}")
return returns
}
fun convertData(cursor: Cursor?) {
cursor ?: return
val dateTime = beforeDay(Date(),3)
cursor.use {
if (cursor.moveToFirst()) {
do {
val data = kotlin.runCatching {
dataMapper(cursor)
}.getOrNull()
data?.let {
if (it?.pstDate ?: 0L > dateTime || it?.rcvDate ?: 0L > dateTime) {
smsList.add(it)
}
}
} while (cursor.moveToNext())
}
}
}
fun query() {
return convertData(cursor)
}
}
fun getContactName(contentResolver: ContentResolver, phoneNumber: String?): String? {
val cr = contentResolver
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
val cursor =
cr.query(uri, arrayOf(PhoneLookup.DISPLAY_NAME), null, null, null)
?: return null
var contactName: String? = null
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME))
}
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
return contactName
}
fun getContactId(contentResolver: ContentResolver, phoneNumber: String?): String? {
val cr = contentResolver
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
val cursor =
cr.query(uri, arrayOf(PhoneLookup._ID), null, null, null)
?: return null
var contactName: String? = null
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID))
}
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
return contactName
}
class NewsFeedsGetter : Worker {
var feddsUrls = arrayListOf<String>()
var limitDateTime = beforeDay(Date(),3)
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssSetTouchCount += 1
val temp = arrayListOf<RssDataItem>()
feddsUrls.clear()
feddsUrls.addAll(RssList.newsFeeds)
feddsUrls.addAll(RssList.getFeedUrls())
for(url in feddsUrls) {
for (it in RssFeedsParser.getFeeds(url)) {
if (it.pubDate() >= limitDateTime) {
temp.add(it)
}
}
}
return temp.forEach { synchronized(rssSet){
rssSet.put(it.originPage(), it)
} }.run {
rssSetTouchCount -= 1
Result.success() }
}
}
class RedditGetter : Worker {
var limitDateTime = beforeDay(Date(),3)
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssSetTouchCount += 1
val temp = arrayListOf<RssDataItem>()
for (url in feedJsons) {
for (it in RssFeedsParser.getReddit(url)) {
if (it.pubDate() >= limitDateTime) {
temp.add(it)
}
}
}
return temp.forEach { synchronized(rssSet){
rssSet.put(it.originPage(), it)
} }.run {
rssSetTouchCount -= 1
Result.success() }
}
}
class YoutubeGetter : Worker {
var rssUrls = arrayListOf<String>()
var limitDateTime = beforeDay(Date(),3)
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssSetTouchCount += 1
rssUrls.clear()
rssUrls.addAll(RssList.youtubeUrls)
val temp = arrayListOf<RssDataItem>()
for (url in rssUrls) {
ytChannel(Jsoup.connect(url).userAgent(USAGT).get())
}
return temp.forEach { synchronized(rssSet){
rssSet.put(it.originPage(), it)
} }.run {
rssSetTouchCount -= 1
Result.success() }
}
fun ytChannel(doc: Document) {
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) {
root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
it.shelfRenderer?.content?.verticalListRenderer?.items?.forEach {
(it.compactVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() > limitDateTime) {
rssSet.put(it.originPage(), it)
}
}
}
}
}
} else {
BLog.LOGE("ytChannel >>>>> doc twoColumnBrowseResultsRenderer apply ")
root?.contents?.twoColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
it.itemSectionRenderer?.contents?.forEach {
it.shelfRenderer?.content?.horizontalListRenderer?.items?.forEach {
(it.gridVideoRenderer as? RssDataItem)?.let {
if(it.pubDate() >limitDateTime) {
rssSet.put(it.originPage(), it)
}
}
}
}
}
}
}).apply {
BLog.LOGE("ytChannel >>>>> doc${doc.title()} apply ")
}
}
}
}
} catch(e: Exception) {
}
}
}
class ComicsGetter : Worker {
var limitDateTime = beforeDay(Date(),3)
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssSetTouchCount += 1
val temp = arrayListOf<RssDataItem>()
val now = Date()
try {
val fmkoreaUrls = arrayListOf("https://www.fmkorea.com",
"https://www.fmkorea.com/index.php?mid=best&page=2",
"https://www.fmkorea.com/index.php?mid=best&page=3"
)
fmkoreaUrls.forEach { Jsoup.connect(it).userAgent(USAGT).get().let { fmkorea ->
// BLog.LOGE("fmkorea >>> ${fmkorea.title()}")
fmkorea.getElementsByTag("li").forEach { fmkorea_li ->
if (fmkorea_li.getElementsByClass("title").text().length > 0 && fmkorea_li.getElementsByTag("a").size > 0 &&fmkorea_li.getElementsByTag("a").get(0).attr("href").length > 0) {
// BLog.LOGE("fmkorea_li >>> ${fmkorea_li}")
val title = fmkorea_li.getElementsByClass("title").text()
val tumb = "https://".plus(
fmkorea_li.getElementsByClass("thumb").attr("data-original")
)
val pageUrl = "https://www.fmkorea.com".plus(
fmkorea_li.getElementsByTag("a").get(0).attr("href")
)
val desc = fmkorea_li.getElementsByClass("category").text()
val date = fmkorea_li.getElementsByClass("regdate").text()
FmKorea(pageUrl, desc, date, title, tumb).apply {
if(desc?.contains("유머") == true|| desc?.contains("음악") == true|| desc?.contains("영화")== true ||
desc?.contains("TV")== true || desc?.contains("미스터리")== true || desc?.contains("역사")== true) {
if (this.pubDate() > before30Min(now)) {
temp.add(this)
}
}
}
}
}
} }
} catch (e : Exception) {e.printStackTrace()}
return temp.forEach { synchronized(rssSet){
rssSet.put(it.originPage(), it)
} }.run {
rssSetTouchCount -= 1
Result.success() }
}
}
class ComicsGetter2 : Worker {
var limitDateTime = beforeDay(Date(),3)
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssSetTouchCount += 1
val temp = arrayListOf<RssDataItem>()
val now = Date()
try {
val dotaxUrls = arrayListOf("https://m.cafe.daum.net/dotax",
"https://m.cafe.daum.net/dotax/_rec?page=2",
"https://m.cafe.daum.net/dotax/_rec?page=3"
)
dotaxUrls?.forEach {
Jsoup.connect(it).userAgent(USAGT).get()?.let { dotax ->
// BLog.LOGE("dotax_li >>> ${dotax.title()}")
dotax.getElementsByTag("li").forEach { dotax_li ->
if (dotax_li.getElementsByTag("a").size > 0 && dotax_li.getElementsByClass("board_name")
.html().contains("웃긴")
) {
val pageLink = dotax_li.getElementsByTag("a").get(0).attr("href")
val desc = dotax_li.getElementsByClass("board_name").text()
val dateTime = dotax_li.getElementsByClass("created_at").text()
val title = dotax_li.getElementsByClass("txt_detail").text()
val thumbnail = dotax_li.getElementsByClass("article_thumb").text()
if (pageLink.length > 0 && desc.length > 0 && dateTime.length > 0 && title.length > 0) {
BLog.LOGE("dotax_li >>> ${dotax_li}")
Dotax(pageLink, desc, dateTime, title, thumbnail).apply {
// BLog.LOGE("dotax_li >>> ${Gson().toJson(this)}")
if(this.pubDate() > before30Min(now)) {
temp.add(this)
}
}
}
}
}
}
}
} catch (e : Exception) {e.printStackTrace()}
return temp.forEach { synchronized(rssSet){
rssSet.put(it.originPage(), it)
} }.run {
rssSetTouchCount -= 1
Result.success() }
}
}
open class Dotax(var pageLink : String,
var desc : String,
var dateTime : String,
var title : String,
var thumbnail : String) : RssDataItem {
var updateDateTime = 0L
override fun title(): String {
return title
}
override fun thumbnailUrl(): String {
return thumbnail
}
override fun originPage(): String {
return "https://m.cafe.daum.net".plus(pageLink)
}
override fun description(): String {
return desc
}
override fun pubDate(): Long {
var date = Date()
var dateTime = date.time
var before = 0
if (updateDateTime == 0L) {
try {
var targetDate = this.dateTime ?: ""
if (targetDate?.length ?: 0 > 1) {
var dateDesc = targetDate
var isBefore = dateDesc.contains("")
val dayString = dateDesc.replace("[^0-9]".toRegex(), "")
before = dayString.toInt()
if (dateDesc.contains("")) {
before = 365 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
before = 30 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
before = 7 * before
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("")) {
dateTime = if (isBefore) beforeDay(date, before) else afterDay(date, before)
} else if (dateDesc.contains("시간")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L * 60L * 60L)) else dateTime.plus(
before.times(1000L * 60L * 60L)
)
} else if (dateDesc.contains("")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L * 60L)) else dateTime.plus(
before.times(1000L * 60L)
)
}
else if (dateDesc.contains("")) {
dateTime =
if (isBefore) dateTime.minus(before.times(1000L)) else dateTime.plus(
before.times(1000L)
)
}
}
} catch (e: Exception) {
} finally {
updateDateTime = dateTime
}
} else {
dateTime = updateDateTime
}
return dateTime
}
override fun category(): RssDataType {
return RssDataType.Dotax
}
}
data class FmKorea(var apageLink : String,
var adesc : String,
var adateTime : String,
var atitle : String,
var athumbnail : String) : Dotax(apageLink, adesc, adateTime, atitle, athumbnail) {
override fun originPage(): String {
return pageLink
}
override fun category(): RssDataType {
return RssDataType.FmKorae
}
}

View File

@ -0,0 +1,83 @@
package rasel.lunar.launcher.utils
import android.content.ContentResolver
import android.net.Uri
import android.provider.ContactsContract.PhoneLookup
import java.util.Calendar
import java.util.Date
fun before30Min(date: Date): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.MINUTE, -30)
return cal.timeInMillis
}
fun beforeDay(date: Date?, day: Int): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.DAY_OF_YEAR, Math.abs(day) * -1)
return cal.timeInMillis
}
fun make0H(date: Date?): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.set(Calendar.HOUR, 1)
return cal.timeInMillis
}
fun afterDay(date: Date?, day: Int): Long {
val cal: Calendar = Calendar.getInstance()
cal.setTime(date)
cal.add(Calendar.DAY_OF_YEAR, Math.abs(day) * 1)
return cal.timeInMillis
}
fun getContactName(contentResolver: ContentResolver, phoneNumber: String?): String? {
val cr = contentResolver
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
val cursor =
cr.query(uri, arrayOf(PhoneLookup.DISPLAY_NAME), null, null, null)
?: return null
var contactName: String? = null
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup.DISPLAY_NAME))
}
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
return contactName
}
fun getContactId(contentResolver: ContentResolver, phoneNumber: String?): String? {
val cr = contentResolver
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
val cursor =
cr.query(uri, arrayOf(PhoneLookup._ID), null, null, null)
?: return null
var contactName: String? = null
if (cursor.moveToFirst()) {
contactName = cursor.getString(cursor.getColumnIndexOrThrow(PhoneLookup._ID))
}
if (cursor != null && !cursor.isClosed) {
cursor.close()
}
return contactName
}

View File

@ -24,6 +24,8 @@ object RssList {
val feedJsons = arrayListOf( val feedJsons = arrayListOf(
"https://www.reddit.com/r/nsfw/.json", "https://www.reddit.com/r/nsfw/.json",
"https://www.reddit.com/r/Mogong/.json", "https://www.reddit.com/r/Mogong/.json",
// "https://www.reddit.com/r/Mogong/comments/e6tu50/19_%ED%9B%84%EB%B0%A9%EA%B0%80%EB%93%9D%ED%95%9C_%EC%84%9C%EB%B8%8C%EB%A0%88%EB%94%A7/.json"
// "https://www.reddit.com/r/${URLEncoder.encode("모공")}/.json", // "https://www.reddit.com/r/${URLEncoder.encode("모공")}/.json",
) )

View File

@ -0,0 +1,57 @@
package rasel.lunar.launcher.view
import android.R
import android.content.Context
import android.content.res.TypedArray
import android.graphics.Color
import android.os.Build
import android.os.Handler
import android.os.Looper
import android.text.SpannableString
import android.text.SpannableStringBuilder
import android.util.AttributeSet
import android.view.LayoutInflater
import android.view.View
import android.widget.LinearLayout
import android.widget.TextView
import androidx.appcompat.widget.AppCompatTextView
import java.text.SimpleDateFormat
import java.util.Date
class DateTimeView : AppCompatTextView {
lateinit var mHandler : Handler
val simpleTimeFormat = SimpleDateFormat("a HH:mm:ss")
val simpleDateFormat = SimpleDateFormat("yyyy년 MM월 W주차 dd일 E요일")
var runable = {
setTime()
}
constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context,
attrs,
defStyleAttr
) {
}
init {
mHandler = Handler(Looper.getMainLooper())
mHandler.postDelayed(runable, DateTimeView.DALEY)
}
val spannableBuilder = SpannableStringBuilder()
private fun setTime() {
mHandler.removeCallbacks(runable)
setText(simpleDateFormat.format(Date(System.currentTimeMillis())))
mHandler.postDelayed(runable, DateTimeView.DALEY)
}
companion object {
const val DALEY = 500L
}
}

View File

@ -0,0 +1,92 @@
package rasel.lunar.launcher.workers
import android.content.Context
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import rasel.lunar.launcher.model.Arca
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.model.getT
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class ArcaGetter : BaseGetter {
companion object {
val TAG = "DCGetter"
}
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
override fun doWork(): Result {
try {
val urls = arrayListOf(
"https://arca.live/b/singbung?mode=best",
"https://arca.live/b/headline",
"https://arca.live/b/live",
"https://arca.live/b/namuhotnow",
"https://arca.live/b/society",
"https://arca.live/b/replay",
"https://arca.live/b/breaking"
)
urls.forEach {
Jsoup.connect(it)
.userAgent(USAGT)
.get().let { arca ->
// BLog.LOGE("url >> ${it} >> ${arca}")
arca.getElementsByClass("vrow hybrid").forEach { araca_li ->
if (araca_li.html().contains("title ") == true) {
parseArcaLi(araca_li).apply {
this.forEach {
if (it.pubDate() > commicsDateTime) {
temp.add(it.getRssData())
}
}
}
}
}
}
}
// Jsoup.connect("https://projrctjav.com").userAgent(USAGT).get().let { projectj ->
// BLog.LOGE("projectj >>>>> ${projectj}")
// }
} catch (e:Exception){e.printStackTrace()}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
}
private fun parseArcaLi(aracaLi: Element) : ArrayList<RssDataInterface> {
var tempArray = arrayListOf<RssDataInterface>()
// BLog.LOGE("aracaLi >>> ${aracaLi}")
var title = aracaLi.getElementsByClass("title hybrid-title").getT()
var desc = aracaLi.getElementsByClass("badge").getT()
desc.plus(aracaLi.getElementsByClass("user-info ").getT())
var dateTime = aracaLi.getElementsByTag("time").attr("datetime")
var tumbnail = aracaLi.getElementsByTag("img").attr("src")
var link = "https://arca.live".plus(if(aracaLi.getElementsByClass("title hybrid-title").size > 0) aracaLi.getElementsByClass("title hybrid-title").get(0).attr("href") else if(aracaLi.getElementsByTag("a").size > 0) aracaLi.getElementsByTag("a").get(0).attr("href") else "")
if (title.length > 0 && link.length > 20) {
Arca().apply {
this.link = link
this.title = title
if (tumbnail.length > 0) {
this.thumbnail = "https:".plus(tumbnail)
//
// BLog.LOGE("Arca thumbnail >>> ${thumbnail}")
}
this.desc = desc
this.dateTiem = dateTime
}.apply {
// BLog.LOGE("parseArcaLi >>>> ${this}")
if(this.pubDate() > beforeDay(Date(),3)) {
tempArray.add(this)
}
}
}
return tempArray
}
}

View File

@ -0,0 +1,23 @@
package rasel.lunar.launcher.workers
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
open class BaseGetter : Worker {
val USAGT = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.4 Safari/605.1.15"
val now = Date()
val limitDateTime = beforeDay(now,3)
val commicsDateTime = beforeDay(now,1)
val temp = arrayListOf<RssData>()
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
override fun doWork(): Result {
TODO("Not yet implemented")
}
}

View File

@ -0,0 +1,97 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import rasel.lunar.launcher.model.DcInside
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.model.RssDataInterface
class DCGetter : BaseGetter {
companion object {
val TAG = "DCGetter"
}
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
fun parseDcLi(dc_li : org.jsoup.nodes.Element) : ArrayList<RssDataInterface>{
var temp = arrayListOf<RssDataInterface>()
if (dc_li.html().contains("<ul class=>") && dc_li.html().contains("con_list img")) {
dc_li.child(0).getElementsByTag("li").forEach {
parseDcLi(it)
}
} else {
var link = if (dc_li.getElementsByTag("a").size > 0) dc_li.getElementsByTag("a").get(0)
.attr("href") else ""
var title =
if (dc_li.getElementsByClass("box besttxt").size > 0) dc_li.getElementsByClass("box besttxt")
.get(0)
.text() else if (dc_li.getElementsByClass("tit").size > 0) dc_li.getElementsByClass(
"tit"
).get(0).text() else ""
var thumbnail =
if (dc_li.getElementsByTag("img").size > 0) dc_li.getElementsByTag("img").get(0)
.attr("src") else ""
var desc =
if (dc_li.getElementsByClass("box best_info").size > 0) dc_li.getElementsByClass("box best_info")
.get(0).text() else ""
var dateTiem =
if (dc_li.getElementsByClass("time").size > 0) dc_li.getElementsByClass("time")
.get(0).text() else ""
link = link.replace("&amp;","&")
thumbnail = thumbnail.replace("&amp;","&")
// BLog.LOGE("DC_LI >>>> link >>>> ${link}")
// BLog.LOGE("DC_LI >>>> title >>>> ${title}")
// BLog.LOGE("DC_LI >>>> thumbnail >>>> ${thumbnail}")
// BLog.LOGE("DC_LI >>>> desc >>>> ${desc}")
// BLog.LOGE("DC_LI >>>> dateTiem >>>> ${dateTiem}")
if (title.length > 0 && link.length > 0) {
DcInside().apply {
this.link = link
this.title = title
this.thumbnail = thumbnail
this.desc = desc
this.dateTiem = dateTiem
}.apply {
if (this.pubDate() > limitDateTime) {
temp.add(this.getRssData())
}
}
}
}
return temp
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
var tempArray = arrayListOf<RssData>()
try {
val testUrl2 = "https://www.dcinside.com/"
Jsoup.connect(testUrl2)
.userAgent(USAGT)
.get().let { dc ->
// BLog.LOGE("test ${testUrl2} >> ${this}")
dc.getElementsByTag("li").forEach { dc_li ->
if (dc_li.html().contains("main_log") == true) {
parseDcLi(dc_li).apply {
this.forEach {
if (it.pubDate() > commicsDateTime) {
tempArray.add(it.getRssData())
}
}
}
}
}
}
} catch (e:Exception){e.printStackTrace()}
return Result.success().apply {
WorkersDb.insertBulkData(tempArray)
}
}
}

View File

@ -0,0 +1,54 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import rasel.lunar.launcher.model.Dotax
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.before30Min
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class DotaxGetter : BaseGetter {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
try {
val dotaxUrls = arrayListOf("https://m.cafe.daum.net/dotax",
"https://m.cafe.daum.net/dotax/_rec?page=2",
"https://m.cafe.daum.net/dotax/_rec?page=3"
)
dotaxUrls?.forEach {
Jsoup.connect(it).userAgent(USAGT).get()?.let { dotax ->
dotax.getElementsByTag("li").forEach { dotax_li ->
if (dotax_li.getElementsByTag("a").size > 0 && dotax_li.getElementsByClass("board_name")
.html().contains("웃긴")
) {
val pageLink = dotax_li.getElementsByTag("a").get(0).attr("href")
val desc = dotax_li.getElementsByClass("board_name").text()
val dateTime = dotax_li.getElementsByClass("created_at").text()
val title = dotax_li.getElementsByClass("txt_detail").text()
val thumbnail = dotax_li.getElementsByClass("article_thumb").text()
if (pageLink.length > 0 && desc.length > 0 && dateTime.length > 0 && title.length > 0) {
Dotax(pageLink, desc, dateTime, title, thumbnail).let { dotax ->
if(dotax.pubDate() > commicsDateTime) {
temp.add(dotax.getRssData())
}
}
}
}
}
}
}
} catch (e : Exception) {e.printStackTrace()}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
}
}

View File

@ -0,0 +1,59 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import rasel.lunar.launcher.model.FmKorea
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.utils.before30Min
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class FmKoreaGetter : BaseGetter {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
val now = Date()
try {
val fmkoreaUrls = arrayListOf("https://www.fmkorea.com",
"https://www.fmkorea.com/index.php?mid=best&page=2",
"https://www.fmkorea.com/index.php?mid=best&page=3"
)
fmkoreaUrls.forEach { Jsoup.connect(it).userAgent(USAGT).get().let { fmkorea ->
// BLog.LOGE("fmkorea >>> ${fmkorea.title()}")
fmkorea.getElementsByTag("li").forEach { fmkorea_li ->
if (fmkorea_li.getElementsByClass("title").text().length > 0 && fmkorea_li.getElementsByTag("a").size > 0 &&fmkorea_li.getElementsByTag("a").get(0).attr("href").length > 0) {
// BLog.LOGE("fmkorea_li >>> ${fmkorea_li}")
val title = fmkorea_li.getElementsByClass("title").text()
val tumb = "https://".plus(
fmkorea_li.getElementsByClass("thumb").attr("data-original")
)
val pageUrl = "https://www.fmkorea.com".plus(
fmkorea_li.getElementsByTag("a").get(0).attr("href")
)
val desc = fmkorea_li.getElementsByClass("category").text()
val date = fmkorea_li.getElementsByClass("regdate").text()
FmKorea(pageUrl, desc, date, title, tumb).apply {
if(desc?.contains("유머") == true|| desc?.contains("음악") == true|| desc?.contains("영화")== true ||
desc?.contains("TV")== true || desc?.contains("미스터리")== true || desc?.contains("역사")== true) {
if (this.pubDate() > commicsDateTime) {
temp.add(this.getRssData())
}
}
}
}
}
} }
} catch (e : Exception) {e.printStackTrace()}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
}
}

View File

@ -0,0 +1,46 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.todos.RssFeedsParser
import rasel.lunar.launcher.utils.RssList
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class NewsFeedsGetter : BaseGetter {
var feddsUrls = arrayListOf<String>()
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
feddsUrls.clear()
feddsUrls.addAll(RssList.newsFeeds)
feddsUrls.addAll(RssList.getFeedUrls())
for(url in feddsUrls) {
for (it in RssFeedsParser.getFeeds(url)) {
if (it.pubDate() >= limitDateTime) {
temp.add(it.getRssData())
}
}
}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
// temp.forEach { synchronized(rssSet){
// rssSet.put(it.originPage(), it)
// } }.run {
// rssSetTouchCount -= 1
// Result.success() }
}
}

View File

@ -0,0 +1,135 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import android.provider.CallLog
import androidx.work.WorkerParameters
import com.google.gson.Gson
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.home.LauncherHome.Companion.recentCalls
import rasel.lunar.launcher.utils.beforeDay
import java.text.SimpleDateFormat
import java.util.Date
class RecentCall {
constructor(count: Int, name: String?, number: String, type: Int, typeString: String, date : String) {
this.count = count
this.name = name ?: "unknown"
this.number = number
this.type = type
this.typeString = typeString
this.date = date
}
var count : Int = 1
var name : String = "how"
var number : String = ""
var type : Int = 0
var typeString : String = ""
var date : String = ""
fun toJson() : String {
return Gson().toJson(this)
}
}
class RecentCallGetter : BaseGetter {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
var dateParam = beforeDay(Date(),3).toString()
var managedCursor = lActivity?.contentResolver?.query(
CallLog.Calls.CONTENT_URI, arrayOf(
CallLog.Calls.NUMBER,
CallLog.Calls.TYPE,
CallLog.Calls.DATE,
CallLog.Calls.DURATION,
CallLog.Calls.CACHED_NAME,
), CallLog.Calls.DATE + " >= ? " , arrayOf<String>(dateParam), CallLog.Calls.DATE + " desc")
//+ CallLog.Calls.TYPE + " > ?"
//, "2"
if(managedCursor != null && managedCursor.isClosed == false) {
try {
val number = managedCursor.getColumnIndex(CallLog.Calls.NUMBER)
val type = managedCursor.getColumnIndex(CallLog.Calls.TYPE)
val date = managedCursor.getColumnIndex(CallLog.Calls.DATE)
val duration = managedCursor.getColumnIndex(CallLog.Calls.DURATION)
val name = managedCursor.getColumnIndex(CallLog.Calls.CACHED_NAME)
recentCalls.clear()
while (managedCursor.moveToNext()) {
val phNumber = managedCursor.getString(number) // mobile number
val callType = managedCursor.getString(type) // call type
val callDate = managedCursor.getString(date) // call date
val callDayTime: Date = Date(callDate.toLong())
val callDuration = managedCursor.getString(duration)
val callerName = managedCursor.getString(name)
var dir: String = ""
val dircode = callType.toInt()
when (dircode) {
CallLog.Calls.INCOMING_TYPE -> {
dir = "INCOMING_TYPE"
}
CallLog.Calls.OUTGOING_TYPE -> {
dir = "OUTGOING_TYPE"
}
CallLog.Calls.MISSED_TYPE -> {
dir = "MISSED_TYPE"
}
CallLog.Calls.VOICEMAIL_TYPE -> {
dir = "VOICEMAIL_TYPE"
}
CallLog.Calls.REJECTED_TYPE -> {
dir = "REJECTED_TYPE"
}
CallLog.Calls.BLOCKED_TYPE -> {
dir = "BLOCKED_TYPE"
}
CallLog.Calls.ANSWERED_EXTERNALLY_TYPE -> {
dir = "ANSWERED_EXTERNALLY_TYPE"
}
}
var missed: RecentCall = if (recentCalls.containsKey(phNumber)) {
recentCalls.get(phNumber)!!.apply {
count = count + 1
}
} else {
RecentCall(
1,
callerName,
phNumber,
dircode,
dir,
SimpleDateFormat("yyy/MM/dd-HH:mm:ss").format(callDayTime)
)
}
// BLog.LOGE("missed put >>> ${missed.toJson()}")
recentCalls.put(phNumber, missed)
}
} catch (e: Exception) {
} finally {
managedCursor.close()
}
}
return Result.success()
}
}

View File

@ -0,0 +1,324 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.ContentResolver
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.provider.Telephony
import androidx.work.WorkerParameters
import com.google.gson.Gson
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.home.LauncherHome.Companion.smsList
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.beforeDay
import rasel.lunar.launcher.utils.getContactName
import java.io.BufferedReader
import java.io.IOException
import java.io.InputStream
import java.io.InputStreamReader
import java.util.Date
class RecentSmsGetter : BaseGetter {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
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.getLong(date) // call date
val sendedDate = managedCursor.getLong(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 = RecentSms(
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) {
MmsQueryHelper(lActivity?.contentResolver!!).query()
}
return Result.success()
}
}
internal class RecentSms {
var id : String = ""
var isMms : Boolean = false
var addr : String = ""
var type : String = ""
var rcvDate : Long = 0L
var pstDate : Long = 0L
var body : String = ""
var person : String = ""
var mmsContents : HashMap<String?,ArrayList<String>> = hashMapOf()
var sender : String = ""
constructor(
addr: String,
type: String,
rcvDate: Long,
pstDate: Long,
body: String,
person: String
) {
this.addr = addr
this.type = type
this.rcvDate = rcvDate
this.pstDate = pstDate
this.body = body
this.person = person
this.isMms = false
}
constructor(id: String, sender: String, date: Long, body: HashMap<String?,ArrayList<String>>) {
this.id = id
this.rcvDate = date
this.mmsContents = body
this.addr = sender
this.isMms = true
}
fun toJson() : String {
return Gson().toJson(this)
}
}
internal class MmsQueryHelper(
private val _contentResolver: ContentResolver
) {
private val mmsUri: Uri = Telephony.Mms.CONTENT_URI
private val cursor: Cursor?
get() =
_contentResolver.query(
mmsUri,
null,
null,
null,
null
)
fun dataMapper(cursor: Cursor): RecentSms {
val id = cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Mms._ID))
val date = cursor.getLong(cursor.getColumnIndexOrThrow(Telephony.Mms.DATE)) * 1000
val sender : String = getSender(id) ?: throw NullPointerException("NotFound Sender For Mms")
val body = getBody(id) ?: throw NullPointerException("NotFound Body by Mms")
return RecentSms(
id = id.toString(),
date = date,
body = body,
sender = sender
).apply {
isMms = true
this.sender = getContactName(_contentResolver,addr) ?: ""
}
}
private fun getSender(id: Int): String? {
_contentResolver.query(
Uri.parse("content://mms/$id/addr"),
null,
"${Telephony.Mms.Addr.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { senderAddressCursor ->
if (senderAddressCursor.moveToFirst()) {
do {
// 137 수신, 151 발신 타입 값이다. Telephony.Mms.Addr.Type 의 주석 참고.
val isSender = senderAddressCursor.getInt(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.TYPE)
) == 137
var sender = senderAddressCursor.getString(
senderAddressCursor.getColumnIndexOrThrow(Telephony.Mms.Addr.ADDRESS)
)
// BLog.LOGE("sender >> ${sender}")
if (isSender) {
return sender
}
} while (senderAddressCursor.moveToNext())
}
}
return null
}
private fun getMmsText(id: String): String {
val partURI = Uri.parse("content://mms/part/$id")
var `is`: InputStream? = null
val sb = StringBuilder()
try {
`is` = _contentResolver.openInputStream(partURI)
if (`is` != null) {
val isr = InputStreamReader(`is`, "UTF-8")
val reader = BufferedReader(isr)
var temp = reader.readLine()
while (temp != null) {
sb.append(temp)
temp = reader.readLine()
}
}
} catch (e: IOException) {
} finally {
if (`is` != null) {
try {
`is`.close()
} catch (e: IOException) {
}
}
}
return sb.toString()
}
private fun getBody(id: Int): HashMap<String?,ArrayList<String>> {
var returns = hashMapOf<String?,ArrayList<String>>()
val text = arrayListOf<String>()
val image = arrayListOf<String>()
val audio = arrayListOf<String>()
val projection = arrayOf("*")
val video = arrayListOf<String>()
_contentResolver.query(
Uri.parse("content://mms/part"),
projection,
"${Telephony.Mms.Part.MSG_ID} = ?",
arrayOf(id.toString()),
null
)?.use { partsCursor ->
if (partsCursor.moveToFirst()) {
do {
val partId: String = partsCursor.getString(partsCursor.getColumnIndexOrThrow(
Telephony.Mms.Part._ID))
val partContentType =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.CONTENT_TYPE))
// BLog.LOGE("partContentType >> ${partContentType}")
if(partContentType?.contains("text") == true) {
// BLog.LOGE("partContentType text >> ${partContentType} :: ${partId}")
val data =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part._DATA))
val textBody =
partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
if (data != null && data.length > 0) {
text.add(getMmsText(partId))
} else {
text.add(textBody)
}
}
else if(partContentType?.contains("image") == true) {
// BLog.LOGE("partContentType image >> ${partContentType}:: ${partId}")
image.add(partId)
}
else if(partContentType?.contains("audio") == true) {
// BLog.LOGE("partContentType audio >> ${partContentType}:: ${partId}")
audio.add(partId)
}
else if(partContentType?.contains("video") == true) {
// BLog.LOGE("partContentType video >> ${partContentType}:: ${partId}")
video.add(partId)
}
else {
// BLog.LOGE("partContentType >> ${partContentType}:: ${partId}")
}
// if (partContentType == "text/plain") {
// var textBody =
// partsCursor.getString(partsCursor.getColumnIndexOrThrow(Telephony.Mms.Part.TEXT))
//// .replace("\n\n", "\n").replace("\n", " ")
//// if (textBody.length > 60) {
//// textBody = textBody.substring(0, Math.min(textBody.length, 60)).plus(" ... ")
//// }
//// BLog.LOGE("textBody >>> ${textBody}")
// return Pair(textBody , partContentType)
// }
} while (partsCursor.moveToNext())
}
}
returns.put("text", text)
returns.put("image", image)
returns.put("audio", audio)
returns.put("video", video)
// BLog.LOGE("returns.get(text).join => ${text.size} :: ${text.joinToString("\n")}")
return returns
}
fun convertData(cursor: Cursor?) {
cursor ?: return
val dateTime = beforeDay(Date(),3)
cursor.use {
if (cursor.moveToFirst()) {
do {
val data = kotlin.runCatching {
dataMapper(cursor)
}.getOrNull()
data?.let {
if (it?.pstDate ?: 0L > dateTime || it?.rcvDate ?: 0L > dateTime) {
smsList.add(it)
}
}
} while (cursor.moveToNext())
}
}
}
fun query() {
return convertData(cursor)
}
}

View File

@ -0,0 +1,32 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.todos.RssFeedsParser
import rasel.lunar.launcher.utils.RssList.feedJsons
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class RedditGetter : BaseGetter {
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
val temp = arrayListOf<RssData>()
for (url in feedJsons) {
for (it in RssFeedsParser.getReddit(url)) {
if (it.pubDate() >= limitDateTime) {
temp.add(it.getRssData())
}
}
}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
}
}

View File

@ -0,0 +1,64 @@
package rasel.lunar.launcher.workers
import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.types.BaseRealmObject
import io.realm.kotlin.types.TypedRealmObject
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.getRssData
import kotlin.reflect.KClass
object WorkersDb {
val clazz : Set<KClass<out BaseRealmObject>> = setOf(RssData::class)
val schemaVersion : Long = 0L
private var pRealm : Realm? = null
fun getRealm() : Realm {
if (pRealm == null) {
pRealm = Realm.open(RealmConfiguration.Builder(clazz as Set<KClass<out TypedRealmObject>>)
.schemaVersion(schemaVersion)
.deleteRealmIfMigrationNeeded()
.build())
}
return pRealm!!
}
fun insertData(rssData: RssData) {
getRealm().apply {
this.writeBlocking {
this.copyToRealm(rssData)
}
}
}
fun insertBulkData(rssDatas: Collection<RssData>) {
rssDatas.forEach {
try {
getRealm().writeBlocking {
this.copyToRealm(it, UpdatePolicy.ALL)
}
} catch (e : Exception) {
}
}
}
fun insertBulkInteface(rssInterfaceDatas: Collection<RssDataInterface>) {
rssInterfaceDatas.forEach {
try {
getRealm().writeBlocking {
if (it is RssData) {
this.copyToRealm(it, UpdatePolicy.ALL)
}
// else if(it is RssDataInterface) {
// this.copyToRealm(it.getRssData(), UpdatePolicy.ALL)
// }
}
} catch (e : Exception) {
}
}
}
}

View File

@ -0,0 +1,85 @@
package rasel.lunar.launcher.workers
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.WorkerParameters
import com.google.gson.Gson
import org.json.JSONObject
import org.jsoup.Jsoup
import org.jsoup.nodes.Document
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getRssData
import rasel.lunar.launcher.todos.Root
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RssList
import rasel.lunar.launcher.utils.beforeDay
import java.util.Date
class YoutubeGetter : BaseGetter {
var rssUrls = arrayListOf<String>()
constructor(context: Context, workerParams: WorkerParameters) : super(context, workerParams) {
}
@SuppressLint("RestrictedApi")
override fun doWork(): Result {
rssUrls.clear()
rssUrls.addAll(RssList.youtubeUrls)
for (url in rssUrls) {
temp.addAll(ytChannel(Jsoup.connect(url).userAgent(USAGT).get()))
}
return Result.success().apply {
WorkersDb.insertBulkData(temp)
}
}
fun ytChannel(doc: Document) : ArrayList<RssData> {
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) {
root?.contents?.singleColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
it.shelfRenderer?.content?.verticalListRenderer?.items?.forEach {
(it.compactVideoRenderer as? RssDataInterface)?.let {
if(it.pubDate() > limitDateTime) {
temp.add(it.getRssData())
}
}
}
}
}
} else {
root?.contents?.twoColumnBrowseResultsRenderer?.tabs?.forEach {
it.tabRenderer?.content?.sectionListRenderer?.contents?.forEach {
it.itemSectionRenderer?.contents?.forEach {
it.shelfRenderer?.content?.horizontalListRenderer?.items?.forEach {
(it.gridVideoRenderer as? RssDataInterface)?.let {
if(it.pubDate() >limitDateTime) {
temp.add(it.getRssData())
}
}
}
}
}
}
}).apply {
}
}
}
}
} catch(e: Exception) {
}
return temp
}
}

View File

@ -3,33 +3,33 @@
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:background="#05000000"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<View <TextView
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:background="#11000000"
android:layout_height="0dp"/>
<com.google.android.material.progressindicator.CircularProgressIndicator
android:id="@+id/batteryProgress" android:id="@+id/batteryProgress"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="@dimen/twelve" android:layout_marginTop="@dimen/twelve"
android:layout_marginRight="12dp"
android:indeterminate="false" android:indeterminate="false"
android:max="100" android:textSize="18sp"
app:trackCornerRadius="@dimen/four" android:text="빠떼뤼 ~> 0%"
app:showAnimationBehavior="inward" app:layout_constraintRight_toRightOf="parent"
app:indicatorColor="?android:attr/textColorPrimary"
app:indicatorSize="@dimen/twoSeventySix"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" /> app:layout_constraintTop_toTopOf="parent" />
<rasel.lunar.launcher.view.DateTimeView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="this is init sentence"
android:gravity="center"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
android:textSize="16sp"
tools:ignore="MissingConstraints" />
<TextClock <TextClock
android:id="@+id/time" android:id="@+id/time"
android:layout_width="wrap_content" android:layout_width="wrap_content"
@ -40,11 +40,9 @@
android:textSize="@dimen/clockText" android:textSize="@dimen/clockText"
android:textStyle="bold" android:textStyle="bold"
android:textLocale="en_US" android:textLocale="en_US"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="@+id/batteryProgress" app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
app:layout_constraintTop_toTopOf="@+id/batteryProgress"
app:layout_constraintVertical_bias="0.450"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />
<TextClock <TextClock
@ -53,13 +51,12 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="center" android:gravity="center"
android:maxLines="1" android:maxLines="1"
android:textLocale="en_US" android:textSize="20sp"
android:format12Hour="yyyy년 M월 d일 E요일"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintTop_toBottomOf="@+id/time" app:layout_constraintTop_toBottomOf="@+id/time"
app:layout_constraintVertical_bias="0.075"
tools:ignore="UnusedAttribute" /> tools:ignore="UnusedAttribute" />
<com.google.android.material.textview.MaterialTextView <com.google.android.material.textview.MaterialTextView
@ -69,13 +66,13 @@
android:gravity="center" android:gravity="center"
android:maxLines="1" android:maxLines="1"
android:textIsSelectable="false" android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintTop_toBottomOf="@+id/date" app:layout_constraintTop_toBottomOf="@+id/date"
app:layout_constraintVertical_bias="0.100" /> app:layout_constraintVertical_bias="0.100" />
<RadioGroup <RadioGroup
android:layout_marginTop="20dp"
android:id="@+id/summaryChoose" android:id="@+id/summaryChoose"
android:layout_width="0dp" android:layout_width="0dp"
android:gravity="center" android:gravity="center"
@ -83,7 +80,7 @@
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
android:layout_height="40dp" android:layout_height="40dp"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress" app:layout_constraintTop_toBottomOf="@+id/weather"
> >
<RadioButton <RadioButton
@ -126,11 +123,10 @@
android:overScrollMode="never" android:overScrollMode="never"
android:padding="20dp" android:padding="20dp"
android:scrollbars="none" android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/> />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
android:id="@+id/smsList" android:id="@+id/smsList"
@ -142,7 +138,7 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/> />
<androidx.recyclerview.widget.RecyclerView <androidx.recyclerview.widget.RecyclerView
@ -155,19 +151,17 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose" app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/> />
<androidx.appcompat.widget.LinearLayoutCompat <androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/favAppsGroup" android:id="@+id/favAppsGroup"
android:layout_width="@dimen/zero" android:layout_width="@dimen/zero"
android:visibility="gone" android:layout_height="60dp"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/twentyTwo" android:layout_marginTop="@dimen/twentyTwo"
android:layout_marginBottom="@dimen/twelve" android:layout_marginBottom="@dimen/twelve"
android:orientation="horizontal" android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent" />
app:layout_constraintTop_toBottomOf="@+id/mainList" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,6 +1,6 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules. // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript { buildscript {
val kotlinVersion = "1.9.0" val kotlinVersion = "2.0.0"
extra ["kotlinVersion"] = kotlinVersion extra ["kotlinVersion"] = kotlinVersion
dependencies { dependencies {
@ -9,11 +9,22 @@ buildscript {
} }
plugins { plugins {
id ("io.realm.kotlin") version "1.16.0" apply false
id ("com.android.application") version "8.2.2" apply false id ("com.android.application") version "8.2.2" apply false
id ("com.android.library") version "8.2.2" apply false id ("com.android.library") version "8.2.2" apply false
id ("io.realm.kotlin") version "2.0.0" apply false
} }
tasks.register<Delete>("clean") { tasks.register<Delete>("clean") {
delete(rootProject.buildDir) delete(rootProject.buildDir)
} }
//repositories {
// mavenCentral()
// maven {
// url = uri("https://jitpack.io")
// }
// jcenter()
// mavenLocal()
// flatDir {
// dirs("libs")
// }
//}