From dab91b1a659374348261c2092736fc43a2877f93 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Tue, 30 Jun 2026 10:00:31 +0900 Subject: [PATCH] ... --- app/src/main/AndroidManifest.xml | 2 +- .../launcher/home/CompletedFilesFragment.kt | 5 +- .../home/tokiz/view/PagedTextLayout.kt | 2 + .../launcher/player/DocumentViewerActivity.kt | 111 +++++++++++++++--- .../lunatic/launcher/player/PageIndexer.kt | 5 +- 5 files changed, 107 insertions(+), 18 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 39483a9e..4bfffcf1 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -130,7 +130,7 @@ android:name=".player.DocumentViewerActivity" android:theme="@style/Theme.Player" android:launchMode="singleInstance" - android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize" + android:configChanges="orientation|screenSize|screenLayout|smallestScreenSize|density|fontScale" android:screenOrientation="portrait" android:excludeFromRecents="false" android:hardwareAccelerated="true" diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt index 7d18bb1a..a3387214 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/CompletedFilesFragment.kt @@ -499,6 +499,7 @@ class CompletedFilesFragment : Fragment() { FileViewMode.GRID_SMALL -> "apps" } } + val MAX_COUNT = 9 private fun setupControls(view: View) { val layoutTitleDefault = view.findViewById(R.id.layoutTitleDefault) val layoutTitleSearch = view.findViewById(R.id.layoutTitleSearch) @@ -577,8 +578,8 @@ class CompletedFilesFragment : Fragment() { } - val message = if (protectedCount > 5) { - Toast.makeText(context, "보호된 폴더 내부는 5개 이하만 동시 삭제 가능함.", Toast.LENGTH_SHORT).show() + val message = if (protectedCount > MAX_COUNT) { + Toast.makeText(context, "보호된 폴더 내부는 ${MAX_COUNT}개 이하만 동시 삭제 가능함.", Toast.LENGTH_SHORT).show() return@setOnClickListener } else { "선택한 ${selectedFiles.size}개 항목을 삭제하시겠습니까?" diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/PagedTextLayout.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/PagedTextLayout.kt index 74473e55..ded0fc13 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/PagedTextLayout.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/PagedTextLayout.kt @@ -160,11 +160,13 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { } var currentPageTextView : TextView? = null + var currentChapter : TextView? = null fun initView(context: Context) { inflate(context, R.layout.layout_textviewer, this) mainTextView = findViewById(R.id.first_view) sencondTextView = findViewById(R.id.sencond_view) currentPageTextView = findViewById(R.id.current_page) + currentChapter = findViewById(R.id.current_chapter) if (mPagedTextViewInterface?.usePageInfo() ?: false) { } else { 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 35ddb3bd..ea2ab73c 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/player/DocumentViewerActivity.kt @@ -29,6 +29,88 @@ class DocumentViewerActivity : AppCompatActivity(), PagedTextViewInterface { private var encoding: String = "utf-8" private lateinit var pageIndexer: PageIndexer private var currentPageIndex = 0 + private var indexingJob: kotlinx.coroutines.Job? = null + + // 2. 기존 initializeReader() 함수를 크기 변경 시에도 재사용 가능하도록 리팩토링 + private fun initializeReader(targetOffset: Long = -1L) { + // 기존 작동 중인 인덱싱이 있다면 취소 + indexingJob?.cancel() + + indexingJob = lifecycleScope.launch { + currentFile?.let { file -> + // 인코딩은 최초 1회만 구해도 무방하므로 검증 로직 제외 가능 + if (encoding.isEmpty()) encoding = detectFileEncoding(file) + + val paint = pagedLayout.mainTextView?.paint ?: return@launch + val targetWidth = (pagedLayout.mainTextView!!.width * 0.8).toInt() + val targetHeight = (pagedLayout.mainTextView!!.height * 0.8).toInt() + + // 0 이하의 크기 방어 (뷰가 아직 가로세로 측정이 안 되었을 때) + if (targetWidth <= 0 || targetHeight <= 0) return@launch + + pageIndexer = PageIndexer( + file, encoding, paint, targetWidth, targetHeight + ) + + var hasRestoredPage = false + + pageIndexer.buildIndex { progress -> + runOnUiThread { + 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 + } + } + } + + pagedLayout.currentPageTextView?.text = "${currentPageIndex + 1} / $currentOffsetsSize" + } + } + } + } + } + + // 3. 팝업 크기 변경 감지 콜백 구현 + override fun onConfigurationChanged(newConfig: android.content.res.Configuration) { + super.onConfigurationChanged(newConfig) + + // 현재 읽고 있던 페이지의 실제 파일 시작 offset을 백업합니다. + val currentOffsetBackup = if (::pageIndexer.isInitialized && currentPageIndex in pageIndexer.pageOffsets.indices) { + pageIndexer.pageOffsets[currentPageIndex] + } else { + -1L + } + + // 뷰가 새로운 크기로 완전히 배치(Layout)된 후 재인덱싱을 돌려야 정확한 가로/세로가 나옵니다. + pagedLayout.post { + initializeReader(targetOffset = currentOffsetBackup) + } + } + + // 4. onDestroy 스케줄러 취소 안전장치 추가 + override fun onDestroy() { + indexingJob?.cancel() + super.onDestroy() + try { + raf.close() + } catch (e: Exception) { + e.printStackTrace() + } + } // SharedPreferences 정의 (마지막 페이지 저장용) private val sharedPreferences by lazy { @@ -151,14 +233,19 @@ class DocumentViewerActivity : AppCompatActivity(), PagedTextViewInterface { val pageText = String(buffer, Charset.forName(encoding)) pagedLayout.text = pageText pagedLayout.currentPageTextView?.text = "${currentPageIndex + 1} / ${pageIndexer.pageOffsets.size}" + pagedLayout.currentChapter?.text = pageIndexer.getChapterForPage(currentPageIndex)?.title + pagedLayout.currentChapter?.setOnClickListener { + if (!::pageIndexer.isInitialized || pageIndexer.pageOffsets.isEmpty()) return@setOnClickListener + showChapterListDialog() + } } override fun onTouch(touchArea: TouchArea) { - if (!::pageIndexer.isInitialized || pageIndexer.pageOffsets.isEmpty()) return - if (touchArea == TouchArea.Center) { -// showPageSeekDialog() - showChapterListDialog() - } +// if (!::pageIndexer.isInitialized || pageIndexer.pageOffsets.isEmpty()) return +// if (touchArea == TouchArea.Center) { +//// showPageSeekDialog() +// showChapterListDialog() +// } } private fun moveToNextChapter() { @@ -302,18 +389,14 @@ class DocumentViewerActivity : AppCompatActivity(), PagedTextViewInterface { } } - override fun onLongClick() {} + override fun onLongClick() { + + } + override fun usePageInfo(): Boolean = true override fun onTimeoverTouch() {} override fun onSwipeDown(count: Int) {} override fun onSwipeUp(count: Int) {} - override fun onDestroy() { - super.onDestroy() - try { - raf.close() - } catch (e: Exception) { - e.printStackTrace() - } - } + } \ No newline at end of file diff --git a/app/src/main/kotlin/bums/lunatic/launcher/player/PageIndexer.kt b/app/src/main/kotlin/bums/lunatic/launcher/player/PageIndexer.kt index cfbf02bb..7431551a 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/player/PageIndexer.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/player/PageIndexer.kt @@ -26,7 +26,10 @@ class PageIndexer( val pageOffsets = ArrayList() val chapters = ArrayList() private val charset = Charset.forName(encoding) - + fun getChapterForPage(currentPageIndex: Int): Chapter? { + // 현재 페이지보다 작거나 같은 시작 페이지를 가진 챕터 중, 가장 마지막 챕터를 찾습니다. + return chapters.lastOrNull { it.pageIndex <= currentPageIndex } + } private val chapterPattern = Pattern.compile( "(?:제\\s*)?\\d+\\s*[화|장|막|절|편]" )