From 74c95e04fd11df2e5828554be45c354ce94393f4 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Mon, 21 Jul 2025 20:10:44 +0900 Subject: [PATCH] ... --- .../extensions/my_extension/background.js | 103 +++++++----- .../extensions/my_extension/manifest.json | 3 +- .../bums/lunatic/launcher/LauncherActivity.kt | 20 +-- .../bums/lunatic/launcher/home/GeckoWeb.kt | 153 ++++++++++++++++-- .../home/{LauncherHome.kt => RssHome.kt} | 76 +++++++-- .../bums/lunatic/launcher/tokiz/BaseToki.kt | 1 - .../bums/lunatic/launcher/utils/JsoupUtils.kt | 2 +- app/src/main/res/drawable/ic_delete.xml | 4 +- app/src/main/res/layout/launcher_home.xml | 142 +++++++++++----- 9 files changed, 378 insertions(+), 126 deletions(-) rename app/src/main/kotlin/bums/lunatic/launcher/home/{LauncherHome.kt => RssHome.kt} (87%) diff --git a/app/src/main/assets/extensions/my_extension/background.js b/app/src/main/assets/extensions/my_extension/background.js index 44fd417f..c5144f01 100644 --- a/app/src/main/assets/extensions/my_extension/background.js +++ b/app/src/main/assets/extensions/my_extension/background.js @@ -1,40 +1,65 @@ - -browser.webRequest.onHeadersReceived.addListener( - function(details) { - let headers = details.responseHeaders || []; - // Cache-Control 헤더가 없거나 no-store, no-cache 등일 때 수정 - let found = false; - for (let header of headers) { - if (header.name.toLowerCase() === "cache-control") { - header.value = "public, max-age=31536000"; // 1년 캐시 - found = true; - } - } - if (!found) { - headers.push({name: "Cache-Control", value: "public, max-age=31536000"}); - } - return {responseHeaders: headers}; - }, - {urls: ["*://*/*.gif"], types: ["image"]}, - ["blocking", "responseHeaders"] -); -//const originalLog = console.log; -//console.log = function(...args) { -// // 메시지 가공 또는 네이티브로 전달 -// originalLog.apply(console, args); -// browser.runtime.sendNativeMessage("browser", args); -//}; - -browser.webRequest.onBeforeRequest.addListener( - function(details) { - return { cancel: true }; - }, - { urls: ["*://*/*.gif"], types: ["image"] }, - ["blocking"] -); -//window.addEventListener('error', function(event) { -// if (event.message && event.message.includes('No impl for message: MozAfterPaint')) { -// // 앱으로 오류 신호 전달 -// browser.runtime.sendMessage({ type: 'RELOAD_REQUEST' }); +//const port = browser.runtime.connectNative("browser"); +//// 모든 요청을 가로챔 +//browser.webRequest.onCompleted.addListener(async (details) => { +// // 원래 요청 URL +// const url = details.url; +// try { +// // 실제 데이터 fetch (credentials, 쿠키 등 필요시 옵션 맞춤) +// const res = await fetch(url, {credentials: "include"}); +// const blob = await res.blob(); +// // 데이터 -> ArrayBuffer +// const arrayBuffer = await blob.arrayBuffer(); +// // base64로 변환 +// const base64 = btoa(String.fromCharCode(...new Uint8Array(arrayBuffer))); +// // 네이티브 앱에게 전달 +// port.postMessage(JSON.stringify({type:"CACAHE",msg:msg , url: url, data: base64})); +//// browser.runtime.sendNativeMessage( +//// "browser", // 등록한 네이티브 앱 id +//// { url: url, data: base64 } +//// ); +// } catch(e) { +// // 에러 처리 +// console.error(e); // } -//}); \ No newline at end of file +//}, {urls: [""]}); +// +//// +////browser.webRequest.onHeadersReceived.addListener( +//// function(details) { +//// let headers = details.responseHeaders || []; +//// // Cache-Control 헤더가 없거나 no-store, no-cache 등일 때 수정 +//// let found = false; +//// for (let header of headers) { +//// if (header.name.toLowerCase() === "cache-control") { +//// header.value = "public, max-age=31536000"; // 1년 캐시 +//// found = true; +//// } +//// } +//// if (!found) { +//// headers.push({name: "Cache-Control", value: "public, max-age=31536000"}); +//// } +//// return {responseHeaders: headers}; +//// }, +//// {urls: ["*://*/*.gif"], types: ["image"]}, +//// ["blocking", "responseHeaders"] +////); +//////const originalLog = console.log; +//////console.log = function(...args) { +////// // 메시지 가공 또는 네이티브로 전달 +////// originalLog.apply(console, args); +////// browser.runtime.sendNativeMessage("browser", args); +//////}; +//// +////browser.webRequest.onBeforeRequest.addListener( +//// function(details) { +//// return { cancel: true }; +//// }, +//// { urls: ["*://*/*.gif"], types: ["image"] }, +//// ["blocking"] +////); +////window.addEventListener('error', function(event) { +//// if (event.message && event.message.includes('No impl for message: MozAfterPaint')) { +//// // 앱으로 오류 신호 전달 +//// browser.runtime.sendMessage({ type: 'RELOAD_REQUEST' }); +//// } +////}); \ No newline at end of file diff --git a/app/src/main/assets/extensions/my_extension/manifest.json b/app/src/main/assets/extensions/my_extension/manifest.json index bce7f3a4..dfb5b5c1 100644 --- a/app/src/main/assets/extensions/my_extension/manifest.json +++ b/app/src/main/assets/extensions/my_extension/manifest.json @@ -22,7 +22,6 @@ "nativeMessagingFromContent", "geckoViewAddons", "webRequest", - "webRequestBlocking", - "*://*/*.gif" + "webRequestBlocking" ] } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/LauncherActivity.kt b/app/src/main/kotlin/bums/lunatic/launcher/LauncherActivity.kt index 5edf0dd2..22374fcc 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/LauncherActivity.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/LauncherActivity.kt @@ -21,9 +21,7 @@ package bums.lunatic.launcher //import rasel.lunar.launcher.home.LauncherHome.Companion.rssSet import android.annotation.SuppressLint -import android.app.NotificationManager import android.appwidget.AppWidgetManager -import android.content.ComponentName import android.content.Intent import android.content.SharedPreferences import android.content.res.Configuration @@ -31,10 +29,8 @@ import android.graphics.Color import android.net.Uri import android.os.Build import android.os.Bundle -import android.os.Environment.isExternalStorageManager import android.os.Handler import android.os.Looper -import android.provider.Settings import android.view.KeyEvent import android.view.KeyEvent.ACTION_UP import android.view.KeyEvent.KEYCODE_BUTTON_A @@ -46,19 +42,14 @@ import android.view.KeyEvent.KEYCODE_BUTTON_Y import android.view.KeyEvent.KEYCODE_DPAD_DOWN import android.view.KeyEvent.KEYCODE_DPAD_UP import android.view.MotionEvent -import android.view.View import android.view.WindowInsets import android.view.WindowManager import androidx.activity.OnBackPressedCallback import androidx.annotation.RequiresApi -import androidx.appcompat.app.AppCompatDelegate -import androidx.appcompat.app.AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM import androidx.core.net.toUri import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen import androidx.core.view.ViewCompat -import androidx.core.view.WindowCompat import androidx.core.view.WindowInsetsCompat -import androidx.core.view.isVisible import androidx.core.view.updatePadding import androidx.work.ExistingPeriodicWorkPolicy import androidx.work.OneTimeWorkRequest @@ -70,24 +61,20 @@ import bums.lunatic.launcher.tokiz.Novels import bums.lunatic.launcher.common.CommonActivity import bums.lunatic.launcher.databinding.LauncherActivityBinding import bums.lunatic.launcher.feeds.WidgetHost -import bums.lunatic.launcher.helpers.BluetoothManager -import bums.lunatic.launcher.helpers.Constants.Companion.KEY_APPLICATION_THEME import bums.lunatic.launcher.helpers.Constants.Companion.KEY_STATUS_BAR import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS import bums.lunatic.launcher.helpers.Constants.Companion.widgetHostId import bums.lunatic.launcher.helpers.HeadsetActionButtonReceiver import bums.lunatic.launcher.helpers.PrefLong -import bums.lunatic.launcher.home.LauncherHome +import bums.lunatic.launcher.home.RssHome import bums.lunatic.launcher.home.RssViewBuilder import bums.lunatic.launcher.model.RssData import bums.lunatic.launcher.model.RssDataType -import bums.lunatic.launcher.receiver.NLService import bums.lunatic.launcher.tokiz.Comics import bums.lunatic.launcher.tokiz.Webtoons import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.FeedParseManager import bums.lunatic.launcher.utils.getJ -import bums.lunatic.launcher.view.TableRadioGroup import bums.lunatic.launcher.workers.AppInfoGetter import bums.lunatic.launcher.workers.ArcaGetter import bums.lunatic.launcher.workers.CalendarGetter @@ -101,7 +88,6 @@ import bums.lunatic.launcher.workers.FmKoreaGetter.Companion.COMIC_WORK_TAG import bums.lunatic.launcher.workers.LocationGetter import bums.lunatic.launcher.workers.NewsFeedsGetter import bums.lunatic.launcher.workers.NewsFeedsGetter.Companion.FEDDS_WORK_TAG -import bums.lunatic.launcher.workers.OpenWeatherGetter import bums.lunatic.launcher.workers.RecentCallGetter import bums.lunatic.launcher.workers.RecentSmsGetter import bums.lunatic.launcher.workers.RecentSmsGetter.Companion.SMS_WORK_TAG @@ -627,7 +613,7 @@ internal class LauncherActivity : CommonActivity() { when(id) { R.id.feeds -> { supportFragmentManager.beginTransaction() - .replace(R.id.fragment_container, LauncherHome()) + .replace(R.id.fragment_container, RssHome()) .commit() } R.id.books ->{ @@ -743,7 +729,7 @@ internal class LauncherActivity : CommonActivity() { override fun handleOnBackPressed() { val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) when(currentFragment) { - is LauncherHome ->{ + is RssHome ->{ currentFragment.doNextPage() } } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt index 11173440..7705deaf 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt @@ -1,12 +1,17 @@ package bums.lunatic.launcher.home +import android.app.DownloadManager import android.content.Context import android.content.Intent +import android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP +import android.content.Intent.FLAG_ACTIVITY_NEW_TASK import android.net.Uri +import android.os.Environment import android.os.Handler import android.os.Looper import android.os.Message import android.util.AttributeSet +import android.util.Base64 import android.util.Log import android.view.KeyEvent import android.view.KeyEvent.ACTION_UP @@ -18,7 +23,10 @@ import android.view.KeyEvent.KEYCODE_BUTTON_X import android.view.KeyEvent.KEYCODE_BUTTON_Y import android.view.KeyEvent.KEYCODE_DPAD_DOWN import android.view.KeyEvent.KEYCODE_DPAD_UP +import android.view.View import android.widget.ProgressBar +import android.widget.Toast +import androidx.appcompat.app.AlertDialog import bums.lunatic.launcher.LauncherActivity.Companion.getRuntime import bums.lunatic.launcher.tokiz.view.BWebview import bums.lunatic.launcher.tokiz.view.JxEvent @@ -39,13 +47,18 @@ import org.mozilla.geckoview.WebExtension.MessageDelegate import org.mozilla.geckoview.WebExtension.PortDelegate import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate import org.mozilla.geckoview.WebRequestError +import java.io.File +import java.text.SimpleDateFormat class GeckoWeb : BWebview { constructor(context: Context?) : super(context) { buildWeb() } - - + var decoViews = arrayListOf() + override fun setVisibility(visibility: Int) { + super.setVisibility(visibility) + decoViews.forEach { it.visibility = visibility } + } constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { buildWeb() @@ -54,6 +67,7 @@ class GeckoWeb : BWebview { val mPortNam = "browser" val extPath = "resource://android/assets/extensions/my_extension/" val extId = "messaging@booktoki468.com" + private fun buildWeb() { getRuntime()?.let { val session: GeckoSession = GeckoSession() @@ -87,7 +101,7 @@ class GeckoWeb : BWebview { var lastedUrl: String? = null var canGoBack: Boolean? = null var mPort: WebExtension.Port? = null - + var mCaache : WebExtension.Port? = null object WebExtensionInfo { val mPortNam = "browser" val extPath = "resource://android/assets/extensions/my_extension/" @@ -238,6 +252,32 @@ class GeckoWeb : BWebview { return super.onRecordMalformedConfigurationEvent(feature, part) } } + + fun showImageDownloadDialog(context: Context, imageUrl: Uri) { + AlertDialog.Builder(context) + .setTitle("이미지 다운로드") + .setMessage("이미지를 저장하시겠습니까?") + .setPositiveButton("저장") { _, _ -> + downloadImage(context, imageUrl) + } + .setNegativeButton("취소", null) + .show() + } + + fun downloadImage(context: Context, url: Uri) { + val fileName = url.lastPathSegment ?: "${SimpleDateFormat("yyyyMMddHHmmsss")}.jpg" + val request = DownloadManager.Request(url) + request.setTitle(fileName) + request.setDescription("이미지 다운로드 중...") + request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, fileName) + // 네트워크타입, 알림설정 등 옵션 추가 가능 + request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) + + val dm = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager + dm.enqueue(request) + Toast.makeText(context, "다운로드 시작: $fileName", Toast.LENGTH_SHORT).show() + } + val contentDelegate = object : GeckoSession.ContentDelegate { override fun onTitleChange( session: GeckoSession, @@ -260,6 +300,21 @@ class GeckoWeb : BWebview { super.onFirstContentfulPaint(session) } + + override fun onContextMenu( + session: GeckoSession, + screenX: Int, + screenY: Int, + element: GeckoSession.ContentDelegate.ContextElement + ) { + if (element.type == GeckoSession.ContentDelegate.ContextElement.TYPE_IMAGE) { + Uri.parse(element.srcUri)?.let { + showImageDownloadDialog(context,it) + } + } + + super.onContextMenu(session, screenX, screenY, element) + } } val progressDelegate = object : GeckoSession.ProgressDelegate { override fun onSecurityChange( @@ -289,6 +344,8 @@ class GeckoWeb : BWebview { Uri.parse(url)?.let { uri -> context.startActivity(Intent().apply { action = Intent.ACTION_VIEW + flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.or(FLAG_ACTIVITY_CLEAR_TOP).or( + FLAG_ACTIVITY_NEW_TASK) data = uri }) } @@ -328,7 +385,18 @@ class GeckoWeb : BWebview { ): GeckoResult? { Blog.LOGE("GeckoView", "onNewSession: $session from WebExtension") - + Uri.parse(uri)?.let { + if(it.host?.let { it1 -> lastedUrl?.contains(it1, true) } == true) { + loadUrl(uri) + } else { + context.startActivity(Intent().apply { + action = Intent.ACTION_VIEW + flags = Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS.or(FLAG_ACTIVITY_CLEAR_TOP).or( + FLAG_ACTIVITY_NEW_TASK) + data = it + }) + } + } return super.onNewSession(session, uri) } @@ -377,17 +445,85 @@ class GeckoWeb : BWebview { override fun onDisconnect(port: WebExtension.Port) { // This port is not usable anymore. - if (port === mPort) { + + mPort = null + + + } + } + + val cacheDelegate: PortDelegate = + object : PortDelegate { + override fun onPortMessage( + message: Any, port: WebExtension.Port + ) { + Blog.LOGE("cacheDelegate", "cacheDelegate message : $message") + + } + + + override fun onDisconnect(port: WebExtension.Port) { + // This port is not usable anymore. + if (port === mCaache) { + mCaache = null } } } + fun onReceiveFromExtension(message: JSONObject) { + val url = message.getString("url") + val dataBase64 = message.getString("data") + val host = Uri.parse(url).host!! + val cacheDir = File(context.filesDir, "webcache/$host") + if (!cacheDir.exists()) cacheDir.mkdirs() + + // 파일명 생성 (중복처리 필요) + val fileName = filenameFromUrl(url) + val resourceFile = File(cacheDir, fileName) + val rawData = Base64.decode(dataBase64, Base64.DEFAULT) + resourceFile.writeBytes(rawData) + } + + + + fun filenameFromUrl(url: String): String { + // URL을 파싱 + val uri = Uri.parse(url) + // 경로 마지막 세그먼트 (예시: /images/logo.png → logo.png) + var filename = uri.lastPathSegment ?: "index.html" + + // 쿼리 파라미터 등 URL이 붙은 경우 처리 (예: index.html?version=2) + if (filename.contains("?")) { + filename = filename.substringBefore("?") + } + if (filename.isEmpty() || filename.endsWith("/")) { + filename = "index.html" + } + + // 파일명에 사용할 수 없는 문자 제거(윈도우, 리눅스, 맥 등 호환) + filename = filename.replace(Regex("[\\\\/:*?\"<>|]"), "_") + + // 너무 긴 파일명은 자르기 + val maxLength = 100 + if (filename.length > maxLength) { + val ext = filename.substringAfterLast('.', "") + filename = filename.take(maxLength - ext.length - 1) + + if (ext.isNotBlank()) ".$ext" else "" + } + + return filename + } + + val messageDelegate: MessageDelegate = object : MessageDelegate { override fun onConnect(port: WebExtension.Port) { - mPort = port - mPort!!.setDelegate(portDelegate) + Blog.LOGE("onConnect port >>> ${port.name}") +// if (port.name === "browser") { +// mPort = port +// mPort!!.setDelegate(portDelegate) +// } } override fun onMessage( @@ -401,11 +537,8 @@ class GeckoWeb : BWebview { ) return super.onMessage(nativeApp, message, sender) } - - } - fun onStart() { } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt similarity index 87% rename from app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt rename to app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt index 793470fc..01a96758 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/LauncherHome.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt @@ -20,7 +20,6 @@ package bums.lunatic.launcher.home import android.annotation.SuppressLint import android.content.SharedPreferences -import android.os.Build import android.os.Bundle import android.os.Handler import android.os.Looper @@ -30,7 +29,7 @@ import android.view.View import android.view.ViewGroup import android.widget.Toast import androidx.annotation.NonNull -import androidx.annotation.RequiresApi +import androidx.core.view.isVisible import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentManager import androidx.recyclerview.widget.DividerItemDecoration @@ -38,7 +37,6 @@ import androidx.recyclerview.widget.ItemTouchHelper import androidx.recyclerview.widget.RecyclerView import bums.lunatic.launcher.LauncherActivity.Companion.lActivity import bums.lunatic.launcher.R -import bums.lunatic.launcher.common.letTrue import bums.lunatic.launcher.databinding.LauncherHomeBinding import bums.lunatic.launcher.helpers.Constants.Companion.PREFS_SETTINGS import bums.lunatic.launcher.home.adapters.RssItemAdapter @@ -47,7 +45,6 @@ import bums.lunatic.launcher.home.adapters.SwipeToDeleteCallback import bums.lunatic.launcher.model.RssData import bums.lunatic.launcher.model.RssDataType import bums.lunatic.launcher.model.WeatherForcast -import bums.lunatic.launcher.openClient import bums.lunatic.launcher.openReddit import bums.lunatic.launcher.openYouTube import bums.lunatic.launcher.tokiz.view.JxEvent @@ -59,7 +56,9 @@ import bums.lunatic.launcher.workers.WorkersDb import com.google.android.material.imageview.ShapeableImageView 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 @@ -69,7 +68,7 @@ import kotlinx.coroutines.Job import kotlinx.coroutines.launch -internal class LauncherHome : Fragment() { +internal class RssHome : Fragment() { lateinit var binding: LauncherHomeBinding private lateinit var fragManager: FragmentManager @@ -77,11 +76,10 @@ internal class LauncherHome : Fragment() { private var shouldResume = true companion object { - var home: LauncherHome? = null + var home: RssHome? = null var lastedFinishedPageUrl: String = "" } - val UPDATE_DELAY = 5L val commandHandler = Handler(Looper.getMainLooper()) val infoUpdate = Runnable { chooseAdpater() } @@ -245,6 +243,7 @@ internal class LauncherHome : Fragment() { targetList.addAll(setString) binding.geckoWeb.loadUrl(rssId) + binding.vote.visibility = binding.geckoWeb.visibility } @SuppressLint("ClickableViewAccessibility") @@ -270,6 +269,42 @@ internal class LauncherHome : Fragment() { return@setOnTouchListener false } } + binding.vote.setOnClickListener { + if (binding.geckoWeb.isVisible) { + vote() + } + } + + binding.hide.setOnClickListener { + if (binding.geckoWeb.isVisible) { + WorkersDb.getRealm().apply { + writeBlocking { + val result = query().query("originPage == $0", rssId).find() + if (result.size > 0) { + result.forEach { + if(it.vote) { + it.vote = false + } + } + } + } + } + doNextPage() + } + } + + binding.home.setOnClickListener { + if (binding.geckoWeb.isVisible) { + binding.geckoWeb.visibility = View.GONE + } + queryInfos() + } + + + binding.bookmark.setOnClickListener { + queryVotes() + } + queryInfos() binding.geckoWeb.progress = binding.progressBar binding.geckoWeb.jxInteface = { jxEvent -> @@ -287,9 +322,11 @@ internal class LauncherHome : Fragment() { } } } - val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL) + val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL) binding.root.setPointerIcon(nullCursor) - + binding.geckoWeb.decoViews.add(binding.hide) + binding.geckoWeb.decoViews.add(binding.vote) + binding.geckoWeb.decoViews.add(binding.progressBar) return binding.root } @@ -352,11 +389,24 @@ internal class LauncherHome : Fragment() { mRssDataResult?.asFlow()?.let { flow -> infosJob = CoroutineScope(Dispatchers.IO).launch { flow.collect { changes: ResultsChange -> - commandHandler.removeCallbacks(infoUpdate) - WorkersDb.getRealm().apply { - lasted = copyFromRealm(changes.list) + when(changes) { + is InitialResults -> { + commandHandler.removeCallbacks(infoUpdate) + WorkersDb.getRealm().apply { + lasted = copyFromRealm(changes.list) + } + commandHandler.post(infoUpdate) + } + is UpdatedResults -> { + CoroutineScope(Dispatchers.Main).launch { + changes.changeRanges.forEach { + + mRssAdapter.notifyItemRangeChanged(it.startIndex, it.length) + } + } + } + } - commandHandler.postDelayed(infoUpdate, UPDATE_DELAY) } } infosJob?.start() diff --git a/app/src/main/kotlin/bums/lunatic/launcher/tokiz/BaseToki.kt b/app/src/main/kotlin/bums/lunatic/launcher/tokiz/BaseToki.kt index 6bba608d..113fbfa5 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/tokiz/BaseToki.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/tokiz/BaseToki.kt @@ -1166,7 +1166,6 @@ abstract class BaseToki : Fragment(), PagedTextViewInterface { } } } - } fun onLoadedContents(aContents: String) { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/utils/JsoupUtils.kt b/app/src/main/kotlin/bums/lunatic/launcher/utils/JsoupUtils.kt index 55467170..4a169ae4 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/utils/JsoupUtils.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/utils/JsoupUtils.kt @@ -1,6 +1,6 @@ package bums.lunatic.launcher.utils -import bums.lunatic.launcher.home.LauncherHome.Companion.lastedFinishedPageUrl +import bums.lunatic.launcher.home.RssHome.Companion.lastedFinishedPageUrl import bums.lunatic.launcher.model.MostItem import bums.lunatic.launcher.model.RssData import bums.lunatic.launcher.model.RssDataType diff --git a/app/src/main/res/drawable/ic_delete.xml b/app/src/main/res/drawable/ic_delete.xml index 8b5f27e8..e4c2456a 100644 --- a/app/src/main/res/drawable/ic_delete.xml +++ b/app/src/main/res/drawable/ic_delete.xml @@ -1,8 +1,8 @@ + android:tint="@color/white"> diff --git a/app/src/main/res/layout/launcher_home.xml b/app/src/main/res/layout/launcher_home.xml index c8f1aec0..4c13e10f 100644 --- a/app/src/main/res/layout/launcher_home.xml +++ b/app/src/main/res/layout/launcher_home.xml @@ -1,45 +1,105 @@ - - - + + android:layout_height="match_parent"> + + + + + + + + + + - - - \ No newline at end of file + + + + \ No newline at end of file