diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4369d47f..b523b1c2 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -125,7 +125,16 @@
android:excludeFromRecents="true"
android:exported="false">
+
+
-
@@ -240,10 +249,10 @@
-
-
-
-
+
+
+
+
+
+
+
+ $Title$
+
+
+$END$
+
+
\ No newline at end of file
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 709effc7..5a45fc84 100644
--- a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt
+++ b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt
@@ -629,7 +629,7 @@ 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.youtube -> TokiFragment.newInstanceYouTube()
@@ -649,6 +649,11 @@ open class NeoRssActivity : CommonActivity() {
R.id.btn_info -> SystemStatusFragment()
R.id.btn_completed_files -> CompletedFilesFragment()
R.id.btn_learn -> LearningFragment()
+ R.id.books -> {
+ startActivity(Intent(this@NeoRssActivity, WebReaderActivity::class.java))
+ finish()
+ return
+ }
R.id.close -> {
finish()
return
diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/WebReaderActivity.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/WebReaderActivity.kt
new file mode 100644
index 00000000..5abb3dc0
--- /dev/null
+++ b/app/src/main/kotlin/bums/lunatic/launcher/home/WebReaderActivity.kt
@@ -0,0 +1,132 @@
+package bums.lunatic.launcher.home
+
+import android.app.Activity
+import android.content.Intent
+import android.net.Uri
+import android.os.Bundle
+import android.view.KeyEvent
+import android.webkit.ValueCallback
+import android.webkit.WebChromeClient
+import android.webkit.WebSettings
+import android.webkit.WebView
+import android.webkit.WebViewClient
+import androidx.activity.result.contract.ActivityResultContracts
+import androidx.appcompat.app.AppCompatActivity
+import bums.lunatic.launcher.R
+
+class WebReaderActivity : AppCompatActivity() {
+
+ private lateinit var webView: WebView
+
+ // 웹뷰에서 파일을 선택할 때 결과를 받을 콜백 변수
+ private var filePathCallback: ValueCallback>? = null
+
+ // 파일 탐색기 결과를 처리하는 런처 (최신 Activity Result API 사용)
+ private val fileChooserLauncher = registerForActivityResult(
+ ActivityResultContracts.StartActivityForResult()
+ ) { result ->
+ if (result.resultCode == Activity.RESULT_OK) {
+ val data = result.data
+ val uriList = if (data?.data != null) {
+ arrayOf(data.data!!)
+ } else {
+ null
+ }
+ // 웹뷰로 선택한 파일 URI 전달
+ filePathCallback?.onReceiveValue(uriList)
+ } else {
+ // 취소했을 경우 반드시 null을 전달해야 웹뷰가 멈추지 않음
+ filePathCallback?.onReceiveValue(null)
+ }
+ filePathCallback = null
+ }
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+ setContentView(R.layout.activity_wr)
+
+ webView = findViewById(R.id.webView)
+
+ setupWebView()
+
+ // assets 폴더에 넣은 HTML 파일 로드
+ webView.loadUrl("https://git.lunaticbum.kr/reader.html")
+ }
+
+
+ override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
+ when (keyCode) {
+ KeyEvent.KEYCODE_VOLUME_DOWN -> {
+ // 볼륨 다운 버튼 -> 다음 페이지 (오른쪽 화살표)
+ // 웹뷰에 JavaScript 키보드 이벤트를 강제로 발생시킴
+ webView.evaluateJavascript(
+ "window.dispatchEvent(new KeyboardEvent('keydown', {'key': 'ArrowRight'}));",
+ null
+ )
+ return true // true를 반환하면 시스템 볼륨이 변경되지 않고 이벤트가 소비됨
+ }
+ KeyEvent.KEYCODE_VOLUME_UP -> {
+ // 볼륨 업 버튼 -> 이전 페이지 (왼쪽 화살표)
+ webView.evaluateJavascript(
+ "window.dispatchEvent(new KeyboardEvent('keydown', {'key': 'ArrowLeft'}));",
+ null
+ )
+ return true // true를 반환하면 시스템 볼륨이 변경되지 않음
+ }
+ }
+
+ // 볼륨 키가 아닌 다른 키(뒤로가기 등)는 기본 안드로이드 동작을 수행하도록 넘김
+ return super.onKeyDown(keyCode, event)
+ }
+
+ private fun setupWebView() {
+ // 1. 웹뷰 기본 설정
+ webView.settings.apply {
+ javaScriptEnabled = true // 자바스크립트 필수
+ domStorageEnabled = true // localStorage, IndexedDB 사용을 위해 필수
+ allowFileAccess = true // 로컬 파일 접근 허용
+ allowContentAccess = true // Content URI 접근 허용
+ mixedContentMode = WebSettings.MIXED_CONTENT_ALWAYS_ALLOW // 보안 정책 우회 (필요시)
+
+ // 모바일 화면에 맞게 뷰포트 설정
+ useWideViewPort = true
+ loadWithOverviewMode = true
+ }
+
+ // 2. 새 창 열림 방지 (앱 내부에서만 렌더링)
+ webView.webViewClient = WebViewClient()
+
+ // 3. 파일 업로드() 처리를 위한 WebChromeClient 설정
+ webView.webChromeClient = object : WebChromeClient() {
+ override fun onShowFileChooser(
+ webView: WebView?,
+ filePathCallback: ValueCallback>?,
+ fileChooserParams: FileChooserParams?
+ ): Boolean {
+ // 이전 콜백이 남아있다면 취소 처리
+ this@WebReaderActivity.filePathCallback?.onReceiveValue(null)
+ this@WebReaderActivity.filePathCallback = filePathCallback
+
+ // 안드로이드 파일 탐색기 호출 Intent
+ val intent = Intent(Intent.ACTION_OPEN_DOCUMENT).apply {
+ addCategory(Intent.CATEGORY_OPENABLE)
+ type = "*/*"
+ // txt, epub만 선택하게 하려면 아래처럼 mimeTypes 지정 가능
+ putExtra(Intent.EXTRA_MIME_TYPES, arrayOf("text/plain", "application/epub+zip"))
+ }
+
+ fileChooserLauncher.launch(intent)
+ return true
+ }
+ }
+ }
+
+ // 뒤로가기 버튼 처리 (웹뷰 내에서 뒤로 갈 수 있으면 웹뷰 뒤로가기 실행)
+ override fun onBackPressed() {
+ if (webView.canGoBack()) {
+ webView.goBack()
+ } else {
+ super.onBackPressed()
+ }
+ }
+}
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 1a2f22ba..3fc953e5 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
@@ -185,13 +185,13 @@ class TokiFragment : RemoteGestureFragment(), PagedTextViewInterface,KeyEventHan
putBoolean(ARG_ENABLE_GESTURE, false)
}
}
-
+// https://git.lunaticbum.kr/reader.html
fun newInstanceNovels(): TokiFragment = TokiFragment().apply {
arguments = Bundle().apply {
putString(ARG_TYPE, "web")
putInt(ARG_LAST_NUM, 468)
- putString(ARG_NAME, "sbxh2")
- putString(ARG_DOT, "com/novel")
+ putString(ARG_NAME, "git.lunaticbum")
+ putString(ARG_DOT, ".kr/reader.html")
putBoolean(ARG_USE_NUM_URL, false)
putBoolean(ARG_ENABLE_GESTURE, true)
}
diff --git a/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt b/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt
index d1a263fa..ae020e3c 100644
--- a/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt
+++ b/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt
@@ -60,28 +60,34 @@ class DocumentViewerActivity : AppCompatActivity(), PagedTextViewInterface {
pageIndexer.buildIndex { progress ->
runOnUiThread {
- val currentOffsetsSize = pageIndexer.pageOffsets.size
+ try {
+ val currentOffsetsSize = pageIndexer.pageOffsets.size
- if (!hasRestoredPage) {
- if (targetOffset >= 0L) {
- // [크기 재조정 케이스] 기억해둔 오프셋 위치가 확보되었는지 확인
- val foundIndex = pageIndexer.pageOffsets.indexOfLast { it <= targetOffset }
- // 마지막 오프셋이거나, 다음 페이지 오프셋까지 리스트에 확보되었을 때 전환
- if (foundIndex >= 0 && (foundIndex < currentOffsetsSize - 1 || progress >= 100)) {
- showPage(foundIndex)
- hasRestoredPage = true
- }
- } else {
- // [최초 진입 케이스] SharedPreferences 복구
- val savedPageIndex = sharedPreferences.getInt(file.absolutePath, 0)
- if (currentOffsetsSize > savedPageIndex) {
- showPage(savedPageIndex)
- hasRestoredPage = true
+ if (!hasRestoredPage) {
+ if (targetOffset >= 0L) {
+
+ // [크기 재조정 케이스] 기억해둔 오프셋 위치가 확보되었는지 확인
+ val foundIndex = pageIndexer.pageOffsets.indexOfLast { it <= targetOffset }
+ // 마지막 오프셋이거나, 다음 페이지 오프셋까지 리스트에 확보되었을 때 전환
+ if (foundIndex >= 0 && (foundIndex < currentOffsetsSize - 1 || progress >= 100)) {
+ showPage(foundIndex)
+ hasRestoredPage = true
+ }
+ } else {
+ // [최초 진입 케이스] SharedPreferences 복구
+ val savedPageIndex = sharedPreferences.getInt(file.absolutePath, 0)
+ if (currentOffsetsSize > savedPageIndex) {
+ showPage(savedPageIndex)
+ hasRestoredPage = true
+ }
}
}
- }
- pagedLayout.currentPageTextView?.text = "${currentPageIndex + 1} / $currentOffsetsSize"
+ pagedLayout.currentPageTextView?.text = "${currentPageIndex + 1} / $currentOffsetsSize"
+ }
+ catch (e : Exception) {
+ e.printStackTrace()
+ }
}
}
}
diff --git a/app/src/main/res/layout/activity_wr.xml b/app/src/main/res/layout/activity_wr.xml
new file mode 100644
index 00000000..081511d9
--- /dev/null
+++ b/app/src/main/res/layout/activity_wr.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
\ No newline at end of file