From 87ded0bda58123bb70732490a221fd4ffbd38038 Mon Sep 17 00:00:00 2001 From: lunaticbum <> Date: Wed, 6 Nov 2024 16:47:13 +0900 Subject: [PATCH] ... --- app/build.gradle.kts | 5 + .../launcher/helpers/BluetoothManager.kt | 2 +- .../lunatic/launcher/home/LauncherHome.kt | 175 +++++++----------- .../launcher/home/adapters/RssItemAdapter.kt | 18 +- .../home/adapters/SwipeToDeleteCallback.kt | 109 +++++++++++ .../lunatic/launcher/model/CommunityData.kt | 1 + .../lunatic/launcher/workers/WorkersDb.kt | 3 +- 7 files changed, 194 insertions(+), 119 deletions(-) create mode 100644 app/src/main/kotlin/bums/lunatic/launcher/home/adapters/SwipeToDeleteCallback.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 9dd42ce..0eabe85 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -1,4 +1,6 @@ import org.jetbrains.kotlin.fir.scopes.debugCollectOverrides +import java.text.SimpleDateFormat +import java.util.Date plugins { id ("com.android.application") @@ -25,12 +27,14 @@ android { isDebuggable = true applicationIdSuffix = ".debug" versionNameSuffix = "-debug" + buildConfigField("Long","BuildDateTime", getDateTime().toString().plus("L")) resValue ("string", "app_name", "Bums Launcher Debug") } getByName("release") { isMinifyEnabled = true isShrinkResources = true + buildConfigField("Long","BuildDateTime", getDateTime().toString().plus("L")) proguardFiles (getDefaultProguardFile("proguard-android-optimize.txt"), "proguard-rules.pro") resValue ("string", "app_name", "Bums Launcher") } @@ -103,3 +107,4 @@ dependencies { // implementation ("androidx.window:window:1.0.0") // implementation("io.github.vaneproject:hanguleditor:1.0.0") } +fun getDateTime() = SimpleDateFormat("yyyyMMddHHmm").format(Date()).toLong() diff --git a/app/src/main/kotlin/bums/lunatic/launcher/helpers/BluetoothManager.kt b/app/src/main/kotlin/bums/lunatic/launcher/helpers/BluetoothManager.kt index ad48c76..47ca17d 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/helpers/BluetoothManager.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/helpers/BluetoothManager.kt @@ -124,7 +124,7 @@ class BluetoothManager { try { val m = device.javaClass.getMethod("isConnected") val connected = m.invoke(device) as Boolean - BLog.LOGE("D >> " + device.name + " || isConnected >>> " + (if (connected) "TRUE" else "FALSE")) +// BLog.LOGE("D >> " + device.name + " || isConnected >>> " + (if (connected) "TRUE" else "FALSE")) return connected } catch (e: Exception) { throw IllegalStateException(e) diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt index d27bfd8..b92a95e 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt @@ -26,6 +26,7 @@ import android.content.Intent import android.content.IntentFilter import android.content.SharedPreferences import android.graphics.Bitmap +import android.graphics.Color import android.media.AudioManager import android.net.Uri import android.os.Bundle @@ -41,6 +42,7 @@ import android.widget.CheckBox import android.widget.EditText import android.widget.TableRow import android.widget.Toast +import androidx.annotation.NonNull import androidx.appcompat.app.AlertDialog import androidx.biometric.BiometricPrompt import androidx.core.view.children @@ -48,10 +50,10 @@ import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.DividerItemDecoration import androidx.recyclerview.widget.GridLayoutManager +import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.LinearLayoutManager import androidx.recyclerview.widget.RecyclerView import androidx.viewpager2.widget.ViewPager2 -import androidx.work.WorkManager import bums.lunatic.launcher.LauncherActivity.Companion.lActivity import bums.lunatic.launcher.R import bums.lunatic.launcher.databinding.LauncherHomeBinding @@ -69,6 +71,7 @@ import bums.lunatic.launcher.home.adapters.NotificationItemAdapter import bums.lunatic.launcher.home.adapters.RecentCallsAdapter import bums.lunatic.launcher.home.adapters.RssItemAdapter import bums.lunatic.launcher.home.adapters.SmsLogsAdapter +import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback import bums.lunatic.launcher.home.adapters.WeatherAdapter import bums.lunatic.launcher.home.adapters.WeatherDressAdatper import bums.lunatic.launcher.home.adapters.WeatherHourlyAdapter @@ -94,15 +97,20 @@ import bums.lunatic.launcher.workers.RecentSms import bums.lunatic.launcher.workers.WorkersDb import bums.lunatic.launcher.workers.latitudeRange import bums.lunatic.launcher.workers.longitudeRange +import com.google.android.material.snackbar.Snackbar +import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.ext.query import io.realm.kotlin.notifications.InitialResults import io.realm.kotlin.notifications.ResultsChange import io.realm.kotlin.notifications.UpdatedResults +import io.realm.kotlin.query.RealmQuery import io.realm.kotlin.query.RealmResults import io.realm.kotlin.query.Sort import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Job +import kotlinx.coroutines.flow.Flow +import kotlinx.coroutines.flow.cancellable import kotlinx.coroutines.launch import org.json.JSONArray import org.json.JSONObject @@ -111,8 +119,6 @@ import java.math.RoundingMode import java.net.URLEncoder import java.util.Calendar import java.util.Date -import java.util.concurrent.Executors -import java.util.concurrent.TimeUnit import java.util.regex.Pattern @@ -141,7 +147,7 @@ internal class LauncherHome : Fragment() { // } // } - val UPDATE_DELAY = 1000L + val UPDATE_DELAY = 5L val commandHandler = Handler(Looper.getMainLooper()) val smsUpdate = Runnable { @@ -154,7 +160,9 @@ internal class LauncherHome : Fragment() { chooseAdpater() } + val infoUpdate = Runnable { + BLog.LOGE("swipeToDeleteCallback data called infoUpdate ") chooseAdpater() } @@ -505,32 +513,29 @@ internal class LauncherHome : Fragment() { } noticeJob?.start() } - - fun queryVotes() { - try { infosJob?.cancel() } catch (e:Exception) {e.printStackTrace()} + val nomoreShowCount = 5 + fun beforeQuery() { mRssDataResult = null - try { - System.gc() - }catch (e : Exception){e.printStackTrace()} + try { infosJob?.cancel() } catch (e:Exception) {e.printStackTrace()} + try { System.gc() }catch (e : Exception){e.printStackTrace()} + WorkersDb.getRealm().writeBlocking { + delete(query().query("pubDate < $0",beforeDay(Date(),3)).query("category != $0 AND category != $1 ", RssDataType.GURU.name,RssDataType.MOST.name).query("vote != $0", true).find()) + } + } - var rQ = WorkersDb.getRealm().query().query("vote == $0",true) - mRssDataResult = rQ.sort("pubDate ", Sort.DESCENDING).find() + fun updateQuery(q : RealmQuery) { + mRssDataResult = q.sort("pubDate ", Sort.DESCENDING).limit(300).find() infosJob = CoroutineScope(Dispatchers.Default).launch { mRssDataResult?.asFlow()?.collect { changes: ResultsChange -> commandHandler.removeCallbacks(hideListView) commandHandler.removeCallbacks(infoUpdate) when (changes) { - is InitialResults -> { -// BLog.LOGE("${this} ::::: queryInfos after changes size >>>> ${changes.list.size}") + is InitialResults,is UpdatedResults -> { WorkersDb.getRealm().apply { lasted = copyFromRealm(changes.list) } commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) } - is UpdatedResults -> { -// lasted = changes.list -// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY * 3) - } else -> { } } @@ -539,59 +544,26 @@ internal class LauncherHome : Fragment() { infosJob?.start() } - fun queryInfos(filter: Collection? = arrayListOf(RssDataType.GURU,RssDataType.MOST,RssDataType.REDDIT_NSFW), noLimit : Boolean = false) { - try { infosJob?.cancel() } catch (e:Exception) {e.printStackTrace()} - mRssDataResult = null - try { - System.gc() - }catch (e : Exception){e.printStackTrace()} + fun queryVotes() { + beforeQuery() + var rQ = WorkersDb.getRealm().query().query("vote == $0",true) + updateQuery(rQ) + } - WorkersDb.getRealm().apply { writeBlocking { - delete(query().query("pubDate < $0",beforeDay(Date(),3)).query("category != $0 AND category != $1 ", RssDataType.GURU.name,RssDataType.MOST.name).query("vote != $0", true).find()) - }} - var rQ = WorkersDb.getRealm().query() + fun queryInfos(filter: Collection? = arrayListOf(RssDataType.GURU,RssDataType.MOST,RssDataType.REDDIT_NSFW), noLimit : Boolean = false) { + beforeQuery() + var rQ = WorkersDb.getRealm().query().query("read < $0", nomoreShowCount) if(!noLimit) rQ.query("pubDate > $0", beforeDay(Date(),3)) filter!!.forEach { rQ = rQ.query("category != $0", it.name) } - //limit(1000) - mRssDataResult = rQ.sort("pubDate ", Sort.DESCENDING).find() -// BLog.LOGE("${this} ::::: queryInfos after query find >>>> ") - infosJob = CoroutineScope(Dispatchers.Default).launch { - mRssDataResult?.asFlow()?.collect { changes: ResultsChange -> - commandHandler.removeCallbacks(hideListView) - commandHandler.removeCallbacks(infoUpdate) - when (changes) { - is InitialResults -> { -// BLog.LOGE("${this} ::::: queryInfos after changes size >>>> ${changes.list.size}") - WorkersDb.getRealm().apply { - lasted = copyFromRealm(changes.list) - } - commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) - } - is UpdatedResults -> { -// lasted = changes.list -// commandHandler.postDelayed(infoUpdate, UPDATE_DELAY * 3) - } - else -> { - } - } - } - } - infosJob?.start() + + updateQuery(rQ) } fun queryInfos(keyword : String, category : ArrayList = arrayListOf(), noLimit : Boolean = false) { - try { infosJob?.cancel() } catch (e:Exception) {e.printStackTrace()} - mRssDataResult = null - try { - System.gc() - }catch (e : Exception){e.printStackTrace()} - - WorkersDb.getRealm().apply { writeBlocking { - delete(query().query("pubDate < $0",beforeDay(Date(),3)).query("category != $0 AND category != $1 ", RssDataType.GURU.name,RssDataType.MOST.name).query("vote != $0", true).find()) - }} - var rQ = WorkersDb.getRealm().query() + beforeQuery() + var rQ = WorkersDb.getRealm().query().query("read < $0", nomoreShowCount) if (!noLimit)rQ.query("pubDate > $0", beforeDay(Date(),3)) if(keyword.length > 0) { // BLog.LOGE("queryInfos it >>> ${keyword}") @@ -627,54 +599,7 @@ internal class LauncherHome : Fragment() { rQ = rQ.query(queryString) } - - mRssDataResult = rQ.sort("pubDate ", Sort.DESCENDING).find() - infosJob = CoroutineScope(Dispatchers.Default).launch { - mRssDataResult?.asFlow()?.collect { changes: ResultsChange -> - 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) - } - else -> { - } - } - } - } - infosJob?.start() - - mRssDataResult = rQ.sort("pubDate ", Sort.DESCENDING).find() - infosJob = CoroutineScope(Dispatchers.Default).launch { - mRssDataResult?.asFlow()?.collect { changes: ResultsChange -> - 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) - } - else -> { - } - } - } - } - infosJob?.start() + updateQuery(rQ) } var infosJob : Job? = null @@ -786,7 +711,7 @@ internal class LauncherHome : Fragment() { queryInfos() true } - + enableSwipeToDeleteAndUndo() } // https://www.youtube.com/results?search_query=sds @@ -921,6 +846,32 @@ internal class LauncherHome : Fragment() { } commandHandler.postDelayed(hideListView, hideListViewTime) } + + private fun enableSwipeToDeleteAndUndo() { + val swipeToDeleteCallback: SwipeToDeleteCallback = object : SwipeToDeleteCallback(requireContext()) { + override fun onSwiped(@NonNull viewHolder: RecyclerView.ViewHolder, i: Int) { + BLog.LOGE("swipeToDeleteCallback start") + (viewHolder.itemView.getTag() as? RssData)?.let { rss -> + WorkersDb.getRealm().apply { + writeBlocking { + if (rss.vote) { + rss.vote = false + rss.read = 0 + } else { + rss.read += nomoreShowCount + } + copyToRealm(rss, UpdatePolicy.ALL) + BLog.LOGE("swipeToDeleteCallback data update ") + } + } + } + BLog.LOGE("swipeToDeleteCallback endEvent") + } + } + + val itemTouchhelper = ItemTouchHelper(swipeToDeleteCallback) + itemTouchhelper.attachToRecyclerView(binding.infoList) + } override fun onResume() { super.onResume() // BLog.LOGE("${this} ::::: onResume >>>> ") diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/RssItemAdapter.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/RssItemAdapter.kt index f7a3ff2..e31ca06 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/RssItemAdapter.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/RssItemAdapter.kt @@ -38,6 +38,7 @@ import bums.lunatic.launcher.openNews import bums.lunatic.launcher.openOpera import bums.lunatic.launcher.openReddit import bums.lunatic.launcher.openYouTube +import bums.lunatic.launcher.utils.BLog import bums.lunatic.launcher.workers.WorkersDb import com.google.android.material.imageview.ShapeableImageView import com.squareup.picasso.Picasso @@ -55,6 +56,12 @@ internal class RssItemAdapter ( val dateViewClick = View.OnClickListener { v -> (v?.tag as? RssData)?.let { rss -> + WorkersDb.getRealm().apply { + writeBlocking { + rss.read = rss.read + 1 + copyToRealm(rss,UpdatePolicy.ALL) + } + } when(rss.category()) { RssDataType.GURU,RssDataType.MOST,RssDataType.REDDIT_NSFW -> { v.findViewById(R.id.circle_preview)?.let { @@ -84,11 +91,11 @@ internal class RssItemAdapter ( (v?.tag as? RssData)?.let { rss -> WorkersDb.getRealm().apply { writeBlocking { - rss.vote = true + rss.vote = !rss.vote copyToRealm(rss,UpdatePolicy.ALL) } } - dateViewClick.onClick(v) +// dateViewClick.onClick(v) } true } @@ -132,14 +139,14 @@ internal class RssItemAdapter ( holder.view.circlePreview.setImageDrawable(null) } - holder.view.root.tag = rssData - holder.view.root.setOnClickListener(dateViewClick) + holder.itemView.tag = rssData + holder.itemView.setOnClickListener(dateViewClick) // v.setOnLongClickListener { // WorkersDb.getRealm().apply { // copyFromRealm(rss) // } // } - holder.view.root.setOnLongClickListener(mLongClickListener) + holder.itemView.setOnLongClickListener(mLongClickListener) } var layoutManager : LinearLayoutManager? = null @@ -151,6 +158,7 @@ internal class RssItemAdapter ( fun updateData(newList: List) { try { + BLog.LOGE("swipeToDeleteCallback data called updateData ${newList} ") // BLog.LOGE("newList >> ${newList}") DiffUtil.calculateDiff(RssItemDiffUtil(rssDataItemLis, newList)).apply { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/SwipeToDeleteCallback.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/SwipeToDeleteCallback.kt new file mode 100644 index 0000000..e1e6dac --- /dev/null +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/adapters/SwipeToDeleteCallback.kt @@ -0,0 +1,109 @@ +package bums.lunatic.launcher.home.adapters + +import android.R +import android.content.Context +import android.graphics.Canvas +import android.graphics.Color +import android.graphics.Paint +import android.graphics.PorterDuff +import android.graphics.PorterDuffXfermode +import android.graphics.drawable.ColorDrawable +import android.graphics.drawable.Drawable +import androidx.annotation.NonNull +import androidx.core.content.ContextCompat +import androidx.recyclerview.widget.ItemTouchHelper +import androidx.recyclerview.widget.RecyclerView + + +abstract class SwipeToDeleteCallback internal constructor(context: Context) : + ItemTouchHelper.Callback() { + var mContext: Context = context + private val mClearPaint = Paint() + private val mBackground = ColorDrawable() + private val backgroundColor = Color.parseColor("#55b80f0a") + private val deleteDrawable: Drawable? + private val intrinsicWidth: Int + private val intrinsicHeight: Int + + + init { + mClearPaint.setXfermode(PorterDuffXfermode(PorterDuff.Mode.CLEAR)) + deleteDrawable = ContextCompat.getDrawable(mContext, R.drawable.ic_delete) + intrinsicWidth = deleteDrawable!!.intrinsicWidth + intrinsicHeight = deleteDrawable.intrinsicHeight + } + + + override fun getMovementFlags( + @NonNull recyclerView: RecyclerView, + @NonNull viewHolder: RecyclerView.ViewHolder + ): Int { + return makeMovementFlags(0, ItemTouchHelper.LEFT) + } + + override fun onMove( + @NonNull recyclerView: RecyclerView, + @NonNull viewHolder: RecyclerView.ViewHolder, + @NonNull viewHolder1: RecyclerView.ViewHolder + ): Boolean { + return false + } + + override fun onChildDraw( + @NonNull c: Canvas, + @NonNull recyclerView: RecyclerView, + @NonNull viewHolder: RecyclerView.ViewHolder, + dX: Float, + dY: Float, + actionState: Int, + isCurrentlyActive: Boolean + ) { + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + + val itemView = viewHolder.itemView + val itemHeight = itemView.height + + val isCancelled = dX == 0f && !isCurrentlyActive + + if (isCancelled) { + clearCanvas( + c, + itemView.right + dX, + itemView.top.toFloat(), + itemView.right.toFloat(), + itemView.bottom.toFloat() + ) + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + return + } + + mBackground.color = backgroundColor + mBackground.setBounds( + itemView.right + dX.toInt(), + itemView.top, + itemView.right, + itemView.bottom + ) + mBackground.draw(c) + + val deleteIconTop = itemView.top + (itemHeight - intrinsicHeight) / 2 + val deleteIconMargin = (itemHeight - intrinsicHeight) / 2 + val deleteIconLeft = itemView.right - deleteIconMargin - intrinsicWidth + val deleteIconRight = itemView.right - deleteIconMargin + val deleteIconBottom = deleteIconTop + intrinsicHeight + + + deleteDrawable!!.setBounds(deleteIconLeft, deleteIconTop, deleteIconRight, deleteIconBottom) + deleteDrawable.draw(c) + + super.onChildDraw(c, recyclerView, viewHolder, dX, dY, actionState, isCurrentlyActive) + } + + private fun clearCanvas(c: Canvas, left: Float, top: Float, right: Float, bottom: Float) { + c.drawRect(left, top, right, bottom, mClearPaint) + } + + override fun getSwipeThreshold(@NonNull viewHolder: RecyclerView.ViewHolder): Float { + return 0.35f + } +} \ No newline at end of file diff --git a/app/src/main/kotlin/bums/lunatic/launcher/model/CommunityData.kt b/app/src/main/kotlin/bums/lunatic/launcher/model/CommunityData.kt index a9924d6..3a868ad 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/model/CommunityData.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/model/CommunityData.kt @@ -220,6 +220,7 @@ class RssData : RealmObject, RssDataInterface { var chosung : String? = null var vote : Boolean = false + var read : Int = 0 @Ignore var mRssDataType : RssDataType? = null diff --git a/app/src/main/kotlin/bums/lunatic/launcher/workers/WorkersDb.kt b/app/src/main/kotlin/bums/lunatic/launcher/workers/WorkersDb.kt index dcd5219..3fe8fbe 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/workers/WorkersDb.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/workers/WorkersDb.kt @@ -1,5 +1,6 @@ package bums.lunatic.launcher.workers +import bums.lunatic.launcher.BuildConfig import bums.lunatic.launcher.apps.SimpleContact import bums.lunatic.launcher.model.AppInfo import bums.lunatic.launcher.model.Astro @@ -49,7 +50,7 @@ object WorkersDb { LocationLog::class ) - val schemaVersion : Long = 4L + val schemaVersion : Long = BuildConfig.BuildDateTime private var pRealm : Realm? = null fun getRealm() : Realm {