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 {
val kotlinVersion: String? by extra
implementation ("androidx.appcompat:appcompat:1.7.0")
implementation ("androidx.biometric:biometric-ktx:1.2.0-alpha05")
implementation ("androidx.browser:browser:1.8.0")
@ -89,5 +88,5 @@ dependencies {
implementation ("com.google.code.gson:gson:2.11.0")
implementation ("io.realm.kotlin:library-base:2.1.0")
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.listItem
import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import rasel.lunar.launcher.home.RssItem
import rasel.lunar.launcher.home.RssTagItem
import rasel.lunar.launcher.model.ArcaGetter
import rasel.lunar.launcher.model.DCGetter
//import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet
import rasel.lunar.launcher.model.RssItem
import rasel.lunar.launcher.model.RssTagItem
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.getT
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.model.getRssData
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.jGuruRanks
import rasel.lunar.launcher.utils.YoutubeGetter
import rasel.lunar.launcher.utils.beforeDay
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.util.Date
import java.util.Locale
@ -115,7 +121,6 @@ internal class LauncherActivity : AppCompatActivity() {
companion object {
private var mWorkManager: WorkManager? = null
val SMS_WORK_TAG = "RecentSmsGetter"
val CALL_WORK_TAG = "MissedCallGetter"
val FEDDS_WORK_TAG = "NewsFeedsGetter"
@ -127,7 +132,6 @@ internal class LauncherActivity : AppCompatActivity() {
val longTimePeriod = 60L
val midTimePeriod = 30L
var isOpendFold = false
var rssSetTouchCount = 0
@JvmStatic var lActivity: LauncherActivity? = null
@JvmStatic var appWidgetManager: AppWidgetManager? = null
@ -149,7 +153,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.enqueueUniquePeriodicWork(
CALL_WORK_TAG,
ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<MissedCallGetter>(longTimePeriod, TimeUnit.MINUTES)
PeriodicWorkRequestBuilder<RecentCallGetter>(longTimePeriod, TimeUnit.MINUTES)
.addTag(CALL_WORK_TAG)
.build())
}, 2, TimeUnit.SECONDS)
@ -191,7 +195,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.cancelAllWorkByTag(COMIC_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(
COMIC_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<ComicsGetter>(midTimePeriod, TimeUnit.MINUTES)
PeriodicWorkRequestBuilder<FmKoreaGetter>(midTimePeriod, TimeUnit.MINUTES)
.addTag(COMIC_WORK_TAG)
.build())
refreshComics2()
@ -202,7 +206,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.cancelAllWorkByTag(COMIC2_WORK_TAG)
mWorkManager?.enqueueUniquePeriodicWork(
COMIC2_WORK_TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<ComicsGetter2>(midTimePeriod, TimeUnit.MINUTES)
PeriodicWorkRequestBuilder<DotaxGetter>(midTimePeriod, TimeUnit.MINUTES)
.addTag(COMIC2_WORK_TAG)
.build())
}, 2, TimeUnit.SECONDS)
@ -247,8 +251,8 @@ internal class LauncherActivity : AppCompatActivity() {
BLog.LOGE("onConfigurationChanged newConfig?.screenWidthDp >> ${newConfig?.screenWidthDp}")
isOpendFold = (newConfig?.screenWidthDp?.toInt() ?: 0 > 700) == true
binding.viewPager.invalidate()
binding.viewPager.currentItem = 1
// binding.viewPager.invalidate()
// binding.viewPager.currentItem = 1
}
override fun onNewIntent(intent: Intent?) {
@ -592,6 +596,7 @@ internal class LauncherActivity : AppCompatActivity() {
val triple = 1000L * 60L * 60L * 24L * 2L
val simpldateFormat = SimpleDateFormat("d MMM, yy", Locale.US)
fun jGuruToday(doc: Document) {
var temp = arrayListOf<RssData>()
doc.getElementsByTag("li").forEach {
if (it.getElementsByTag("img").size > 0) {
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 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) {
listItem.add(
temp.add(
RssItem(
model = model,
title = title,
@ -608,20 +613,13 @@ internal class LauncherActivity : AppCompatActivity() {
image = imgg,
tags = actor,
date = beforeDay(Date(),3) + 360000
)
).getRssData()
)
}
}
}.apply {
this@LauncherActivity.callBack?.invoke()
var idx = 0
listItem?.forEach {
if(it.date > beforeDay(Date(),3) && idx < 10) {
it.date = it.date + (10000L * idx)
rssSet.put(it.pageLink,it)
idx += 1
}
}
WorkersDb.insertBulkInteface(temp)
Toast.makeText(this@LauncherActivity,
"Stored rank data", Toast.LENGTH_LONG).show()
binding.searcher01?.post { binding.searcher01.loadUrl(jGuruMain) }
@ -629,6 +627,7 @@ internal class LauncherActivity : AppCompatActivity() {
}
fun jGuruMain(doc: Document) {
// 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")
doc.getElementsByClass("column").forEach {
var title = it.getElementsByAttribute("title").get(0).text()
@ -641,23 +640,10 @@ internal class LauncherActivity : AppCompatActivity() {
minDate = Math.min(minDate,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 {
// 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
listItem.sortByDescending { it.date }
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
}
}
WorkersDb.insertBulkInteface(temp)
BLog.LOGE("Stored data :: ${listItem.size}items ${simpldateFormat.format(Date(minDate))} ~ ${simpldateFormat.format(Date(maxDate))} set in ${itemC}")
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()
@ -681,7 +667,7 @@ internal class LauncherActivity : AppCompatActivity() {
}
}
}.apply {
listTags.sortByDescending { it.count }
listTags.sortByDescending { it.pubDate() }
Toast.makeText(this@LauncherActivity,
"Stored data :: ${listTags.size}tags", Toast.LENGTH_SHORT).show()
this@LauncherActivity.callBack?.invoke()
@ -693,7 +679,7 @@ internal class LauncherActivity : AppCompatActivity() {
@JavascriptInterface
fun sendValueFromHtml(result: String) {
BLog.LOGE("binding.otherCheck start with ${result}")
// BLog.LOGE("binding.otherCheck start with ${result}")
if (lastedFinishedPageUrl.contains(jGuruMain)) {
var htmlString = result.replace("\\u003","<")
val doc: Document = Jsoup.parse(htmlString)
@ -710,12 +696,31 @@ internal class LauncherActivity : AppCompatActivity() {
} else if (lastedFinishedPageUrl?.contains("youtube") == true) {
// val doc: Document = Jsoup.parse(result)
// ytChannel(doc)
} else if (lastedFinishedPageUrl?.contains("missjav")==true) {
} else if (lastedFinishedPageUrl?.contains("missav")==true) {
val doc: Document = Jsoup.parse(result)
BLog.LOGE("missav >>> ${doc}")
doc.getElementsByTag("li").forEach { miss_li ->
BLog.LOGE("miss_li >>>> ${miss_li}")
// BLog.LOGE("missav >>> ${doc}")
var temp = arrayListOf<RssData>()
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")
}
@ -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.repeatOnLifecycle
import com.google.android.material.button.MaterialButtonToggleGroup
import io.realm.kotlin.ext.query
import kotlinx.coroutines.*
import rasel.lunar.launcher.LauncherActivity.Companion.appWidgetHost
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.home.LauncherHome.Companion.listItem
import rasel.lunar.launcher.home.LauncherHome.Companion.listTags
import rasel.lunar.launcher.home.RssItem
import rasel.lunar.launcher.home.RssTagItem
import rasel.lunar.launcher.model.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.workers.WorkersDb
import java.util.*
@ -65,12 +69,12 @@ internal class Feeds : Fragment() {
private lateinit var binding: FeedsBinding
private val requestCodeString = "requestCode"
var mRssAdapter : RssAdapter<RssItem>? = null
var mRssAdapter : RssAdapter<RssDataInterface>? = null
var mRssAdapter2 : RssAdapter<RssTagItem>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
binding = FeedsBinding.inflate(inflater, container, false)
mRssAdapter = RssAdapter(listItem, requireContext())
mRssAdapter2 = RssAdapter(listTags, requireContext())
mRssAdapter = RssAdapter(requireContext())
mRssAdapter2 = RssAdapter(requireContext())
binding.feedsRss.rss.adapter = mRssAdapter
binding.feedsRss.rss2.adapter = mRssAdapter2
updateWidgets()
@ -166,7 +170,11 @@ internal class Feeds : Fragment() {
rss.adapter = mRssAdapter
loading.visibility = View.VISIBLE
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
loading.visibility = View.GONE
refresh.visibility = View.GONE
@ -177,6 +185,7 @@ internal class Feeds : Fragment() {
var call = {
if (listItem.size > 0) {
rss?.postDelayed( {
listItem.sortByDescending { it.pubDate() }
mRssAdapter?.updateData(listItem)
loading.visibility = View.GONE
refresh.visibility = View.GONE
@ -192,7 +201,7 @@ internal class Feeds : Fragment() {
lActivity?.doWebParseStart("https://projectjav.com") {}
}
"jmiss" -> {
lActivity?.doWebParseStart("https://missjav.com") {}
lActivity?.doWebParseStart("https://missav.com/dm11/ko") {}
}
"jreq" -> {
lActivity?.doWebParseStart(jGuruMain) {}

View File

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

View File

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

View File

@ -24,12 +24,13 @@ import android.content.Intent
import android.os.BatteryManager
import android.provider.Settings
import android.view.animation.AnimationUtils
import android.widget.TextView
import com.google.android.material.progressindicator.CircularProgressIndicator
import rasel.lunar.launcher.R
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 */
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 */
progressBar.progress = batteryPercentage(intent!!)
progressBar.text = "빠떼뤼 ~> ${batteryPercentage(intent!!)}%"
/* progress bar animation */
if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_CHARGING ||
chargingStatus(intent) == BatteryManager.BATTERY_STATUS_FULL) {
if (progressBar.animation == null && animationDuration != 0f) {
progressBar.startAnimation(
AnimationUtils.loadAnimation(context, R.anim.rotate_clockwise)
)
}
} else if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_DISCHARGING ||
chargingStatus(intent) == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
progressBar.clearAnimation()
}
// if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_CHARGING ||
// chargingStatus(intent) == BatteryManager.BATTERY_STATUS_FULL) {
// if (progressBar.animation == null && animationDuration != 0f) {
// progressBar.startAnimation(
// AnimationUtils.loadAnimation(context, R.anim.rotate_clockwise)
// )
// }
// } else if (chargingStatus(intent) == BatteryManager.BATTERY_STATUS_DISCHARGING ||
// chargingStatus(intent) == BatteryManager.BATTERY_STATUS_NOT_CHARGING) {
// progressBar.clearAnimation()
// }
}
}

View File

@ -41,12 +41,16 @@ import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentManager
import androidx.recyclerview.widget.DividerItemDecoration
import androidx.recyclerview.widget.LinearLayoutManager
import com.google.gson.Gson
import kotlinx.coroutines.GlobalScope
import io.realm.kotlin.ext.query
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 org.json.JSONArray
import org.json.JSONObject
import org.jsoup.Jsoup
import rasel.lunar.launcher.LauncherActivity.Companion.CALL_WORK_TAG
import rasel.lunar.launcher.LauncherActivity.Companion.FEDDS_WORK_TAG
import rasel.lunar.launcher.LauncherActivity.Companion.SMS_WORK_TAG
@ -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.lockMethod
import rasel.lunar.launcher.home.weather.WeatherExecutor
import rasel.lunar.launcher.model.ArcaGetter
import rasel.lunar.launcher.model.DCGetter
import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.qaccess.QuickAccess
import rasel.lunar.launcher.settings.SettingsActivity
import rasel.lunar.launcher.todos.MissedCallsAdapter
import rasel.lunar.launcher.todos.RssDataItem
import rasel.lunar.launcher.todos.RssDataType
import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.todos.RssItemAdapter
import rasel.lunar.launcher.todos.SmsLogsAdapter
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import rasel.lunar.launcher.utils.SimpleFingerGestures
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.Date
import java.util.Locale
import java.util.concurrent.Executors
import java.util.concurrent.TimeUnit
internal class LauncherHome : Fragment() {
@ -99,17 +104,11 @@ internal class LauncherHome : Fragment() {
private var shouldResume = true
companion object {
var lastedFinishedPageUrl : String = ""
var missedCalls = hashMapOf<String, MissedCall>()
var callList = arrayListOf<MissedCall>()
var smsList = arrayListOf<RecentSmsLog>()
var listTags = arrayListOf<RssTagItem>()
var listItem = arrayListOf<RssItem>()
var rssSet = hashMapOf<String,RssDataItem>()
var rssList = arrayListOf<RssDataItem>()
var recentCalls = hashMapOf<String, RecentCall>()
var callList = arrayListOf<RecentCall>()
var smsList = arrayListOf<RecentSms>()
var listTags = arrayListOf<RssDataInterface>()
var listItem = arrayListOf<RssDataInterface>()
}
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 smsUpdate = Runnable {
@ -130,18 +129,24 @@ internal class LauncherHome : Fragment() {
}
val callUpdate = Runnable {
binding.missedCalls.text = "최근 통화 [${missedCalls.size}]"
BLog.LOGE("observeForever missedCalls.size >>> ${missedCalls.size}")
binding.missedCalls.text = "최근 통화 [${recentCalls.size}]"
BLog.LOGE("observeForever missedCalls.size >>> ${recentCalls.size}")
chooseAdpater()
}
val infoUpdate = Runnable {
binding.otherCheck.text = "최근 정보[${rssSet.size}]"
BLog.LOGE("observeForever rssSet.size >>> ${rssSet.size}")
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 {
binding = LauncherHomeBinding.inflate(inflater, container, false)
@ -162,7 +167,7 @@ internal class LauncherHome : Fragment() {
binding.smsList.visibility = View.GONE
binding.infoList.visibility = View.GONE
binding.favAppsGroup.visibility = View.GONE
// binding.favAppsGroup.visibility = View.GONE
binding.mainList.layoutManager = LinearLayoutManager(requireContext())
binding.smsList.layoutManager = LinearLayoutManager(requireContext())
@ -207,14 +212,46 @@ internal class LauncherHome : Fragment() {
registerReceiver(requireContext(),nReceiver, filter,RECEIVER_EXPORTED)
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
}
lateinit var mMissedCallsAdapter : MissedCallsAdapter
lateinit var mSmsLogsAdapter : SmsLogsAdapter
lateinit var mRssAdapter : RssItemAdapter
lateinit var mRssDataResult : RealmResults<RssData>
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
@ -249,26 +286,27 @@ internal class LauncherHome : Fragment() {
}
binding.otherCheck.setOnClickListener {
binding.otherCheck.isChecked = true
chooseAdpater()
commandHandler.removeCallbacks(infoUpdate)
commandHandler.post(infoUpdate)
}
binding.otherCheck.setOnLongClickListener {
synchronized(rssSet) {
val now = Date()
var keys = arrayListOf<String>()
rssSet.forEach { t, u ->
if (u.pubDate() <= beforeDay(now,3)) {
keys.add(t)
}
}.apply {
keys.forEach { rssSet.remove(it) }
}.apply {
refreshYoutube()
refreshComics()
refreshFeeds()
refreshReddit()
}
}
// synchronized(rssSet) {
// val now = Date()
// var keys = arrayListOf<String>()
// rssSet.forEach { t, u ->
// if (u.pubDate() <= beforeDay(now,3)) {
// keys.add(t)
// }
// }.apply {
// keys.forEach { rssSet.remove(it) }
// }.apply {
refreshYoutube()
refreshComics()
refreshFeeds()
refreshReddit()
// }
// }
true
}
@ -284,14 +322,15 @@ internal class LauncherHome : Fragment() {
fun chooseAdpater () {
binding.mainList.visibility = View.GONE
binding.smsList.visibility = View.GONE
binding.infoList.visibility = View.GONE
if (binding.missedCalls.isChecked == false) binding.mainList.visibility = View.GONE else binding.mainList.visibility = View.VISIBLE
if (binding.recentSms.isChecked == false) binding.smsList.visibility = View.GONE else binding.smsList.visibility = View.VISIBLE
if (binding.otherCheck.isChecked == false) binding.infoList.visibility = View.GONE else binding.infoList.visibility = View.VISIBLE
if (binding.missedCalls.isChecked) {
if (missedCalls.size > 0 && isAdded && isResumed && isVisible) {
if (recentCalls.size > 0 && isAdded && isResumed && isVisible) {
try {
callList.clear()
missedCalls.forEach { t, u ->
recentCalls.forEach { t, u ->
callList.add(u)
}.apply {
callList.sortByDescending { it.date }
@ -317,48 +356,50 @@ internal class LauncherHome : Fragment() {
}
}
} else if(binding.otherCheck.isChecked) {
try {
GlobalScope.launch {
(rssSet.clone() as? HashMap<String,RssDataItem>)?.let { temMap ->
synchronized(binding.infoList) {
var tempList = arrayListOf<RssDataItem>()
temMap.forEach { k,v ->
if(v.pubDate() > beforeDay(Date(),3)) {
tempList.add(v)
} else {
}
}.apply {
tempList.sortByDescending { it.pubDate() }
rssList.clear()
rssList.addAll(tempList)
Handler(Looper.getMainLooper()).post {
binding.infoList.visibility = View.VISIBLE
mRssAdapter.updateData(rssList)
}
}
}
}
}
}catch (e : Exception){}
// try {
// GlobalScope.launch {
// (rssSet.clone() as? HashMap<String,RssDataInterface>)?.let { temMap ->
// synchronized(binding.infoList) {
// var tempList = arrayListOf<RssDataInterface>()
// temMap.forEach { k,v ->
// if(v.pubDate() > beforeDay(Date(),3)) {
// tempList.add(v)
// } else {
//
// }
// }.apply {
// tempList.sortByDescending { it.pubDate() }
// rssList.clear()
// rssList.addAll(tempList)
// Handler(Looper.getMainLooper()).post {
// binding.infoList.visibility = View.VISIBLE
// mRssAdapter.updateData(rssList)
// }
// }
// }
// }
// }
// }catch (e : Exception){}
}
}
override fun onResume() {
super.onResume()
BLog.LOGE("onResume()")
BLog.LOGE(SimpleDateFormat("yyyy년 M월 W주차, dd일 E요일").format(Date()))
if (shouldResume) {
/* register battery changes */
requireContext().registerReceiver(batteryReceiver, IntentFilter(Intent.ACTION_BATTERY_CHANGED))
/* time and date */
binding.time.textLocale = Locale.US
binding.date.textLocale = Locale.US
if (DateFormat.is24HourFormat(requireContext())) {
// binding.time.textLocale = Locale.US
// binding.date.textLocale = Locale.US
// if (DateFormat.is24HourFormat(requireContext())) {
binding.time.format24Hour = timeFormat
binding.date.format24Hour = dateFormat
} else {
binding.time.format12Hour = timeFormat
binding.date.format12Hour = dateFormat
}
binding.date.format24Hour = "yyyy년 M월 W주차, dd일 E요일"
// } else {
// binding.time.format12Hour = timeFormat
// binding.date.format12Hour = dateFormat
// }
/* show weather */
WeatherExecutor(settingsPrefs).generateWeatherString(binding.weather)
}
@ -594,16 +635,16 @@ internal class LauncherHome : Fragment() {
/* get time format string */
private val timeFormat: String? get() {
when (settingsPrefs.getInt(KEY_TIME_FORMAT, 0)) {
0 -> return if (DateFormat.is24HourFormat(requireContext())) {
"kk:mm"
} else {
"HH:mm a"
}
1 -> return "HH:mm a"
2 -> return "kk:mm"
}
return null
// when (settingsPrefs.getInt(KEY_TIME_FORMAT, 0)) {
// 0 -> return if (DateFormat.is24HourFormat(requireContext())) {
// "kk:mm"
// } else {
// "HH:mm a"
// }
// 1 -> return "HH:mm a"
// 2 -> return "kk:mm"
// }
return "a HH : mm"
}
/* get date number suffix */
@ -618,127 +659,18 @@ internal class LauncherHome : Fragment() {
/* get date format string */
private val dateFormat: String get() {
settingsPrefs.getString(KEY_DATE_FORMAT, DEFAULT_DATE_FORMAT).let {
return if (it!!.contains("x")) {
it.replace("x", dateNumberSuffix)
} else {
it
}
}
}
}
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)
// settingsPrefs.getString(KEY_DATE_FORMAT, DEFAULT_DATE_FORMAT).let {
// return if (it!!.contains("x")) {
// it.replace("x", dateNumberSuffix)
// } else {
// it
// }
// }
return "yyyy년 M월 W주차, dd일 E요일"
}
}
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
import android.annotation.SuppressLint
import android.content.Context
import androidx.work.Worker
import androidx.work.WorkerParameters
import org.jsoup.Jsoup
import org.jsoup.nodes.Element
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey
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.USAGT
import rasel.lunar.launcher.utils.afterDay
import rasel.lunar.launcher.utils.beforeDay
import java.text.SimpleDateFormat
@ -20,91 +12,17 @@ import java.util.Date
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 {
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 {
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 {
fun Elements.getT() = if (size > 0) get(0).text() else ""
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
class Arca : RssDataInterface {
var link : String? = null
var title : String? = null
var thumbnail : String? = null
var desc : String? = null
var dateTiem : String? = null
var updateDateTime : Long = 0L
var updateDateTime : Long = 0L
override fun title(): String {
return title ?: ""
}
@ -120,18 +38,18 @@ var updateDateTime : Long = 0L
override fun description(): String {
return desc ?: ""
}
val dateFormat = SimpleDateFormat("hh:mm / yy - MM - dd")
override fun pubDate(): Long {
var date = Date()
var dateTime = date.time
var before = 0
if (updateDateTime == 0L) {
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'")
sdf.timeZone = TimeZone.getTimeZone("GMT")
updateDateTime = sdf.parse(this.dateTiem!!).time
BLog.LOGE("updateDateTime >>>> ${dateFormat.format(Date(updateDateTime))}" )
// BLog.LOGE("updateDateTime >>>> ${dateFormat.format(Date(updateDateTime))}" )
// var targetDate = this.dateTiem ?: ""
// if (targetDate?.length ?: 0 > 1) {
// var dateDesc = targetDate
@ -176,7 +94,6 @@ var updateDateTime : Long = 0L
} else {
dateTime = updateDateTime
}
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 title : String? = null
var thumbnail : String? = null
@ -282,7 +117,6 @@ class DcInside : RssDataItem {
var dateTiemL : Long = 0L
val dateF = SimpleDateFormat("MM-dd")
val timeF = SimpleDateFormat("HH:mm")
override fun title(): String {
@ -333,3 +167,142 @@ class DcInside : RssDataItem {
}
}
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
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.utils.beforeDay
import java.sql.Date
class Reddit {
}
class Child {
var kind: String? = null
var data: Data? = null
@ -129,7 +122,7 @@ class CrosspostParentList {
var link_flair_template_id: String? = null
}
class Data : RssDataItem {
class Data : RssDataInterface {
var after: String? = null
var dist: Int = 0
var modhash: String? = null
@ -280,6 +273,7 @@ class Data : RssDataItem {
override fun category(): RssDataType {
return RssDataType.REDDIT
}
}
class Gif {
@ -362,7 +356,7 @@ class Resolution {
var height: Int = 0
}
class Root {
class Reddit {
var kind: String? = null
var data: Data? = null
}

View File

@ -1,4 +1,4 @@
package rasel.lunar.launcher.todos
package rasel.lunar.launcher.model
enum class RssDataType {
NO_DATA,
@ -13,7 +13,7 @@ enum class RssDataType {
Arca,
}
interface RssDataItem {
interface RssDataInterface {
fun title() : String
fun thumbnailUrl() : 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.TodoDialogBinding
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.RecentSmsLog
import rasel.lunar.launcher.utils.getContactId
import rasel.lunar.launcher.workers.RecentCall
import java.util.*
import kotlin.collections.ArrayList
internal class MissedCallsAdapter(
private val callList: ArrayList<MissedCall>,
private val callList: ArrayList<RecentCall>,
private val context: Context) : RecyclerView.Adapter<MissedCallsAdapter.MissedCallsHolder>() {
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))
diffUtilResult.dispatchUpdatesTo(this)
// callList.clear()
@ -135,7 +134,7 @@ internal class MissedCallsAdapter(
}
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() {
override fun getOldListSize(): Int = oldList.size

View File

@ -2,10 +2,10 @@ package rasel.lunar.launcher.todos
import android.util.Xml
import com.google.gson.Gson
import com.google.gson.JsonParser
import org.xmlpull.v1.XmlPullParser
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.beforeDay
import java.io.IOException
@ -21,32 +21,28 @@ import java.util.Locale
object RssFeedsParser {
var parseDateFormat: SimpleDateFormat = SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH)
var limitDateTime = beforeDay(Date(),3)
fun getFeeds(url : String) : List<RssDataItem> {
var returnList = mutableListOf<RssDataItem>()
fun getFeeds(url : String) : List<RssDataInterface> {
var returnList = mutableListOf<RssDataInterface>()
try {
returnList.addAll(parse(getInputStream(url)!!))
BLog.LOGE("getInputStream >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${returnList.size}")
} catch (e : Exception) {
e.printStackTrace()
}
return returnList
}
fun getReddit(url : String): List<RssDataItem> {
var returnList = mutableListOf<RssDataItem>()
fun getReddit(url : String): List<RssDataInterface> {
var returnList = mutableListOf<RssDataInterface>()
var dateTime = beforeDay(Date(),3)
try {
var mRoot = Gson().fromJson(InputStreamReader(getInputStream(url)!!),rasel.lunar.launcher.model.Root::class.java)
mRoot.data?.children?.forEach {
// BLog.LOGE("getReddit >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${Gson().toJson(it)}")
var mReddit = Gson().fromJson(InputStreamReader(getInputStream(url)!!),rasel.lunar.launcher.model.Reddit::class.java)
mReddit.data?.children?.forEach {
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? RssDataItem)?.let { rss ->
(it.data as? RssDataInterface)?.let { rss ->
returnList.add(rss)
}
}
}
BLog.LOGE("getReddit >>>>> link ${URLDecoder.decode(url,"utf-8")} , itemSize = ${returnList.size}")
} catch (e : Exception) {
e.printStackTrace()
}
@ -62,13 +58,12 @@ object RssFeedsParser {
ioException.printStackTrace()
null
}.apply {
BLog.LOGE("getInputStream >>>>> link $link")
}
}
@Throws(XmlPullParserException::class, IOException::class)
private fun parse(inputStream: InputStream): List<RssDataItem> {
private fun parse(inputStream: InputStream): List<RssDataInterface> {
return inputStream.use { stream ->
val parser = Xml.newPullParser()
parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false)
@ -179,7 +174,7 @@ object RssFeedsParser {
}
}
class RssFeed : RssDataItem{
class RssFeed : RssDataInterface {
var title : 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.R
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.util.Date
internal class RssItemAdapter (
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 {
val binding = ListItemWithBinding.inflate(LayoutInflater.from(viewGroup.context), viewGroup, false)
return RssTag(binding)
@ -142,7 +144,7 @@ internal class RssItemAdapter (
holder.view.desc.text = todo.description().plus(" ").plus(todo.category().name)
holder.view.desc.visibility = View.VISIBLE
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.postDelayed({
holder.view.circlePreview.visibility = View.GONE
@ -168,7 +170,8 @@ internal class RssItemAdapter (
openReddit(todo.originPage())
} else if( todo.category().equals(RssDataType.Dotax)) {
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())
}
true
@ -186,15 +189,17 @@ internal class RssItemAdapter (
}
fun updateData(newList: List<RssDataItem>) {
fun updateData(newList: List<RssDataInterface>) {
try {
BLog.LOGE("newList >> ${newList}")
DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply {
}.dispatchUpdatesTo(this).apply {
notifyItemRangeChanged(0,10)
// notifyItemRangeChanged(0,10)
}
rssDataItemLis.clear()
rssDataItemLis.addAll(newList)
BLog.LOGE("rssDataItemLis >> ${rssDataItemLis}")
}catch ( e : Exception) {
e.printStackTrace()
}
@ -239,7 +244,7 @@ internal class RssItemAdapter (
internal class RssTag(var view: ListItemWithBinding) : RecyclerView.ViewHolder(view.root)
internal class RssItemDiffUtil(
var oldList: List<RssDataItem>, var newList: List<RssDataItem>
var oldList: List<RssDataInterface>, var newList: List<RssDataInterface>
) : DiffUtil.Callback() {
override fun getOldListSize(): Int = oldList.size

View File

@ -20,23 +20,15 @@ package rasel.lunar.launcher.todos
import android.annotation.SuppressLint
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.core.content.ContextCompat.startActivity
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import com.google.gson.Gson
import rasel.lunar.launcher.LauncherActivity.Companion.lActivity
import rasel.lunar.launcher.R
import rasel.lunar.launcher.databinding.ListItemBinding
import rasel.lunar.launcher.home.RssTagItem
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import java.text.SimpleDateFormat
import java.util.Date
import rasel.lunar.launcher.model.RssTagItem
internal class RssTagAdapter(
private val smsList: ArrayList<RssTagItem>,
@ -58,7 +50,6 @@ internal class RssTagAdapter(
val todo = smsList[position]
holder.view.itemText.text = "\u25CF ${Gson().toJson(todo)}"
BLog.LOGE("holder.view.itemText.text >>> ${holder.view.itemText.text}")
/* multiline texts are enabled for TodoManager */
// holder.view.itemText.isSingleLine = false
/* 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.databinding.ListItemBinding
import rasel.lunar.launcher.utils.BLog
import rasel.lunar.launcher.utils.RecentSmsLog
import rasel.lunar.launcher.workers.RecentSms
import java.text.SimpleDateFormat
import java.util.Date
internal class SmsLogsAdapter(
private val smsList: ArrayList<RecentSmsLog>,
private val smsList: ArrayList<RecentSms>,
private val context: Context) : RecyclerView.Adapter<SmsLogHolder>() {
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))
diffUtilResult.dispatchUpdatesTo(this)
// smsList.clear()
@ -142,7 +142,7 @@ internal class SmsLogsAdapter(
}
class SmsLogHolder(var view: ListItemBinding) : RecyclerView.ViewHolder(view.root)
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() {
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
import org.json.JSONObject
import rasel.lunar.launcher.model.Image
import rasel.lunar.launcher.model.Source
import rasel.lunar.launcher.model.RssDataInterface
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.beforeDay
import java.util.Date
@ -90,7 +92,7 @@ class Avatar {
}
class AvatarViewModel {
var image: Image? = null
var YTBImage: YTBImage? = null
var avatarImageSize: String? = null
var loggingDirectives: LoggingDirectives? = null
}
@ -589,19 +591,19 @@ class Identifier {
}
class Image {
var sources: ArrayList<Source>? = null
var sources: ArrayList<YTBSource>? = null
var decoratedAvatarViewModel: DecoratedAvatarViewModel? = null
var processor: Processor? = null
}
class ImageBannerViewModel {
var image: Image? = null
var YTBImage: YTBImage? = null
var style: String? = null
var rendererContext: RendererContext? = null
}
class ImageType {
var image: Image? = null
var YTBImage: YTBImage? = null
}
class InlineContent {
@ -653,7 +655,7 @@ class LayoutProperties {
}
class LeadingImage {
var sources: ArrayList<Source>? = null
var sources: ArrayList<YTBSource>? = null
}
class Left {
@ -973,7 +975,7 @@ class PageHeaderRenderer {
class PageHeaderViewModel {
var title: Title? = null
var image: Image? = null
var YTBImage: YTBImage? = null
var metadata: Metadata? = null
var actions: Action? = null
var description: Description? = null
@ -1565,7 +1567,7 @@ class VideoCountText {
var runs: ArrayList<Run>? = null
}
open class VideoRenderer : RssDataItem {
open class VideoRenderer : RssDataInterface {
var videoId: String? = null
var thumbnail: Thumbnail? = 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(
"https://www.reddit.com/r/nsfw/.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",
)

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:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:background="#05000000"
android:layout_width="match_parent"
android:layout_height="match_parent">
<View
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
<TextView
android:id="@+id/batteryProgress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/twelve"
android:layout_marginRight="12dp"
android:indeterminate="false"
android:max="100"
app:trackCornerRadius="@dimen/four"
app:showAnimationBehavior="inward"
app:indicatorColor="?android:attr/textColorPrimary"
app:indicatorSize="@dimen/twoSeventySix"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
android:textSize="18sp"
android:text="빠떼뤼 ~> 0%"
app:layout_constraintRight_toRightOf="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
android:id="@+id/time"
android:layout_width="wrap_content"
@ -40,11 +40,9 @@
android:textSize="@dimen/clockText"
android:textStyle="bold"
android:textLocale="en_US"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintTop_toTopOf="@+id/batteryProgress"
app:layout_constraintVertical_bias="0.450"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
tools:ignore="UnusedAttribute" />
<TextClock
@ -53,13 +51,12 @@
android:layout_height="wrap_content"
android:gravity="center"
android:maxLines="1"
android:textLocale="en_US"
android:textSize="20sp"
android:format12Hour="yyyy년 M월 d일 E요일"
android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/time"
app:layout_constraintVertical_bias="0.075"
tools:ignore="UnusedAttribute" />
<com.google.android.material.textview.MaterialTextView
@ -69,13 +66,13 @@
android:gravity="center"
android:maxLines="1"
android:textIsSelectable="false"
app:layout_constraintBottom_toBottomOf="@+id/batteryProgress"
app:layout_constraintEnd_toEndOf="@+id/batteryProgress"
app:layout_constraintStart_toStartOf="@+id/batteryProgress"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@+id/date"
app:layout_constraintVertical_bias="0.100" />
<RadioGroup
android:layout_marginTop="20dp"
android:id="@+id/summaryChoose"
android:layout_width="0dp"
android:gravity="center"
@ -83,7 +80,7 @@
android:orientation="horizontal"
app:layout_constraintRight_toRightOf="parent"
android:layout_height="40dp"
app:layout_constraintTop_toBottomOf="@+id/batteryProgress"
app:layout_constraintTop_toBottomOf="@+id/weather"
>
<RadioButton
@ -126,11 +123,10 @@
android:overScrollMode="never"
android:padding="20dp"
android:scrollbars="none"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/smsList"
@ -142,7 +138,7 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/>
<androidx.recyclerview.widget.RecyclerView
@ -155,19 +151,17 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/summaryChoose"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintBottom_toTopOf="@id/favAppsGroup"
/>
<androidx.appcompat.widget.LinearLayoutCompat
android:id="@+id/favAppsGroup"
android:layout_width="@dimen/zero"
android:visibility="gone"
android:layout_height="wrap_content"
android:layout_height="60dp"
android:layout_marginTop="@dimen/twentyTwo"
android:layout_marginBottom="@dimen/twelve"
android:orientation="horizontal"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintTop_toBottomOf="@+id/mainList" />
app:layout_constraintBottom_toBottomOf="parent" />
</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.
buildscript {
val kotlinVersion = "1.9.0"
val kotlinVersion = "2.0.0"
extra ["kotlinVersion"] = kotlinVersion
dependencies {
@ -9,11 +9,22 @@ buildscript {
}
plugins {
id ("io.realm.kotlin") version "1.16.0" apply false
id ("com.android.application") 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") {
delete(rootProject.buildDir)
}
//repositories {
// mavenCentral()
// maven {
// url = uri("https://jitpack.io")
// }
// jcenter()
// mavenLocal()
// flatDir {
// dirs("libs")
// }
//}