This commit is contained in:
lunaticbum 2025-08-22 17:06:04 +09:00
parent a11e40c56c
commit fd0d61c584
9 changed files with 75 additions and 25 deletions

View File

@ -306,15 +306,21 @@ document.addEventListener('DOMContentLoaded', function () {
}
})
if(location.href.search("youtube") < 0) {
const keywords = ["youtube", "mojeek"];
const url = location.href;
if (keywords.every(keyword => !url.includes(keyword))) {
document.addEventListener('touchstart', function(e) {
console.log('터치 시작');
});
document.addEventListener('touchend', function(e) {
autoScrollAndSave()
setTimeout(() => {
autoScrollAndSave();
}, 5);
});
}
function scrollToLazyImg(fastMode) {
(function(autoScrollAndSave){
// 한 번에 이동할 픽셀

View File

@ -186,8 +186,6 @@ class ForeGroundService : Service() {
.setSmallIcon(R.drawable.ic_b)
.setContentIntent(pendingIntent)
.addAction(android.R.drawable.ic_btn_speak_now,"퇴근", makeSendMsgAction(0,"돼지 퇴근했다요~!"))
.addAction(android.R.drawable.ic_btn_speak_now,"버스 탐", makeSendMsgAction(1,"돼지 버스 탔다요~!"))
.addAction(android.R.drawable.ic_btn_speak_now,"버스 내림", makeSendMsgAction(2,"돼지 버스 내린다요~!"))
.setOngoing(true) // 사용자가 알림을 스와이프로 지울 수 없게 만듦
.setProgress(max, progress, false)
.build())
@ -205,7 +203,7 @@ class ForeGroundService : Service() {
Blog.LOGE("onBind intent >>> ${intent}")
return null
}
private val CHANNEL_ID = "ble_service_channel"
private val CHANNEL_ID = "bums_service_channel"
private val CHANNEL_NAME = "BUM'S 서비스"

View File

@ -316,10 +316,11 @@ internal class RssHome : Fragment() {
override fun onSearch(
keyword: String,
category: List<String>,
onlyVote : Boolean,
addReaded: Boolean,
addVoted: Boolean
) {
queryInfos(keywords = keyword.split(" "), category , addReaded, addVoted)
queryInfos(keywords = keyword.split(" "), category ,onlyVote, addReaded, addVoted)
}
}
bottomSheet.show(childFragmentManager, "SearchBottomSheet")
@ -340,11 +341,20 @@ internal class RssHome : Fragment() {
privateMode: Boolean
) {
when (category) {
RssDataType.ANYTHING -> {
if (binding.geckoWeb.lastedUrl?.contains("search.brave") == true) {
binding.geckoWeb.sendSearch(keyword)
} else {
binding.geckoWeb.loadUrl("https://search.brave.com/", if (keyword.length ?: 0 > 0) { "search?q=${keyword}" } else { null })
}
binding.geckoWeb.privateMode = false
}
RssDataType.GOOGLE -> {
if (binding.geckoWeb.lastedUrl?.contains("www.google") == true) {
binding.geckoWeb.sendSearch(keyword)
} else {
binding.geckoWeb.loadUrl("https://www.google.com/", if (keyword.length ?: 0 > 0) { "search/?q=${keyword}" } else { null })
binding.geckoWeb.loadUrl("https://www.google.com/", if (keyword.length ?: 0 > 0) { "search?q=${keyword}" } else { null })
}
binding.geckoWeb.privateMode = false
}
@ -400,6 +410,7 @@ internal class RssHome : Fragment() {
var currentRss : RssData? = null
@SuppressLint("SimpleDateFormat")
fun openGecko(rssData: RssData? = null) {
Blog.LOGE("rssData >>> ${rssData}")
binding.layoutRssSummary.root.visibility = View.GONE
if (rssData?.category()?.equals(RssDataType.PRIVATE) == false && rssData?.originPage?.isNotEmpty() == true) {
rssData?.let { rss ->
@ -692,7 +703,7 @@ internal class RssHome : Fragment() {
Blog.LOGE("updateQuery >>> ${q.description()}")
infosJob?.cancel()
commandHandler.removeCallbacks(infoUpdate)
mLastedQuery = q.query("hide != $0", true).sort("pubDate ", Sort.DESCENDING).limit(300).distinct("originPage", "title")
mLastedQuery = q.query("hide != $0", true).sort("pubDate ", Sort.DESCENDING).limit(500).distinct("originPage", "title")
mRssDataResult = mLastedQuery?.find()
mRssDataResult?.asFlow()?.let { flow ->
infosJob = CoroutineScope(Dispatchers.IO).launch {
@ -769,13 +780,23 @@ internal class RssHome : Fragment() {
fun queryInfos(
keywords: List<String>,
category: List<String>,
onlyVote : Boolean = false,
includeVote : Boolean = false,
includeRead : Boolean = false
) {
beforeQuery()
var rQ = getRealm().query<RssData>().sort("read", Sort.ASCENDING)
if (!includeRead) { rQ = rQ.query("read == $0", 0)}
if (!includeVote) { rQ = rQ.query("vote != $0", true)}
if (onlyVote) {
rQ = rQ.query("vote == $0", true)
} else {
if (!includeRead) {
rQ = rQ.query("read == $0", 0)
}
if (!includeVote) {
rQ = rQ.query("vote != $0", true)
}
}
category.forEach {
rQ = rQ.query("category != $0", it)
}
@ -960,7 +981,7 @@ internal class RssHome : Fragment() {
imageView.visibility = View.INVISIBLE
}
}
fun randomOrNull() : RssData? = lasted.filter { it.vote == false && it.read < 2 }.randomOrNull()
fun randomOrNull() : RssData? = lasted.randomOrNull()
}
var toast: Toast? = null
fun Context.toast(string: String) {

View File

@ -40,22 +40,25 @@ class SearchBottomSheet : BottomSheetDialogFragment() {
}
interface OnSearchListener {
fun onSearch(keyword: String, category: List<String>, addReaded : Boolean, addVoted: Boolean)
fun onSearch(keyword: String, category: List<String>, onlyVoted : Boolean, addReaded : Boolean, addVoted: Boolean)
}
var listener: OnSearchListener? = null
private val categoryStates = mutableMapOf<String, Boolean>()
lateinit var onlyVote : CheckBox
lateinit var addVote : CheckBox
lateinit var addRead : CheckBox
lateinit var inputKeyword : EditText
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
inputKeyword = view.findViewById<EditText>(R.id.inputKeyword)
val categoryContainer = view.findViewById<LinearLayout>(R.id.categoryContainer)
onlyVote = view.findViewById<CheckBox>(R.id.only_vote) as CheckBox
addVote = view.findViewById<CheckBox>(R.id.add_vote) as CheckBox
addRead = view.findViewById<CheckBox>(R.id.add_read) as CheckBox
addVote.setOnCheckedChangeListener {v,b->triggerSearchWithDebounce(inputKeyword.text.toString())}
addRead.setOnCheckedChangeListener {v,b->triggerSearchWithDebounce(inputKeyword.text.toString())}
onlyVote.setOnCheckedChangeListener {v,b->triggerSearchWithDebounce(inputKeyword.text.toString())}
// 카테고리 목록
val categories = RssDataType.getAll()
categories.forEach { categoryStates[it.name] = true }
@ -112,10 +115,8 @@ class SearchBottomSheet : BottomSheetDialogFragment() {
inputKeyword.setOnEditorActionListener { _, actionId, _ ->
if (actionId == EditorInfo.IME_ACTION_SEARCH) {
val keyword = inputKeyword.text.toString()
if (keyword.isNotEmpty()) {
triggerSearchWithDebounce(keyword)
dismiss() // 필요 시 닫기
}
triggerSearchWithDebounce(keyword)
dismiss() // 필요 시 닫기
true
} else {
false
@ -128,7 +129,7 @@ class SearchBottomSheet : BottomSheetDialogFragment() {
searchRunnable?.let { debounceHandler.removeCallbacks(it) }
searchRunnable = Runnable {
val disabledCategories = categoryStates.filter { it.value == false }.keys.toList()
listener?.onSearch(keyword, disabledCategories, addRead.isChecked,addVote.isChecked)
listener?.onSearch(keyword, disabledCategories,onlyVote.isChecked ,addRead.isChecked,addVote.isChecked)
}
debounceHandler.postDelayed(searchRunnable!!, debounceDelay)
}

View File

@ -54,9 +54,11 @@ class WebBottomSheet : BottomSheetDialogFragment() {
inputKeyword = view.findViewById<EditText>(R.id.inputKeyword)
val categoryContainer = view.findViewById<RadioGroup>(R.id.categoryContainer)
privateMode = view.findViewById<CheckBox>(R.id.check_private) as CheckBox
privateMode.setOnCheckedChangeListener {v,b->triggerSearchWithDebounce(inputKeyword.text.toString())}
privateMode.setOnCheckedChangeListener {v,b->
// triggerSearchWithDebounce(inputKeyword.text.toString())
}
// 카테고리 목록
val categories = listOf<RssDataType>(RssDataType.GOOGLE, RssDataType.NAVER,RssDataType.NEWS,RssDataType.NEWSFEED,RssDataType.NAMU,RssDataType.PRIVATE)
val categories = listOf<RssDataType>(RssDataType.ANYTHING,RssDataType.GOOGLE, RssDataType.NAVER,RssDataType.NEWS,RssDataType.NEWSFEED,RssDataType.NAMU,RssDataType.PRIVATE)
// 버튼 동적 생성
categoryContainer.removeAllViews()
@ -80,7 +82,7 @@ class WebBottomSheet : BottomSheetDialogFragment() {
setTextColor(Color.WHITE)
setBackgroundResource(R.color.tabs_black)
setOnClickListener {
triggerSearchWithDebounce(inputKeyword.text.toString())
// triggerSearchWithDebounce(inputKeyword.text.toString())
}
// setOnLongClickListener {
// categoryContainer.forEach { (it as? RadioButton)?.let { it.isChecked = false} }
@ -104,7 +106,7 @@ class WebBottomSheet : BottomSheetDialogFragment() {
// EditText 입력 실시간 감지 + debounce
inputKeyword.addTextChangedListener(object : TextWatcher {
override fun afterTextChanged(s: Editable?) {
triggerSearchWithDebounce(s.toString())
// triggerSearchWithDebounce(s.toString())
}
override fun beforeTextChanged(s: CharSequence?, start: Int, count: Int, after: Int) {}
override fun onTextChanged(s: CharSequence?, start: Int, before: Int, count: Int) {}

View File

@ -290,8 +290,12 @@ class RssData : RealmObject, RssDataInterface {
}
override fun category(): RssDataType {
if (mRssDataType == null)
mRssDataType = RssDataType.valueOf(category!!.uppercase())
try {
if (mRssDataType == null)
mRssDataType = RssDataType.valueOf(category!!.uppercase())
} catch (e: Exception) {
mRssDataType = RssDataType.NO_DATA
}
return mRssDataType!!
}

View File

@ -22,6 +22,7 @@ enum class RssDataType {
THEQOO,
NAVER,
GOOGLE,
ANYTHING,
NAMU,
ARCA;

View File

@ -4,6 +4,8 @@ import android.content.Context
import androidx.annotation.CallSuper
import androidx.work.Worker
import androidx.work.WorkerParameters
import bums.lunatic.launcher.LauncherActivity
import bums.lunatic.launcher.LunaticLauncher
import bums.lunatic.launcher.model.RssData
import bums.lunatic.launcher.utils.beforeDay
import bums.lunatic.launcher.utils.beforeOneDay
@ -33,6 +35,7 @@ open abstract class BaseGetter : Worker {
@CallSuper
override fun doWork(): Result {
LunaticLauncher.mHourlyLogWriter?.writeLog("${this::class.java.simpleName} doWork()")
val currentTime = before10Min()
if (lastedUpdateTime > 0L && currentTime > lastedUpdateTime) {
return Result.success().apply {
@ -40,7 +43,7 @@ open abstract class BaseGetter : Worker {
}
}
return realWork().apply {
LunaticLauncher.mHourlyLogWriter?.writeLog("${this@BaseGetter::class.java.simpleName} return realWork() ")
}
}
abstract fun realWork() : Result

View File

@ -22,6 +22,20 @@
android:singleLine="true" />
<CheckBox
app:layout_constraintRight_toLeftOf="@id/add_vote"
app:layout_constraintBottom_toTopOf="@+id/accessoryToolbar"
android:layout_margin="0dp"
android:padding="0dp"
android:minHeight="0dp"
android:includeFontPadding="false"
android:text="Only Vote"
android:textColor="@color/white"
android:id="@+id/only_vote"
android:checked="false"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<CheckBox
app:layout_constraintRight_toLeftOf="@id/add_read"
app:layout_constraintBottom_toTopOf="@+id/accessoryToolbar"