From 257ddb6776928dc7238881d5472761324dfe1aac Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Thu, 30 Apr 2026 17:28:30 +0900 Subject: [PATCH] ... --- .../extensions/my_extension/messaging.js | 103 +++++++++++++- .../bums/lunatic/launcher/BookmarkUploader.kt | 6 +- .../bums/lunatic/launcher/home/GeckoWeb.kt | 7 + .../lunatic/launcher/home/NeoRssActivity.kt | 133 +++++++++++------- .../bums/lunatic/launcher/home/RssHome.kt | 3 +- .../launcher/home/tokiz/TokiFragment.kt | 6 +- .../launcher/workers/TorrentManager.kt | 2 +- app/src/main/res/layout/rss_activity.xml | 16 +-- 8 files changed, 206 insertions(+), 70 deletions(-) diff --git a/app/src/main/assets/extensions/my_extension/messaging.js b/app/src/main/assets/extensions/my_extension/messaging.js index dda42cc2..5a6d20bf 100644 --- a/app/src/main/assets/extensions/my_extension/messaging.js +++ b/app/src/main/assets/extensions/my_extension/messaging.js @@ -469,8 +469,13 @@ if(document.querySelector(".list-body") !== null) { var listBody = null try {listBody = document.querySelector(".list-body");}catch (e) {} getList(listBody.children) -} -if(document.querySelector("#novel_content") !== null){ +} else if(document.querySelector(".novel-eps") !== null) { + //document.querySelector(".novel-eps").children + removeSpecificGifs() + var listBody = null + try {listBody = document.querySelector(".novel-eps");}catch (e) {} + getList2(listBody.children) +} else if(document.querySelector("#novel_content") !== null){ removeSpecificGifs() var title = null var contents = null @@ -487,6 +492,23 @@ if(document.querySelector("#novel_content") !== null){ } ); } +} else if(document.querySelector('[style^="--novel"]') !== null){ + removeSpecificGifs() + var title = null + var contents = null + try {title = toonTitle(document.querySelector(".page-desc")); }catch (e) {} + try {contents = toonContents(document.querySelector('[style^="--novel"]'))}catch (e) {} + if (toonTitle !== undefined && toonContents !== undefined && toonTitle !== "" && toonContents !=="") { + sendMessage( + { + type: "BookContents", + book : { + chapterTitle : title, + bookContents : contents + } + } + ); + } } if(document.querySelector("#html_encoder_div")) { sendMessage( @@ -572,6 +594,83 @@ function getList(children) { } } +function getList2(children) { + const contentsArray = []; + const maxCount = children.length; + + // 반복문 내부에서 공통으로 사용될 변수 미리 선언 + let bookTitle = ""; + const viewTitleEl = document.getElementsByClassName('view-title')[0]; + if (viewTitleEl) { + bookTitle = viewTitleEl.getElementsByTagName('span')[0].innerText; + } + + for (let i = 0; i < maxCount; i++) { + const item = children[i]; + + // 1. 에피소드 번호 추출 (data-ep 속성 활용) + const chapterNum = item.getAttribute('data-ep'); + + // 2. URL 및 제목 요소 찾기 + const linkAnchor = item.getElementsByTagName('a')[0]; + if (!linkAnchor) continue; + + let pageUrl = linkAnchor.href; + const chapterTitle = item.getElementsByClassName('ne-title')[0]?.innerText || ""; + + // 3 콘텐츠 타입 판별 + const contentsType = location.hostname.includes("book") ? "book" : + location.hostname.includes("mana") ? "comics" : + location.hostname.includes("new") ? "webtoon" : "web"; + + // 4. URL 정제 (기존 로직 유지) + if (pageUrl && pageUrl.startsWith("http")) { + try { + const urlObj = new URL(pageUrl); + let paths = urlObj.pathname.split('/').filter(p => p !== ""); + + if (paths.length > 0) { + const last = paths[paths.length - 1]; + // 마지막 요소가 숫자가 아니면 제거 (예: 파라미터나 기타 경로) + if (!/^\d+$/.test(last)) { + paths.pop(); + } + } + pageUrl = "/" + paths.join('/'); + } catch (e) { + console.error("URL parsing error:", e); + } + } + + // 5. 데이터 객체 생성 + const data = { + 'chapterID': Number(chapterNum), + 'chapterNum': Number(chapterNum), + 'pathUrl': pageUrl, + 'contentsType': contentsType, + 'bookPageUrl': location.pathname, + 'chapterTitle': chapterTitle.trim(), + 'bookTitle': bookTitle, + }; + + contentsArray.push(data); + } + + // 6. 결과 전송 + if (contentsArray.length > 0) { + sendMessage({ + type: "getListResult", + bookInfos: { + 'contentsType': contentsArray[0].contentsType, + 'bookTitle': bookTitle, + 'bookPageUrl': location.pathname, + 'pages': contentsArray, + } + }); + } +} + + function toonTitle(toon_title) { return toon_title != null ? toon_title.innerText : null } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/BookmarkUploader.kt b/app/src/main/kotlin/bums/lunatic/launcher/BookmarkUploader.kt index 9b0311da..3c27fe36 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/BookmarkUploader.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/BookmarkUploader.kt @@ -230,7 +230,8 @@ object BookmarkUploader { } } - private fun saveImageToLocal(context: Context, imageData: ByteArray, imageUrl: String) { + private fun saveImageToLocal(context: Context, imageData: ByteArray, imageUrl: String) : String { + var fileName = android.net.Uri.parse(imageUrl).lastPathSegment ?: "img_${System.currentTimeMillis()}.jpg" try { val saveDir = File(context.getExternalFilesDir(null), "completed_torrents") if (!saveDir.exists()) { @@ -238,7 +239,7 @@ object BookmarkUploader { } // URL에서 원본 파일명 추출 시도 (실패 시 타임스탬프로 대체) - var fileName = android.net.Uri.parse(imageUrl).lastPathSegment ?: "img_${System.currentTimeMillis()}.jpg" + // 이름이 중복되어 덮어써지는 것을 막기 위해 타임스탬프를 앞에 붙여줍니다. fileName = "${System.currentTimeMillis()}_$fileName" @@ -250,6 +251,7 @@ object BookmarkUploader { } catch (e: Exception) { println("🔥 로컬 보관함 저장 실패: ${e.message}") } + return fileName } /** 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 bc763d07..0a2a2964 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt @@ -914,6 +914,13 @@ open class GeckoWeb @JvmOverloads constructor( session?.setActive(true) } + override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { + return false + } + + override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean { + return false + } // dp 변환 확장 함수 private fun Int.dpToPx(): Int = (this * context.resources.displayMetrics.density).toInt() fun prev10() { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt index 53f6d2ab..f0f5f3fd 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt @@ -19,6 +19,8 @@ import android.view.KeyEvent.KEYCODE_BUTTON_START 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_LEFT +import android.view.KeyEvent.KEYCODE_DPAD_RIGHT import android.view.KeyEvent.KEYCODE_DPAD_UP import android.view.KeyEvent.KEYCODE_MEDIA_PAUSE import android.view.KeyEvent.KEYCODE_MEDIA_PLAY @@ -195,74 +197,74 @@ open class NeoRssActivity : CommonActivity() { if (ev?.device?.name?.contains("JX-05") == true) { if (ev.action?.equals(KeyEvent.ACTION_UP) == true) { - when(ev.keyCode) { - KEYCODE_MEDIA_PLAY_PAUSE->{ - onRemoteKeyDetected("RIGHT_ARROW", true) - } - KEYCODE_MEDIA_PAUSE->{ + when(ev.keyCode) { + KEYCODE_MEDIA_PLAY_PAUSE->{ + onRemoteKeyDetected("RIGHT_ARROW", true) + } + KEYCODE_MEDIA_PAUSE->{ // onRemoteKeyDetected("LEFT_ARROW", true) - } - KEYCODE_VOLUME_UP->{ - onRemoteKeyDetected("UP_ARROW", true) - } - KEYCODE_VOLUME_DOWN->{ - onRemoteKeyDetected("DOWN_ARROW", true) - } - }} + } + KEYCODE_VOLUME_UP->{ + onRemoteKeyDetected("UP_ARROW", true) + } + KEYCODE_VOLUME_DOWN->{ + onRemoteKeyDetected("DOWN_ARROW", true) + } + }} return true }else if (ev?.device?.name?.contains("SM-031N Mouse") == true) { - when(ev.action) { - ACTION_UP -> { - when(ev.keyCode) { - KEYCODE_BUTTON_Y->{ + when(ev.action) { + ACTION_UP -> { + when(ev.keyCode) { + KEYCODE_BUTTON_Y->{ - } - KEYCODE_BUTTON_X->{ + } + KEYCODE_BUTTON_X->{ - } - KEYCODE_BUTTON_A->{ - WorkersDb.getRealm().apply { - writeBlocking { + } + KEYCODE_BUTTON_A->{ + WorkersDb.getRealm().apply { + writeBlocking { + } } } - } - KEYCODE_BUTTON_B->{ + KEYCODE_BUTTON_B->{ - } - KEYCODE_DPAD_DOWN->{ + } + KEYCODE_DPAD_DOWN->{ - } - KEYCODE_DPAD_UP->{ + } + KEYCODE_DPAD_UP->{ - } - KEYCODE_BUTTON_START->{ - onClickCenterButton() - } - KEYCODE_BUTTON_SELECT->{ - WorkersDb.getRealm().apply { - writeBlocking { + } + KEYCODE_BUTTON_START->{ + onClickCenterButton() + } + KEYCODE_BUTTON_SELECT->{ + WorkersDb.getRealm().apply { + writeBlocking { + } } } + else -> {} } - else -> {} + } + else->{} + } + return true + } + else { + + val currentFragment = targetFragment ?: supportFragmentManager.fragments.find { it.isAdded && (!it.isHidden || it.isVisible) } + if (currentFragment is KeyEventHandler) { + if (currentFragment.onKeyEvent(ev)) { + return true } } - else->{} + else { return super.dispatchKeyEvent(ev) } } - return true - } - else { - - val currentFragment = targetFragment ?: supportFragmentManager.fragments.find { it.isAdded && (!it.isHidden || it.isVisible) } - if (currentFragment is KeyEventHandler) { - if (currentFragment.onKeyEvent(ev)) { - return true - } - } - else { return super.dispatchKeyEvent(ev) } - } return super.dispatchKeyEvent(ev) } @@ -342,7 +344,7 @@ open class NeoRssActivity : CommonActivity() { when(keyType) { "UP_ARROW"->{showContents(R.id.feeds)} "DOWN_ARROW"->{showContents(R.id.close)} - "RIGHT_ARROW"->{showContents(R.id.books)} +// "RIGHT_ARROW"->{showContents(R.id.books)} "LEFT_ARROW"->{ } "CENTER_SINGLE_TAP" -> { } "CENTER_DOUBLE_TAP" -> { showContents(R.id.btn_torrent) } @@ -380,9 +382,34 @@ open class NeoRssActivity : CommonActivity() { override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean { Blog.LOGE("onKeyUp >> $keyCode $event") + if ("Virtual".equals(event?.device?.name)) { + val currentFragment = targetFragment ?: supportFragmentManager.fragments.find { it.isVisible } + if (currentFragment is RemoteGestureFragment && currentFragment.isRemoteEnabled) { + + + when (keyCode) { + KEYCODE_DPAD_UP -> { + currentFragment.onRemoteUp(false) + } + KEYCODE_DPAD_DOWN -> { + currentFragment.onRemoteDown(false) + } + KEYCODE_DPAD_LEFT -> { + currentFragment.onRemoteLeft(false) + } + KEYCODE_DPAD_RIGHT -> { + currentFragment.onRemoteRight(false) + } + + } + } + } return super.onKeyUp(keyCode, event) } + + override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean { +// Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev?.device?.name ?: ""}: ${ev} ") if ("Virtual".equals(ev?.device?.name)) return true Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev?.device?.name ?: ""}: ${ev} ") if (ev?.device?.name?.contains("BLE-M3") == true) { @@ -603,8 +630,8 @@ open class NeoRssActivity : CommonActivity() { targetFragment = when(id) { R.id.feeds -> RssHome() R.id.books -> TokiFragment.newInstanceNovels() - R.id.webtoons -> TokiFragment.newInstanceWebtoons() - R.id.comics -> TokiFragment.newInstanceComics() +// R.id.webtoons -> TokiFragment.newInstanceWebtoons() +// R.id.comics -> TokiFragment.newInstanceComics() R.id.youtube -> TokiFragment.newInstanceYouTube() R.id.perplexity -> TokiFragment.newInstancePerplexity() R.id.zzalbang -> BookmarkPagerFragment() diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt index 612f2fbe..87ee8a3e 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/RssHome.kt @@ -169,7 +169,7 @@ internal class RssHome : RemoteGestureFragment() , KeyEventHandler { val infoUpdate = Runnable { chooseAdpater() } var result: RealmResults? = null - val nomoreShowCount = 5 + val nomoreShowCount = 1 fun rssStateVote() = (lasted?.filter { it.vote == true }?.size ?: -1) == (lasted?.size ?: 0) var lasted: ArrayList = arrayListOf() var infosJob: Job? = null @@ -534,6 +534,7 @@ internal class RssHome : RemoteGestureFragment() , KeyEventHandler { } + @SuppressLint("ClickableViewAccessibility") override fun onCreateView( inflater: LayoutInflater, diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt index d3dd808e..f162687d 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/TokiFragment.kt @@ -186,9 +186,9 @@ class TokiFragment : RemoteGestureFragment(), PagedTextViewInterface,KeyEventHan arguments = Bundle().apply { putString(ARG_TYPE, "book") putInt(ARG_LAST_NUM, 468) - putString(ARG_NAME, "booktoki") - putString(ARG_DOT, "com") - putBoolean(ARG_USE_NUM_URL, true) + putString(ARG_NAME, "ntk01") + putString(ARG_DOT, "com/novel") + putBoolean(ARG_USE_NUM_URL, false) putBoolean(ARG_ENABLE_GESTURE, true) } } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt b/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt index 8321f4ab..c8689311 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/workers/TorrentManager.kt @@ -211,7 +211,7 @@ class TorrentService : Service() { // 2. 파일 다운로드: 계산된 점수(finalScore)가 낮은 순으로 정렬 if (isCharging) { - val maxSlots = if (isWifiConnected) 6 else 2 + val maxSlots = if (isWifiConnected) 6 else 1 val sortedByPriority = torrentsWithMetadata.sortedBy { it.second } sortedByPriority.forEachIndexed { index, pair -> diff --git a/app/src/main/res/layout/rss_activity.xml b/app/src/main/res/layout/rss_activity.xml index fac7b95e..2380e729 100644 --- a/app/src/main/res/layout/rss_activity.xml +++ b/app/src/main/res/layout/rss_activity.xml @@ -46,14 +46,14 @@ app:fab_label="📚" style="@style/CommonFabStyle" android:id="@+id/books"/> - - + + + + + + + +