...
This commit is contained in:
@@ -146,6 +146,10 @@
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".workers.WatchGestureService"
|
||||
android:enabled="true"
|
||||
android:exported="false" />
|
||||
|
||||
<service
|
||||
android:name=".workers.TorrentService"
|
||||
|
||||
@@ -0,0 +1,120 @@
|
||||
(function() {
|
||||
var retryCount = 0;
|
||||
var maxRetries = 2;
|
||||
|
||||
function tryExtract() {
|
||||
try {
|
||||
const newUrl = window.location.origin + window.location.pathname;
|
||||
const hostname = window.location.hostname;
|
||||
const contentsType = hostname.includes("book") ? "booktoki" :
|
||||
hostname.includes("mana") ? "manatoki" :
|
||||
hostname.includes("new") ? "newtoki" : "web";
|
||||
|
||||
// 1. 목차(List) 감지 로직
|
||||
const listBody = document.querySelector(".list-body");
|
||||
const novelContent = document.querySelector("#novel_content");
|
||||
|
||||
// [중요] 두 핵심 요소가 모두 없으면 재시도 결정
|
||||
if (!listBody && !novelContent) {
|
||||
if (retryCount < maxRetries) {
|
||||
retryCount++;
|
||||
console.log("DEBUG_LOG: [JS] 요소를 찾지 못해 재시도 중... (" + retryCount + ")");
|
||||
setTimeout(tryExtract, 500); // 0.5초 후 다시 실행
|
||||
return;
|
||||
} else {
|
||||
console.log("DEBUG_LOG: [JS] 최대 재시도 횟수 초과");
|
||||
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
|
||||
'type': 'JP',
|
||||
'currentUrl' : newUrl
|
||||
}));
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
// --- 1. 목차 추출 실행 ---
|
||||
if (listBody !== null) {
|
||||
const contentsArray = [];
|
||||
const children = listBody.children;
|
||||
const bookTitleEl = document.querySelector('.view-title span');
|
||||
const bookTitle = bookTitleEl ? bookTitleEl.innerText.trim() : "Unknown";
|
||||
const pagination = document.querySelector(".pagination");
|
||||
let nextPagingUrl = null;
|
||||
|
||||
if (pagination) {
|
||||
const activeLi = pagination.querySelector("li.active");
|
||||
if (activeLi && activeLi.nextElementSibling) {
|
||||
const nextA = activeLi.nextElementSibling.querySelector("a");
|
||||
// 다음 엘리먼트가 존재하고, 'disabled' 클래스가 없으며, href가 있는 경우
|
||||
if (nextA && nextA.href && !activeLi.nextElementSibling.classList.contains("disabled")) {
|
||||
nextPagingUrl = nextA.href;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < children.length; i++) {
|
||||
try {
|
||||
const wrNumEl = children[i].getElementsByClassName('wr-num')[0];
|
||||
const wrSubjectA = children[i].getElementsByClassName('wr-subject')[0]?.getElementsByTagName('a')[0];
|
||||
if (!wrNumEl || !wrSubjectA) continue;
|
||||
|
||||
let pageUrl = new URL(wrSubjectA.href, window.location.origin).pathname;
|
||||
let paths = pageUrl.split('/').filter(p => p);
|
||||
if (paths.length > 0) {
|
||||
var lastPart = paths[paths.length - 1];
|
||||
var isOnlyNumber = lastPart && Array.from(lastPart).every(ch => ch >= '0' && ch <= '9');
|
||||
if (!isOnlyNumber) paths.pop();
|
||||
}
|
||||
pageUrl = "/" + paths.join('/');
|
||||
|
||||
contentsArray.push({
|
||||
'chapterID': parseInt(wrNumEl.textContent.replace(/[^0-9]/g, "")),
|
||||
'chapterNum': parseInt(wrNumEl.textContent.replace(/[^0-9]/g, "")),
|
||||
'pathUrl': pageUrl,
|
||||
'contentsType': contentsType,
|
||||
'bookPageUrl': window.location.pathname,
|
||||
'chapterTitle': wrSubjectA.innerText.split('\n').pop().trim(),
|
||||
'bookTitle': bookTitle,
|
||||
'currentUrl' : newUrl
|
||||
});
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
if (contentsArray.length > 0) {
|
||||
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
|
||||
'type': 'getListResult',
|
||||
'contentsType': contentsType,
|
||||
'bookTitle': bookTitle,
|
||||
'bookPageUrl': window.location.pathname,
|
||||
'pages': contentsArray,
|
||||
'currentUrl' : newUrl,
|
||||
'nextPagingUrl': nextPagingUrl
|
||||
}));
|
||||
return; // 전송 성공 시 종료
|
||||
}
|
||||
}
|
||||
|
||||
// --- 2. 본문 추출 실행 ---
|
||||
if (novelContent !== null) {
|
||||
const titleEl = document.querySelector(".page-desc");
|
||||
const chapterTitle = titleEl ? titleEl.innerText.trim() : "";
|
||||
const contents = novelContent.innerText.trim();
|
||||
|
||||
|
||||
if (contents.length > 100) {
|
||||
window.webkit.messageHandlers.ContentsRcv.postMessage(JSON.stringify({
|
||||
'type': 'BookContents',
|
||||
'chapterTitle': chapterTitle,
|
||||
'bookContents': contents,
|
||||
'pageUrl' : window.location.pathname,
|
||||
'currentUrl' : newUrl
|
||||
}));
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
console.log("Unified Script Error: " + e);
|
||||
}
|
||||
}
|
||||
|
||||
// 최초 실행
|
||||
tryExtract();
|
||||
})();
|
||||
@@ -0,0 +1,25 @@
|
||||
package bums.lunatic.launcher.workers
|
||||
|
||||
import bums.lunatic.launcher.utils.Blog
|
||||
import com.google.android.gms.wearable.MessageEvent
|
||||
import com.google.android.gms.wearable.WearableListenerService
|
||||
|
||||
class WatchGestureService : WearableListenerService() {
|
||||
override fun onMessageReceived(messageEvent: MessageEvent) {
|
||||
when (messageEvent.path) {
|
||||
"/gesture/next" -> {
|
||||
// 런처의 다음 페이지로 이동하거나, 이북 앱에 키 이벤트 전송
|
||||
handleGestureAction("NEXT")
|
||||
}
|
||||
"/gesture/prev" -> {
|
||||
handleGestureAction("PREV")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun handleGestureAction(action: String) {
|
||||
// Broadcast를 런처 메인 Activity로 쏘거나,
|
||||
// 직접 AccessibilityService를 호출하여 시스템 이벤트를 발생시킵니다.
|
||||
Blog.LOGE("WatchGesture", "Gesture Received: $action")
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user