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