From 9f6c424e04d688c1c362b5cae45b4e52ee67baf7 Mon Sep 17 00:00:00 2001 From: lunaticbum Date: Fri, 30 Jan 2026 16:52:36 +0900 Subject: [PATCH] ... --- app/build.gradle.kts | 1 + app/src/main/AndroidManifest.xml | 2 - .../launcher/apps/AppDrawerBottomSheet.kt | 4 +- .../bums/lunatic/launcher/home/GeckoWeb.kt | 77 +- .../lunatic/launcher/home/NeoRssActivity.kt | 143 +- .../lunatic/launcher/home/tokiz/BaseToki.kt | 3407 ++++++++--------- .../launcher/home/tokiz/TokiFragment.kt | 6 +- .../launcher/home/tokiz/view/BWebview.kt | 336 -- .../home/tokiz/view/PagedTextLayout.kt | 390 +- app/src/main/res/layout/layout_textviewer.xml | 28 +- 10 files changed, 1917 insertions(+), 2477 deletions(-) delete mode 100644 app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/BWebview.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 2bc8d4fd..b4199ed8 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -155,6 +155,7 @@ dependencies { // implementation 'com.vladsch.flexmark:flexmark-all:0.64.8' // implementation("org.opencv:opencv-android:4.11.0") // build.gradle에 추가 + implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3") // implementation ("com.github.aeonSolutions:FloatingActionButtonMenuDrag:1.1") implementation("io.github.junkfood02.youtubedl-android:library:0.17.4") implementation("io.github.junkfood02.youtubedl-android:ffmpeg:0.17.4") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index ce96f5ee..eb9ed1ab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -91,8 +91,6 @@ android:screenOrientation="userPortrait" android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|screenLayout|layoutDirection|navigation" android:windowSoftInputMode="adjustResize" - android:noHistory="true" - android:excludeFromRecents="true" android:exported="false"> diff --git a/app/src/main/kotlin/bums/lunatic/launcher/apps/AppDrawerBottomSheet.kt b/app/src/main/kotlin/bums/lunatic/launcher/apps/AppDrawerBottomSheet.kt index 45d18774..b454529d 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/apps/AppDrawerBottomSheet.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/apps/AppDrawerBottomSheet.kt @@ -291,7 +291,9 @@ class AppDrawerBottomSheet : BottomSheetDialogFragment() { if (item.type == "APP") { val app = realm.query("pkgName == $0", item.key).first().find() if (app != null && !app.blockRecommend) { - unifiedList.add(RecommendationItem.AppItem(realm.copyFromRealm(app))) + try { if(pm.getLaunchIntentForPackage(app.pkgName ?: "") != null) { + unifiedList.add(RecommendationItem.AppItem(realm.copyFromRealm(app))) + }} catch (e: Exception) { } } } else if (item.type == "CONTACT") { // 연락처 ID나 전화번호로 조회 (Log 저장 시 key가 무엇인지에 따라 다름) 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 6a9c4566..e408d668 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/GeckoWeb.kt @@ -82,6 +82,40 @@ open class GeckoWeb @JvmOverloads constructor( // --- 1. Properties & Initialization --- + // 1. 세션 상태를 저장할 SharedPreferences 키 + private val PREF_SESSION_STATE = "gecko_session_state" + + // 2. 현재 세션 상태 저장 메서드 + fun saveCurrentSessionState() { + + lastSessionState?.let { state -> + // SessionState.toString()은 내부적으로 JSON 문자열을 반환합니다. + val stateJson = state.toString() + + context.getSharedPreferences("GeckoPrefs", Context.MODE_PRIVATE) + .edit() + .putString("gecko_session_state", stateJson) + .apply() + + Log.d("GeckoWeb", "Session State Saved: $stateJson") + } + } + + // 3. 저장된 세션 상태 복구 메서드 + fun restoreSessionState(session: GeckoSession) { + val stateJson = context.getSharedPreferences("GeckoPrefs", Context.MODE_PRIVATE) + .getString("gecko_session_state", null) + + if (!stateJson.isNullOrEmpty()) { + // 문자열에서 SessionState 객체 생성 + val state = GeckoSession.SessionState.fromString(stateJson) + if (state != null) { + session.restoreState(state) + Log.d("GeckoWeb", "Session State Restored") + } + } + } + // UI & State var decoViews = arrayListOf() var progress: ProgressBar? = null @@ -138,8 +172,8 @@ open class GeckoWeb @JvmOverloads constructor( override fun onLongPress(targetView: View, fingers: Int) = true }) - class GKCookie { var COOKIES: String? = null } - var mGKCookie: GKCookie? = null +// class GKCookie { var COOKIES: String? = null } +// var mGKCookie: GKCookie? = null // Markdown/Scraping var markdownContents: String? = null @@ -192,23 +226,23 @@ open class GeckoWeb @JvmOverloads constructor( CoroutineScope(Dispatchers.IO).launch { try { val request = YoutubeDLRequest(url) - mGKCookie?.COOKIES?.let { cookieStr -> - val cookieFile = File(context.filesDir, "cookies.txt") - val cookies = cookieStr.split(";").mapNotNull { - val p = it.trim().split("=", limit = 2) - if (p.size == 2) p[0] to p[1] else null - }.toMap() - val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7 - - val content = buildString { - appendLine("# Netscape HTTP Cookie File") - cookies.forEach { (k, v) -> - appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$k\t$v") - } - } - cookieFile.writeText(content) - request.addOption("--cookies", cookieFile.absolutePath) - } +// mGKCookie?.COOKIES?.let { cookieStr -> +// val cookieFile = File(context.filesDir, "cookies.txt") +// val cookies = cookieStr.split(";").mapNotNull { +// val p = it.trim().split("=", limit = 2) +// if (p.size == 2) p[0] to p[1] else null +// }.toMap() +// val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7 +// +// val content = buildString { +// appendLine("# Netscape HTTP Cookie File") +// cookies.forEach { (k, v) -> +// appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$k\t$v") +// } +// } +// cookieFile.writeText(content) +// request.addOption("--cookies", cookieFile.absolutePath) +// } val videoInfo = YoutubeDL.getInstance().getInfo(request) if (videoInfo != null && !videoInfo.title.isNullOrEmpty()) { @@ -321,12 +355,14 @@ open class GeckoWeb @JvmOverloads constructor( } override fun onPageStop(session: GeckoSession, success: Boolean) { onPageStopCallback?.invoke(success) + saveCurrentSessionState() } override fun onSessionStateChange(session: GeckoSession, sessionState: GeckoSession.SessionState) { + onSessionStateChangeCallback?.invoke(sessionState) } } - + private var lastSessionState: GeckoSession.SessionState? = null // [Extension Delegates] private val addonManagerDelegate = object : AddonManagerDelegate { override fun onReady(extension: WebExtension) { mExtension = extension } @@ -386,6 +422,7 @@ open class GeckoWeb @JvmOverloads constructor( private fun buildWeb() { getRuntime()?.let { runtime -> val session = GeckoSession() + restoreSessionState(session) session.open(runtime) this.setSession(session) 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 92c5cacd..aa09b07d 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/NeoRssActivity.kt @@ -41,12 +41,7 @@ import bums.lunatic.launcher.home.adapters.BookmarkPagerFragment import bums.lunatic.launcher.model.RssData import bums.lunatic.launcher.model.RssDataType import bums.lunatic.launcher.settings.SettingsActivity -import bums.lunatic.launcher.home.tokiz.Comics -import bums.lunatic.launcher.home.tokiz.Novels -import bums.lunatic.launcher.home.tokiz.Perplexity import bums.lunatic.launcher.home.tokiz.TokiFragment -import bums.lunatic.launcher.home.tokiz.Webtoons -import bums.lunatic.launcher.home.tokiz.YouTube import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.beforeDay import bums.lunatic.launcher.workers.WorkersDb @@ -63,6 +58,7 @@ import org.mozilla.geckoview.ExperimentDelegate import org.mozilla.geckoview.GeckoResult import org.mozilla.geckoview.GeckoRuntime import org.mozilla.geckoview.GeckoRuntimeSettings +import java.io.File open class NeoRssActivity : CommonActivity() { @@ -116,7 +112,7 @@ open class NeoRssActivity : CommonActivity() { var onExit = false var lastAction = MotionEvent.ACTION_HOVER_EXIT override fun dispatchKeyEvent(ev: KeyEvent): Boolean { - val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) + Blog.LOGE("dispatchKeyEvent >>> ${ev}") if (ev?.device?.name?.contains("SM-031N Mouse") == true) { when(ev.action) { ACTION_UP -> { @@ -162,36 +158,35 @@ open class NeoRssActivity : CommonActivity() { } else { val currentFragment = supportFragmentManager.findFragmentById(R.id.fragment_container) - when(currentFragment) { - is Novels -> { - if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) { - return when (ev.keyCode) { - KeyEvent.KEYCODE_VOLUME_DOWN -> { - if(currentFragment is Novels){ currentFragment.actionNextEvent() } - true - } - KeyEvent.KEYCODE_VOLUME_UP -> { - if(currentFragment is Novels){ currentFragment.actionPrevEvent() } - true - } - else -> false + Blog.LOGE("currentFragment >>> ${currentFragment} ${currentFragment is TokiFragment && currentFragment.isbooktoki()}") + if (currentFragment is TokiFragment && currentFragment.isbooktoki()) { + if(MotionEvent.ACTION_UP.equals(ev?.action ?: MotionEvent.ACTION_CANCEL) == true) { + return when (ev.keyCode) { + KeyEvent.KEYCODE_VOLUME_DOWN -> { + if(currentFragment is TokiFragment){ currentFragment.actionNextEvent() } + true } - } else { - return when (ev.keyCode) { - KeyEvent.KEYCODE_VOLUME_DOWN -> { - true - } - - KeyEvent.KEYCODE_VOLUME_UP -> { - true - } - - else -> false + KeyEvent.KEYCODE_VOLUME_UP -> { + if(currentFragment is TokiFragment){ currentFragment.actionPrevEvent() } + true } + else -> false + } + } else { + return when (ev.keyCode) { + KeyEvent.KEYCODE_VOLUME_DOWN -> { + true + } + + KeyEvent.KEYCODE_VOLUME_UP -> { + true + } + + else -> false } } - else -> return super.dispatchKeyEvent(ev) } + else { return super.dispatchKeyEvent(ev) } } return super.dispatchKeyEvent(ev) } @@ -293,67 +288,6 @@ open class NeoRssActivity : CommonActivity() { showContents(v.id) } -// override fun onNewIntent(intent: Intent) { -// Blog.LOGE("onNewIntent intent >> ${intent}") -// if(intent?.action?.equals(Intent.ACTION_SEND) == true && -// intent?.hasExtra(Intent.EXTRA_TEXT) == true) { -// intent?.getStringExtra(Intent.EXTRA_TEXT)?.let { -// if(it.startsWith("http") == false) { -// it.split("http").forEach { string -> -// if(string.startsWith("http")) { -// try { -// string.toUri()?.let { uri -> -// Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.host}") -// Blog.LOGE("onNewIntent string uri.lastPathSegment >>>>> ${uri.lastPathSegment}") -// } -// } catch (e: Exception) { -// -// } -// } -// } -// } else { -// try { -// it.toUri()?.let { uri -> -// Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.host}") -// Blog.LOGE("onNewIntent it uri.lastPathSegment >>>>> ${uri.lastPathSegment}") -// } -// } catch (e: Exception) { -// -// } -// } -// } -// } else if (intent?.action == Intent.ACTION_WEB_SEARCH) { -// openWithIntent(intent) -// } else { -// Blog.LOGE("onNewIntent intent?.hasExtra >> ${intent?.hasExtra(Intent.EXTRA_STREAM)}") -// -// -// if (intent?.action?.equals(Intent.ACTION_MAIN) == true && intent.categories.contains( -// Intent.CATEGORY_HOME -// ) && intent.hasExtra("android.intent.extra.EXTRA_START_REASON") && intent.getStringExtra( -// "android.intent.extra.EXTRA_START_REASON" -// ).equals("startDockOrHome") -// ) { -// -// } else { -// intent?.extras?.keySet()?.forEach { -// try { -// Blog.LOGE( -// "onNewIntent :: key >> ${it} :: value >> ${ -// intent?.extras?.getString( -// it -// ) -// }" -// ) -// } catch (e: Exception) { -// e.printStackTrace() -// } -// -// } -// } -// } -// super.onNewIntent(intent) -// } private fun openWithIntent(intent: Intent){ Blog.LOGE("intent >> ${intent}") @@ -528,7 +462,13 @@ open class NeoRssActivity : CommonActivity() { private fun initGeckoRuntime() { if (sRuntime == null) { try { + val profileDir = File(this.filesDir, "geckoview_profile") + if (!profileDir.exists()) profileDir.mkdirs() + sRuntime = GeckoRuntime.create(this, GeckoRuntimeSettings.Builder() + .configFilePath(profileDir.absolutePath) + .aboutConfigEnabled(true) + .javaScriptEnabled(true) .extensionsProcessEnabled(true) .extensionsWebAPIEnabled(true) .experimentDelegate(experimentDelegate) @@ -559,16 +499,9 @@ open class NeoRssActivity : CommonActivity() { sRuntime = null } catch (e: Exception) { e.printStackTrace() } - // appWidgetHost?.stopListening() // 이 줄은 제거하고 onStop으로 이동 super.onDestroy() } - override fun onUserLeaveHint() { - - showContents(R.id.close) - - super.onUserLeaveHint() - } @RequiresApi(Build.VERSION_CODES.O_MR1) override fun onResume() { @@ -605,12 +538,12 @@ open class NeoRssActivity : CommonActivity() { currentFragment.doNextPage() } } - is YouTube -> { - currentFragment.back() - } - is Novels -> { - currentFragment.actionNextEvent(false) - } +// is YouTube -> { +// currentFragment.back() +// } +// is Novels -> { +// currentFragment.actionNextEvent(false) +// } else -> { showContents(R.id.close) } diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/BaseToki.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/BaseToki.kt index 589b520b..f2d86c9c 100644 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/BaseToki.kt +++ b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/BaseToki.kt @@ -1,1723 +1,1722 @@ -package bums.lunatic.launcher.home.tokiz - -import android.content.DialogInterface -import android.content.Intent -import android.content.res.Configuration -import android.net.Uri -import android.os.Bundle -import android.os.Handler -import android.os.Looper -import android.os.Message -import android.text.InputType -import android.text.SpannableStringBuilder -import android.text.style.RelativeSizeSpan -import android.util.Log -import android.view.LayoutInflater -import android.view.MotionEvent -import android.view.PointerIcon -import android.view.View -import android.view.View.GONE -import android.view.View.OnTouchListener -import android.view.View.VISIBLE -import android.view.View.inflate -import android.view.ViewGroup -import android.widget.ArrayAdapter -import android.widget.EditText -import android.widget.ImageButton -import android.widget.TextView -import android.widget.Toast -import androidx.appcompat.app.AlertDialog -import androidx.core.net.toUri -import androidx.core.view.isVisible -import androidx.fragment.app.Fragment -import bums.lunatic.launcher.R -import bums.lunatic.launcher.databinding.BooktokiBinding -import bums.lunatic.launcher.home.GeckoWeb -import bums.lunatic.launcher.home.GeckoWeb.GKCookie -import bums.lunatic.launcher.home.GeckoWeb.JxEvent -import bums.lunatic.launcher.home.NeoRssActivity -import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime -import bums.lunatic.launcher.home.toast -import bums.lunatic.launcher.home.tokiz.view.PagedTextLayout -import bums.lunatic.launcher.home.tokiz.view.PagedTextViewInterface -import bums.lunatic.launcher.utils.Blog -import bums.lunatic.launcher.workers.WorkersDb -import com.google.gson.Gson -import io.realm.kotlin.Realm -import io.realm.kotlin.UpdatePolicy -import io.realm.kotlin.ext.copyFromRealm -import io.realm.kotlin.ext.query -import org.json.JSONException -import org.json.JSONObject -import org.mozilla.gecko.util.ThreadUtils -import org.mozilla.geckoview.GeckoResult -import org.mozilla.geckoview.GeckoSession -import org.mozilla.geckoview.GeckoSessionSettings -import org.mozilla.geckoview.MediaSession -import org.mozilla.geckoview.WebExtension -import org.mozilla.geckoview.WebExtension.MessageDelegate -import org.mozilla.geckoview.WebExtension.PortDelegate -import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate -import org.mozilla.geckoview.WebRequestError -import java.lang.System.currentTimeMillis -import java.net.URL -import java.text.SimpleDateFormat -import java.util.Date -import kotlin.random.Random - - -abstract class BaseToki : Fragment(), PagedTextViewInterface { - fun openRealm(): Realm = HistoryManager.openRealm - var lastInfo: LastInfo? = null - var currentPage: ContentsPageInfo? = null - var saveContinuation = false - open var isPrivateMode = false - val handle = object : Handler(Looper.getMainLooper()) { - override fun handleMessage(msg: Message) { - if (msg.what == 0) { - (msg.obj as? ReaderConfig)?.let { - } - } - } - } - - - override fun onConfigurationChanged(newConfig: Configuration) { - super.onConfigurationChanged(newConfig) - Blog.LOGD(log = "onConfigurationChanged ${this::class.java.name} >> newConfig ${newConfig}") - } - - var lastedUrl: String? = null - var canGoBack: Boolean? = null - protected lateinit var binding: BooktokiBinding - - var mPort: WebExtension.Port? = null - val mPortNam = "browser" - val extPath = "resource://android/assets/extensions/my_extension/" - val extId = "messaging@booktoki468.com" - var mExtension: WebExtension? = null - abstract val contentsType: String - abstract var lastNumber: Int - abstract val webcontentsName: String - abstract val afterDot: String - open fun getLastedDoamin(): String { - return String.format("https://%s%d.%s", webcontentsName, lastNumber, afterDot) - } - - val OnTouchListener = object : OnTouchListener { - - override fun onTouch(v: View?, event: MotionEvent): Boolean { - when (event.getAction()) { - MotionEvent.ACTION_DOWN -> { - handle.removeCallbacks(mActionUp) - handle.removeCallbacks(mActionDown) - if (!binding.pagedLayer.isVisible) { - - } - } - - MotionEvent.ACTION_UP -> { - handle.removeCallbacks(mActionUp) - handle.removeCallbacks(mActionDown) - } - } - return false - } - - var mActionDown: Runnable = object : Runnable { - override fun run() { - sendScrollDown(false) - handle.postDelayed(this, 150) - } - } - var mActionUp: Runnable = object : Runnable { - override fun run() { - sendScrollDown(true) - handle.postDelayed(this, 150) - } - } - } - - - var mOnGenericMotionListener = object : View.OnGenericMotionListener { - override fun onGenericMotion( - v: View?, - event: MotionEvent? - ): Boolean { - Blog.LOGE("event >>>> $event") - return true - } - } - - val addonManagerDelegate = object : AddonManagerDelegate { - override fun onReady(extension: WebExtension) { - Blog.LOGE("onReady ${extension.id} from WebExtension") - mExtension = extension - - } - - override fun onEnabling(extension: WebExtension) { - Blog.LOGE("onEnabling ${extension.id} from WebExtension") - } - - override fun onEnabled(extension: WebExtension) { - Blog.LOGE("onEnabled ${extension.id} from WebExtension") -// extension?.setMessageDelegate(messageDelegate, mPortNam) - mExtension = extension - - } - } - - private fun aceptUrl(string: String): Boolean { - Blog.LOGE( - "string >>> ${string}, domain >>> ${getLastedDoamin()} :: isAcept ${ - string.contains( - getLastedDoamin() - ) - }" - ) - return string.contains(getLastedDoamin()) - } - - fun processPageUrl(pageUrl: String): String { - if (pageUrl != null && pageUrl.isNotEmpty() && pageUrl.startsWith("http")) { - var workingUrl = pageUrl - val paths = workingUrl.split("/").toMutableList() - if (paths.isNotEmpty()) { - val last = paths.last() - if (last.isNotEmpty() && last.all { it in '0'..'9' }) { - Log.d("TAG", "only nums $last") - } else { - Log.d("TAG", "not only nums $last") - paths.removeAt(paths.size - 1) - } - } - workingUrl = paths.joinToString("/") - // URL이 정상적으로 파싱되는지 확인(try-catch 권장) - val path = try { - URL(workingUrl).path - } catch (e: Exception) { - Log.d("TAG", "Invalid URL: $workingUrl") - return pageUrl - } - return path - } else { - var workingUrl = pageUrl - val paths = workingUrl.split("/").toMutableList() - if (paths.isNotEmpty()) { - val last = paths.last() - if (last.isNotEmpty() && last.all { it in '0'..'9' }) { - Log.d("TAG", "only nums $last") - } else { - Log.d("TAG", "not only nums $last") - paths.removeAt(paths.size - 1) - } - } - workingUrl = paths.joinToString("/") - return workingUrl - } - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - Blog.LOGD(log = "onCreate ${this::class.java.name} >> savedInstanceState ${savedInstanceState}") - binding = BooktokiBinding.inflate(inflater) - binding.menuWeb.let { - it.visibility = View.VISIBLE - it.lastDomain = getLastedDoamin() - it.setOnLongClickListener { - onTouch(TouchArea.Center) - return@setOnLongClickListener false - } - it.setOnGenericMotionListener(mOnGenericMotionListener) - it.onPageStopCallback = { success -> - if (success && mPort != null) { - if (mPort != null) { - if (lastedUrl?.contains("youtube.com") == true) { - - } else { - binding.menuWeb.postDelayed({ - - Blog.LOGE("onPageStop $success from WebExtension ${mPort!!.name}") - val message: JSONObject = JSONObject() - try { - message.put("type", "getList") - message.put("event", "sadsadds") -// message.put("tab", session.settings.screenId) - } catch (ex: JSONException) { - throw RuntimeException(ex) - } - - mPort!!.postMessage(message) - - - when (this@BaseToki) { - is Comics, is Webtoons -> { - lastInfo - } - - else -> { - - } - } - binding.progress.visibility = GONE - }, 10L) - } - } - } - } - it.onPageStartCallback = { url -> - binding.progress.visibility = VISIBLE - } - it.onSessionStateChangeCallback = { sessionState -> - when (this@BaseToki) { - is Comics, is Webtoons -> { - onStateChange(sessionState) - } - - else -> { - - } - } - } - - it.onPortMessageCallback = { lPortMessage -> - try { - when (lPortMessage.type) { - "getListResult" -> { - lPortMessage.bookInfos?.let { onBookInfos(it.sort()) } - } - - "BookContents" -> { - lPortMessage?.book?.chapterTitle?.let { onFindTitle(it) } - lPortMessage?.book?.bookContents?.let { onLoadedContents(it) } - } - - "NotRegistered" -> { - binding.pagedLayer.visibility = GONE - } - - "WebtoonContents" -> { - binding.pagedLayer.visibility = GONE - } - - "MSG" -> { - lPortMessage.msg?.let { - Toast.makeText( - requireContext(), - it, - Toast.LENGTH_SHORT - ).show() - } - } - - "SHOWVIEWER" -> { - binding.progress.visibility = GONE - } - - "PRIVATES" -> { - lPortMessage.privates?.let { - requireContext().toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}") - WorkersDb.insertBulkData(it) - } - } - - else -> { - - } - } - binding.progress.visibility = GONE - } catch (e: Exception) { - e.printStackTrace() - } - } - it.onLocationChangeCallback = { url -> - if (url?.startsWith("about") ?: true) { - - } else { - // url이 현재 로드된 주소입니다. - Blog.LOGE("GeckoView", "현재 주소: $url") - Blog.LOGE("GeckoView", "현재 session: ${binding.menuWeb.session}") - url?.let { url -> - if (url.split("//").size > 1) { - url.replace("//", "/").replace("https:/", "https://").let { - Blog.LOGE("url >> ${url} , it >>> ${it}") - lastedUrl = url - } - } else { - lastedUrl = url - } -// binding.menuWeb.checkIfDownloadable(url) -// binding.menuWeb.decoViews.filter { it != null && it.id > -1 }.forEach { -// if (it != null && it.id > -1) { -// if (it.id == R.id.back) { -// it.setOnClickListener { binding.menuWeb.session?.goBack() } -// } else if (it.id == R.id.current_address) { -// (it as? TextView)?.let { -// it.tag = currentTitle -// it.text = url +//package bums.lunatic.launcher.home.tokiz +// +//import android.content.DialogInterface +//import android.content.Intent +//import android.content.res.Configuration +//import android.net.Uri +//import android.os.Bundle +//import android.os.Handler +//import android.os.Looper +//import android.os.Message +//import android.text.InputType +//import android.text.SpannableStringBuilder +//import android.text.style.RelativeSizeSpan +//import android.util.Log +//import android.view.LayoutInflater +//import android.view.MotionEvent +//import android.view.PointerIcon +//import android.view.View +//import android.view.View.GONE +//import android.view.View.OnTouchListener +//import android.view.View.VISIBLE +//import android.view.View.inflate +//import android.view.ViewGroup +//import android.widget.ArrayAdapter +//import android.widget.EditText +//import android.widget.ImageButton +//import android.widget.TextView +//import android.widget.Toast +//import androidx.appcompat.app.AlertDialog +//import androidx.core.net.toUri +//import androidx.core.view.isVisible +//import androidx.fragment.app.Fragment +//import bums.lunatic.launcher.R +//import bums.lunatic.launcher.databinding.BooktokiBinding +//import bums.lunatic.launcher.home.GeckoWeb +//import bums.lunatic.launcher.home.GeckoWeb.JxEvent +//import bums.lunatic.launcher.home.NeoRssActivity +//import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime +//import bums.lunatic.launcher.home.toast +//import bums.lunatic.launcher.home.tokiz.view.PagedTextLayout +//import bums.lunatic.launcher.home.tokiz.view.PagedTextViewInterface +//import bums.lunatic.launcher.utils.Blog +//import bums.lunatic.launcher.workers.WorkersDb +//import com.google.gson.Gson +//import io.realm.kotlin.Realm +//import io.realm.kotlin.UpdatePolicy +//import io.realm.kotlin.ext.copyFromRealm +//import io.realm.kotlin.ext.query +//import org.json.JSONException +//import org.json.JSONObject +//import org.mozilla.gecko.util.ThreadUtils +//import org.mozilla.geckoview.GeckoResult +//import org.mozilla.geckoview.GeckoSession +//import org.mozilla.geckoview.GeckoSessionSettings +//import org.mozilla.geckoview.MediaSession +//import org.mozilla.geckoview.WebExtension +//import org.mozilla.geckoview.WebExtension.MessageDelegate +//import org.mozilla.geckoview.WebExtension.PortDelegate +//import org.mozilla.geckoview.WebExtensionController.AddonManagerDelegate +//import org.mozilla.geckoview.WebRequestError +//import java.lang.System.currentTimeMillis +//import java.net.URL +//import java.text.SimpleDateFormat +//import java.util.Date +//import kotlin.random.Random +// +// +//abstract class BaseToki : Fragment(), PagedTextViewInterface { +// fun openRealm(): Realm = HistoryManager.openRealm +// var lastInfo: LastInfo? = null +// var currentPage: ContentsPageInfo? = null +// var saveContinuation = false +// open var isPrivateMode = false +// val handle = object : Handler(Looper.getMainLooper()) { +// override fun handleMessage(msg: Message) { +// if (msg.what == 0) { +// (msg.obj as? ReaderConfig)?.let { +// } +// } +// } +// } +// +// +// override fun onConfigurationChanged(newConfig: Configuration) { +// super.onConfigurationChanged(newConfig) +// Blog.LOGD(log = "onConfigurationChanged ${this::class.java.name} >> newConfig ${newConfig}") +// } +// +// var lastedUrl: String? = null +// var canGoBack: Boolean? = null +// protected lateinit var binding: BooktokiBinding +// +// var mPort: WebExtension.Port? = null +// val mPortNam = "browser" +// val extPath = "resource://android/assets/extensions/my_extension/" +// val extId = "messaging@booktoki468.com" +// var mExtension: WebExtension? = null +// abstract val contentsType: String +// abstract var lastNumber: Int +// abstract val webcontentsName: String +// abstract val afterDot: String +// open fun getLastedDoamin(): String { +// return String.format("https://%s%d.%s", webcontentsName, lastNumber, afterDot) +// } +// +// val OnTouchListener = object : OnTouchListener { +// +// override fun onTouch(v: View?, event: MotionEvent): Boolean { +// when (event.getAction()) { +// MotionEvent.ACTION_DOWN -> { +// handle.removeCallbacks(mActionUp) +// handle.removeCallbacks(mActionDown) +// if (!binding.pagedLayer.isVisible) { +// +// } +// } +// +// MotionEvent.ACTION_UP -> { +// handle.removeCallbacks(mActionUp) +// handle.removeCallbacks(mActionDown) +// } +// } +// return false +// } +// +// var mActionDown: Runnable = object : Runnable { +// override fun run() { +// sendScrollDown(false) +// handle.postDelayed(this, 150) +// } +// } +// var mActionUp: Runnable = object : Runnable { +// override fun run() { +// sendScrollDown(true) +// handle.postDelayed(this, 150) +// } +// } +// } +// +// +// var mOnGenericMotionListener = object : View.OnGenericMotionListener { +// override fun onGenericMotion( +// v: View?, +// event: MotionEvent? +// ): Boolean { +// Blog.LOGE("event >>>> $event") +// return true +// } +// } +// +// val addonManagerDelegate = object : AddonManagerDelegate { +// override fun onReady(extension: WebExtension) { +// Blog.LOGE("onReady ${extension.id} from WebExtension") +// mExtension = extension +// +// } +// +// override fun onEnabling(extension: WebExtension) { +// Blog.LOGE("onEnabling ${extension.id} from WebExtension") +// } +// +// override fun onEnabled(extension: WebExtension) { +// Blog.LOGE("onEnabled ${extension.id} from WebExtension") +//// extension?.setMessageDelegate(messageDelegate, mPortNam) +// mExtension = extension +// +// } +// } +// +// private fun aceptUrl(string: String): Boolean { +// Blog.LOGE( +// "string >>> ${string}, domain >>> ${getLastedDoamin()} :: isAcept ${ +// string.contains( +// getLastedDoamin() +// ) +// }" +// ) +// return string.contains(getLastedDoamin()) +// } +// +// fun processPageUrl(pageUrl: String): String { +// if (pageUrl != null && pageUrl.isNotEmpty() && pageUrl.startsWith("http")) { +// var workingUrl = pageUrl +// val paths = workingUrl.split("/").toMutableList() +// if (paths.isNotEmpty()) { +// val last = paths.last() +// if (last.isNotEmpty() && last.all { it in '0'..'9' }) { +// Log.d("TAG", "only nums $last") +// } else { +// Log.d("TAG", "not only nums $last") +// paths.removeAt(paths.size - 1) +// } +// } +// workingUrl = paths.joinToString("/") +// // URL이 정상적으로 파싱되는지 확인(try-catch 권장) +// val path = try { +// URL(workingUrl).path +// } catch (e: Exception) { +// Log.d("TAG", "Invalid URL: $workingUrl") +// return pageUrl +// } +// return path +// } else { +// var workingUrl = pageUrl +// val paths = workingUrl.split("/").toMutableList() +// if (paths.isNotEmpty()) { +// val last = paths.last() +// if (last.isNotEmpty() && last.all { it in '0'..'9' }) { +// Log.d("TAG", "only nums $last") +// } else { +// Log.d("TAG", "not only nums $last") +// paths.removeAt(paths.size - 1) +// } +// } +// workingUrl = paths.joinToString("/") +// return workingUrl +// } +// } +// +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// Blog.LOGD(log = "onCreate ${this::class.java.name} >> savedInstanceState ${savedInstanceState}") +// binding = BooktokiBinding.inflate(inflater) +// binding.menuWeb.let { +// it.visibility = View.VISIBLE +// it.lastDomain = getLastedDoamin() +// it.setOnLongClickListener { +// onTouch(TouchArea.Center) +// return@setOnLongClickListener false +// } +// it.setOnGenericMotionListener(mOnGenericMotionListener) +// it.onPageStopCallback = { success -> +// if (success && mPort != null) { +// if (mPort != null) { +// if (lastedUrl?.contains("youtube.com") == true) { +// +// } else { +// binding.menuWeb.postDelayed({ +// +// Blog.LOGE("onPageStop $success from WebExtension ${mPort!!.name}") +// val message: JSONObject = JSONObject() +// try { +// message.put("type", "getList") +// message.put("event", "sadsadds") +//// message.put("tab", session.settings.screenId) +// } catch (ex: JSONException) { +// throw RuntimeException(ex) +// } +// +// mPort!!.postMessage(message) +// +// +// when (this@BaseToki) { +// is Comics, is Webtoons -> { +// lastInfo +// } +// +// else -> { +// +// } +// } +// binding.progress.visibility = GONE +// }, 10L) +// } +// } +// } +// } +// it.onPageStartCallback = { url -> +// binding.progress.visibility = VISIBLE +// } +// it.onSessionStateChangeCallback = { sessionState -> +// when (this@BaseToki) { +// is Comics, is Webtoons -> { +// onStateChange(sessionState) +// } +// +// else -> { +// +// } +// } +// } +// +// it.onPortMessageCallback = { lPortMessage -> +// try { +// when (lPortMessage.type) { +// "getListResult" -> { +// lPortMessage.bookInfos?.let { onBookInfos(it.sort()) } +// } +// +// "BookContents" -> { +// lPortMessage?.book?.chapterTitle?.let { onFindTitle(it) } +// lPortMessage?.book?.bookContents?.let { onLoadedContents(it) } +// } +// +// "NotRegistered" -> { +// binding.pagedLayer.visibility = GONE +// } +// +// "WebtoonContents" -> { +// binding.pagedLayer.visibility = GONE +// } +// +// "MSG" -> { +// lPortMessage.msg?.let { +// Toast.makeText( +// requireContext(), +// it, +// Toast.LENGTH_SHORT +// ).show() +// } +// } +// +// "SHOWVIEWER" -> { +// binding.progress.visibility = GONE +// } +// +// "PRIVATES" -> { +// lPortMessage.privates?.let { +// requireContext().toast("Received Msg privates form ${lPortMessage.currentPage} data => ${it?.size ?: 0}") +// WorkersDb.insertBulkData(it) +// } +// } +// +// else -> { +// +// } +// } +// binding.progress.visibility = GONE +// } catch (e: Exception) { +// e.printStackTrace() +// } +// } +// it.onLocationChangeCallback = { url -> +// if (url?.startsWith("about") ?: true) { +// +// } else { +// // url이 현재 로드된 주소입니다. +// Blog.LOGE("GeckoView", "현재 주소: $url") +// Blog.LOGE("GeckoView", "현재 session: ${binding.menuWeb.session}") +// url?.let { url -> +// if (url.split("//").size > 1) { +// url.replace("//", "/").replace("https:/", "https://").let { +// Blog.LOGE("url >> ${url} , it >>> ${it}") +// lastedUrl = url +// } +// } else { +// lastedUrl = url +// } +//// binding.menuWeb.checkIfDownloadable(url) +//// binding.menuWeb.decoViews.filter { it != null && it.id > -1 }.forEach { +//// if (it != null && it.id > -1) { +//// if (it.id == R.id.back) { +//// it.setOnClickListener { binding.menuWeb.session?.goBack() } +//// } else if (it.id == R.id.current_address) { +//// (it as? TextView)?.let { +//// it.tag = currentTitle +//// it.text = url +//// } +//// }else if (it.id == R.id.reload) { +//// it.setOnClickListener { binding.menuWeb.session?.reload() } +//// } +//// } +//// } +// } +// completePageLoad(LastInfo().apply { +// this.pageUrl = url?.toUri()?.path ?: getLastedDoamin() ?: "" +// this.contentsName = webcontentsName ?: "" +// this.contentsType = if (url?.contains("book", true) == true) { +// "book" +// } else if (url?.contains("new", true) == true) { +// "webtoon" +// } else if (url?.contains("mana", true) == true) { +// "comics" +// } else "web" +// this.pageIndex = 0 +// }) +// } +// } +// it.jxInteface = { jxEvent -> +// when (jxEvent) { +// JxEvent.SCROLL_UP -> sendScrollDown(true) +// JxEvent.SCROLL_DOWN -> sendScrollDown(false) +// JxEvent.SWIPE_LEFT -> if (contentsType == "comics") sendViewerTouch("left") else actionNextEvent() +// JxEvent.SWIPE_RIGHT -> if (contentsType == "comics") sendViewerTouch("right") else actionPrevEvent() +// else -> {} +// } +// } +// (activity as? NeoRssActivity)?.let { activity -> +// it.decoViews.clear() +// it.decoViews.add(activity.findViewById(R.id.current_address)) +// it.decoViews.add(activity.findViewById(R.id.back)) +// it.decoViews.add(activity.findViewById(R.id.reload)) +// it.decoViews.add(activity.findViewById(R.id.dl_video)) +// } +// } +// +// binding.btnList.setOnClickListener { v -> +// lastedUrl?.let { +// Uri.parse(it).path?.let { +// HistoryManager.getBookInfos(contentsType, processPageUrl(it), { +// it?.let { +// it.pages.sortBy { it.pathUrl } +// Blog.LOGE("bind ing.btnList it >>> $it") +// showList(it) +// } +// }) +// } +// } +// } +// +// +// binding.btnSetting.setOnClickListener { v -> +// activity?.startActivity(Intent(requireContext(), Settings::class.java)) +// } +// binding.btnHistory.setOnClickListener { v -> +// getHistory()?.let { +// showHistory(it) +// } +// } +// +// binding.btnHome.setOnClickListener { v -> +// binding.pagedLayer.visibility = GONE +// goToHome() +// } +// +// val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL) +// binding.root.setPointerIcon(nullCursor) +// return binding.root +// } +// +// +// private fun getHistory(): List? { +// try { +// var realm = openRealm() +// return realm.query().query("contentsType == $0", contentsType).find() +// ?.copyFromRealm()?.reversed() +// } catch (e: Exception) { +// e.printStackTrace() +// } +// return null +// } +// +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL) +// binding.root.setPointerIcon(nullCursor) +// loadLastInfo() +// } +// +// fun getLastinfo(): LastInfo? { +// lastInfo = openRealm().query("contentsType == $0", contentsType).find().last() +// ?.copyFromRealm() +// Blog.LOGE("lastInfo >>> ${Gson().toJson(lastInfo)}") +// return lastInfo +// } +// +// fun loadLastInfo() { +// var targetUrl = getLastedDoamin() +// try { +// applyReaderConfig() +// getLastinfo()?.let { lastInfo -> +// Blog.LOGE("lastInfo >>> ${lastInfo} path ::> ${lastInfo.pageUrl}") +// HistoryManager.getBookPageInfo(contentsType, lastInfo.pageUrl) { +// it?.let { +// currentPage = it +// Blog.LOGE("currentBooinfo :: ${currentPage} ${currentPage?.pathUrl}") +// if ((currentPage?.pathUrl?.length ?: 0) > 1) { +// HistoryManager.save( +// historyItem = HistoryItem().putHistory( +// currentPage, +// currentPage?.pathUrl ?: getLastedDoamin() +// ) +// ) +// currentPage?.pathUrl?.let { targetPath -> +// if (targetPath.startsWith("http", true)) { +// targetUrl = targetPath +// } else { +// targetUrl = getLastedDoamin() + targetPath // } -// }else if (it.id == R.id.reload) { -// it.setOnClickListener { binding.menuWeb.session?.reload() } // } // } // } - } - completePageLoad(LastInfo().apply { - this.pageUrl = url?.toUri()?.path ?: getLastedDoamin() ?: "" - this.contentsName = webcontentsName ?: "" - this.contentsType = if (url?.contains("book", true) == true) { - "book" - } else if (url?.contains("new", true) == true) { - "webtoon" - } else if (url?.contains("mana", true) == true) { - "comics" - } else "web" - this.pageIndex = 0 - }) - } - } - it.jxInteface = { jxEvent -> - when (jxEvent) { - JxEvent.SCROLL_UP -> sendScrollDown(true) - JxEvent.SCROLL_DOWN -> sendScrollDown(false) - JxEvent.SWIPE_LEFT -> if (contentsType == "comics") sendViewerTouch("left") else actionNextEvent() - JxEvent.SWIPE_RIGHT -> if (contentsType == "comics") sendViewerTouch("right") else actionPrevEvent() - else -> {} - } - } - (activity as? NeoRssActivity)?.let { activity -> - it.decoViews.clear() - it.decoViews.add(activity.findViewById(R.id.current_address)) - it.decoViews.add(activity.findViewById(R.id.back)) - it.decoViews.add(activity.findViewById(R.id.reload)) - it.decoViews.add(activity.findViewById(R.id.dl_video)) - } - } - - binding.btnList.setOnClickListener { v -> - lastedUrl?.let { - Uri.parse(it).path?.let { - HistoryManager.getBookInfos(contentsType, processPageUrl(it), { - it?.let { - it.pages.sortBy { it.pathUrl } - Blog.LOGE("bind ing.btnList it >>> $it") - showList(it) - } - }) - } - } - } - - - binding.btnSetting.setOnClickListener { v -> - activity?.startActivity(Intent(requireContext(), Settings::class.java)) - } - binding.btnHistory.setOnClickListener { v -> - getHistory()?.let { - showHistory(it) - } - } - - binding.btnHome.setOnClickListener { v -> - binding.pagedLayer.visibility = GONE - goToHome() - } - - val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL) - binding.root.setPointerIcon(nullCursor) - return binding.root - } - - - private fun getHistory(): List? { - try { - var realm = openRealm() - return realm.query().query("contentsType == $0", contentsType).find() - ?.copyFromRealm()?.reversed() - } catch (e: Exception) { - e.printStackTrace() - } - return null - } - - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - val nullCursor = PointerIcon.getSystemIcon(requireContext(), PointerIcon.TYPE_NULL) - binding.root.setPointerIcon(nullCursor) - loadLastInfo() - } - - fun getLastinfo(): LastInfo? { - lastInfo = openRealm().query("contentsType == $0", contentsType).find().last() - ?.copyFromRealm() - Blog.LOGE("lastInfo >>> ${Gson().toJson(lastInfo)}") - return lastInfo - } - - fun loadLastInfo() { - var targetUrl = getLastedDoamin() - try { - applyReaderConfig() - getLastinfo()?.let { lastInfo -> - Blog.LOGE("lastInfo >>> ${lastInfo} path ::> ${lastInfo.pageUrl}") - HistoryManager.getBookPageInfo(contentsType, lastInfo.pageUrl) { - it?.let { - currentPage = it - Blog.LOGE("currentBooinfo :: ${currentPage} ${currentPage?.pathUrl}") - if ((currentPage?.pathUrl?.length ?: 0) > 1) { - HistoryManager.save( - historyItem = HistoryItem().putHistory( - currentPage, - currentPage?.pathUrl ?: getLastedDoamin() - ) - ) - currentPage?.pathUrl?.let { targetPath -> - if (targetPath.startsWith("http", true)) { - targetUrl = targetPath - } else { - targetUrl = getLastedDoamin() + targetPath - } - } - } - } - } - } ?: Blog.LOGE("lastInfo is Null") - } catch (e1: Exception) { - - } finally { - if ((lastedUrl?.contains(targetUrl) == true)) { - - } else { - contentsLoad(targetUrl) - } - } - } - - - fun onBookInfos(aInfos: ContentsCollection) { - Blog.LOGE("onBookInfos(aInfos: ${aInfos})") - activity?.runOnUiThread { - showList(aInfos) - } - } - - - fun onBookInfos(jsonString: String) { - Blog.LOGE("onBookInfos", "jsonString >> ${jsonString}") - val realm = openRealm() - var infos: ContentsCollection? = null - realm.writeBlocking { - try { - var infosj: PageInfosJ? = null - infosj = Gson().fromJson(jsonString, PageInfosJ::class.java) - - HistoryManager.getBookInfos(contentsType, infosj.bookPageUrl!!) { - if (it != null) { - - infos = copyToRealm(it!!, UpdatePolicy.ALL) - for (item in infosj.pages) { - if (infos!!.hasItem(item.getRealm()) == false) { - infos!!.pages.add(item.getRealm()) - } - } - if (infos != null) { - infos = this.copyFromRealm(infos!!) - } - } else { - infos = infosj?.getR() - if (infos != null) { - infos = copyToRealm(infos!!, UpdatePolicy.ALL) - for (item in infosj.pages) { - infos?.pages?.add(item.getRealm()) - } - } - if (infos != null) { - infos = this.copyFromRealm(infos!!) - } - } - } - - } catch (e: Exception) { - e.printStackTrace() - } finally { - infos?.bookPageUrl?.let { - HistoryManager.getBookInfos(contentsType, it) { - it?.let { - Blog.LOGE(s(), "onBookInfos it >> ${it}") - activity?.runOnUiThread { showList(it) } - } - } - } - } - } - } - - fun onBookInfos(infosj: PageInfosJ) { - Blog.LOGE("onBookInfos", "jsonString >> ${infosj}") - val realm = openRealm() - var infos: ContentsCollection? = null - realm.writeBlocking { - try { - infosj.bookPageUrl?.let { - infosj.bookPageUrl = processPageUrl(it) - } - infosj.pages?.forEach { item -> - item.pathUrl?.let { - item.pathUrl?.let { - item.pathUrl = processPageUrl(it) - } - item.bookPageUrl?.let { - item.bookPageUrl = processPageUrl(it) - } - } - } - HistoryManager.getBookInfos(contentsType, processPageUrl(infosj.bookPageUrl!!)) { - if (it != null) { - - infos = copyToRealm(it!!, UpdatePolicy.ALL) - - for (item in infosj.pages) { - if (infos!!.hasItem(item.getRealm()) == false) { - infos!!.pages.add(item.getRealm()) - } - } - if (infos != null) { - infos = this.copyFromRealm(infos!!) - } - } else { - infos = infosj?.getR() - if (infos != null) { - infos = copyToRealm(infos!!, UpdatePolicy.ALL) - for (item in infosj.pages) { - infos?.pages?.add(item.getRealm()) - } - } - if (infos != null) { - infos = this.copyFromRealm(infos!!) - } - } - } - - } catch (e: Exception) { - e.printStackTrace() - } finally { - infos?.bookPageUrl?.let { - HistoryManager.getBookInfos(contentsType, it) { - it?.let { - Blog.LOGE(s(), "onBookInfos it >> ${it}") - activity?.runOnUiThread { showList(it) } - } - } - } - } - } - } - - private fun s() = "onBookInfos" - - - fun showHistory(infos: List) { - - val builderSingle: AlertDialog.Builder = AlertDialog.Builder(requireContext()) - builderSingle.setTitle("${currentTitle} : ${currentChapter} -> Select One ") - val arrayAdapter = - ArrayAdapter(requireContext(), android.R.layout.select_dialog_singlechoice) - for (item in infos) { - arrayAdapter.addAll(item.title) - } - - builderSingle.setNegativeButton( - "cancel", - DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() }) - - builderSingle.setAdapter( - arrayAdapter, - DialogInterface.OnClickListener { dialog, which -> - val strName = arrayAdapter.getItem(which) - val item = infos.get(which) - val builderInner: AlertDialog.Builder = AlertDialog.Builder(requireContext()) - builderInner.setMessage(strName) - builderInner.setTitle("${infos.get(which).title}로 이동 고고!?") - builderInner.setPositiveButton( - "Ok", - DialogInterface.OnClickListener { dialog, which -> - contentsLoad(item.pageUrl) - dialog.dismiss() - }) - builderInner.setNeutralButton( - "삭제", - DialogInterface.OnClickListener { dialog, which -> - var realm = openRealm() - realm?.writeBlocking { - this.query().query("title == '${item.title}'").find() - ?.last()?.let { - this.delete(it) - } - } - dialog.dismiss() - }) - builderInner.setNegativeButton( - "취소", - DialogInterface.OnClickListener { dialog, which -> - dialog.dismiss() - }) - builderInner.show() - }) - var ddddd = builderSingle.create() - ddddd.setOnShowListener { d -> - (d as? AlertDialog)?.let { - it.listView?.setSelection(currentChapter) - } - } - - ddddd.show() - } - - fun showList(infos: ContentsCollection) { - Blog.LOGE("showList infos >>>>${infos}") - if (infos != null && infos.pages.size ?: 0 > 0) { - var items: ArrayList = arrayListOf() - for (item in infos.pages) { - items.add(item) - } - - items.sortBy { it.chapterID } - - DefaultList.showDefaultList( - requireContext(), - "현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라", - items, - currentChapter, - { position -> - return@showDefaultList items?.get(position)?.chapterTitle ?: "" - }, - { position -> - items?.get(position)?.let { moveTo(it) } - }, { state -> - if (state < 0) { - saveContinuation = true - moveToNext(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) - } - }) - } - } - - val String.cleanTextContent: String - get() { - // strips off all non-ASCII characters - var text = this - text = text.replace("[^\\x00-\\x7F]".toRegex(), "") - - // erases all the ASCII control characters - text = text.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "") - - // removes non-printable characters from Unicode - text = text.replace("\\p{C}".toRegex(), "") - return text.trim() - } - - - fun showToast(origin: String) { - activity?.runOnUiThread { - val toast = Toast(requireContext()) - toast.duration = Toast.LENGTH_SHORT - val biggerText = SpannableStringBuilder(origin) - biggerText.setSpan(RelativeSizeSpan(1.6f), 0, origin.length, 0) - val view: View = inflate(requireContext(), R.layout.simple_toast, null) - view.findViewById(R.id.text).text = biggerText - toast.view = view - toast.show() -// Toast.makeText( -// baseContext, -// biggerText, -// Toast.LENGTH_SHORT -// ).show() - } - } - - var delayed = 3500L + Math.abs(Random.nextLong().rem(9999L)) - var finishedUrl: String? = null - - private fun moveTo(item: ContentsPageInfo?) { - Blog.LOGE("item >>> ${item}") - item?.pathUrl?.let { newPath -> - contentsLoad(newPath) - } - } - - - fun moveToNext(pathUrl: String?) { - if (pathUrl != null && pathUrl.length > 6) { - HistoryManager.getNextPage(contentsType, pathUrl) { - if (it != null && (it.pathUrl?.length ?: 0) > 6) { - moveTo(it) - } else { - showToast("다음 편이 없다요.") - } - } - } - } - - fun moveToPrev(pathUrl: String?) { - if (pathUrl != null && pathUrl.length > 6) { - HistoryManager.getPrevPage(contentsType, pathUrl) { - if (it != null && (it.pathUrl?.length ?: 0) > 6) { - moveTo(it) - } else { - showToast("이전 편이 없다요.") - } - } - } - } - - fun contentsLoad(pathUrl: String) { - fun applyCurrentBook(contentsPageInfo: ContentsPageInfo) { - applyReaderConfig() - contentsPageInfo.contents?.let { onLoadedContents(it) } - contentsPageInfo.chapterTitle?.let { onFindTitle(it) } - if (contentsPageInfo.pathUrl?.startsWith("http") == true) { - binding.menuWeb.loadUrl(pathUrl) - } else { - binding.menuWeb.loadUrl(getLastedDoamin() + contentsPageInfo.pathUrl!!) - } - HistoryManager.save( - HistoryItem().putHistory( - contentsPageInfo, - contentsPageInfo.pathUrl!! - ) - ) - } - - if (currentPage?.pathUrl.equals(pathUrl)) { - applyCurrentBook(currentPage!!) - } else { - HistoryManager.getBookPageInfo(contentsType, pathUrl) { - Blog.LOGE("contentsLoad :::: pathUrl >> ${pathUrl} , book >> ${it}") - if (it != null && it.isValidBook()) { - currentPage = it - applyCurrentBook(it) - } else if (lastInfo != null) { - binding.pagedLayer.visibility = GONE - binding.menuWeb.loadUrl(getLastedDoamin() + lastInfo!!.pageUrl) - } else { - binding.menuWeb.loadUrl(getLastedDoamin()) - } - } - } - } - - - fun actionNextEvent(fast: Boolean = false) { - if (binding.pagedLayer.isVisible && binding.pagedLayer.size() > 0 && (binding.pagedLayer.current() < binding.pagedLayer!!.size() - 1)) { - binding.pagedLayer.doNext(fast) - updateLastInfo(binding.pagedLayer!!) - } else { - moveToNext(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) - } - } - - fun applyReaderConfig() { - var realm = HistoryManager.openRealm - realm.query().find().let { - if (it.isNotEmpty()) { - realm.copyFromRealm(it.first()).let { - activity?.runOnUiThread { - var typeface = - typesfacez.get(getIndex(typesfacez as PairArray, it.font ?: "")) - binding.pagedLayer.setTypeface(resources.getFont(typeface.second)) - val color = colorz.get(it.style ?: 0) - binding.pagedLayer.setColorStyle(color.second) - binding.pagedLayer.setTextSize(it.textSize?.toFloat() ?: 14f) - binding.pagedLayer.setLineSpacing(it.lineSpace?.toFloat() ?: 1f) - binding.pagedLayer.setLetterSpacing(it.letterSpace?.toFloat() ?: 1f) - binding.pagedLayer.setPadding( - it.padding ?: 1, - it.padding ?: 1, - it.padding ?: 1, - it.padding ?: 1 - ) - binding.pagedLayer.invalidate() - } - } - } - } - } - - fun actionPrevEvent(fast: Boolean = false) { - if (binding.pagedLayer.isVisible && binding.pagedLayer.size() > 0 && binding.pagedLayer.current() > 0) { - binding.pagedLayer.doPrev(fast) - updateLastInfo(binding.pagedLayer) - } else { - moveToPrev(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) - } - } +// } +// } ?: Blog.LOGE("lastInfo is Null") +// } catch (e1: Exception) { // -// override fun onBackPressed() { +// } finally { +// if ((lastedUrl?.contains(targetUrl) == true)) { +// +// } else { +// contentsLoad(targetUrl) +// } +// } +// } // // +// fun onBookInfos(aInfos: ContentsCollection) { +// Blog.LOGE("onBookInfos(aInfos: ${aInfos})") +// activity?.runOnUiThread { +// showList(aInfos) +// } +// } // -// if (binding.pagedLayer.isVisible) { -// didBackPress = false -// binding.pagedLayer.visibility = GONE -// onTouch(TouchArea.Center) -// return +// +// fun onBookInfos(jsonString: String) { +// Blog.LOGE("onBookInfos", "jsonString >> ${jsonString}") +// val realm = openRealm() +// var infos: ContentsCollection? = null +// realm.writeBlocking { +// try { +// var infosj: PageInfosJ? = null +// infosj = Gson().fromJson(jsonString, PageInfosJ::class.java) +// +// HistoryManager.getBookInfos(contentsType, infosj.bookPageUrl!!) { +// if (it != null) { +// +// infos = copyToRealm(it!!, UpdatePolicy.ALL) +// for (item in infosj.pages) { +// if (infos!!.hasItem(item.getRealm()) == false) { +// infos!!.pages.add(item.getRealm()) +// } +// } +// if (infos != null) { +// infos = this.copyFromRealm(infos!!) +// } +// } else { +// infos = infosj?.getR() +// if (infos != null) { +// infos = copyToRealm(infos!!, UpdatePolicy.ALL) +// for (item in infosj.pages) { +// infos?.pages?.add(item.getRealm()) +// } +// } +// if (infos != null) { +// infos = this.copyFromRealm(infos!!) +// } +// } +// } +// +// } catch (e: Exception) { +// e.printStackTrace() +// } finally { +// infos?.bookPageUrl?.let { +// HistoryManager.getBookInfos(contentsType, it) { +// it?.let { +// Blog.LOGE(s(), "onBookInfos it >> ${it}") +// activity?.runOnUiThread { showList(it) } +// } +// } +// } +// } +// } +// } +// +// fun onBookInfos(infosj: PageInfosJ) { +// Blog.LOGE("onBookInfos", "jsonString >> ${infosj}") +// val realm = openRealm() +// var infos: ContentsCollection? = null +// realm.writeBlocking { +// try { +// infosj.bookPageUrl?.let { +// infosj.bookPageUrl = processPageUrl(it) +// } +// infosj.pages?.forEach { item -> +// item.pathUrl?.let { +// item.pathUrl?.let { +// item.pathUrl = processPageUrl(it) +// } +// item.bookPageUrl?.let { +// item.bookPageUrl = processPageUrl(it) +// } +// } +// } +// HistoryManager.getBookInfos(contentsType, processPageUrl(infosj.bookPageUrl!!)) { +// if (it != null) { +// +// infos = copyToRealm(it!!, UpdatePolicy.ALL) +// +// for (item in infosj.pages) { +// if (infos!!.hasItem(item.getRealm()) == false) { +// infos!!.pages.add(item.getRealm()) +// } +// } +// if (infos != null) { +// infos = this.copyFromRealm(infos!!) +// } +// } else { +// infos = infosj?.getR() +// if (infos != null) { +// infos = copyToRealm(infos!!, UpdatePolicy.ALL) +// for (item in infosj.pages) { +// infos?.pages?.add(item.getRealm()) +// } +// } +// if (infos != null) { +// infos = this.copyFromRealm(infos!!) +// } +// } +// } +// +// } catch (e: Exception) { +// e.printStackTrace() +// } finally { +// infos?.bookPageUrl?.let { +// HistoryManager.getBookInfos(contentsType, it) { +// it?.let { +// Blog.LOGE(s(), "onBookInfos it >> ${it}") +// activity?.runOnUiThread { showList(it) } +// } +// } +// } +// } +// } +// } +// +// private fun s() = "onBookInfos" +// +// +// fun showHistory(infos: List) { +// +// val builderSingle: AlertDialog.Builder = AlertDialog.Builder(requireContext()) +// builderSingle.setTitle("${currentTitle} : ${currentChapter} -> Select One ") +// val arrayAdapter = +// ArrayAdapter(requireContext(), android.R.layout.select_dialog_singlechoice) +// for (item in infos) { +// arrayAdapter.addAll(item.title) // } // -// if (canGoBack == true) { -// didBackPress = false -// canGoBack = false -// binding.menuWeb.session?.goBack() -// return +// builderSingle.setNegativeButton( +// "cancel", +// DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() }) +// +// builderSingle.setAdapter( +// arrayAdapter, +// DialogInterface.OnClickListener { dialog, which -> +// val strName = arrayAdapter.getItem(which) +// val item = infos.get(which) +// val builderInner: AlertDialog.Builder = AlertDialog.Builder(requireContext()) +// builderInner.setMessage(strName) +// builderInner.setTitle("${infos.get(which).title}로 이동 고고!?") +// builderInner.setPositiveButton( +// "Ok", +// DialogInterface.OnClickListener { dialog, which -> +// contentsLoad(item.pageUrl) +// dialog.dismiss() +// }) +// builderInner.setNeutralButton( +// "삭제", +// DialogInterface.OnClickListener { dialog, which -> +// var realm = openRealm() +// realm?.writeBlocking { +// this.query().query("title == '${item.title}'").find() +// ?.last()?.let { +// this.delete(it) +// } +// } +// dialog.dismiss() +// }) +// builderInner.setNegativeButton( +// "취소", +// DialogInterface.OnClickListener { dialog, which -> +// dialog.dismiss() +// }) +// builderInner.show() +// }) +// var ddddd = builderSingle.create() +// ddddd.setOnShowListener { d -> +// (d as? AlertDialog)?.let { +// it.listView?.setSelection(currentChapter) +// } // } // -// if (!didBackPress) { -// firstBackPress() -// return +// ddddd.show() +// } +// +// fun showList(infos: ContentsCollection) { +// Blog.LOGE("showList infos >>>>${infos}") +// if (infos != null && infos.pages.size ?: 0 > 0) { +// var items: ArrayList = arrayListOf() +// for (item in infos.pages) { +// items.add(item) +// } +// +// items.sortBy { it.chapterID } +// +// DefaultList.showDefaultList( +// requireContext(), +// "현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라", +// items, +// currentChapter, +// { position -> +// return@showDefaultList items?.get(position)?.chapterTitle ?: "" +// }, +// { position -> +// items?.get(position)?.let { moveTo(it) } +// }, { state -> +// if (state < 0) { +// saveContinuation = true +// moveToNext(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) +// } +// }) +// } +// } +// +// val String.cleanTextContent: String +// get() { +// // strips off all non-ASCII characters +// var text = this +// text = text.replace("[^\\x00-\\x7F]".toRegex(), "") +// +// // erases all the ASCII control characters +// text = text.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "") +// +// // removes non-printable characters from Unicode +// text = text.replace("\\p{C}".toRegex(), "") +// return text.trim() +// } +// +// +// fun showToast(origin: String) { +// activity?.runOnUiThread { +// val toast = Toast(requireContext()) +// toast.duration = Toast.LENGTH_SHORT +// val biggerText = SpannableStringBuilder(origin) +// biggerText.setSpan(RelativeSizeSpan(1.6f), 0, origin.length, 0) +// val view: View = inflate(requireContext(), R.layout.simple_toast, null) +// view.findViewById(R.id.text).text = biggerText +// toast.view = view +// toast.show() +//// Toast.makeText( +//// baseContext, +//// biggerText, +//// Toast.LENGTH_SHORT +//// ).show() +// } +// } +// +// var delayed = 3500L + Math.abs(Random.nextLong().rem(9999L)) +// var finishedUrl: String? = null +// +// private fun moveTo(item: ContentsPageInfo?) { +// Blog.LOGE("item >>> ${item}") +// item?.pathUrl?.let { newPath -> +// contentsLoad(newPath) +// } +// } +// +// +// fun moveToNext(pathUrl: String?) { +// if (pathUrl != null && pathUrl.length > 6) { +// HistoryManager.getNextPage(contentsType, pathUrl) { +// if (it != null && (it.pathUrl?.length ?: 0) > 6) { +// moveTo(it) +// } else { +// showToast("다음 편이 없다요.") +// } +// } +// } +// } +// +// fun moveToPrev(pathUrl: String?) { +// if (pathUrl != null && pathUrl.length > 6) { +// HistoryManager.getPrevPage(contentsType, pathUrl) { +// if (it != null && (it.pathUrl?.length ?: 0) > 6) { +// moveTo(it) +// } else { +// showToast("이전 편이 없다요.") +// } +// } +// } +// } +// +// fun contentsLoad(pathUrl: String) { +// fun applyCurrentBook(contentsPageInfo: ContentsPageInfo) { +// applyReaderConfig() +// contentsPageInfo.contents?.let { onLoadedContents(it) } +// contentsPageInfo.chapterTitle?.let { onFindTitle(it) } +// if (contentsPageInfo.pathUrl?.startsWith("http") == true) { +// binding.menuWeb.loadUrl(pathUrl) +// } else { +// binding.menuWeb.loadUrl(getLastedDoamin() + contentsPageInfo.pathUrl!!) +// } +// HistoryManager.save( +// HistoryItem().putHistory( +// contentsPageInfo, +// contentsPageInfo.pathUrl!! +// ) +// ) +// } +// +// if (currentPage?.pathUrl.equals(pathUrl)) { +// applyCurrentBook(currentPage!!) // } else { -// Activity.finishAffinity() -// didBackPress = false -// super.onBackPressed() +// HistoryManager.getBookPageInfo(contentsType, pathUrl) { +// Blog.LOGE("contentsLoad :::: pathUrl >> ${pathUrl} , book >> ${it}") +// if (it != null && it.isValidBook()) { +// currentPage = it +// applyCurrentBook(it) +// } else if (lastInfo != null) { +// binding.pagedLayer.visibility = GONE +// binding.menuWeb.loadUrl(getLastedDoamin() + lastInfo!!.pageUrl) +// } else { +// binding.menuWeb.loadUrl(getLastedDoamin()) +// } +// } // } // } - - - fun showAlert(alert: String) { - Log.i(TAG, "showAlert >> " + alert) - } - - - fun onStateChange(sessionState: GeckoSession.SessionState) { - - if (sessionState.last().uri.length > 10) { - lastedUrl?.let { - Uri.parse(it)?.let { uri -> - uri.path?.let { - HistoryManager.getBookPageInfo(contentsType, it) { - it?.let { - this@BaseToki.currentPage = it - currentChapter = it?.chapterNum ?: 0 - HistoryManager.save( - historyItem = HistoryItem().putHistory( - it, - lastedUrl!! - ) - ) - (currentPage?.pathUrl ?: lastedUrl?.toUri()?.path)?.let { - HistoryManager.setBookPageInfo( - contentsType, - it, - binding.pagedLayer.current() - ) - } - val realm = openRealm() - realm.writeBlocking { - var q = this.query("contentsType == $0", contentsType) - .find() - if (q.size > 0) { - q.last()?.let { - it.title = currentTitle - it.chapter = currentChapter - it.pageIndex = 0 - it.contentsType = currentPage!!.contentsType - this@BaseToki.lastInfo = copyFromRealm(it) - } - } else { - LastInfo()?.let { - it.title = currentTitle - it.chapter = currentChapter - it.pageIndex = 0 - it.contentsType = currentPage!!.contentsType - it._id = - if (lastedUrl?.contains("book", true) == true) { - "book" - } else if (lastedUrl?.contains( - "new", - true - ) == true - ) { - "webtoon" - } else if (lastedUrl?.contains( - "mana", - true - ) == true - ) { - "comics" - } else "web" - copyToRealm(it, UpdatePolicy.ALL) - this@BaseToki.lastInfo = it - } - } - } - - } - } - } - if (saveContinuation) { - binding.menuWeb.postDelayed({ - moveToNext( - currentPage?.pathUrl ?: lastedUrl?.toUri()?.path - ) - }, 10000) - } - } - } - } - } - - fun onLoadedContents(aContents: String) { - Blog.LOGE("onLoadedContents ") - binding.pagedLayer.let { view -> - view.post { - if (aContents.length > 10) { - var contents = aContents.replace("\\\"", "\"") - contents = (contents.replace("\\n", System.getProperty("line.separator"))) - view.mPagedTextViewInterface = this@BaseToki - if (lastInfo != null && lastedUrl?.endsWith(lastInfo!!.pageUrl) == true) { - binding.progress.visibility = VISIBLE - binding.pagedLayer.postDelayed({ - binding.progress.visibility = GONE - }, 1000) - } - applyReaderConfig() - activity?.runOnUiThread { - view.text = contents - view.visibility = VISIBLE - binding.menuWeb.visibility = GONE - } - view.forceUpdateUI() - lastedUrl?.let { - Uri.parse(it)?.let { uri -> - uri.path?.let { - HistoryManager.getBookPageInfo(contentsType, it) { - it?.let { - this@BaseToki.currentPage = it - currentChapter = it?.chapterNum ?: 0 - view.currentPage = it?.chapterNum ?: 0 - HistoryManager.save( - historyItem = HistoryItem().putHistory( - it, - lastedUrl!! - ) - ) - } - } - HistoryManager.getBooPageInfoContentsSave( - contentsType, - it, - contents - ) - } - if (saveContinuation) { - binding.menuWeb.postDelayed({ - moveToNext( - currentPage?.pathUrl ?: lastedUrl?.toUri()?.path - ) - }, 10000) - - } - } - } - } - - } - } -// Log.i(TAG, "onLoadedContents >> " + aContents) - } - - var currentTitle: String = "" - var currentChapter: Int = 0 - - fun onFindTitle(contents: String) { - binding.textviewTitle.text = contents - binding.textviewTitle.setOnClickListener { - val builder = AlertDialog.Builder(requireContext()) - builder.setTitle("Title") - val input = EditText(requireContext()) - input.setText(lastedUrl ?: "") - input.inputType = InputType.TYPE_CLASS_TEXT - builder.setView(input) - builder.setPositiveButton( - "OK" - ) { dialog, which -> - var m_Text = input.text.toString() - contentsLoad(m_Text.trim()) - } - builder.setNegativeButton( - "Cancel" - ) { dialog, which -> dialog.cancel() } - builder.show() - } - var testRegex = """[^0-9]""".toRegex() - Blog.LOGI(TAG, "onFindTitle >> " + contents + " ::: ${testRegex.replace(contents, "")}") - if (contents.contains("-")) { - currentTitle = contents.split("-")[0] - try { - currentChapter = testRegex.replace(contents.split("-")[1], "").toInt() - } catch (e: Exception) { - currentChapter = 0 - } - } else if (testRegex.replace(contents, "").length > 0) { - currentChapter = testRegex.replace(contents, "").toInt() - currentTitle = contents.split(testRegex.replace(contents, ""))[0] - } else { - val dateFormat = "yyyyMMdd-HH" - val date = Date(currentTimeMillis()) - val simpleDateFormat = SimpleDateFormat(dateFormat) - currentTitle = simpleDateFormat.format(date) - } - - } - - fun onStartLoad() { - binding.progress.visibility = VISIBLE - } - - fun completePageLoad(lastInfo: LastInfo) { - saveLastInfo(lastInfo) - } - -// override fun onTouchEvent(event: MotionEvent?): Boolean { -// return super.onTouchEvent(event) -// if (saveContinuation) { -// saveContinuation = false +// +// +// fun actionNextEvent(fast: Boolean = false) { +// if (binding.pagedLayer.isVisible && binding.pagedLayer.size() > 0 && (binding.pagedLayer.current() < binding.pagedLayer!!.size() - 1)) { +// binding.pagedLayer.doNext(fast) +// updateLastInfo(binding.pagedLayer!!) +// } else { +// moveToNext(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) // } // } - - fun saveLastInfo(lastInfo: LastInfo) { - val realm = openRealm() - if ((realm.query("contentsType == $0", contentsType)?.count()?.find() ?: 0) > 0) { - realm.writeBlocking { - this.query("contentsType == $0", contentsType)?.find()?.last()?.let { - it.pageUrl = lastInfo.pageUrl - it.title = currentTitle - it.chapter = currentChapter - it.pageIndex = lastInfo.pageIndex - it.contentsName = lastInfo.contentsName - it.displayOrientation = lastInfo.displayOrientation - it.contentsType = lastInfo.contentsType - this@BaseToki.lastInfo = copyFromRealm(it) - Blog.LOGE("lastInfo >>>> ${this@BaseToki.lastInfo}") - } - } - } else if ((lastInfo._id?.length ?: 0) > 3) { - realm.writeBlocking { - Blog.LOGE("lastInfo >>>> $lastInfo") - copyToRealm(lastInfo, UpdatePolicy.ALL) - } - } +// +// fun applyReaderConfig() { +// var realm = HistoryManager.openRealm +// realm.query().find().let { +// if (it.isNotEmpty()) { +// realm.copyFromRealm(it.first()).let { +// activity?.runOnUiThread { +// var typeface = +// typesfacez.get(getIndex(typesfacez as PairArray, it.font ?: "")) +// binding.pagedLayer.setTypeface(resources.getFont(typeface.second)) +// val color = colorz.get(it.style ?: 0) +// binding.pagedLayer.setColorStyle(color.second) +// binding.pagedLayer.setTextSize(it.textSize?.toFloat() ?: 14f) +// binding.pagedLayer.setLineSpacing(it.lineSpace?.toFloat() ?: 1f) +// binding.pagedLayer.setLetterSpacing(it.letterSpace?.toFloat() ?: 1f) +// binding.pagedLayer.setPadding( +// it.padding ?: 1, +// it.padding ?: 1, +// it.padding ?: 1, +// it.padding ?: 1 +// ) +// binding.pagedLayer.invalidate() +// } +// } +// } +// } +// } +// +// fun actionPrevEvent(fast: Boolean = false) { +// if (binding.pagedLayer.isVisible && binding.pagedLayer.size() > 0 && binding.pagedLayer.current() > 0) { +// binding.pagedLayer.doPrev(fast) +// updateLastInfo(binding.pagedLayer) +// } else { +// moveToPrev(currentPage?.pathUrl ?: lastedUrl?.toUri()?.path) +// } +// } +//// +//// override fun onBackPressed() { +//// +//// +//// +//// if (binding.pagedLayer.isVisible) { +//// didBackPress = false +//// binding.pagedLayer.visibility = GONE +//// onTouch(TouchArea.Center) +//// return +//// } +//// +//// if (canGoBack == true) { +//// didBackPress = false +//// canGoBack = false +//// binding.menuWeb.session?.goBack() +//// return +//// } +//// +//// if (!didBackPress) { +//// firstBackPress() +//// return +//// } else { +//// Activity.finishAffinity() +//// didBackPress = false +//// super.onBackPressed() +//// } +//// } +// +// +// fun showAlert(alert: String) { +// Log.i(TAG, "showAlert >> " + alert) +// } +// +// +// fun onStateChange(sessionState: GeckoSession.SessionState) { +// +// if (sessionState.last().uri.length > 10) { +// lastedUrl?.let { +// Uri.parse(it)?.let { uri -> +// uri.path?.let { +// HistoryManager.getBookPageInfo(contentsType, it) { +// it?.let { +// this@BaseToki.currentPage = it +// currentChapter = it?.chapterNum ?: 0 +// HistoryManager.save( +// historyItem = HistoryItem().putHistory( +// it, +// lastedUrl!! +// ) +// ) +// (currentPage?.pathUrl ?: lastedUrl?.toUri()?.path)?.let { +// HistoryManager.setBookPageInfo( +// contentsType, +// it, +// binding.pagedLayer.current() +// ) +// } +// val realm = openRealm() +// realm.writeBlocking { +// var q = this.query("contentsType == $0", contentsType) +// .find() +// if (q.size > 0) { +// q.last()?.let { +// it.title = currentTitle +// it.chapter = currentChapter +// it.pageIndex = 0 +// it.contentsType = currentPage!!.contentsType +// this@BaseToki.lastInfo = copyFromRealm(it) +// } +// } else { +// LastInfo()?.let { +// it.title = currentTitle +// it.chapter = currentChapter +// it.pageIndex = 0 +// it.contentsType = currentPage!!.contentsType +// it._id = +// if (lastedUrl?.contains("book", true) == true) { +// "book" +// } else if (lastedUrl?.contains( +// "new", +// true +// ) == true +// ) { +// "webtoon" +// } else if (lastedUrl?.contains( +// "mana", +// true +// ) == true +// ) { +// "comics" +// } else "web" +// copyToRealm(it, UpdatePolicy.ALL) +// this@BaseToki.lastInfo = it +// } +// } +// } +// +// } +// } +// } +// if (saveContinuation) { +// binding.menuWeb.postDelayed({ +// moveToNext( +// currentPage?.pathUrl ?: lastedUrl?.toUri()?.path +// ) +// }, 10000) +// } +// } +// } +// } +// } +// +// fun onLoadedContents(aContents: String) { +// Blog.LOGE("onLoadedContents ") +// binding.pagedLayer.let { view -> +// view.post { +// if (aContents.length > 10) { +// var contents = aContents.replace("\\\"", "\"") +// contents = (contents.replace("\\n", System.getProperty("line.separator"))) +// view.mPagedTextViewInterface = this@BaseToki +// if (lastInfo != null && lastedUrl?.endsWith(lastInfo!!.pageUrl) == true) { +// binding.progress.visibility = VISIBLE +// binding.pagedLayer.postDelayed({ +// binding.progress.visibility = GONE +// }, 1000) +// } +// applyReaderConfig() +// activity?.runOnUiThread { +// view.text = contents +// view.visibility = VISIBLE +// binding.menuWeb.visibility = GONE +// } +// view.forceUpdateUI() +// lastedUrl?.let { +// Uri.parse(it)?.let { uri -> +// uri.path?.let { +// HistoryManager.getBookPageInfo(contentsType, it) { +// it?.let { +// this@BaseToki.currentPage = it +// currentChapter = it?.chapterNum ?: 0 +// view.currentPage = it?.chapterNum ?: 0 +// HistoryManager.save( +// historyItem = HistoryItem().putHistory( +// it, +// lastedUrl!! +// ) +// ) +// } +// } +// HistoryManager.getBooPageInfoContentsSave( +// contentsType, +// it, +// contents +// ) +// } +// if (saveContinuation) { +// binding.menuWeb.postDelayed({ +// moveToNext( +// currentPage?.pathUrl ?: lastedUrl?.toUri()?.path +// ) +// }, 10000) +// +// } +// } +// } +// } +// +// } +// } +//// Log.i(TAG, "onLoadedContents >> " + aContents) +// } +// +// var currentTitle: String = "" +// var currentChapter: Int = 0 +// +// fun onFindTitle(contents: String) { +// binding.textviewTitle.text = contents +// binding.textviewTitle.setOnClickListener { +// val builder = AlertDialog.Builder(requireContext()) +// builder.setTitle("Title") +// val input = EditText(requireContext()) +// input.setText(lastedUrl ?: "") +// input.inputType = InputType.TYPE_CLASS_TEXT +// builder.setView(input) +// builder.setPositiveButton( +// "OK" +// ) { dialog, which -> +// var m_Text = input.text.toString() +// contentsLoad(m_Text.trim()) +// } +// builder.setNegativeButton( +// "Cancel" +// ) { dialog, which -> dialog.cancel() } +// builder.show() +// } +// var testRegex = """[^0-9]""".toRegex() +// Blog.LOGI(TAG, "onFindTitle >> " + contents + " ::: ${testRegex.replace(contents, "")}") +// if (contents.contains("-")) { +// currentTitle = contents.split("-")[0] +// try { +// currentChapter = testRegex.replace(contents.split("-")[1], "").toInt() +// } catch (e: Exception) { +// currentChapter = 0 +// } +// } else if (testRegex.replace(contents, "").length > 0) { +// currentChapter = testRegex.replace(contents, "").toInt() +// currentTitle = contents.split(testRegex.replace(contents, ""))[0] +// } else { +// val dateFormat = "yyyyMMdd-HH" +// val date = Date(currentTimeMillis()) +// val simpleDateFormat = SimpleDateFormat(dateFormat) +// currentTitle = simpleDateFormat.format(date) +// } +// +// } +// +// fun onStartLoad() { +// binding.progress.visibility = VISIBLE +// } +// +// fun completePageLoad(lastInfo: LastInfo) { +// saveLastInfo(lastInfo) +// } +// +//// override fun onTouchEvent(event: MotionEvent?): Boolean { +//// return super.onTouchEvent(event) +//// if (saveContinuation) { +//// saveContinuation = false +//// } +//// } +// +// fun saveLastInfo(lastInfo: LastInfo) { +// val realm = openRealm() +// if ((realm.query("contentsType == $0", contentsType)?.count()?.find() ?: 0) > 0) { +// realm.writeBlocking { +// this.query("contentsType == $0", contentsType)?.find()?.last()?.let { +// it.pageUrl = lastInfo.pageUrl +// it.title = currentTitle +// it.chapter = currentChapter +// it.pageIndex = lastInfo.pageIndex +// it.contentsName = lastInfo.contentsName +// it.displayOrientation = lastInfo.displayOrientation +// it.contentsType = lastInfo.contentsType +// this@BaseToki.lastInfo = copyFromRealm(it) +// Blog.LOGE("lastInfo >>>> ${this@BaseToki.lastInfo}") +// } +// } +// } else if ((lastInfo._id?.length ?: 0) > 3) { +// realm.writeBlocking { +// Blog.LOGE("lastInfo >>>> $lastInfo") +// copyToRealm(lastInfo, UpdatePolicy.ALL) +// } +// } +//// Blog.LOGD(log = "Successfully opened realm: ${realm.configuration.name}") +// } +// +// fun updateLastInfo(pagedTextLayout: PagedTextLayout) { +// (currentPage?.pathUrl ?: lastedUrl?.toUri()?.path)?.let { +// HistoryManager.setBookPageInfo(contentsType, it, binding.pagedLayer.current()) +// } +// val configuration: Configuration = getResources().configuration +// val realm = openRealm() +// realm.writeBlocking { +// var q = this.query("contentsType == $0", contentsType) +// if (q.count().find() > 0) { +// q.find().last()?.let { +// it.displayOrientation = configuration.orientation +// it.title = currentTitle +// it.chapter = currentChapter +// it.pageIndex = pagedTextLayout.current() +// this@BaseToki.lastInfo = copyFromRealm(it) +// } +// if (currentTitle.length > 0 && currentChapter > 0) { +// this@BaseToki.lastInfo?.makeHistoryItem()?.let { +// copyToRealm(it, UpdatePolicy.ALL) +// } +// } +// } else { +// +// LastInfo().let { +// it.title = currentTitle +// it.chapter = currentChapter +// it.pageIndex = 0 +// +// it._id = if (lastedUrl?.contains("book", true) == true) { +// "book" +// } else if (lastedUrl?.contains("new", true) == true) { +// "webtoon" +// } else if (lastedUrl?.contains("mana", true) == true) { +// "comics" +// } else "web" +// it.contentsType = currentPage?.contentsType ?: it._id +// copyToRealm(it, UpdatePolicy.ALL) +// this@BaseToki.lastInfo = it +// } +// if (currentTitle.length > 0 && currentChapter > 0) { +// this@BaseToki.lastInfo?.makeHistoryItem()?.let { +// copyToRealm(it, UpdatePolicy.ALL) +// } +// } +// } +// } +// val message: JSONObject = JSONObject() +// try { +// message.put("type", "scrollDown") +// message.put("max", binding.pagedLayer.size()) +// message.put("current", binding.pagedLayer.current()) +// } catch (ex: JSONException) { +// throw RuntimeException(ex) +// } +// mPort?.postMessage(message) // Blog.LOGD(log = "Successfully opened realm: ${realm.configuration.name}") - } - - fun updateLastInfo(pagedTextLayout: PagedTextLayout) { - (currentPage?.pathUrl ?: lastedUrl?.toUri()?.path)?.let { - HistoryManager.setBookPageInfo(contentsType, it, binding.pagedLayer.current()) - } - val configuration: Configuration = getResources().configuration - val realm = openRealm() - realm.writeBlocking { - var q = this.query("contentsType == $0", contentsType) - if (q.count().find() > 0) { - q.find().last()?.let { - it.displayOrientation = configuration.orientation - it.title = currentTitle - it.chapter = currentChapter - it.pageIndex = pagedTextLayout.current() - this@BaseToki.lastInfo = copyFromRealm(it) - } - if (currentTitle.length > 0 && currentChapter > 0) { - this@BaseToki.lastInfo?.makeHistoryItem()?.let { - copyToRealm(it, UpdatePolicy.ALL) - } - } - } else { - - LastInfo().let { - it.title = currentTitle - it.chapter = currentChapter - it.pageIndex = 0 - - it._id = if (lastedUrl?.contains("book", true) == true) { - "book" - } else if (lastedUrl?.contains("new", true) == true) { - "webtoon" - } else if (lastedUrl?.contains("mana", true) == true) { - "comics" - } else "web" - it.contentsType = currentPage?.contentsType ?: it._id - copyToRealm(it, UpdatePolicy.ALL) - this@BaseToki.lastInfo = it - } - if (currentTitle.length > 0 && currentChapter > 0) { - this@BaseToki.lastInfo?.makeHistoryItem()?.let { - copyToRealm(it, UpdatePolicy.ALL) - } - } - } - } - val message: JSONObject = JSONObject() - try { - message.put("type", "scrollDown") - message.put("max", binding.pagedLayer.size()) - message.put("current", binding.pagedLayer.current()) - } catch (ex: JSONException) { - throw RuntimeException(ex) - } - mPort?.postMessage(message) - Blog.LOGD(log = "Successfully opened realm: ${realm.configuration.name}") - } - - private fun sendViewerTouch(string: String) { - val message: JSONObject = JSONObject() - try { - message.put("type", "ViewerTouch") - message.put("area", string) - } catch (ex: JSONException) { - throw RuntimeException(ex) - } - Blog.LOGE(Gson().toJson(message)) - mPort?.postMessage(message) - } - - fun sendScrollDown(isUp: Boolean) { - val message: JSONObject = JSONObject() - try { - message.put("type", "scrollDown") - message.put("isUpDown", if (isUp) +1 else -1) - } catch (ex: JSONException) { - throw RuntimeException(ex) - } - Blog.LOGE(Gson().toJson(message)) - mPort?.postMessage(message) - } - - - private fun goToHome() { - binding.menuWeb.loadUrl(getLastedDoamin()) - } - - - companion object { - private const val TAG = "DualScreenStatus" - } - - - open fun back() { +// } +// +// private fun sendViewerTouch(string: String) { +// val message: JSONObject = JSONObject() +// try { +// message.put("type", "ViewerTouch") +// message.put("area", string) +// } catch (ex: JSONException) { +// throw RuntimeException(ex) +// } +// Blog.LOGE(Gson().toJson(message)) +// mPort?.postMessage(message) +// } +// +// fun sendScrollDown(isUp: Boolean) { +// val message: JSONObject = JSONObject() +// try { +// message.put("type", "scrollDown") +// message.put("isUpDown", if (isUp) +1 else -1) +// } catch (ex: JSONException) { +// throw RuntimeException(ex) +// } +// Blog.LOGE(Gson().toJson(message)) +// mPort?.postMessage(message) +// } +// +// +// private fun goToHome() { +// binding.menuWeb.loadUrl(getLastedDoamin()) +// } +// +// +// companion object { +// private const val TAG = "DualScreenStatus" +// } +// +// +// open fun back() { +//// binding.menuWeb.session?.goBack() +// } +// +//} +// +//class YouTube : BaseToki() { +// override val contentsType = "youtube" +// override var lastNumber: Int = 143 +// override val webcontentsName: String = " be" +// override val afterDot = "com" +// override var isPrivateMode: Boolean = true +// +// override fun getLastedDoamin(): String { +// return String.format("https://%s.%s", webcontentsName, afterDot) +// } +// +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// } +// +// override fun back() { // binding.menuWeb.session?.goBack() - } - -} - -class YouTube : BaseToki() { - override val contentsType = "youtube" - override var lastNumber: Int = 143 - override val webcontentsName: String = "youtube" - override val afterDot = "com" - override var isPrivateMode: Boolean = true - - override fun getLastedDoamin(): String { - return String.format("https://%s.%s", webcontentsName, afterDot) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - } - - override fun back() { - binding.menuWeb.session?.goBack() - } - - override fun onTouch(touchArea: TouchArea) { - } - - override fun onTimeoverTouch() { - } - - override fun onSwipeLeft(touchCount: Int) { - } - - override fun onSwipeRight(touchCount: Int) { - } - - override fun onSwipeDown(touchCount: Int) { - } - - override fun onSwipeUp(touchCount: Int) { - } - - override fun onLongClick() { - } -} - -class Comics : BaseToki(), PagedTextViewInterface { - - override val contentsType = "comics" - override var lastNumber: Int = 468 - override val webcontentsName: String = "manatoki" - override val afterDot = "net" - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - } - - override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log = "onTouch ${touchArea}") - when (touchArea) { - TouchArea.Center -> { - - } - - TouchArea.Right -> { - actionNextEvent() - } - - TouchArea.Left -> { - actionPrevEvent() - } - - TouchArea.DoubleRight -> { - actionNextEvent(true) - } - - TouchArea.DoubleLeft -> { - actionPrevEvent(true) - } - - else -> { - - } - } - - - } - - override fun onLongClick() { - Blog.LOGD(log = "onLongClick") - - } - - override fun onSwipeLeft(count: Int) { - Blog.LOGD(log = "onSwipeLeft ${count}") - actionNextEvent(count > 1) - - } - - override fun onSwipeRight(count: Int) { - Blog.LOGD(log = "onSwipeRight ${count}") - actionPrevEvent(count > 1) - } - - override fun onSwipeUp(touchCount: Int) { - - } - - override fun onSwipeDown(touchCount: Int) { - if (touchCount == 2) { - if (binding.pagedLayer.isVisible) { - binding.pagedLayer.visibility = GONE - } - } - } - - override fun onTimeoverTouch() { - - } -} - -class Magnet : BaseToki(), PagedTextViewInterface { - // "https://btsearch.love/ - override val contentsType = "btsearch" - override var lastNumber: Int = 143 - override val webcontentsName: String = "btsearch" - override val afterDot = "love" - override fun getLastedDoamin(): String { - return String.format("https://%s.%s", webcontentsName, afterDot) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - } - - override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log = "onTouch ${touchArea}") - when (touchArea) { - TouchArea.Center -> { - - } - - TouchArea.Right -> { - actionNextEvent() - } - - TouchArea.Left -> { - actionPrevEvent() - } - - TouchArea.DoubleRight -> { - actionNextEvent(true) - } - - TouchArea.DoubleLeft -> { - actionPrevEvent(true) - } - - else -> { - - } - } - - - } - - override fun onLongClick() { - Blog.LOGD(log = "onLongClick") - - } - - override fun onSwipeLeft(count: Int) { - Blog.LOGD(log = "onSwipeLeft ${count}") - actionNextEvent(count > 1) - - } - - override fun onSwipeRight(count: Int) { - Blog.LOGD(log = "onSwipeRight ${count}") - actionPrevEvent(count > 1) - } - - override fun onSwipeUp(touchCount: Int) { - - } - - override fun onSwipeDown(touchCount: Int) { - if (touchCount == 2) { - if (binding.pagedLayer.isVisible) { - binding.pagedLayer.visibility = GONE - } - } - } - - override fun onTimeoverTouch() { - - } -} - -class Novels : BaseToki(), PagedTextViewInterface { - - override val contentsType = "book" - override var lastNumber: Int = 468 - override val webcontentsName: String = "booktoki" - override val afterDot = "com" - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - } - - override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log = "onTouch ${touchArea}") - when (touchArea) { - TouchArea.Center -> { - - } - - TouchArea.Right -> { - actionNextEvent() - } - - TouchArea.Left -> { - actionPrevEvent() - } - - TouchArea.DoubleRight -> { - actionNextEvent(true) - } - - TouchArea.DoubleLeft -> { - actionPrevEvent(true) - } - - else -> { - - } - } - - - } - - override fun onLongClick() { - Blog.LOGD(log = "onLongClick") - - } - - override fun onSwipeLeft(count: Int) { - Blog.LOGD(log = "onSwipeLeft ${count}") - actionNextEvent(count > 1) - - } - - override fun onSwipeRight(count: Int) { - Blog.LOGD(log = "onSwipeRight ${count}") - actionPrevEvent(count > 1) - } - - override fun onSwipeUp(touchCount: Int) { - - } - - override fun onSwipeDown(touchCount: Int) { - if (touchCount == 2) { - if (binding.pagedLayer.isVisible) { - binding.pagedLayer.visibility = GONE - } - binding.menuWeb.visibility = VISIBLE - } - } - - override fun onTimeoverTouch() { - - } -} - -class Perplexity : BaseToki(), PagedTextViewInterface { - // "https://btsearch.love/ - override val contentsType = "perplexity" - override var lastNumber: Int = 143 - override val webcontentsName: String = "www.perplexity" - override val afterDot = "ai" - override fun getLastedDoamin(): String { - return String.format("https://%s.%s", webcontentsName, afterDot) - } - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - } - - override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log = "onTouch ${touchArea}") - when (touchArea) { - TouchArea.Center -> { - - } - - TouchArea.Right -> { - actionNextEvent() - } - - TouchArea.Left -> { - actionPrevEvent() - } - - TouchArea.DoubleRight -> { - actionNextEvent(true) - } - - TouchArea.DoubleLeft -> { - actionPrevEvent(true) - } - - else -> { - - } - } - - - } - - override fun onLongClick() { - Blog.LOGD(log = "onLongClick") - - } - - override fun onSwipeLeft(count: Int) { - Blog.LOGD(log = "onSwipeLeft ${count}") - actionNextEvent(count > 1) - - } - - override fun onSwipeRight(count: Int) { - Blog.LOGD(log = "onSwipeRight ${count}") - actionPrevEvent(count > 1) - } - - override fun onSwipeUp(touchCount: Int) { - - } - - override fun onSwipeDown(touchCount: Int) { - if (touchCount == 2) { - if (binding.pagedLayer.isVisible) { - binding.pagedLayer.visibility = GONE - } - } - } - - override fun onTimeoverTouch() { - - } -} - -class Webtoons : BaseToki(), PagedTextViewInterface { - - override val contentsType = "webtoon" - override var lastNumber: Int = 468 - override val webcontentsName: String = "newtoki" - override val afterDot = "com" - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - super.onCreateView(inflater, container, savedInstanceState) - return binding.root - } - - - override fun onStart() { - super.onStart() - } - - override fun onResume() { - super.onResume() - loadLastInfo() - Blog.LOGE("binding.root >>> ${binding.root}") - } - - override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log = "onTouch ${touchArea}") - when (touchArea) { - TouchArea.Center -> { - - } - - TouchArea.Right -> { - actionNextEvent() - } - - TouchArea.Left -> { - actionPrevEvent() - } - - TouchArea.DoubleRight -> { - actionNextEvent(true) - } - - TouchArea.DoubleLeft -> { - actionPrevEvent(true) - } - - else -> { - - } - } - - - } - - override fun onLongClick() { - Blog.LOGD(log = "onLongClick") - - } - - override fun onSwipeLeft(count: Int) { - Blog.LOGD(log = "onSwipeLeft ${count}") - actionNextEvent(count > 1) - - } - - override fun onSwipeRight(count: Int) { - Blog.LOGD(log = "onSwipeRight ${count}") - actionPrevEvent(count > 1) - } - - override fun onSwipeUp(touchCount: Int) { - - } - - override fun onSwipeDown(touchCount: Int) { - if (touchCount == 2) { - if (binding.pagedLayer.isVisible) { - binding.pagedLayer.visibility = GONE - } - } - } - - override fun onTimeoverTouch() { - - } -} \ No newline at end of file +// } +// +// override fun onTouch(touchArea: TouchArea) { +// } +// +// override fun onTimeoverTouch() { +// } +// +// override fun onSwipeLeft(touchCount: Int) { +// } +// +// override fun onSwipeRight(touchCount: Int) { +// } +// +// override fun onSwipeDown(touchCount: Int) { +// } +// +// override fun onSwipeUp(touchCount: Int) { +// } +// +// override fun onLongClick() { +// } +//} +// +//class Comics : BaseToki(), PagedTextViewInterface { +// +// override val contentsType = "comics" +// override var lastNumber: Int = 468 +// override val webcontentsName: String = "manatoki" +// override val afterDot = "net" +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// } +// +// override fun onTouch(touchArea: TouchArea) { +// Blog.LOGD(log = "onTouch ${touchArea}") +// when (touchArea) { +// TouchArea.Center -> { +// +// } +// +// TouchArea.Right -> { +// actionNextEvent() +// } +// +// TouchArea.Left -> { +// actionPrevEvent() +// } +// +// TouchArea.DoubleRight -> { +// actionNextEvent(true) +// } +// +// TouchArea.DoubleLeft -> { +// actionPrevEvent(true) +// } +// +// else -> { +// +// } +// } +// +// +// } +// +// override fun onLongClick() { +// Blog.LOGD(log = "onLongClick") +// +// } +// +// override fun onSwipeLeft(count: Int) { +// Blog.LOGD(log = "onSwipeLeft ${count}") +// actionNextEvent(count > 1) +// +// } +// +// override fun onSwipeRight(count: Int) { +// Blog.LOGD(log = "onSwipeRight ${count}") +// actionPrevEvent(count > 1) +// } +// +// override fun onSwipeUp(touchCount: Int) { +// +// } +// +// override fun onSwipeDown(touchCount: Int) { +// if (touchCount == 2) { +// if (binding.pagedLayer.isVisible) { +// binding.pagedLayer.visibility = GONE +// } +// } +// } +// +// override fun onTimeoverTouch() { +// +// } +//} +// +//class Magnet : BaseToki(), PagedTextViewInterface { +// // "https://btsearch.love/ +// override val contentsType = "btsearch" +// override var lastNumber: Int = 143 +// override val webcontentsName: String = "btsearch" +// override val afterDot = "love" +// override fun getLastedDoamin(): String { +// return String.format("https://%s.%s", webcontentsName, afterDot) +// } +// +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// } +// +// override fun onTouch(touchArea: TouchArea) { +// Blog.LOGD(log = "onTouch ${touchArea}") +// when (touchArea) { +// TouchArea.Center -> { +// +// } +// +// TouchArea.Right -> { +// actionNextEvent() +// } +// +// TouchArea.Left -> { +// actionPrevEvent() +// } +// +// TouchArea.DoubleRight -> { +// actionNextEvent(true) +// } +// +// TouchArea.DoubleLeft -> { +// actionPrevEvent(true) +// } +// +// else -> { +// +// } +// } +// +// +// } +// +// override fun onLongClick() { +// Blog.LOGD(log = "onLongClick") +// +// } +// +// override fun onSwipeLeft(count: Int) { +// Blog.LOGD(log = "onSwipeLeft ${count}") +// actionNextEvent(count > 1) +// +// } +// +// override fun onSwipeRight(count: Int) { +// Blog.LOGD(log = "onSwipeRight ${count}") +// actionPrevEvent(count > 1) +// } +// +// override fun onSwipeUp(touchCount: Int) { +// +// } +// +// override fun onSwipeDown(touchCount: Int) { +// if (touchCount == 2) { +// if (binding.pagedLayer.isVisible) { +// binding.pagedLayer.visibility = GONE +// } +// } +// } +// +// override fun onTimeoverTouch() { +// +// } +//} +// +//class Novels : BaseToki(), PagedTextViewInterface { +// +// override val contentsType = "book" +// override var lastNumber: Int = 468 +// override val webcontentsName: String = "booktoki" +// override val afterDot = "com" +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// } +// +// override fun onTouch(touchArea: TouchArea) { +// Blog.LOGD(log = "onTouch ${touchArea}") +// when (touchArea) { +// TouchArea.Center -> { +// +// } +// +// TouchArea.Right -> { +// actionNextEvent() +// } +// +// TouchArea.Left -> { +// actionPrevEvent() +// } +// +// TouchArea.DoubleRight -> { +// actionNextEvent(true) +// } +// +// TouchArea.DoubleLeft -> { +// actionPrevEvent(true) +// } +// +// else -> { +// +// } +// } +// +// +// } +// +// override fun onLongClick() { +// Blog.LOGD(log = "onLongClick") +// +// } +// +// override fun onSwipeLeft(count: Int) { +// Blog.LOGD(log = "onSwipeLeft ${count}") +// actionNextEvent(count > 1) +// +// } +// +// override fun onSwipeRight(count: Int) { +// Blog.LOGD(log = "onSwipeRight ${count}") +// actionPrevEvent(count > 1) +// } +// +// override fun onSwipeUp(touchCount: Int) { +// +// } +// +// override fun onSwipeDown(touchCount: Int) { +// if (touchCount == 2) { +// if (binding.pagedLayer.isVisible) { +// binding.pagedLayer.visibility = GONE +// } +// binding.menuWeb.visibility = VISIBLE +// } +// } +// +// override fun onTimeoverTouch() { +// +// } +//} +// +//class Perplexity : BaseToki(), PagedTextViewInterface { +// // "https://btsearch.love/ +// override val contentsType = "perplexity" +// override var lastNumber: Int = 143 +// override val webcontentsName: String = "www.perplexity" +// override val afterDot = "ai" +// override fun getLastedDoamin(): String { +// return String.format("https://%s.%s", webcontentsName, afterDot) +// } +// +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// } +// +// override fun onTouch(touchArea: TouchArea) { +// Blog.LOGD(log = "onTouch ${touchArea}") +// when (touchArea) { +// TouchArea.Center -> { +// +// } +// +// TouchArea.Right -> { +// actionNextEvent() +// } +// +// TouchArea.Left -> { +// actionPrevEvent() +// } +// +// TouchArea.DoubleRight -> { +// actionNextEvent(true) +// } +// +// TouchArea.DoubleLeft -> { +// actionPrevEvent(true) +// } +// +// else -> { +// +// } +// } +// +// +// } +// +// override fun onLongClick() { +// Blog.LOGD(log = "onLongClick") +// +// } +// +// override fun onSwipeLeft(count: Int) { +// Blog.LOGD(log = "onSwipeLeft ${count}") +// actionNextEvent(count > 1) +// +// } +// +// override fun onSwipeRight(count: Int) { +// Blog.LOGD(log = "onSwipeRight ${count}") +// actionPrevEvent(count > 1) +// } +// +// override fun onSwipeUp(touchCount: Int) { +// +// } +// +// override fun onSwipeDown(touchCount: Int) { +// if (touchCount == 2) { +// if (binding.pagedLayer.isVisible) { +// binding.pagedLayer.visibility = GONE +// } +// } +// } +// +// override fun onTimeoverTouch() { +// +// } +//} +// +//class Webtoons : BaseToki(), PagedTextViewInterface { +// +// override val contentsType = "webtoon" +// override var lastNumber: Int = 468 +// override val webcontentsName: String = "newtoki" +// override val afterDot = "com" +// override fun onCreateView( +// inflater: LayoutInflater, +// container: ViewGroup?, +// savedInstanceState: Bundle? +// ): View { +// super.onCreateView(inflater, container, savedInstanceState) +// return binding.root +// } +// +// +// override fun onStart() { +// super.onStart() +// } +// +// override fun onResume() { +// super.onResume() +// loadLastInfo() +// Blog.LOGE("binding.root >>> ${binding.root}") +// } +// +// override fun onTouch(touchArea: TouchArea) { +// Blog.LOGD(log = "onTouch ${touchArea}") +// when (touchArea) { +// TouchArea.Center -> { +// +// } +// +// TouchArea.Right -> { +// actionNextEvent() +// } +// +// TouchArea.Left -> { +// actionPrevEvent() +// } +// +// TouchArea.DoubleRight -> { +// actionNextEvent(true) +// } +// +// TouchArea.DoubleLeft -> { +// actionPrevEvent(true) +// } +// +// else -> { +// +// } +// } +// +// +// } +// +// override fun onLongClick() { +// Blog.LOGD(log = "onLongClick") +// +// } +// +// override fun onSwipeLeft(count: Int) { +// Blog.LOGD(log = "onSwipeLeft ${count}") +// actionNextEvent(count > 1) +// +// } +// +// override fun onSwipeRight(count: Int) { +// Blog.LOGD(log = "onSwipeRight ${count}") +// actionPrevEvent(count > 1) +// } +// +// override fun onSwipeUp(touchCount: Int) { +// +// } +// +// override fun onSwipeDown(touchCount: Int) { +// if (touchCount == 2) { +// if (binding.pagedLayer.isVisible) { +// binding.pagedLayer.visibility = GONE +// } +// } +// } +// +// override fun onTimeoverTouch() { +// +// } +//} \ No newline at end of file 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 aa3cedec..76fc3ede 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 @@ -33,7 +33,6 @@ import androidx.fragment.app.Fragment import bums.lunatic.launcher.R import bums.lunatic.launcher.databinding.BooktokiBinding import bums.lunatic.launcher.home.GeckoWeb -import bums.lunatic.launcher.home.GeckoWeb.GKCookie import bums.lunatic.launcher.home.GeckoWeb.JxEvent import bums.lunatic.launcher.home.NeoRssActivity import bums.lunatic.launcher.home.NeoRssActivity.Companion.getRuntime @@ -224,6 +223,9 @@ class TokiFragment : Fragment(), PagedTextViewInterface { } } + fun isbooktoki() : Boolean { + return webcontentsName.contains("booktoki") + } override fun onSwipeLeft(count: Int) { if (!enableGestures) return Blog.LOGD(log = "onSwipeLeft ${count}") @@ -1060,7 +1062,7 @@ class TokiFragment : Fragment(), PagedTextViewInterface { view.visibility = VISIBLE binding.menuWeb.visibility = GONE } - view.forceUpdateUI() +// view.forceUpdateUI() lastedUrl?.let { Uri.parse(it)?.let { uri -> uri.path?.let { diff --git a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/BWebview.kt b/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/BWebview.kt deleted file mode 100644 index 3b25fa4f..00000000 --- a/app/src/main/kotlin/bums/lunatic/launcher/home/tokiz/view/BWebview.kt +++ /dev/null @@ -1,336 +0,0 @@ -//package bums.lunatic.launcher.home.tokiz.view -// -//import android.annotation.SuppressLint -//import android.content.Context -//import android.content.Intent -//import android.os.Build -//import android.util.AttributeSet -//import android.view.MotionEvent -//import android.view.PointerIcon -//import android.view.View -//import androidx.core.net.toUri -//import androidx.core.view.isVisible -//import bums.lunatic.launcher.R -//import bums.lunatic.launcher.helpers.ForeGroundService -//import bums.lunatic.launcher.helpers.ForeGroundService.Companion.ACTION_VIDEO_DOWNLOAD -//import bums.lunatic.launcher.helpers.ForeGroundService.Companion.EXTRA_TARGET_URL -//import bums.lunatic.launcher.utils.Blog -//import bums.lunatic.launcher.utils.SimpleFingerGestures -//import com.yausername.youtubedl_android.YoutubeDL -//import com.yausername.youtubedl_android.YoutubeDLRequest -//import kotlinx.coroutines.CoroutineScope -//import kotlinx.coroutines.Dispatchers -//import kotlinx.coroutines.launch -//import org.mozilla.gecko.util.ThreadUtils.runOnUiThread -//import org.mozilla.geckoview.GeckoView -//import java.io.File -//import java.util.Base64 -//import kotlin.collections.iterator -// -//enum class JxEvent { -// SCROLL_UP, -// SCROLL_DOWN, -// SWIPE_LEFT, -// SWIPE_RIGHT, -// ON_CLICK, -//} -//typealias JxInteface = (JxEvent)->Unit -//open class BWebview : GeckoView { -// var decoViews = arrayListOf() -// @SuppressLint("ClickableViewAccessibility") -// constructor(context: Context?) : super(context) { -// this.setOnTouchListener { v, event -> -// if (event.device.name?.contains( -// "JX-12", -// true -// ) == true || event.device.name?.equals("J06", true) == true -// ) { -// return@setOnTouchListener mSimpleFingerGestures.onTouch(v, event) -// } else { -// return@setOnTouchListener super.onTouchEvent(event) -// } -// } -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { -// val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL) -// this.setPointerIcon(nullCursor) -// } -// } -// -// -// @SuppressLint("ClickableViewAccessibility") -// constructor(context: Context?, attrs: AttributeSet?) : super(context, attrs) { -// this.setOnTouchListener { v,event -> -// if (event.device.name?.contains("JX-12",true) == true|| event.device.name?.equals("J06",true) == true) { -// return@setOnTouchListener mSimpleFingerGestures.onTouch(v,event) -// } else { -// return@setOnTouchListener super.onTouchEvent(event) -// } -// } -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { -// val nullCursor = PointerIcon.getSystemIcon(context!!, PointerIcon.TYPE_NULL) -// this.setPointerIcon(nullCursor) -// } -// } -// fun videoDlownLoad(videoUrl : String) { -// val actionIntent = Intent(context, ForeGroundService::class.java).apply { -// action = ACTION_VIDEO_DOWNLOAD -// putExtra(EXTRA_TARGET_URL, videoUrl) // 전달할 데이터 -// } -// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { -// context.startForegroundService(actionIntent) -// } else { -// context.startService(actionIntent) -// } -// } -// -// class GKCookie { -// var COOKIES : String? = null -// } -// -// var mGKCookie : GKCookie? = null -// -// fun checkIfDownloadable(url: String) { -// CoroutineScope(Dispatchers.Main).launch { -// runOnUiThread { -// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let { -// it.setOnClickListener {} -// it.visibility = GONE -// }}} -// Blog.LOGE("checkIfDownloadable ${url}") -// CoroutineScope(Dispatchers.IO).launch { -// try { -// var request = YoutubeDLRequest(url) -// (mGKCookie?.COOKIES)?.let{ -// Blog.LOGE(it) -// val cookies = it.split(";") -// .map { it.trim() } -// .mapNotNull { -// val parts = it.split("=", limit = 2) -// if (parts.size == 2) parts[0] to parts[1] else null -// } -// .toMap() -// val expires = (System.currentTimeMillis() / 1000) + 3600 * 24 * 7 // 일주일 후 만료 예시 -// -// val cookieFileContent = buildString { -// appendLine("# Netscape HTTP Cookie File") -// for ((name, value) in cookies) { -// appendLine(".${url.toUri().host}\tTRUE\t/\tTRUE\t$expires\t$name\t$value") -// } -// } -// val cookieFile = File(context.filesDir, "cookies.txt") -// cookieFile.writeText(cookieFileContent) -// request.addOption("--cookies", cookieFile.absolutePath) -// } -// -// val videoInfo = YoutubeDL.getInstance().getInfo(request) -// // videoInfo 가 null 아니고, 필요한 키(예: title, url 등)가 있으면 다운로드 가능 -// Blog.LOGE("checkIfDownloadable ${url}\n videoInfo : ${videoInfo}") -// var canVideoDown = videoInfo != null && !videoInfo.title.isNullOrEmpty() -// CoroutineScope(Dispatchers.Main).launch { -// runOnUiThread { -// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let { -// it.setOnClickListener { -// videoDlownLoad(url) -// } -// it.visibility = if (canVideoDown){ -// VISIBLE -// } else{ -// GONE -// } -// } -// } -// } -// -// } catch (e: Exception) { -// e.printStackTrace() -// Blog.LOGE("checkIfDownloadable ${url} ${e}") -// CoroutineScope(Dispatchers.Main).launch { -// runOnUiThread { -// decoViews.filter { it.id == R.id.dl_video }.firstOrNull()?.let { -// it.setOnClickListener {} -// it.visibility = GONE -// }}} -// } -// } -// } -// val mSimpleFingerGestures = SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{ -// -// override fun onSwipeUp( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("") -// jxInteface?.invoke(JxEvent.SCROLL_UP ) -// return true -// } -// -// override fun onSwipeDown( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("") -// jxInteface?.invoke(JxEvent.SCROLL_DOWN) -// return true -// } -// -// override fun onSwipeLeft( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("") -// jxInteface?.invoke(JxEvent.SWIPE_LEFT) -// return true -// } -// -// override fun onSwipeRight( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("") -// jxInteface?.invoke(JxEvent.SWIPE_RIGHT) -// return true -// } -// -// override fun onPinch( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("onPinch") -// return true -// } -// -// override fun onUnpinch( -// targetView: View, -// fingers: Int, -// gestureDuration: Long, -// gestureDistance: Double -// ): Boolean { -// Blog.LOGE("") -// return true -// } -// -// override fun onDoubleTap( -// targetView: View, -// fingers: Int -// ): Boolean { -// Blog.LOGE("") -// return true -// } -// -// override fun onLongPress( -// targetView: View, -// fingers: Int -// ): Boolean { -// Blog.LOGE("onLongPress") -// return true -// } -// -// override fun onClick( -// targetView: View, -// fingers: Int -// ): Boolean { -// Blog.LOGE("onClick") -// jxInteface?.invoke(JxEvent.ON_CLICK) -// return true -// } -// -// -// }) -// companion object { -// var currentRetryCount = 0 -// } -// -// var jxInteface : JxInteface? = null -// -// var lastDomain : String = "" -// -// open fun loadUrl(url: String, param : String? = null) { -// var nUrl = url -// Blog.LOGE("url >>>> ${url}") -// if (url.endsWith("=")) { -// nUrl = String(Base64.getMimeDecoder().decode(url.toByteArray())) -// param?.let { -// nUrl = nUrl.plus(param) -// } -// } else if (url.startsWith("http") == false) { -// nUrl = lastDomain -// } -// if (this.isVisible == false) { -// this.visibility = VISIBLE -// } -// Blog.LOGE("nUrl >>>> ${nUrl}") -// -// -// nUrl?.let { url -> -// if (url.split("//").size > 1) { -// url.replace("//","/").replace("https:/","https://").let { -// Blog.LOGE("url >> ${url} , it >>> ${it}") -// this.session?.loadUri(it) -// } -// } else { -// this.session?.loadUri(url) -// } -// } -// currentRetryCount = 0; -// } -// private var lastX = 0f -// private var lastY = 0f -// -// -// override fun onTouchEvent(event: MotionEvent): Boolean { -// Blog.LOGE("event.device.name >>> ${event.device.name}") -// if (event.device.name?.contains("JX-12",true) == true || event.device.name?.equals("J06",true) == true) { -// Blog.LOGE("BWebview onTouchEvent $event") -// when (event.action) { -// MotionEvent.ACTION_DOWN -> { -// lastX = event.x -// lastY = event.y -// return true -// } -// -// MotionEvent.ACTION_MOVE -> { -// val deltaX = event.x - lastX -// val deltaY = event.y - lastY -// // 상하 이동이 더 크면(즉, 거의 수직 이동이면)만 처리 -// if (Math.abs(deltaY) > Math.abs(deltaX)) { -// // 원하는 감도 적용 -// val scrollFactor = 0.1f -//// scrollBy(0, (-deltaY * scrollFactor).toInt()) -// -// jxInteface?.invoke(if ((-deltaY * scrollFactor).toInt() > 0){ -// JxEvent.SCROLL_DOWN -// } else { -// JxEvent.SCROLL_UP -// }) -// lastY = event.y -// lastX = event.x -// Blog.LOGE("return true for scroll") -// return true -// } -// // 좌우 이동은 무시 -// lastY = event.y -// lastX = event.x -// Blog.LOGE("return false") -// return false -// } -// -// else -> { -// Blog.LOGE("call super") -// return super.onTouchEvent(event) -// } -// } -// } else { -// return super.onTouchEvent(event) -// } -// } -//} \ No newline at end of file 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 bec90f0e..d3173d58 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 @@ -3,11 +3,13 @@ package bums.lunatic.launcher.home.tokiz.view import android.annotation.TargetApi import android.content.Context import android.graphics.Color +import android.graphics.Paint import android.graphics.Typeface import android.os.Build import android.os.Handler import android.text.Layout import android.text.StaticLayout +import android.text.TextPaint import android.util.AttributeSet import android.util.TypedValue import android.view.View @@ -19,8 +21,10 @@ import bums.lunatic.launcher.R import bums.lunatic.launcher.home.tokiz.TouchArea import bums.lunatic.launcher.utils.Blog import bums.lunatic.launcher.utils.SimpleFingerGestures +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.MainScope import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext import kotlin.math.min @@ -33,248 +37,6 @@ interface PagedTextViewInterface { fun onSwipeUp(touchCount : Int) fun onLongClick() } -class PagedTextView : AppCompatTextView { - - private var needPaginate = false - private var isPaginating = false - private val pageList = arrayListOf() - private var pageIndex: Int = 0 - private var pageHeight: Int = 0 - private var originalText: CharSequence = "" - - var mPagedTextGenerateInterface : PagedTextGenerateInterface? = null - - - constructor(context: Context?) : super(context!!){initView(context)} - - constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs){initView(context)} - - constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr){initView(context)} - - fun initView(context: Context?){ - - } - - - - - - fun size(): Int = pageList.size - fun current() : Int = pageIndex - - fun doPrev() { - if (pageIndex > 0 ) - pageIndex = pageIndex - 1 - setPageText() - } - - fun doNext() { - if (pageIndex < pageList.size) - pageIndex = pageIndex + 1 - setPageText() - } - - fun next(index: Int) { - pageIndex = index - setPageText() - } - - private fun setPageText() { - if(pageList.size > 0) { - isPaginating = true - text = pageList[pageIndex] - isPaginating = false - } - } - - fun setTxtF(text: CharSequence?) { - needPaginate = true - this.setText(text , null) - } - - override fun setText(text: CharSequence?, type: BufferType?) { - if (!isPaginating) { - needPaginate = true - originalText = text ?: "" - } - super.setText(text, type) - } - - - - override fun setTextSize(size: Float) { - setTextSize(TypedValue.COMPLEX_UNIT_SP, size) - } - - override fun setTextSize(unit: Int, size: Float) { - super.setTextSize(unit, size) - paint.textSize = TypedValue.applyDimension(unit, size, context.resources.getDisplayMetrics()) - needPaginate = true - } - - override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) { - super.setPadding(left, top, right, bottom) - needPaginate = true - } - - override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) { - super.setPaddingRelative(start, top, end, bottom) - needPaginate = true - } - - override fun setTextScaleX(size: Float) { - if (size != textScaleX) { - needPaginate = true - } - super.setTextScaleX(size) - } - - override fun setTypeface(tf: Typeface?) { - if (typeface != null && tf != typeface) { - needPaginate = true - paint.typeface = tf - } - super.setTypeface(tf) - } - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - override fun setLetterSpacing(letterSpacing: Float) { - if (letterSpacing != this.letterSpacing) { - needPaginate = true - } - super.setLetterSpacing(letterSpacing) - } - - override fun setHorizontallyScrolling(whether: Boolean) { - super.setHorizontallyScrolling(false) - } - - override fun setLineSpacing(add: Float, mult: Float) { - if (add != lineSpacingExtra || mult != lineSpacingMultiplier) { - needPaginate = true - } - super.setLineSpacing(add, mult) - } - - override fun setMaxLines(maxLines: Int) { - if (maxLines != this.maxLines) { - needPaginate = true - } - - super.setMaxLines(maxLines) - } - - override fun setLines(lines: Int) { - super.setLines(lines) - - if (lines != this.lineCount) { - needPaginate = true - } - } - - override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { - super.onSizeChanged(w, h, oldw, oldh) - pageHeight = h - (paddingTop + paddingBottom) // 마진 제외 - } - - override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { - super.onLayout(changed, left, top, right, bottom) - Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}") - if (changed || needPaginate) { - paginate() - setPageText() - needPaginate = false - } - - } - fun doUpdate() { - if (needPaginate && layout != null) { - paginate() - setPageText() - needPaginate = false - } - } - private fun paginate() { - if (layout != null) { - MainScope().launch { - pageList.clear() -// Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}") - val layout = from(layout) - val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 1} else {min(maxLines, layout.lineCount)} - var startOffset = 0 - val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom) - var height = heightWithoutPaddings - - for (i in 0 until lines) { - if (height < layout.getLineBottom(i)) { - pageList.add( - layout.text.subSequence(startOffset, layout.getLineStart(i)) - ) - startOffset = layout.getLineStart(i) - height = layout.getLineTop(i) + heightWithoutPaddings - } - - if (i == lines - 1) { - pageList.add( - if(layout.lineCount > i) { - layout.text.subSequence(startOffset, layout.getLineEnd(i + 1)) - } else { - layout.text.subSequence(startOffset, layout.getLineEnd(i)) - } - ) - - } - } - mPagedTextGenerateInterface?.completePagination(pageList) - } - } - } - - private fun from(layout: Layout): Layout = - if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { - @Suppress("DEPRECATION") - StaticLayout( - originalText, - paint, - layout.width - paddingLeft - paddingRight, // margin 제외 - layout.alignment, - lineSpacingMultiplier, - lineSpacingExtra, - includeFontPadding - ) - } else { - StaticLayout.Builder - .obtain( - originalText, 0, originalText.length, paint, - (layout.width - paddingLeft - paddingRight) - ) - .setAlignment(layout.alignment) - .setLineSpacing(lineSpacingExtra, lineSpacingMultiplier) - .setIncludePad(includeFontPadding) - .setUseLineSpacingFromFallbacks() - .setBreakStrategy(breakStrategy) - .setHyphenationFrequency(hyphenationFrequency) - .setMaxLines(maxLines) - .build() - } - - private fun StaticLayout.Builder.setUseLineSpacingFromFallbacks(): StaticLayout.Builder { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) { - this.setUseLineSpacingFromFallbacks(isFallbackLineSpacing) - } - - return this - } - - private fun StaticLayout.Builder.setJustificationMode(): StaticLayout.Builder { - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { - this.setJustificationMode(justificationMode) - } - - return this - } - -} interface PagedTextGenerateInterface { fun completePagination(pageList: ArrayList) @@ -297,26 +59,95 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { var mainTextView : TextView? = null var sencondTextView : TextView? = null var demp : View? = null - var hiddenTextView : PagedTextView? = null +// var hiddenTextView : PagedTextView? = null var guideLine : Guideline? = null - var pageList: ArrayList? = null + var pageList = mutableListOf() var summaryText : String = "" var text : String = "" set(new) { -// Blog.LOGE("field >> ${field}") -// Blog.LOGE("new >> ${new}") field = new val summary = new.replace(" " ,"").replace("\n" ,"").substring(0,Math.min(30,new.length)) - if (summary.equals(summaryText)) { + if (summary.equals(summaryText) && summaryText.length > 100) { } else { -// Blog.LOGE("field >> ${field}") - hiddenTextView?.setTxtF(field) - hiddenTextView?.visibility = VISIBLE + if (field.length > 0) { + post { + if (width > 0 && height > 0) { + MainScope().launch { + pageList.clear() + val contentWidth = + mainTextView!!.width - (mainTextView!!.paddingLeft + mainTextView!!.paddingRight) + val contentHeight = + mainTextView!!.height - (mainTextView!!.paddingTop + mainTextView!!.paddingBottom) + val pages = paginateAsync(text, contentWidth, contentHeight) + pageList.addAll(pages) + Blog.LOGE("pages >>> ${pages.size}") + setPageBy(0) + } + } + } + } } summaryText = summary } + suspend fun paginateAsync(text: CharSequence, width: Int, height: Int): List = withContext(Dispatchers.Default) { + val resultPages = ArrayList() + val paint = mainTextView?.paint ?: TextPaint() + val lineSpacingMult = mainTextView?.lineSpacingMultiplier ?: 1.0f + val lineSpacingAdd = mainTextView?.lineSpacingExtra ?: 1.0f + val letterSpacing = mainTextView?.letterSpacing ?: 1.0f + val includePad = false + Blog.LOGE("text ${text.length}, width $width, height $height") + // 1. 전체 텍스트에 대한 StaticLayout 생성 (API 버전에 따른 분기 처리 권장) + val layout = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) { + StaticLayout.Builder.obtain(text, 0, text.length, paint, width) + .setAlignment(Layout.Alignment.ALIGN_NORMAL) + .setLineSpacing(lineSpacingAdd, lineSpacingMult) + .setIncludePad(includePad) + .build() + } else { + @Suppress("DEPRECATION") + StaticLayout(text, paint, width, Layout.Alignment.ALIGN_NORMAL, lineSpacingMult, lineSpacingAdd, includePad) + } + val totalLines = layout.lineCount + var startLine = 0 + var startOffset = 0 + + // 2. 라인 정보를 순회하며 높이 계산 + while (startLine < totalLines) { + // 현재 페이지의 시작 y 좌표 + val pageTopY = layout.getLineTop(startLine) + // 현재 페이지가 끝날 수 있는 최대 y 좌표 + val targetBottomY = pageTopY + height + + // 이 페이지에 들어갈 수 있는 마지막 라인 찾기 + var endLine = layout.getLineForVertical(targetBottomY) + + // getLineForVertical은 정확한 좌표가 없으면 마지막 라인을 반환하므로 검증 필요 + if (layout.getLineBottom(endLine) > targetBottomY) { + endLine-- + } + + // 한 줄도 못 들어가는 경우(폰트가 뷰보다 큰 경우 등) 방어 코드 + if (endLine < startLine) endLine = startLine + + // 페이지 범위의 텍스트 추출 + // endLine의 끝 오프셋을 가져옴 + val endOffset = layout.getLineEnd(endLine) + + // 텍스트 자르기 (subSequence는 메모리 복사를 최소화함) + if (startOffset < endOffset) { + resultPages.add(text.subSequence(startOffset, endOffset)) + } + + // 다음 페이지 준비 + startOffset = endOffset + startLine = endLine + 1 + } + + return@withContext resultPages + } private val hanler = Handler() var mPagedTextViewInterface : PagedTextViewInterface? = null val touchTimeover = Runnable { @@ -328,11 +159,8 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { inflate(context, R.layout.layout_textviewer, this) mainTextView = findViewById(R.id.first_view) sencondTextView = findViewById(R.id.sencond_view) - demp = findViewById(R.id.demp) currentPageTextView = findViewById(R.id.current_page) - hiddenTextView = findViewById(R.id.hidden_view) - hiddenTextView?.mPagedTextGenerateInterface = this currentPageTextView?.text = "" hanler.removeCallbacks(touchTimeover) setOnLongClickListener { v -> @@ -450,8 +278,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { super.onLayout(changed, left, top, right, bottom) Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}") if(changed) { - hiddenTextView?.text = text - forceUpdateUI() +// forceUpdateUI() } } override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) { @@ -470,14 +297,12 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { var currentPage = 0 override fun completePagination(pageList: ArrayList) { -// Blog.LOGD(log = "completePagination>> ${this::class.java.name} >> pageList ${pageList}") if(text.length > 0 && pageList!= null && pageList.size == 0) { } else { this.pageList = pageList setPageBy(0) } - hiddenTextView?.visibility = GONE } var defaultAlpha = 171 fun setColorStyle(colors : Array) { @@ -490,11 +315,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { sencondTextView?.setTextColor(Color.parseColor("#FFFFFF")) } -// fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface) -// fun setText(replace: String) = hiddenTextView?.setText(replace) - fun setTextSize(fl: Float) { - hiddenTextView?.setTextSize(fl) mainTextView?.setTextSize(fl) sencondTextView?.setTextSize(fl) } @@ -508,22 +329,38 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { } fun setPageBy(num : Int) { - this@PagedTextLayout.currentPage = num - var realPage = if(isDualPage()) this@PagedTextLayout.currentPage * 2 else this@PagedTextLayout.currentPage - Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1 }}") - realPage = if(pageList?.size ?: 0 > realPage) { realPage} else { (pageList?.size ?: 0) - 1 } - currentPageTextView?.text = "${realPage + 1 }/${ pageList?.size ?: 0 + 1}" + if (pageList.size > 0) { + this@PagedTextLayout.currentPage = num + var realPage = if (isDualPage()) this@PagedTextLayout.currentPage * 2 else this@PagedTextLayout.currentPage + Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1}}") + realPage = if (pageList?.size ?: 0 > realPage) { + realPage + } else { + (pageList?.size ?: 0) - 1 + } + currentPageTextView?.text = "${realPage + 1}/${pageList?.size ?: 0 + 1}" - mainTextView?.text = pageList?.get(realPage) ?: "NONE" - if(isDualPage()) { - realPage = realPage.inc() - sencondTextView?.text = if(pageList?.size ?: 0 > realPage) { pageList?.get(realPage)} else { "끝"} - } else { - sencondTextView?.text = "" + mainTextView?.text = pageList?.get(realPage) ?: "NONE" + Blog.LOGE("pageList.get($realPage) ${pageList?.get(realPage)}") + if (isDualPage()) { + realPage = realPage.inc() + sencondTextView?.text = if (pageList?.size ?: 0 > realPage) { + pageList?.get(realPage) + } else { + "끝" + } + } else { + sencondTextView?.text = "" + } } } - fun size(): Int = if(isDualPage()) Math.round((hiddenTextView?.size() ?:0) * 0.5f) else hiddenTextView?.size() ?: 0 + fun size(): Int = (if(isDualPage()) { + Math.round(pageList.size * 0.5f) + }else { + pageList.size + }) + fun getFastPageCount() = if(isDualPage()) 3 else 6 fun current(): Int = this@PagedTextLayout.currentPage fun doNext(fast : Boolean = false) { @@ -547,33 +384,26 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { } } - fun forceUpdateUI() { - hiddenTextView?.doUpdate() - } override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) { - hiddenTextView?.setPadding(left,top,right, bottom) mainTextView?.setPadding(left,top,right, bottom) sencondTextView?.setPadding(left,top,right, bottom) } fun setTypeface(tf: Typeface?) { - hiddenTextView?.setTypeface(tf) mainTextView?.setTypeface(tf) sencondTextView?.setTypeface(tf) } @TargetApi(Build.VERSION_CODES.LOLLIPOP) fun setLetterSpacing(letterSpacing: Float) { - hiddenTextView?.letterSpacing = letterSpacing.times(0.01f) mainTextView?.letterSpacing = letterSpacing.times(0.01f) sencondTextView?.letterSpacing = letterSpacing.times(0.01f) } fun setLineSpacing(mult: Float) { - hiddenTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f))) mainTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f))) sencondTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f))) } diff --git a/app/src/main/res/layout/layout_textviewer.xml b/app/src/main/res/layout/layout_textviewer.xml index f19bfa39..b377d4b8 100644 --- a/app/src/main/res/layout/layout_textviewer.xml +++ b/app/src/main/res/layout/layout_textviewer.xml @@ -6,32 +6,6 @@ android:layout_margin="5dp" xmlns:app="http://schemas.android.com/apk/res-auto"> - - - - -