Compare commits

...

10 Commits

Author SHA1 Message Date
a6d54b7f17 ... 2025-02-11 13:42:22 +09:00
a2d90b16bf ... 2025-02-11 13:25:17 +09:00
lunaticbum
fc5f17018a ... 2024-11-18 18:04:29 +09:00
lunaticbum
e8ed60f300 ... 2024-11-18 17:36:26 +09:00
aa6fa8a79e ... 2024-09-20 14:04:34 +09:00
0fff1f5aa3 ... 2024-09-07 18:34:52 +09:00
ac6523b2dd ... 2024-09-07 17:55:28 +09:00
f5003d9378 Merge branch 'main' of https://bitbucket.org/gbumhan/tokkiz
# Conflicts:
#	app/src/main/java/com/mime/dualscreenview/webcontents/BaseWebContentsViewer.kt
.
2024-09-07 16:13:11 +09:00
c393439a85 . 2024-09-07 16:12:05 +09:00
lunaticbum
3b1c4a6403 ... 2024-08-26 18:35:11 +09:00
63 changed files with 489 additions and 197 deletions

View File

@ -64,7 +64,7 @@ dependencies {
implementation 'com.google.code.gson:gson:2.10.1'
// implementation files('libs/DualScreen.jar')
implementation ("org.jsoup:jsoup:1.18.1")
implementation 'io.realm.kotlin:library-base:2.0.0'

Binary file not shown.

View File

@ -1,24 +0,0 @@
package com.mime.dualscreenview
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.ext.junit.runners.AndroidJUnit4
import org.junit.Test
import org.junit.runner.RunWith
import org.junit.Assert.*
/**
* Instrumented test, which will execute on an Android device.
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
@RunWith(AndroidJUnit4::class)
class ExampleInstrumentedTest {
@Test
fun useAppContext() {
// Context of the app under test.
val appContext = InstrumentationRegistry.getInstrumentation().targetContext
assertEquals("com.mime.dualscreenview", appContext.packageName)
}
}

View File

@ -14,6 +14,7 @@
android:usesCleartextTraffic="true"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:largeHeap="true"
android:theme="@style/Theme.DualScreenView"
tools:targetApi="31" >

View File

@ -15,6 +15,7 @@ import android.view.KeyEvent.KEYCODE_MEDIA_REWIND
import android.view.KeyEvent.KEYCODE_VOLUME_DOWN
import android.view.KeyEvent.KEYCODE_VOLUME_MUTE
import android.view.KeyEvent.KEYCODE_VOLUME_UP
import android.view.MotionEvent
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import com.mime.dualscreenview.common.Blog
@ -57,6 +58,55 @@ open class Base : AppCompatActivity() {
}
var actionButtonPressX = 0f
var actionButtonPressY = 0f
override fun dispatchGenericMotionEvent(ev: MotionEvent?): Boolean {
if (ev?.device?.name?.contains("BLE-M3") == true) {
Blog.LOGE("keyEvent >>>>> dispatchGenericMotionEvent ${ev}")
ev?.action?.let { action ->
when(action) {
MotionEvent.ACTION_HOVER_ENTER -> {
return false
}
MotionEvent.ACTION_HOVER_MOVE ->{return false}
MotionEvent.ACTION_BUTTON_PRESS ->{
if (actionButtonPressX * actionButtonPressY == 0f) {
actionButtonPressX = ev.x ?: 0f
actionButtonPressY = ev.y ?: 0f
}
return true
}
MotionEvent.ACTION_BUTTON_RELEASE ->{
if (actionButtonPressY == ev.y) {
if (actionButtonPressX.minus(ev.x ?: 0f) > 0f) {
Blog.LOGE("Arrow Right Click")
onKeyClick(KeyEvent.KEYCODE_VOLUME_DOWN)
} else {
Blog.LOGE("Arrow Left Click")
onKeyClick(KeyEvent.KEYCODE_VOLUME_UP)
}
} else {
if (actionButtonPressY.minus(ev.y ?: 0f) > 0f) {
Blog.LOGE("Arrow Down Click")
} else {
Blog.LOGE("Arrow Up Click")
}
}
return false
}
MotionEvent.ACTION_HOVER_EXIT ->{
actionButtonPressX = 0f
actionButtonPressY = 0f
return false
}
else -> {return false}
}
}
}
return super.dispatchGenericMotionEvent(ev)
}
override fun onKeyDown(keyCode: Int, event: KeyEvent?): Boolean {
Blog.LOGD(log = "keyCode : ${keyCode}, event : ${event}")

View File

@ -5,7 +5,6 @@ import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.res.Configuration
import android.graphics.Bitmap
import android.net.ConnectivityManager
import android.net.Uri
import android.os.Build
import android.os.Bundle
@ -16,11 +15,12 @@ import android.text.InputType
import android.text.SpannableStringBuilder
import android.text.style.RelativeSizeSpan
import android.util.Log
import android.view.Gravity
import android.view.KeyEvent
import android.view.View
import android.view.View.GONE
import android.view.View.VISIBLE
import android.view.View.inflate
import android.webkit.JavascriptInterface
import android.webkit.WebSettings
import android.webkit.WebView
import android.webkit.WebViewClient
@ -55,11 +55,12 @@ import com.mime.dualscreenview.view.PagedTextViewInterface
import com.mime.dualscreenview.view.TouchArea
import com.mime.dualscreenview.webcontents.BaseWebContentsViewer
import com.mime.dualscreenview.webcontents.MainControllInterface
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere
import com.mime.dualscreenview.webcontents.contentsinfo.NewtokiOne
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.copyFromRealm
import io.realm.kotlin.ext.query
import org.jsoup.Jsoup
import java.lang.System.currentTimeMillis
import java.text.SimpleDateFormat
import java.util.Date
@ -88,7 +89,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
fun getCurrentUrl() : String {
var currentPath = currentBooinfo?.pathUrl ?: mBaseWebContentsViewer.webview.url?.toUri()?.path ?: ""
var domain = PrefManager.getLastDomain()
return domain.plus("/").plus(if (currentPath.length > 4) currentPath else "")
return domain.plus(if (currentPath.length > 4) currentPath else "")
}
override fun onConfigurationChanged(newConfig: Configuration) {
@ -119,7 +120,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
mBaseWebContentsViewer?.webview?.url?.let {
Uri.parse(it).path?.let {
HistoryManager.getBookInfos(it, {
it?.let { showList(it) }
it?.let {
it.pages.sortBy { it.pathUrl }
showList(it)
}
})
}
}
@ -127,6 +131,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
binding.hiddenWeb?.let { v->
contentsSaver = v
contentsSaver?.webViewClient = saveClient
try {
contentsSaver?.removeJavascriptInterface("MyJavaScriptInterface")
} catch (e:Exception) {e.printStackTrace()}
contentsSaver?.addJavascriptInterface(SaveHelper(),"MyJavaScriptInterface")
contentsSaver?.settings?.textZoom = 100
contentsSaver?.settings?.javaScriptEnabled = true
contentsSaver?.settings?.javaScriptCanOpenWindowsAutomatically = false
@ -155,7 +163,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
binding.btnHome.setOnClickListener { v->
paged_layer.visibility = GONE
mBaseWebContentsViewer.loadContents(Booktoki)
mBaseWebContentsViewer.loadContents(NewtokiOne)
}
loadLastInfo()
@ -169,7 +177,6 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
HistoryManager.getBookPageInfo(Uri.parse(lastInfo!!.pageUrl!!).path!!) {
it?.let {
currentBooinfo = it
paged_layer.text = it!!.contents!!
paged_layer.visibility = VISIBLE
if(it?.pathUrl?.length ?: 0 > 0) {
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
@ -178,8 +185,8 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
Blog.LOGE("HistoryManager.getNextPage(${lastInfo?.pageUrl})")
mBaseWebContentsViewer.webview.loadUrl(lastInfo!!.pageUrl!!.replace(Uri.parse(lastInfo!!.pageUrl)!!.path!!,it?.pathUrl!!))
} else {
Blog.LOGE("HistoryManager.getNextPage(${Booktoki.getLastedDoamin()})")
mBaseWebContentsViewer.webview.loadUrl(Booktoki.getLastedDoamin() + it?.pathUrl!!)
Blog.LOGE("HistoryManager.getNextPage(${NewtokiOne.getLastedDoamin()})")
mBaseWebContentsViewer.webview.loadUrl(NewtokiOne.getLastedDoamin() + it?.pathUrl!!)
}
it?.pathUrl?.let {
HistoryManager.getBookInfos(it) {
@ -191,26 +198,11 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
HistoryManager.openRealm.query<ReaderConfig>()?.find()?.let {
if (it.size > 0) {
realm.copyFromRealm(it.first()).let {
runOnUiThread {
paged_layer.setTextSize(it.textSize?.toFloat()?: 14f)
paged_layer.setLineSpacing(it.lineSpace?.toFloat() ?: 1f)
paged_layer.setLetterSpacing(it.letterSpace?.toFloat() ?: 1f)
paged_layer.setPadding(
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1)
var typeface = typesfacez.get(getIndex(typesfacez as PairArray<Any>,it.font ?: ""))
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
paged_layer.setTypeface(resources.getFont(typeface.second))
}
val color = colorz.get(it.style ?: 0)
paged_layer.setColorStyle(color.second)
}
applyReaderConfig()
}
}
}
paged_layer.text = it!!.contents!!
}
}
}
@ -227,8 +219,15 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
}
}
override fun onBookInfos(aInfos: BookPageInfos) {
Blog.LOGE("onBookInfos(aInfos: ${aInfos})")
runOnUiThread {
showList(aInfos)
}
}
override fun onBookInfos(jsonString: String) {
Blog.LOGE("onBookInfos" , "onBookInfos >> ${jsonString}")
Blog.LOGE("onBookInfos" , "jsonString >> ${jsonString}")
val realm = openRealm()
var infos : BookPageInfos? = null
realm.writeBlocking {
@ -267,7 +266,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
infos?.bookPageUrl?.let {
HistoryManager.getBookInfos(it){
it?.let {
Blog.LOGE("onBookInfos" , "onBookInfos it >> ${it}")
Blog.LOGE(s(), "onBookInfos it >> ${it}")
runOnUiThread {
showList(it)
}
@ -278,12 +277,14 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
}
}
private fun s() = "onBookInfos"
fun reloadTo(lastInfo: LastInfo?) {
findViewById<WebView>(R.id.menu_web)?.postDelayed({
if (lastInfo != null) {
mBaseWebContentsViewer.loadLastInfo(lastInfo!!)
} else {
mBaseWebContentsViewer.loadContents(Booktoki)
mBaseWebContentsViewer.loadContents(NewtokiOne)
}
},200L)
}
@ -377,16 +378,18 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
}
fun showList(infos: BookPageInfos) {
Blog.LOGE("showList infos >>>>${infos}")
if (infos != null && infos.pages.size ?: 0 > 0) {
var items : ArrayList<BookPageInfo> = arrayListOf()
for (item in infos.pages) {
items.add(item)
}
items.sortBy { it.chapterNum }
items.sortBy { it.chapterID }
DefaultList.showDefaultList(
this@Intro,
"현제는 ${currentTitle} - ${(infos.pages.size ?: 0) - currentChapter} -> 다른화를 골라",
"현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라",
items,
currentChapter,
{ position ->
@ -417,69 +420,77 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
var isLoading = false
var saveClient = object : WebViewClient() {
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
isLoading = true
Blog.LOGE("saveClient >>> ${isLoading} ${url}")
}
override fun onPageFinished(webView: WebView?, url: String?) {
super.onPageFinished(webView, url)
isLoading = false
webView?.postDelayed({ autoScrollDown(webView, url) },(1300L + Random(System.currentTimeMillis()).nextLong().rem(1286L)))
}
fun showToast(origin: String) {
runOnUiThread {
val biggerText = SpannableStringBuilder(origin)
biggerText.setSpan(RelativeSizeSpan(1.6f), 0, origin.length, 0)
Toast.makeText(
baseContext,
biggerText,
Toast.LENGTH_SHORT
).show()
}
}
fun autoScrollDown(webView: WebView?, url: String?) {
webView?.let { webView ->
val ramdomTimeSec =
800L.plus(Random(System.currentTimeMillis()).nextLong().rem(789L))
Blog.LOGE("ramdomTime >>> ${ramdomTimeSec}")
if (((webView?.scrollY ?: 0) + (webView?.height
?: 0)) < webView?.contentHeight ?: 0
) {
webView?.postDelayed({
webView?.pageDown(false)
autoScrollDown(webView, url)
}, ramdomTimeSec)
} else {
webView?.postDelayed({
var findContents = Booktoki.getFindContentsJs()
webView?.evaluateJavascript(findContents) { result: String? ->
result?.let { string: String ->
if (string.length > 10) {
val contents = string.replace("\\\"", "\"")
.replace("\\n", System.getProperty("line.separator"))
.replace("\\n", System.getProperty("line.separator"))
Uri.parse(url)?.let {
it.path?.let {
HistoryManager.getBooPageInfoContentsSave(it, contents.replace(Char(0x20).toString(), " "))
HistoryManager.getBookPageInfo(it) { info ->
info?.let { showToast(info.getTitleItem()) }
}
}
}
override fun onPageFinished(webView: WebView?, url: String?) {
super.onPageFinished(webView, url)
// val delayed = 3500L + Math.abs(Random.nextLong().rem(9999L))
finishedUrl = url ?: ""
webView?.postDelayed({
webView?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
isLoading = false
}
}, delayed)
}
}
fun showToast(origin: String) {
runOnUiThread {
val toast = Toast(this)
toast.duration = Toast.LENGTH_SHORT
val biggerText = SpannableStringBuilder(origin)
biggerText.setSpan(RelativeSizeSpan(1.6f), 0, origin.length, 0)
val view: View = inflate(this, com.mime.dualscreenview.R.layout.simple_toast,null)
view.findViewById<TextView>(com.mime.dualscreenview.R.id.text).text = biggerText
toast.setView(view)
toast.show()
// Toast.makeText(
// baseContext,
// biggerText,
// Toast.LENGTH_SHORT
// ).show()
}
}
var delayed = 3500L + Math.abs(Random.nextLong().rem(9999L))
var finishedUrl : String? = null
inner class SaveHelper {
@JavascriptInterface
fun sendValueFromHtml(string: String) {
Jsoup.parse(string)?.let { html ->
val view_padding = html.getElementsByClass("view-padding")
if (view_padding.size > 0){
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
val contents = view_padding.get(0).children().html().replace("<p>"," ").replace("</p>","\n\n")
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: view_padding.get(0)\n${contents}")
if (contents.length > 20) {
Uri.parse(finishedUrl).path?.let {
delayed = 3500L + Math.abs(Random.nextLong().rem(9999L))
HistoryManager.getBooPageInfoContentsSave(it, contents).apply {
HistoryManager.getBookPageInfo(it) { book ->
showToast("saved ${book?.getTitleItem()} \n:: lenght = ${contents.length} \n:: saveTarget = ${saveTarget.size}\n:: delayed >> ${delayed}")
}
var ramdomTime = 2000L.plus(Random(System.currentTimeMillis()).nextLong().rem(1785L))
Blog.LOGE("afterNextPageTime >>> ${ramdomTime}")
contentsSaver?.postDelayed({ saveItem(null) }, ramdomTime)
}.apply {
HistoryManager.getBookInfos(it) { saveItem(it)}
}
}
}, ramdomTimeSec)
}
} else {
}
}
}
}
var saveTarget : ArrayList<BookPageInfo> = arrayListOf()
private fun saveItem(infos: BookPageInfos?) {
Blog.LOGE("saveItem >>> infos?.pages ${infos?.pages?.size ?: 0}")
@ -506,10 +517,9 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
}
}
Blog.LOGE("saveItem >>> saveTarget ${saveTarget.count()}")
if (isLoading == false) {
try {
try {
if (isLoading == false) {
saveTarget.removeFirst().let {
Blog.LOGE("saveItem >>> ${it.pathUrl}")
runOnUiThread {
@ -522,11 +532,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
}
}
}
} catch ( e : Exception) {
e.printStackTrace()
}
} catch ( e : Exception) {
e.printStackTrace()
}
}
private fun moveTo(item: BookPageInfo?) {
@ -592,22 +601,27 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
fun contentsLoad(pathUrl : String) {
HistoryManager.getBookPageInfo(pathUrl) {
Blog.LOGE("contentsLoad :::: pathUrl >> ${pathUrl}")
it?.pathUrl?.let {
HistoryManager.getBookInfos(it) { saveItem(it) }
Blog.LOGE("contentsLoad :::: pathUrl >> ${it}")
HistoryManager.getBookInfos(it) {
Blog.LOGE("contentsLoad :::: getBookInfos >> ${it}")
saveItem(it)
}
}
if (it != null) currentBooinfo = it
if (it != null && (it?.contents?.length ?: 0) > 10) {
paged_layer.visibility = VISIBLE
paged_layer.text = it!!.contents!!
if((it?.pathUrl?.length ?: 0) > 0) {
if (lastInfo?.pageUrl?.length ?: 0 > 0 && lastInfo?.pageUrl!!.startsWith("http")) {
mBaseWebContentsViewer.webview.loadUrl(lastInfo!!.pageUrl!!.replace(Uri.parse(lastInfo!!.pageUrl)!!.path!!,it?.pathUrl!!))
} else {
mBaseWebContentsViewer.webview.loadUrl(Booktoki.getLastedDoamin() + it?.pathUrl!!)
mBaseWebContentsViewer.webview.loadUrl(NewtokiOne.getLastedDoamin() + it?.pathUrl!!)
}
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
}
applyReaderConfig()
paged_layer.text = it!!.contents!!
} else {
if(it?.pathUrl?.length ?: 0 > 0) {
if (lastInfo?.pageUrl?.length ?: 0 > 0 && lastInfo?.pageUrl!!.startsWith("http")) {
@ -615,7 +629,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
mBaseWebContentsViewer.webview.loadUrl(lastInfo!!.pageUrl!!.replace(Uri.parse(lastInfo!!.pageUrl)!!.path!!,it?.pathUrl!!))
} else {
paged_layer.visibility = GONE
mBaseWebContentsViewer.webview.loadUrl(Booktoki.getLastedDoamin() + it?.pathUrl!!)
mBaseWebContentsViewer.webview.loadUrl(NewtokiOne.getLastedDoamin() + it?.pathUrl!!)
}
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
}
@ -656,16 +670,18 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
paged_layer?.setTypeface(resources.getFont(typeface.second))
}
paged_layer.setPadding(
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1)
val color = colorz.get(it.style ?: 0)
paged_layer?.setColorStyle(color.second)
paged_layer.setTextSize(it.textSize?.toFloat()?: 14f)
paged_layer.setLineSpacing(it.lineSpace?.toFloat() ?: 1f)
paged_layer.setLetterSpacing(it.letterSpace?.toFloat() ?: 1f)
paged_layer.setPadding(
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1,
it.padding ?: 1)
paged_layer.invalidate()
}
}
}
@ -721,34 +737,41 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
@RequiresApi(Build.VERSION_CODES.O)
override fun onLoadedContents(aContents: String) {
paged_layer.apply {
if (aContents != null && aContents.length > 10) {
var contents = aContents.replace("\\\"","\"")
contents = (contents.replace("\\n", System.getProperty("line.separator")))
contents = (contents.replace("\\n", System.getProperty("line.separator")))
mPagedTextViewInterface = this@Intro
if(lastInfo != null && mBaseWebContentsViewer.webview.url?.endsWith(lastInfo!!.pageUrl) ?: false) {
binding.progress.visibility = VISIBLE
paged_layer.postDelayed({
binding.progress.visibility = GONE
},1000)
}
applyReaderConfig()
runOnUiThread {
text = contents
visibility = VISIBLE
}
forceUpdateUI()
mBaseWebContentsViewer.webview.url?.let {
Uri.parse(it)?.let {
it.path?.let {
HistoryManager.getBookPageInfo(it){
currentBooinfo = it
currentChapter = it?.chapterNum ?: 0
currentPage = it?.chapterNum ?: 0
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
paged_layer.post {
if (aContents != null && aContents.length > 10) {
var contents = aContents.replace("\\\"", "\"")
contents = (contents.replace("\\n", System.getProperty("line.separator")))
contents = (contents.replace("\\n", System.getProperty("line.separator")))
mPagedTextViewInterface = this@Intro
if (lastInfo != null && mBaseWebContentsViewer.webview.url?.endsWith(lastInfo!!.pageUrl) ?: false) {
binding.progress.visibility = VISIBLE
paged_layer.postDelayed({
binding.progress.visibility = GONE
}, 1000)
}
applyReaderConfig()
runOnUiThread {
text = contents
visibility = VISIBLE
}
forceUpdateUI()
mBaseWebContentsViewer.webview.url?.let {
Uri.parse(it)?.let {
it.path?.let {
HistoryManager.getBookPageInfo(it) {
currentBooinfo = it
currentChapter = it?.chapterNum ?: 0
currentPage = it?.chapterNum ?: 0
HistoryManager.save(
historyItem = HistoryItem().putHistory(
it,
mBaseWebContentsViewer.webview.url!!
)
)
}
}
HistoryManager.getBooPageInfoContentsSave(it!!.path!!, contents)
}
HistoryManager.getBooPageInfoContentsSave(it!!.path!!,contents)
}
}
}

View File

@ -13,7 +13,21 @@ val colorz : PairArray<Array<String>> = arrayOf<Pair<String,Array<String>>>(
Pair("color set 07",arrayOf<String>("#F8BBD0", "#263238")),
Pair("color set 08",arrayOf<String>("#E6EE9C", "#455A64")),
Pair("color set 09",arrayOf<String>("#CFD8DC", "#455A64")),
Pair("color set 10",arrayOf<String>("#FFF59D", "#37474F"))
Pair("color set 10",arrayOf<String>("#FFF59D", "#37474F")),
Pair("color set 21",arrayOf<String>("#263238","#E1F5FE")),
Pair("color set 22",arrayOf<String>("#37474F","#F0F4C3")),
Pair("color set 23",arrayOf<String>("#455A64","#ECEFF1")),
Pair("color set 24",arrayOf<String>("#263238","#E0F7FA")),
Pair("color set 25",arrayOf<String>("#263238","#F5F5F5")),
Pair("color set 26",arrayOf<String>("#263238","#ECEFF1")),
Pair("color set 27",arrayOf<String>("#263238","#F8BBD0")),
Pair("color set 28",arrayOf<String>("#455A64","#E6EE9C")),
Pair("color set 29",arrayOf<String>("#455A64","#CFD8DC")),
Pair("color set 30",arrayOf<String>("#37474F","#FFF59D")),
Pair("color set 31",arrayOf<String>("#FFFFFF","#1C1B1B")),
Pair("color set 32",arrayOf<String>("#272727","#FFFFFF")),
Pair("color set 33",arrayOf<String>("#1C1B1B","#FFFFFF")),
Pair("color set 34",arrayOf<String>("#FFFFFF","#272727"))
)
val typesfacez : PairArray<Int> = arrayOf<Pair<String,Int>>(
Pair("정선 아리랑 혼", R.font.jsarirang_hon),
@ -22,6 +36,37 @@ val typesfacez : PairArray<Int> = arrayOf<Pair<String,Int>>(
Pair("손기정체", R.font.kcc_sonkeechung),
Pair("교보 손글씨", R.font.kyobo_handwriting_2021sjy),
Pair("태백 은하수", R.font.taebaek_milkyway),
Pair("taebaek_milkyway",R.font.taebaek_milkyway),
Pair("kccahnjunggeun",R.font.kccahnjunggeun),
Pair("kotra_songeulssi",R.font.kotra_songeulssi),
Pair("kotra_bold",R.font.kotra_bold),
Pair("cafe24oneprettynight",R.font.cafe24oneprettynight),
Pair("nnsgc_wsjidyp",R.font.nnsgc_wsjidyp),
Pair("nnsgc_yjc",R.font.nnsgc_yjc),
Pair("nnsgc_brhp",R.font.nnsgc_brhp),
Pair("nnsgc_md",R.font.nnsgc_md),
Pair("nnsgc_gd_an_gd",R.font.nnsgc_gd_an_gd),
Pair("dovemayo",R.font.dovemayo),
Pair("gabia_solmee",R.font.gabia_solmee),
Pair("ylee_mortal_heart_immortal_memory",R.font.ylee_mortal_heart_immortal_memory),
Pair("kcc_kimhoon",R.font.kcc_kimhoon),
Pair("taefont_tsthlml",R.font.taefont_tsthlml),
Pair("ssshinb7",R.font.ssshinb7),
Pair("godomaum",R.font.godomaum),
Pair("tvn_jguiyg_medium",R.font.tvn_jguiyg_medium),
Pair("tvn_jguiyg_light",R.font.tvn_jguiyg_light),
Pair("on_jsuhr",R.font.on_jsuhr),
Pair("on_jsuhl",R.font.on_jsuhl),
Pair("on_ychyuhr",R.font.on_ychyuhr),
Pair("on_ychyuhl",R.font.on_ychyuhl),
Pair("on_treeususimgul_r",R.font.on_treeususimgul_r),
Pair("on_treeususimgul",R.font.on_treeususimgul),
Pair("on_wibsr",R.font.on_wibsr),
Pair("on_wisbl",R.font.on_wisbl),
Pair("on_sbsjl",R.font.on_sbsjl),
Pair("on_sbsjr",R.font.on_sbsjr),
Pair("wandohoper",R.font.wandohoper),
Pair("ebs_r",R.font.ebs_r),
)
@JvmName("getIndexAny")

View File

@ -3,6 +3,7 @@ package com.mime.dualscreenview.common
import android.content.Context
import android.content.SharedPreferences
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.NewtokiOne
object PrefManager {
private val mainName = "Main_Pref_"
@ -20,7 +21,7 @@ object PrefManager {
}
fun getLastDomain() : String {
return main.getString(domainKey, Booktoki.getLastedDoamin()) ?: Booktoki.getLastedDoamin()
return main.getString(domainKey, NewtokiOne.getLastedDoamin()) ?: NewtokiOne.getLastedDoamin()
}
fun putLastDomain(domain : String) {
Blog.LOGE("domain >>> ${domain}")

View File

@ -61,12 +61,17 @@ object HistoryManager {
url = url.replace("//","/").trim()
}
}
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0 || bookPageUrl == $1","${url}","${url}").find()
Blog.LOGE("aUrl >>> ${aUrl}")
Blog.LOGE("aUrl >>> ${aUrl}")
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0 || bookPageUrl == $0","${url}").find()
if (bookPageInfo != null && bookPageInfo.count() > 0) {
Blog.LOGE("get ${bookPageInfo}" )
this.query(BookPageInfos::class,"bookPageUrl == $0",bookPageInfo.first().bookPageUrl).find().first().let {
Blog.LOGE("get ${it} , ${it?.pages}" )
callback.invoke(this.copyFromRealm(it))
var pgs = this.query(BookPageInfos::class,"bookPageUrl == $0", bookPageInfo.first().bookPageUrl).find()
if (pgs.size > 0) {
pgs.first().let {
Blog.LOGE("get ${it} , ${it?.pages}")
callback.invoke(this.copyFromRealm(it))
}
}
} else {
callback.invoke(null)

View File

@ -286,9 +286,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
}
fun forceUpdateUI() {
// mPagedTextViewInterface?.onTouch(TouchArea.Center)
hiddenTextView?.doUpdate()
// hanler?.postDelayed(touchTimeover, 3000L)
}
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {

View File

@ -162,7 +162,7 @@ class PagedTextView : AppCompatTextView {
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
super.onSizeChanged(w, h, oldw, oldh)
Blog.LOGD(log = "onSizeChanged>> ${this::class.java.name}")
pageHeight = ((h - (marginTop + marginBottom + paddingTop + paddingBottom)) * 0.8f).toInt()
pageHeight = ((h - (marginTop + marginBottom + paddingTop + paddingBottom)) * 1f).toInt()
}
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
@ -190,7 +190,7 @@ class PagedTextView : AppCompatTextView {
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)
val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom)
var height = heightWithoutPaddings
for (i in 0 until lines) {

View File

@ -1,5 +1,6 @@
package com.mime.dualscreenview.webcontents
import android.annotation.SuppressLint
import android.app.AlertDialog
import android.graphics.Bitmap
import android.net.Uri
@ -7,15 +8,22 @@ import android.net.http.SslError
import android.util.Log
import android.webkit.*
import androidx.core.net.toUri
import com.google.gson.Gson
import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.common.PrefManager
import com.mime.dualscreenview.data.HistoryManager
import com.mime.dualscreenview.data.model.BookPageInfo
import com.mime.dualscreenview.data.model.BookPageInfos
import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.DidFindContents
import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.realmListOf
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONObject
import org.jsoup.Jsoup
import org.jsoup.select.Elements
open class BaseWebContentsViewer {
@ -38,6 +46,7 @@ open class BaseWebContentsViewer {
}
}
@SuppressLint("JavascriptInterface")
constructor(webview : WebView, mainControllInterface : MainControllInterface ) {
this.webview = webview
this.mainControllInterface = mainControllInterface
@ -51,6 +60,10 @@ open class BaseWebContentsViewer {
webview.settings.setPluginState(WebSettings.PluginState.ON)
webview.settings.domStorageEnabled = true
webview.clearCache(true);
try {
webview.removeJavascriptInterface("MyJavaScriptInterface")
}catch (e :Exception){e.printStackTrace()}
webview.addJavascriptInterface( BookHelper(),"MyJavaScriptInterface")
webview.clearHistory();
webview.clearSslPreferences();
WebView.setWebContentsDebuggingEnabled(true)
@ -83,7 +96,7 @@ open class BaseWebContentsViewer {
webview.loadUrl(last.pageUrl)
} else {
try {
webview.loadUrl(PrefManager.getLastDomain().plus("/").plus(last.pageUrl))
webview.loadUrl(PrefManager.getLastDomain().plus(last.pageUrl))
} catch (e : Exception) {
webview.loadUrl(PrefManager.getLastDomain())
}
@ -92,21 +105,20 @@ open class BaseWebContentsViewer {
}
val rootWebViewClient = object : WebViewClient() {
override fun shouldInterceptRequest(
view: WebView?,
request: WebResourceRequest?
): WebResourceResponse? {
Log.e("shouldInterceptRequest", " >>>> ${request?.url?.toString()} , ${request?.url?.toString()?.contains("gif")}")
if(request?.url?.toString()?.contains("gif") ?: false) {
return WebResourceResponse("text/javascript", "UTF-8", null);
}
// if(request?.url?.toString()?.contains(currentContentsProvider?.acccceptResourceKeyword() ?: "") == false && request?.url?.toString()?.contains(currentContentsProvider?.getLastedDoamin() ?: "") == false) {
// override fun shouldInterceptRequest(
// view: WebView?,
// request: WebResourceRequest?
// ): WebResourceResponse? {
// Log.e("shouldInterceptRequest", " >>>> ${request?.url?.toString()} , ${request?.url?.toString()?.contains("gif")}")
//
// if(request?.url?.toString()?.contains("gif") ?: false) {
// return WebResourceResponse("text/javascript", "UTF-8", null);
// }
return super.shouldInterceptRequest(view, request)
}
//// if(request?.url?.toString()?.contains(currentContentsProvider?.acccceptResourceKeyword() ?: "") == false && request?.url?.toString()?.contains(currentContentsProvider?.getLastedDoamin() ?: "") == false) {
//// return WebResourceResponse("text/javascript", "UTF-8", null);
//// }
// return super.shouldInterceptRequest(view, request)
// }
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
super.onPageStarted(view, url, favicon)
@ -131,8 +143,10 @@ open class BaseWebContentsViewer {
// super.onReceivedHttpError(view, request, errorResponse)
}
override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url)
finishedUrl = url ?: ""
view?.let {
url?.toUri()?.let {
PrefManager.putLastDomain(it.scheme.plus("::/").plus(it.host))
@ -143,11 +157,22 @@ open class BaseWebContentsViewer {
Blog.LOGE("onPageFinished", url ?: "")
}
} else if (url?.contains("booktoki") ?: false){
findListItem {
Blog.LOGE("onPageFinished", url ?: "")
}
// findListItem {
// Blog.LOGE("onPageFinished", url ?: "")
// }
}
view?.postDelayed({
view?.evaluateJavascript(
"function getAll() {\n" +
" MyJavaScriptInterface.sendValueFromHtml(document.getElementsByTagName('html')[0].innerHTML)" +
" };getAll()"
) { result ->
(result as? String)?.let {
}
}
}, 500L)
currentContentsProvider?.doOnloaded(it , { result ->
result?.let { mainControllInterface.onLoadedContents(it) }
} , { complete ->
@ -162,4 +187,71 @@ open class BaseWebContentsViewer {
}
}
}
}
var finishedUrl : String = ""
inner class BookHelper {
@JavascriptInterface
fun sendValueFromHtml(string: String) {
Jsoup.parse(string)?.let { html ->
val toon_intro = html.getElementsByClass("toon_index")?.first()
val view_padding = html.select("#bo_v_con")
if (toon_intro != null) {
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
val bookPageInfos = BookPageInfos()
bookPageInfos.bookPageUrl = Uri.parse(finishedUrl).path
bookPageInfos.bookTitle = if (toon_intro.getElementsByTag("h3").size > 0) toon_intro.getElementsByTag("h3").get(0).text() else ""
bookPageInfos.pages = realmListOf<BookPageInfo>()
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookPageInfos >>>> ${Gson().toJson(bookPageInfos)}")
val listParent = toon_intro.getElementsByTag("ul").first()
if (listParent != null) {
listParent.getElementsByTag("li").reversed().forEachIndexed { idx, bookitem ->
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookItemInfo ${bookitem.html()}")
try {
val bookPageInfo = BookPageInfo()
bookPageInfo.bookTitle = bookPageInfos.bookTitle
bookPageInfo.chapterNum = idx + 1
bookPageInfo.chapterID = idx + 1
bookPageInfo.chapterTitle = bookitem.getElementsByTag("a").getT()
bookPageInfo.bookPageUrl = bookPageInfos.bookPageUrl
val href = bookitem.getElementsByTag("a").get(0).attr("href")
bookPageInfo.pathUrl = Uri.parse(href).path
bookPageInfos.pages.add(bookPageInfo)
}catch (nfe : NumberFormatException) {
nfe.printStackTrace()
}
}.apply {
HistoryManager.openRealm.writeBlocking {
copyToRealm(bookPageInfos, UpdatePolicy.ALL)
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookPageInfos saved >>>> ${bookPageInfos.bookPageUrl}")
}
mainControllInterface.onBookInfos(bookPageInfos)
}
}
}else if (view_padding.size > 0){
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
val contents = StringBuffer()
view_padding.get(0).getElementsByTag("P").forEach {
it.text().apply {
contents.append(this).append("\n")
}
}
if (contents.length > 20) {
Uri.parse(finishedUrl).path?.let {
HistoryManager.getBooPageInfoContentsSave(it, contents.toString())
mainControllInterface.onLoadedContents(contents.toString())
}
}
} else {
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: whole body ${html}")
}
}
}
}
}
fun Elements.getT() = if (size > 0) get(0).text() else ""

View File

@ -1,5 +1,6 @@
package com.mime.dualscreenview.webcontents
import com.mime.dualscreenview.data.model.BookPageInfos
import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere
@ -16,5 +17,6 @@ interface MainControllInterface {
fun onFindTitle(contents :String)
fun onBookInfos(jsonString : String)
fun onBookInfos(infos : BookPageInfos)
}

View File

@ -2,9 +2,10 @@ package com.mime.dualscreenview.webcontents
import com.mime.dualscreenview.webcontents.contentsinfo.Agit
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.NewtokiOne
object WebContentsManger {
val allContentsList : ArrayList<BaseWebContents> = arrayListOf(Booktoki)
val allContentsList : ArrayList<BaseWebContents> = arrayListOf(NewtokiOne)
fun getBaseWebContentsBy(name : String) : BaseWebContents {
var correctContents : BaseWebContents = Booktoki

View File

@ -4,7 +4,7 @@ import com.mime.dualscreenview.webcontents.BaseWebContents
object Booktoki : BaseWebContents() {
override var lastNumber : Int = 350
override var lastNumber : Int = 351
override fun getWebcontentsName(): String {
return "Booktoki"

View File

@ -0,0 +1,95 @@
package com.mime.dualscreenview.webcontents.contentsinfo
import com.mime.dualscreenview.webcontents.BaseWebContents
object NewtokiOne : BaseWebContents() {
override var lastNumber : Int = 351
override fun getWebcontentsName(): String {
return "newtokione"
}
override fun getLastedDoamin(): String {
return "https://newtoki.biz"
}
override fun getContentsList(): String {
return "function getList() {\n" +
" const contentsArray = [];\n" +
" var children = document.getElementsByClassName('list-body')[0].children;\n" +
" var maxCount = children.length;\n" +
" for (i= 0; i < maxCount; i++) {\n" +
" var chapterNum = children[i].getElementsByClassName('wr-num')[0].textContent;\n" +
" var pageUrl = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].href;\n" +
" if (pageUrl != null && pageUrl.length > 0 && pageUrl.startsWith(\"http\")) {\n" +
" pageUrl = new URL(pageUrl).pathname;\n" +
" }\n" +
" var chapterTitle = children[i].getElementsByClassName('wr-subject')[0].getElementsByTagName('a')[0].innerText;\n" +
" if(chapterTitle.split('\\n').length > 1) {\n" +
" chapterTitle = chapterTitle.split('\\n')[1];\n" +
" }\n" +
"\n" +
" var bookPageUrl = location.pathname;\n" +
" var bookTitle = document.getElementsByClassName('view-title')[0].getElementsByTagName('span')[0].innerText;\n" +
" var data = {\n" +
" 'chapterID': Number(chapterNum),\n" +
" 'chapterNum': Number(chapterNum),\n" +
" 'pathUrl': pageUrl,\n" +
" 'bookPageUrl': bookPageUrl,\n" +
" 'chapterTitle': chapterTitle,\n" +
" 'bookTitle': bookTitle,\n" +
" };\n" +
" contentsArray.push(\n" +
" data\n" +
" );\n" +
" }\n" +
" \n" +
" if(contentsArray.length > 0) {\n" +
" PAgit.onBookInfo(JSON.stringify({\n" +
" 'bookTitle': bookTitle,\n" +
" 'bookPageUrl': new URL(location.href).pathname,\n" +
" 'pages': contentsArray ,\n" +
" }));\n" +
" }\n" +
"}\n" +
"getList()\n" +
""
}
override fun acccceptResourceKeyword(): String {
return "toki"
}
override fun getNextButtonJs(): String {
return "goNextBtn"
}
override fun getPrevButtonJs(): String {
return "goPrevBtn"
}
override fun getTitleJs(): String {
return "document.getElementsByClassName(\"toon-title\").length > 0 ? document.getElementsByClassName(\"toon-title\")[0].title : null"
}
override fun getFindContentsJs(): String {
return "document.getElementById(\"novel_content\") != null ? document.getElementById(\"novel_content\").innerText : null"
}
override fun checkCorrectContents(contents: String): String {
return if (contents != null && !contents.isNullOrEmpty()) {
contents
} else {
"fail load"
}
}
// "if(document.getElementsByClassName(\"hd_pops\") != null && document.getElementsByClassName(\"hd_pops\").length > 0) document.getElementsByClassName(\"hd_pops\")[0].remove();" +
// "if(document.getElementsByClassName(\"hd_pops\") != null && document.getElementsByClassName(\"hd_pops\").length > 0) document.getElementsByClassName(\"hd_pops\")[0].remove();" +
// "if(document.getElementById(\"main-banner-view\") != null) document.getElementById(\"main-banner-view\").remove();" +
// "if(document.getElementsByClassName(\"board-tail-banner\") != null && document.getElementsByClassName(\"board-tail-banner\").length > 0)document.getElementsByClassName(\"board-tail-banner\")[0].remove();" +
// "if(document.getElementById(\"id_mbv\") != null)document.getElementById(\"id_mbv\").remove();"
override fun onLoadedJs(): String {
return ""
}
}

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle">
<corners android:radius="10dp"/>
<solid android:color="#44ffffff"/>
<stroke android:color="@color/white" android:width="1dp"/>
</shape>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:background="@drawable/simple_bg"
android:layout_height="wrap_content">
<TextView
android:layout_gravity="center"
android:gravity="left"
android:id="@+id/text"
android:textColor="@color/black"
android:background="@null"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
</FrameLayout>

View File

@ -1,17 +0,0 @@
package com.mime.dualscreenview
import org.junit.Test
import org.junit.Assert.*
/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class ExampleUnitTest {
@Test
fun addition_isCorrect() {
assertEquals(4, 2 + 2)
}
}