today's dress by the hour

This commit is contained in:
JUNGGWAN KIM 2024-10-02 17:43:18 +09:00
parent 3561137c6b
commit 002c9a9e2d
7 changed files with 137 additions and 50 deletions

View File

@ -304,7 +304,7 @@ internal class LauncherActivity : AppCompatActivity() {
mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG) mWorkManager?.cancelAllWorkByTag(LocationGetter.TAG)
mWorkManager?.enqueueUniquePeriodicWork( mWorkManager?.enqueueUniquePeriodicWork(
LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE, LocationGetter.TAG, ExistingPeriodicWorkPolicy.CANCEL_AND_REENQUEUE,
PeriodicWorkRequestBuilder<OpenWeatherGetter>(midTimePeriod, TimeUnit.MINUTES) PeriodicWorkRequestBuilder<LocationGetter>(midTimePeriod, TimeUnit.MINUTES)
.addTag(LocationGetter.TAG) .addTag(LocationGetter.TAG)
.build()) .build())
}, weatherDelay, TimeUnit.SECONDS) }, weatherDelay, TimeUnit.SECONDS)

View File

@ -53,9 +53,13 @@ import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import androidx.work.OneTimeWorkRequest import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager import androidx.work.WorkManager
import io.realm.kotlin.ext.asFlow
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import io.realm.kotlin.notifications.InitialObject
import io.realm.kotlin.notifications.InitialResults import io.realm.kotlin.notifications.InitialResults
import io.realm.kotlin.notifications.ObjectChange
import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.notifications.ResultsChange
import io.realm.kotlin.notifications.UpdatedObject
import io.realm.kotlin.notifications.UpdatedResults import io.realm.kotlin.notifications.UpdatedResults
import io.realm.kotlin.query.RealmResults import io.realm.kotlin.query.RealmResults
import io.realm.kotlin.query.Sort import io.realm.kotlin.query.Sort
@ -86,11 +90,13 @@ import rasel.lunar.launcher.home.adapters.NotificationItemAdapter
import rasel.lunar.launcher.home.adapters.RecentCallsAdapter import rasel.lunar.launcher.home.adapters.RecentCallsAdapter
import rasel.lunar.launcher.home.adapters.RssItemAdapter import rasel.lunar.launcher.home.adapters.RssItemAdapter
import rasel.lunar.launcher.home.adapters.SmsLogsAdapter import rasel.lunar.launcher.home.adapters.SmsLogsAdapter
import rasel.lunar.launcher.home.adapters.WeatherAdapter
import rasel.lunar.launcher.model.CurrentPlayItem import rasel.lunar.launcher.model.CurrentPlayItem
import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.NotificationItem
import rasel.lunar.launcher.model.RssData import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.RssDataInterface import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.RssDataType import rasel.lunar.launcher.model.RssDataType
import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.qaccess.QuickAccess import rasel.lunar.launcher.qaccess.QuickAccess
import rasel.lunar.launcher.settings.SettingsActivity import rasel.lunar.launcher.settings.SettingsActivity
import rasel.lunar.launcher.utils.BLog import rasel.lunar.launcher.utils.BLog
@ -166,6 +172,7 @@ internal class LauncherHome : Fragment() {
home = this home = this
BLog.LOGE("${this} ::::: onCreate >>>> ") BLog.LOGE("${this} ::::: onCreate >>>> ")
} }
var mWeatherResult : RealmResults<WeatherForcast>? = null
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View { override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
BLog.LOGE("${this} ::::: onCreateView >>>> ") BLog.LOGE("${this} ::::: onCreateView >>>> ")
binding = LauncherHomeBinding.inflate(inflater, container, false) binding = LauncherHomeBinding.inflate(inflater, container, false)
@ -176,6 +183,11 @@ internal class LauncherHome : Fragment() {
mSmsLogsAdapter = SmsLogsAdapter(arrayListOf(), requireContext()) mSmsLogsAdapter = SmsLogsAdapter(arrayListOf(), requireContext())
mNotiAdapter = NotificationItemAdapter(requireContext()) mNotiAdapter = NotificationItemAdapter(requireContext())
mRssAdapter = RssItemAdapter(requireContext()) mRssAdapter = RssItemAdapter(requireContext())
mWeatherAdapter = WeatherAdapter(arrayListOf())
// WorkersDb.getRealm().query<WeatherForcast>().first().find()?.forecast?.let {
// mWeatherAdapter?.update(it.forecastday)
// BLog.LOGE("saved weatherForcast >>> ${it.forecastday}")
// }
val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL) val decoration = DividerItemDecoration(requireContext(), DividerItemDecoration.VERTICAL)
@ -189,12 +201,13 @@ internal class LauncherHome : Fragment() {
binding.mainList.layoutManager = GridLayoutManager(requireContext(),2) binding.mainList.layoutManager = GridLayoutManager(requireContext(),2)
binding.smsList.layoutManager = GridLayoutManager(requireContext(),2) binding.smsList.layoutManager = GridLayoutManager(requireContext(),2)
binding.infoList.layoutManager = LinearLayoutManager(requireContext()) binding.infoList.layoutManager = LinearLayoutManager(requireContext())
binding.noticeSummary.weatherRecycller.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.HORIZONTAL, false)
binding.mainList.adapter = mRecentCallsAdapter binding.mainList.adapter = mRecentCallsAdapter
binding.smsList.adapter = mSmsLogsAdapter binding.smsList.adapter = mSmsLogsAdapter
binding.infoList.adapter = mRssAdapter binding.infoList.adapter = mRssAdapter
binding.notiList.adapter = mNotiAdapter binding.notiList.adapter = mNotiAdapter
binding.noticeSummary.weatherRecycller.adapter = mWeatherAdapter
binding.favAppsGroup.setOnClickListener { searchData() } binding.favAppsGroup.setOnClickListener { searchData() }
try{binding.mainList.removeOnScrollListener(onScrChanged)}catch (e : Exception){e.printStackTrace()} try{binding.mainList.removeOnScrollListener(onScrChanged)}catch (e : Exception){e.printStackTrace()}
@ -272,12 +285,45 @@ internal class LauncherHome : Fragment() {
mAudioManager.dispatchMediaKeyEvent(upEvent) mAudioManager.dispatchMediaKeyEvent(upEvent)
} }
queryInfos() queryInfos()
queryNotice() queryNotice()
queryWeather()
return binding.root return binding.root
} }
@SuppressLint("NotifyDataSetChanged")
private fun queryWeather() {
mWeatherResult = WorkersDb.getRealm().query<WeatherForcast>().find()
val weatherJob = CoroutineScope(Dispatchers.Default).launch {
mWeatherResult?.asFlow()?.collect { changes ->
BLog.LOGE("saved weatherForcast >>> asFlow ${changes.list}")
if (changes.list.size > 0) {
changes.list.first().forecast?.forecastdayRealm?.let { li ->
BLog.LOGE("LauncherHome Saved Forecastdays >>> ${li.size}")
Handler(Looper.getMainLooper()).post {
mWeatherAdapter?.let{
it.update(
it.filter(
li.first()
.hourRealm
.also { hli ->
BLog.LOGE("LauncherHome Saved hli >>> ${hli.size}")
}
).also { fli ->
BLog.LOGE("LauncherHome Saved fli >>> ${fli.size}")
}
)
it.notifyDataSetChanged()
}
}
}
}
}
}
weatherJob.start()
}
val hideListViewTime = 1000L * 60L * 15L val hideListViewTime = 1000L * 60L * 15L
val hideListView = { val hideListView = {
@ -451,6 +497,30 @@ internal class LauncherHome : Fragment() {
} }
is UpdatedResults -> { is UpdatedResults -> {
// lasted = changes.list // lasted = changes.list
// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY * 3)
}
else -> {
}
}
}
}
infosJob?.start()
mRssDataResult = rQ.sort("pubDate ", Sort.DESCENDING).find()
infosJob = CoroutineScope(Dispatchers.Default).launch {
mRssDataResult?.asFlow()?.collect { changes: ResultsChange<RssData> ->
commandHandler.removeCallbacks(hideListView)
commandHandler.removeCallbacks(infoUpdate)
when (changes) {
is InitialResults -> {
WorkersDb.getRealm().apply {
lasted = copyFromRealm(changes.list)
}
commandHandler.postDelayed(infoUpdate, UPDATE_DELAY)
}
is UpdatedResults -> {
// lasted = changes.list
// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY * 3) // commandHandler.postDelayed(infoUpdate, UPDATE_DELAY * 3)
} }
else -> { else -> {
@ -468,6 +538,7 @@ internal class LauncherHome : Fragment() {
lateinit var mSmsLogsAdapter : SmsLogsAdapter lateinit var mSmsLogsAdapter : SmsLogsAdapter
lateinit var mRssAdapter : RssItemAdapter lateinit var mRssAdapter : RssItemAdapter
lateinit var mNotiAdapter : NotificationItemAdapter lateinit var mNotiAdapter : NotificationItemAdapter
var mWeatherAdapter: WeatherAdapter? =null
var mRssDataResult : RealmResults<RssData>? = null var mRssDataResult : RealmResults<RssData>? = null
var mNotificationResult : RealmResults<NotificationItem>? = null var mNotificationResult : RealmResults<NotificationItem>? = null

View File

@ -1,19 +1,23 @@
package rasel.lunar.launcher.home.adapters package rasel.lunar.launcher.home.adapters
import android.annotation.SuppressLint
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.ImageView import android.widget.ImageView
import android.widget.TextView import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import io.realm.kotlin.ext.toRealmList
import rasel.lunar.launcher.R import rasel.lunar.launcher.R
import rasel.lunar.launcher.home.adapters.WeatherAdapter.ViewHolder import rasel.lunar.launcher.home.adapters.WeatherAdapter.ViewHolder
import rasel.lunar.launcher.model.Forecastday
import rasel.lunar.launcher.model.Hour import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.WeatherForcast import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.utils.BLog
import java.time.Instant import java.time.Instant
import java.time.ZoneId import java.time.ZoneId
class WeatherAdapter(private val dataSet: Array<String>): RecyclerView.Adapter<ViewHolder>(){ class WeatherAdapter(private val dataSet: ArrayList<Hour>): RecyclerView.Adapter<ViewHolder>(){
var isShowAmOrPm: Boolean = true var isShowAmOrPm: Boolean = true
class ViewHolder(view: View): RecyclerView.ViewHolder(view) { class ViewHolder(view: View): RecyclerView.ViewHolder(view) {
@ -24,42 +28,58 @@ class WeatherAdapter(private val dataSet: Array<String>): RecyclerView.Adapter<V
} }
} }
// @SuppressLint("NotifyDataSetChanged")
fun update(li: Collection<Hour>) {
li.toList()
this.dataSet.clear()
this.dataSet.addAll(li)
// notifyDataSetChanged()
}
fun filter(arr: Collection<Hour>) = mutableListOf<Hour>()
.apply {
arr.forEach {
if (it.time_epoch >= (System.currentTimeMillis() / 1000)) {
this.add(it)
}
}
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder { override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
val view = LayoutInflater.from(parent.context) val view = LayoutInflater.from(parent.context)
.inflate(R.layout.recommended_hourly_dress, parent, false) .inflate(R.layout.item_rec_hourly_dress, parent, false)
return ViewHolder(view) return ViewHolder(view)
} }
override fun onBindViewHolder(holder: ViewHolder, position: Int) { override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val data = dataSet[position] as? Hour val data = dataSet[position] as? Hour
BLog.LOGE("saved weatherForcast >>> asFlow ${dataSet.size}")
data?.let { data?.let {
if (it.time_epoch >= (System.currentTimeMillis() / 1000)) { holder.viewItem.findViewById<TextView>(R.id.amOrPm)
holder.viewItem.findViewById<TextView>(R.id.amOrPm) .run {
.run { this.text = Instant.ofEpochSecond(it.time_epoch.toLong())
this.text = Instant.ofEpochSecond(it.time_epoch.toLong()) .atZone(ZoneId.systemDefault())
.atZone(ZoneId.systemDefault()) .hour
.hour .run {
.run { if (this < 12) "오전" else "오후"
if (this < 12) "오전" else "오후" }
} }
} holder.viewItem.findViewById<TextView>(R.id.hour)
holder.viewItem.findViewById<TextView>(R.id.hour) .run {
.run { val hour = Instant.ofEpochSecond(it.time_epoch.toLong())
val hour = Instant.ofEpochSecond(it.time_epoch.toLong()) .atZone(ZoneId.systemDefault())
.atZone(ZoneId.systemDefault()) .hour
.hour .toString()
.toString() this.text = "${hour}"
this.text = "${hour}" }
} holder.viewItem.findViewById<ImageView>(R.id.imgDress)
holder.viewItem.findViewById<ImageView>(R.id.imgDress) .run { this.setImageResource(R.drawable.ico_time) }
.run { this.setImageResource(R.drawable.ico_time) } holder.viewItem.findViewById<TextView>(R.id.temperature)
holder.viewItem.findViewById<TextView>(R.id.temperature) .run {
.run { this.text = "${it.temp_c}"
this.text = "${it.temp_c}" }
}
} }
}
} }
override fun getItemCount(): Int = 3 override fun getItemCount(): Int = dataSet.size
} }

View File

@ -4,6 +4,7 @@ import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.Ignore import io.realm.kotlin.types.annotations.Ignore
import io.realm.kotlin.types.annotations.PrimaryKey
class WeatherForcast: RealmObject { class WeatherForcast: RealmObject {
@ -82,6 +83,7 @@ class Condition: RealmObject {
// Forecast // Forecast
class Forecastday: RealmObject { class Forecastday: RealmObject {
var date: String? = null var date: String? = null
@PrimaryKey
var date_epoch = 0 var date_epoch = 0
var day: Day? = null var day: Day? = null
var astro: Astro? = null var astro: Astro? = null
@ -131,6 +133,7 @@ class Astro: RealmObject {
} }
class Hour: RealmObject { class Hour: RealmObject {
@PrimaryKey
var time_epoch = 0 var time_epoch = 0
var time: String? = null var time: String? = null
var temp_c = 0.0 var temp_c = 0.0

View File

@ -15,7 +15,6 @@ import rasel.lunar.launcher.apps.SimpleContact
import rasel.lunar.launcher.model.AppInfo import rasel.lunar.launcher.model.AppInfo
import rasel.lunar.launcher.model.Astro import rasel.lunar.launcher.model.Astro
import rasel.lunar.launcher.model.BotCommandEentitie import rasel.lunar.launcher.model.BotCommandEentitie
import rasel.lunar.launcher.model.Clouds
import rasel.lunar.launcher.model.Condition import rasel.lunar.launcher.model.Condition
import rasel.lunar.launcher.model.Current import rasel.lunar.launcher.model.Current
import rasel.lunar.launcher.model.CurrentPlayItem import rasel.lunar.launcher.model.CurrentPlayItem
@ -24,19 +23,15 @@ import rasel.lunar.launcher.model.Forecast
import rasel.lunar.launcher.model.Forecastday import rasel.lunar.launcher.model.Forecastday
import rasel.lunar.launcher.model.Hour import rasel.lunar.launcher.model.Hour
import rasel.lunar.launcher.model.Location import rasel.lunar.launcher.model.Location
import rasel.lunar.launcher.model.Main
import rasel.lunar.launcher.model.NotificationItem import rasel.lunar.launcher.model.NotificationItem
import rasel.lunar.launcher.model.RssData import rasel.lunar.launcher.model.RssData
import rasel.lunar.launcher.model.RssDataInterface import rasel.lunar.launcher.model.RssDataInterface
import rasel.lunar.launcher.model.Sys
import rasel.lunar.launcher.model.TelegramBotUpdate import rasel.lunar.launcher.model.TelegramBotUpdate
import rasel.lunar.launcher.model.TelegramChat import rasel.lunar.launcher.model.TelegramChat
import rasel.lunar.launcher.model.TelegramData import rasel.lunar.launcher.model.TelegramData
import rasel.lunar.launcher.model.TelegramFrom import rasel.lunar.launcher.model.TelegramFrom
import rasel.lunar.launcher.model.TelegramMessage import rasel.lunar.launcher.model.TelegramMessage
import rasel.lunar.launcher.model.Weather
import rasel.lunar.launcher.model.WeatherForcast import rasel.lunar.launcher.model.WeatherForcast
import rasel.lunar.launcher.model.Wind
import kotlin.reflect.KClass import kotlin.reflect.KClass
object WorkersDb { object WorkersDb {

View File

@ -128,15 +128,15 @@
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<androidx.recyclerview.widget.RecyclerView <include
android:id="@+id/noticeSummary" android:id="@+id/noticeSummary"
layout="@layout/recommended_hourly_dress"
android:layout_margin="10dp" android:layout_margin="10dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/current_music" app:layout_constraintTop_toBottomOf="@id/current_music"
android:layout_width="0dp" android:layout_width="match_parent"
android:layout_height="40dp"> android:layout_height="wrap_content"/>
</androidx.recyclerview.widget.RecyclerView>
<LinearLayout <LinearLayout

View File

@ -32,15 +32,13 @@
android:textSize="14sp" android:textSize="14sp"
android:layout_marginLeft="10dp"/> android:layout_marginLeft="10dp"/>
</LinearLayout> </LinearLayout>
<HorizontalScrollView <androidx.recyclerview.widget.RecyclerView
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toBottomOf="@id/linearLayout" app:layout_constraintTop_toBottomOf="@id/linearLayout"
app:layout_constraintLeft_toLeftOf="@id/linearLayout" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="@id/linearLayout"> app:layout_constraintRight_toRightOf="parent"
<androidx.recyclerview.widget.RecyclerView android:id="@+id/weather_recycller"
android:layout_width="match_parent" app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager"
android:layout_height="match_parent"> android:layout_width="match_parent"
</androidx.recyclerview.widget.RecyclerView> android:layout_height="wrap_content">
</HorizontalScrollView> </androidx.recyclerview.widget.RecyclerView>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>