This commit is contained in:
lun_admin 2024-07-31 20:38:44 +09:00
parent ae743bf784
commit 4c620872af
25 changed files with 1230 additions and 875 deletions

View File

@ -2,7 +2,7 @@ plugins {
id 'com.android.application' id 'com.android.application'
id 'org.jetbrains.kotlin.android' id 'org.jetbrains.kotlin.android'
id 'io.realm.kotlin' id 'io.realm.kotlin'
id 'kotlin-android-extensions' // id 'kotlin-android-extensions'
} }
android { android {

View File

@ -23,12 +23,12 @@ import android.widget.ArrayAdapter
import android.widget.EditText import android.widget.EditText
import android.widget.ImageButton import android.widget.ImageButton
import android.widget.ProgressBar import android.widget.ProgressBar
import android.widget.TextView
import android.widget.Toast import android.widget.Toast
import androidx.annotation.RequiresApi import androidx.annotation.RequiresApi
import androidx.appcompat.app.AlertDialog import androidx.appcompat.app.AlertDialog
import androidx.appcompat.widget.AppCompatButton import androidx.appcompat.widget.AppCompatButton
import com.google.gson.Gson import com.google.gson.Gson
import com.lge.display.DisplayManagerHelper
import com.mime.dualscreenview.R import com.mime.dualscreenview.R
import com.mime.dualscreenview.common.Blog import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.common.PairArray import com.mime.dualscreenview.common.PairArray
@ -38,6 +38,7 @@ import com.mime.dualscreenview.common.typesfacez
import com.mime.dualscreenview.data.HistoryManager import com.mime.dualscreenview.data.HistoryManager
import com.mime.dualscreenview.data.model.BookPageInfo import com.mime.dualscreenview.data.model.BookPageInfo
import com.mime.dualscreenview.data.model.BookPageInfos import com.mime.dualscreenview.data.model.BookPageInfos
import com.mime.dualscreenview.data.model.BookPageInfosJ
import com.mime.dualscreenview.data.model.HistoryItem import com.mime.dualscreenview.data.model.HistoryItem
import com.mime.dualscreenview.data.model.LastInfo import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.data.model.ReaderConfig import com.mime.dualscreenview.data.model.ReaderConfig
@ -47,14 +48,14 @@ import com.mime.dualscreenview.view.PagedTextViewInterface
import com.mime.dualscreenview.view.TouchArea import com.mime.dualscreenview.view.TouchArea
import com.mime.dualscreenview.webcontents.BaseWebContentsViewer import com.mime.dualscreenview.webcontents.BaseWebContentsViewer
import com.mime.dualscreenview.webcontents.MainControllInterface import com.mime.dualscreenview.webcontents.MainControllInterface
import com.mime.dualscreenview.webcontents.contentsinfo.Agit
import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki
import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere
import io.realm.kotlin.Realm
import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.copyFromRealm import io.realm.kotlin.ext.copyFromRealm
import io.realm.kotlin.ext.query import io.realm.kotlin.ext.query
import kotlinx.android.synthetic.main.intro.paged_layer import io.realm.kotlin.query.find
import kotlinx.android.synthetic.main.intro.textview_title
import kotlinx.android.synthetic.main.settings.preview
import java.lang.System.currentTimeMillis import java.lang.System.currentTimeMillis
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.Date import java.util.Date
@ -62,33 +63,21 @@ import java.util.Date
class Intro : Base() , MainControllInterface, PagedTextViewInterface { class Intro : Base() , MainControllInterface, PagedTextViewInterface {
private var displayManagerHelper: DisplayManagerHelper? = null
// This callbacks where receive events from the cover
private var coverDisplayCallback: MainCoverDisplayCallback? = null
private var smartCoverCallback: MainSmartCoverCallback? = null
// Save previous state of dual screens // Save previous state of dual screens
private var prevDualScreenState = DisplayManagerHelper.STATE_UNMOUNT
private var isLGDualScreen: Boolean = false
private lateinit var mBaseWebContentsViewer : BaseWebContentsViewer private lateinit var mBaseWebContentsViewer : BaseWebContentsViewer
var lastInfo : LastInfo? = null var lastInfo : LastInfo? = null
lateinit var paged_layer : PagedTextLayout
lateinit var textview_title : TextView
val handle = object : Handler() { val handle = object : Handler() {
override fun handleMessage(msg: Message) { override fun handleMessage(msg: Message) {
// super.handleMessage(msg) // super.handleMessage(msg)
if (msg.what == 0 ) { if (msg.what == 0 ) {
(msg.obj as? ReaderConfig)?.let { (msg.obj as? ReaderConfig)?.let {
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?.forceUpdateUI()
} }
} }
@ -106,35 +95,16 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
setContentView(R.layout.intro) setContentView(R.layout.intro)
mBaseWebContentsViewer = BaseWebContentsViewer(findViewById<WebView>(R.id.menu_web),this) mBaseWebContentsViewer = BaseWebContentsViewer(findViewById<WebView>(R.id.menu_web),this)
try {
// Try to construct the DisplayMangerHelper.
// If it isn't successful, this device isn't LG dual screens
displayManagerHelper = DisplayManagerHelper(applicationContext)
coverDisplayCallback = MainCoverDisplayCallback()
smartCoverCallback = MainSmartCoverCallback()
// Register the callbacks for covers paged_layer =findViewById<PagedTextLayout>(R.id.paged_layer)
displayManagerHelper?.registerCoverDisplayEnabledCallback( textview_title =findViewById<TextView>(R.id.textview_title)
applicationContext.packageName,
coverDisplayCallback
)
displayManagerHelper?.registerSmartCoverCallback(smartCoverCallback)
isLGDualScreen = true
} catch (e: Exception) {
isLGDualScreen = false
Log.e(TAG, "This device isn't LG dual screens", e)
}
findViewById<ImageButton>(R.id.btn_list).setOnClickListener { v -> findViewById<ImageButton>(R.id.btn_list).setOnClickListener { v ->
mBaseWebContentsViewer?.findListItem {result -> mBaseWebContentsViewer?.webview?.url?.let {
if (result != null && "null".equals(result) == false && result?.length ?: 0 > 10) { Uri.parse(it).path?.let {
try { HistoryManager.getBooInfo(it, {
Gson().fromJson(result, BookPageInfos::class.java)?.let{ it?.let { showList(it) }
showList(it) })
}
} catch (e : Exception) {
}
} }
} }
} }
@ -142,8 +112,9 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
findViewById<View>(R.id.btn_rotate).setOnClickListener { v-> findViewById<View>(R.id.btn_rotate).setOnClickListener { v->
switcvhOrient() switcvhOrient()
} }
findViewById<View>(R.id.btn_setting).setOnClickListener { v-> findViewById<View>(R.id.btn_setting).setOnClickListener { v->
startActivity(Intent(this@Intro, Settings::class.java)) // startActivity(Intent(this@Intro, Settings::class.java))
} }
findViewById<View>(R.id.btn_history).setOnClickListener { v-> findViewById<View>(R.id.btn_history).setOnClickListener { v->
var realm = openRealm() var realm = openRealm()
@ -157,7 +128,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
findViewById<View>(R.id.btn_home).setOnClickListener { v-> findViewById<View>(R.id.btn_home).setOnClickListener { v->
paged_layer?.visibility = GONE paged_layer?.visibility = GONE
mBaseWebContentsViewer.loadContents(Booktoki) mBaseWebContentsViewer.loadContents(Agit)
} }
loadLastInfo() loadLastInfo()
@ -175,12 +146,51 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
} }
} }
override fun onBookInfos(jsonString: String) {
Blog.LOGE("onBookInfos" , "onBookInfos >> ${jsonString}")
val realm = openRealm()
var infos : BookPageInfos? = null
realm.writeBlocking {
try {
var infosj : BookPageInfosJ? = null
infosj = Gson().fromJson(jsonString, BookPageInfosJ::class.java)
Blog.LOGE("onBookInfos" , "onBookInfos 2 >> ${infosj}")
Blog.LOGE("onBookInfos" , "onBookInfos 2 - 1 >> ${infosj?.pages}")
// realm.createObjectFromJson
Blog.LOGE("onBookInfos" , "onBookInfos 2 - 1 >> ${infosj?.getR()}")
infos = infosj?.getR()
if (infos != null) {
infos = copyToRealm(infos!!, UpdatePolicy.ALL)
for (item in infosj.pages) {
infos?.pages?.add(item.getRealm())
}
Blog.LOGE("onBookInfos", "onBookInfos 3 >> ${realm.query<BookPageInfos>().find().size}")
Blog.LOGE("onBookInfos", "onBookInfos 4 >> ${realm.query<BookPageInfo>().find().size}")
}
} catch (e :Exception) {
e.printStackTrace()
}
}
realm.close()
infos?.let {
Blog.LOGE("onBookInfos" , "onBookInfos it >> ${it}")
showList(it)
}
}
fun reloadTo(lastInfo: LastInfo?) { fun reloadTo(lastInfo: LastInfo?) {
findViewById<WebView>(R.id.menu_web)?.postDelayed({ findViewById<WebView>(R.id.menu_web)?.postDelayed({
if (lastInfo != null) { if (lastInfo != null) {
mBaseWebContentsViewer.loadLastInfo(lastInfo!!) mBaseWebContentsViewer.loadLastInfo(lastInfo!!)
} else { } else {
mBaseWebContentsViewer.loadContents(Booktoki) mBaseWebContentsViewer.loadContents(Agit)
} }
},200L) },200L)
} }
@ -266,17 +276,17 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
} }
fun showList(infos: BookPageInfos) { fun showList(infos: BookPageInfos) {
DefaultList.showDefaultList(this@Intro,"현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라",infos.getTitleArray(),currentChapter, { position -> DefaultList.showDefaultList(this@Intro,"현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라",infos.getTitleArray().reversed(),currentChapter, { position ->
return@showDefaultList infos.list?.get(position)?.title ?: "" return@showDefaultList infos.pages?.get(position)?.chapterTitle ?: ""
},{position -> },{position ->
infos.list?.get(position)?.let{moveTo(it)} infos.pages?.reversed()?.get(position)?.let{moveTo(it)}
}) })
} }
private fun moveTo(item: BookPageInfo?) { private fun moveTo(item: BookPageInfo?) {
item?.link?.let { newPath -> item?.pathUrl?.let { newPath ->
mBaseWebContentsViewer?.webview?.url?.let { currentUrl -> mBaseWebContentsViewer?.webview?.url?.let { currentUrl ->
Uri.parse(currentUrl)?.lastPathSegment?.let { Uri.parse(currentUrl)?.path?.let {
currentUrl.replace(it, newPath)?.let { currentUrl.replace(it, newPath)?.let {
mBaseWebContentsViewer?.webview?.loadUrl(it) mBaseWebContentsViewer?.webview?.loadUrl(it)
} }
@ -297,123 +307,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
override fun onDestroy() { override fun onDestroy() {
// Remove all callbacks when this activity is destroyed
displayManagerHelper?.unregisterCoverDisplayEnabledCallback(applicationContext.packageName)
displayManagerHelper?.unregisterSmartCoverCallback(smartCoverCallback)
super.onDestroy() super.onDestroy()
} }
/**
* Convert cover display states to string to serve for logging
*
* @param state is the value integer of state
* @return a string for this state
*/
private fun coverDisplayStateToString(state: Int): String {
return when (state) {
DisplayManagerHelper.STATE_UNMOUNT -> "STATE_UNMOUNT"
DisplayManagerHelper.STATE_DISABLED -> "STATE_DISABLED"
DisplayManagerHelper.STATE_ENABLED -> "STATE_ENABLED"
else -> "UNKNOWN_STATE"
}
}
/**
* Convert smart cover display states to string to serve for logging
*
* @param state is the value integer of state
* @return a string for this state
*/
private fun smartCoverStateToString(state: Int): String {
return when (state) {
DisplayManagerHelper.STATE_COVER_OPENED -> "STATE_COVER_OPENED"
DisplayManagerHelper.STATE_COVER_CLOSED -> "STATE_COVER_CLOSED"
DisplayManagerHelper.STATE_COVER_FLIPPED_OVER -> "STATE_COVER_FLIPPED_OVER"
else -> "UNKNOWN_STATE"
}
}
/**
* Navigate to the second screen.
*
* See more at https://developer.android.com/guide/topics/ui/foldables?#using_secondary_screens
*/
private fun toSecondScreen(screenNumStr : String) {
var screenNum = screenNumStr.toInt()
// DisplayManager manages the properties of attached displays.
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager
// List displays was attached
val displays = displayManager.displays
if (displays.size > screenNum) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Activity options are used to select the display screen.
val options = ActivityOptions.makeBasic()
// Select the display screen that you want to show the second activity
options.launchDisplayId = displays[screenNum].displayId
// To display on the second screen that your intent must be set flag to make
// single task (combine FLAG_ACTIVITY_CLEAR_TOP and FLAG_ACTIVITY_NEW_TASK)
// or you also set it in the manifest (see more at the manifest file)
startActivity(
Intent(this@Intro, Main::class.java).apply {
},
options.toBundle()
)
}
} else {
Toast.makeText(this, "Not found the second screen", Toast.LENGTH_SHORT).show()
}
}
private inner class MainCoverDisplayCallback : DisplayManagerHelper.CoverDisplayCallback() {
override fun onCoverDisplayEnabledChangedCallback(state: Int) {
displayManagerHelper?.coverDisplayState?.let {
Log.i(TAG, "Current DualScreen Callback state: ${coverDisplayStateToString(it)}")
}
if (prevDualScreenState != state) {
when (state) {
DisplayManagerHelper.STATE_UNMOUNT -> {
Log.i(TAG, "Changed DualScreen State to STATE_UNMOUNT")
}
DisplayManagerHelper.STATE_DISABLED -> {
Log.i(TAG, "Changed DualScreen State to STATE_DISABLED")
}
DisplayManagerHelper.STATE_ENABLED -> {
// toSecondScreen()
Log.i(TAG, "Changed DualScreen State to STATE_ENABLED")
}
}
prevDualScreenState = state
}
}
}
private inner class MainSmartCoverCallback : DisplayManagerHelper.SmartCoverCallback() {
override fun onTypeChanged(type: Int) {
Log.i(TAG, "SmartCoverCallback type: ${displayManagerHelper?.coverType}")
}
override fun onStateChanged(state: Int) {
displayManagerHelper?.coverState?.let {
Log.i(TAG, "Current SmartCoverCallback state: ${smartCoverStateToString(it)}")
}
when (state) {
DisplayManagerHelper.STATE_COVER_OPENED -> {
Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_OPENED")
}
DisplayManagerHelper.STATE_COVER_CLOSED -> {
Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_CLOSED")
}
DisplayManagerHelper.STATE_COVER_FLIPPED_OVER -> {
Log.i(TAG, "Received SmartCoverCallback is STATE_COVER_FLIPPED_OVER")
}
}
}
}
var onNextClickAction: GotoSomeWhere? = null var onNextClickAction: GotoSomeWhere? = null
override fun showNextBtn(find : Boolean , onClickAction: GotoSomeWhere) { override fun showNextBtn(find : Boolean , onClickAction: GotoSomeWhere) {
@ -432,7 +329,27 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
paged_layer!!.doNext() paged_layer!!.doNext()
updateLastInfo(paged_layer!!) updateLastInfo(paged_layer!!)
}else { }else {
onNextClickAction?.let { it() } Uri.parse(mBaseWebContentsViewer.webview.url)?.let {
it.path?.let {
HistoryManager.getNextPage(it) {
Blog.LOGE("HistoryManager.getNextPage(${it})")
if(it?.pathUrl?.length ?: 0 > 0) {
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
Blog.LOGE("HistoryManager.getNextPage(${it?.pathUrl})")
if (lastInfo?.pageUrl?.length ?: 0 > 0 && lastInfo?.pageUrl!!.startsWith("http")) {
Blog.LOGE("HistoryManager.getNextPage(${lastInfo?.pageUrl})")
mBaseWebContentsViewer.webview.loadUrl(lastInfo!!.pageUrl!!.replace(Uri.parse(lastInfo!!.pageUrl)!!.path!!,it?.pathUrl!!))
paged_layer?.visibility = GONE
} else {
Blog.LOGE("HistoryManager.getNextPage(${Agit.getLastedDoamin()})")
mBaseWebContentsViewer.webview.loadUrl(Agit.getLastedDoamin() + it?.pathUrl!!)
paged_layer?.visibility = GONE
}
}
}
}
}
// onNextClickAction?.let { it() }
} }
} }
@ -454,11 +371,26 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
paged_layer!!.doPrev() paged_layer!!.doPrev()
updateLastInfo(paged_layer!!) updateLastInfo(paged_layer!!)
} else { } else {
onPrevClickAction?.let{ it() } Uri.parse(mBaseWebContentsViewer.webview.url)?.let {
it.path?.let {
HistoryManager.getPrevPage(it) {
if(it?.pathUrl?.length ?: 0 > 0) {
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
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(Agit.getLastedDoamin() + it?.pathUrl!!)
}
}
}
}
}
// onPrevClickAction?.let{ it() }
} }
} }
override fun onBackPressed() { override fun onBackPressed() {
super.onBackPressed()
var layer = findViewById<PagedTextLayout>(R.id.paged_layer) var layer = findViewById<PagedTextLayout>(R.id.paged_layer)
if (!didBackPress) { if (!didBackPress) {
@ -492,9 +424,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
} }
@RequiresApi(Build.VERSION_CODES.O) @RequiresApi(Build.VERSION_CODES.O)
override fun onLoadedContents(contents: String) { override fun onLoadedContents(aContents: String) {
paged_layer.apply { paged_layer.apply {
if (contents != null) { if (aContents != null) {
var contents = aContents.replace("\\\"","\"")
visibility = VISIBLE visibility = VISIBLE
mPagedTextViewInterface = this@Intro mPagedTextViewInterface = this@Intro
var realm = HistoryManager.openRealm() var realm = HistoryManager.openRealm()
@ -522,7 +455,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
setText(contents.replace("\\n", System.getProperty("line.separator"))) text = (contents.replace("\\n", System.getProperty("line.separator")))
if(lastInfo != null && lastInfo!!.pageUrl.equals(mBaseWebContentsViewer.webview.url)) { if(lastInfo != null && lastInfo!!.pageUrl.equals(mBaseWebContentsViewer.webview.url)) {
this@Intro.findViewById<ProgressBar>(R.id.progress)?.visibility = VISIBLE this@Intro.findViewById<ProgressBar>(R.id.progress)?.visibility = VISIBLE
paged_layer?.postDelayed({ paged_layer?.postDelayed({
@ -533,9 +466,20 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
},1000) },1000)
} }
forceUpdateUI() forceUpdateUI()
HistoryManager.getBooPageInfo(mBaseWebContentsViewer.webview.url!!){
HistoryManager.openRealm().apply {
this.writeBlocking {
it?.contents = contents
if (it != null) {
copyToRealm(it, UpdatePolicy.ALL)
} }
} }
Log.i(TAG,"onLoadedContents >> " + contents) }.close()
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
}
}
}
Log.i(TAG,"onLoadedContents >> " + aContents)
} }
var currentTitle : String = "" var currentTitle : String = ""
@ -680,6 +624,12 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
} }
override fun onLongClick() {
Blog.LOGD(log="onLongClick")
if (paged_layer?.visibility == VISIBLE) {
paged_layer?.visibility = GONE
}
}
override fun onSwipeLeft() { override fun onSwipeLeft() {
Blog.LOGD(log="onSwipeLeft") Blog.LOGD(log="onSwipeLeft")
actionNextEvent() actionNextEvent()
@ -709,4 +659,4 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface {
companion object { companion object {
private const val TAG = "DualScreenStatus" private const val TAG = "DualScreenStatus"
} }
} }

View File

@ -1,128 +1,128 @@
package com.mime.dualscreenview.activity //package com.mime.dualscreenview.activity
//
import android.graphics.Color //import android.graphics.Color
import android.os.Build //import android.os.Build
import android.os.Bundle //import android.os.Bundle
import androidx.annotation.RequiresApi //import androidx.annotation.RequiresApi
import com.mime.dualscreenview.R //import com.mime.dualscreenview.R
import com.mime.dualscreenview.common.PairArray //import com.mime.dualscreenview.common.PairArray
import com.mime.dualscreenview.common.colorz //import com.mime.dualscreenview.common.colorz
import com.mime.dualscreenview.common.getIndex //import com.mime.dualscreenview.common.getIndex
import com.mime.dualscreenview.common.typesfacez //import com.mime.dualscreenview.common.typesfacez
import com.mime.dualscreenview.data.HistoryManager //import com.mime.dualscreenview.data.HistoryManager
import com.mime.dualscreenview.data.model.ReaderConfig //import com.mime.dualscreenview.data.model.ReaderConfig
import io.realm.kotlin.UpdatePolicy //import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.ext.query //import io.realm.kotlin.ext.query
import kotlinx.android.synthetic.main.settings.letter_space //import kotlinx.android.synthetic.main.settings.letter_space
import kotlinx.android.synthetic.main.settings.line_space //import kotlinx.android.synthetic.main.settings.line_space
import kotlinx.android.synthetic.main.settings.page_padding //import kotlinx.android.synthetic.main.settings.page_padding
import kotlinx.android.synthetic.main.settings.page_style //import kotlinx.android.synthetic.main.settings.page_style
import kotlinx.android.synthetic.main.settings.page_typesface //import kotlinx.android.synthetic.main.settings.page_typesface
import kotlinx.android.synthetic.main.settings.preview //import kotlinx.android.synthetic.main.settings.preview
import kotlinx.android.synthetic.main.settings.text_size //import kotlinx.android.synthetic.main.settings.text_size
//
class Settings : Base() { //class Settings : Base() {
//
var readerConfig : ReaderConfig? = null // var readerConfig : ReaderConfig? = null
override fun onCreate(savedInstanceState: Bundle?) { // override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) // super.onCreate(savedInstanceState)
setContentView(R.layout.settings) // setContentView(R.layout.settings)
var realm = HistoryManager.openRealm() // var realm = HistoryManager.openRealm()
realm.writeBlocking { // realm.writeBlocking {
this.query<ReaderConfig>()?.find()?.let { // this.query<ReaderConfig>()?.find()?.let {
if (it.size > 0) { // if (it.size > 0) {
readerConfig = copyFromRealm(it.first()) // readerConfig = copyFromRealm(it.first())
} else { // } else {
readerConfig = ReaderConfig() // readerConfig = ReaderConfig()
} // }
} // }
//
} // }
realm.close() // realm.close()
} // }
//
@RequiresApi(Build.VERSION_CODES.O) // @RequiresApi(Build.VERSION_CODES.O)
override fun onResume() { // override fun onResume() {
super.onResume() // super.onResume()
text_size.displayFormat = "글자 크기 : %d" // text_size.displayFormat = "글자 크기 : %d"
text_size.value = readerConfig?.textSize ?: 14 // text_size.value = readerConfig?.textSize ?: 14
text_size.mValueChange = { // text_size.mValueChange = {
preview.textSize = it.toFloat() ; // preview.textSize = it.toFloat() ;
if (readerConfig?.textSize != it) { // if (readerConfig?.textSize != it) {
readerConfig?.textSize = it // readerConfig?.textSize = it
configSave() // configSave()
} // }
} // }
//
//
page_padding.displayFormat = "페이지 여백 : %d" // page_padding.displayFormat = "페이지 여백 : %d"
page_padding.value = readerConfig?.padding ?: 5 // page_padding.value = readerConfig?.padding ?: 5
page_padding.mValueChange = { // page_padding.mValueChange = {
preview.setPadding(it,it,it,it) ; // preview.setPadding(it,it,it,it) ;
if (readerConfig?.padding != it) { // if (readerConfig?.padding != it) {
readerConfig?.padding = it // readerConfig?.padding = it
configSave() // configSave()
} // }
} // }
//
//
letter_space.displayFormat = "자간 : %d" // letter_space.displayFormat = "자간 : %d"
letter_space.value = readerConfig?.letterSpace ?: 1 // letter_space.value = readerConfig?.letterSpace ?: 1
letter_space.mValueChange = { // letter_space.mValueChange = {
preview.letterSpacing = it.times(0.01).toFloat() ; // preview.letterSpacing = it.times(0.01).toFloat() ;
if (readerConfig?.letterSpace != it) { // if (readerConfig?.letterSpace != it) {
readerConfig?.letterSpace = it // readerConfig?.letterSpace = it
configSave() // configSave()
} // }
} // }
//
//
line_space.displayFormat = "행간 : %d" // line_space.displayFormat = "행간 : %d"
line_space.value = readerConfig?.lineSpace ?: 1 // line_space.value = readerConfig?.lineSpace ?: 1
line_space.mValueChange = { // line_space.mValueChange = {
preview.setLineSpacing(1f, 1f.plus(it.times(0.01f))) ; // preview.setLineSpacing(1f, 1f.plus(it.times(0.01f))) ;
if (readerConfig?.lineSpace != it) { // if (readerConfig?.lineSpace != it) {
readerConfig?.lineSpace = it // readerConfig?.lineSpace = it
configSave() // configSave()
} // }
} // }
//
//
//
page_typesface.displayFormat = "폰트 : %s" // page_typesface.displayFormat = "폰트 : %s"
page_typesface.titleArray = typesfacez.map { it.first }.toTypedArray() // page_typesface.titleArray = typesfacez.map { it.first }.toTypedArray()
page_typesface.value = getIndex(typesfacez as PairArray<Any>,readerConfig?.font ?: "") // page_typesface.value = getIndex(typesfacez as PairArray<Any>,readerConfig?.font ?: "")
page_typesface.mValueChange = { // page_typesface.mValueChange = {
val pair = typesfacez.get(it) // val pair = typesfacez.get(it)
preview.setTypeface(resources.getFont(pair.second)) // preview.setTypeface(resources.getFont(pair.second))
if (readerConfig?.font != pair.first) { // if (readerConfig?.font != pair.first) {
readerConfig?.font = pair.first ?: "" // readerConfig?.font = pair.first ?: ""
configSave() // configSave()
} // }
} // }
//
page_style.displayFormat = "스타일 : %s" // page_style.displayFormat = "스타일 : %s"
page_style.titleArray = colorz.map { it.first }.toTypedArray() // page_style.titleArray = colorz.map { it.first }.toTypedArray()
page_style.value = readerConfig?.style ?: 0 // page_style.value = readerConfig?.style ?: 0
page_style.mValueChange = { // page_style.mValueChange = {
val pair = colorz.get(it) // val pair = colorz.get(it)
preview.setBackgroundColor(Color.parseColor(pair.second.last())) // preview.setBackgroundColor(Color.parseColor(pair.second.last()))
preview.setTextColor(Color.parseColor(pair.second.first())) // preview.setTextColor(Color.parseColor(pair.second.first()))
if (readerConfig?.style != it) { // if (readerConfig?.style != it) {
readerConfig?.style = it ?: 0 // readerConfig?.style = it ?: 0
configSave() // configSave()
} // }
} // }
//
} // }
//
//
//
fun configSave() { // fun configSave() {
var realm = HistoryManager.openRealm() // var realm = HistoryManager.openRealm()
realm.writeBlocking { // realm.writeBlocking {
copyToRealm(readerConfig!!, UpdatePolicy.ALL) // copyToRealm(readerConfig!!, UpdatePolicy.ALL)
} // }
realm.close() // realm.close()
} // }
} //}

View File

@ -31,6 +31,10 @@ object Blog {
LOG(BLogType.E,tag,log) LOG(BLogType.E,tag,log)
} }
fun LOGE(log: String){
LOG(BLogType.E,DEFAULT_TAG,log)
}
private fun LOG(type : BLogType, tag : String, log : String) { private fun LOG(type : BLogType, tag : String, log : String) {
if (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.contains("debug")) { if (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.contains("debug")) {
when(type) { when(type) {

View File

@ -1,20 +1,27 @@
package com.mime.dualscreenview.data package com.mime.dualscreenview.data
import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.data.model.BookPageInfo
import com.mime.dualscreenview.data.model.BookPageInfos
import com.mime.dualscreenview.data.model.HistoryItem import com.mime.dualscreenview.data.model.HistoryItem
import com.mime.dualscreenview.data.model.LastInfo import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.data.model.ReaderConfig import com.mime.dualscreenview.data.model.ReaderConfig
import io.realm.kotlin.Realm import io.realm.kotlin.Realm
import io.realm.kotlin.RealmConfiguration import io.realm.kotlin.RealmConfiguration
import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.UpdatePolicy
import io.realm.kotlin.log.LogLevel
import io.realm.kotlin.types.BaseRealmObject import io.realm.kotlin.types.BaseRealmObject
import io.realm.kotlin.types.TypedRealmObject
import kotlin.reflect.KClass import kotlin.reflect.KClass
object HistoryManager { object HistoryManager {
val clazz : Set<KClass<out BaseRealmObject>> = setOf(LastInfo::class, HistoryItem::class, ReaderConfig::class) val clazz : Set<KClass<out BaseRealmObject>> = setOf(LastInfo::class, HistoryItem::class, ReaderConfig::class, BookPageInfos::class, BookPageInfo::class)
val schemaVersion : Long = 3 val schemaVersion : Long = 5
fun openRealm() : Realm = Realm.open(RealmConfiguration.Builder(clazz) fun openRealm() : Realm = Realm.open(RealmConfiguration.Builder(clazz as Set<KClass<out TypedRealmObject>>)
.schemaVersion(schemaVersion) .schemaVersion(schemaVersion)
.log(LogLevel.ALL)
// .deleteRealmIfMigrationNeeded()
.build()) .build())
fun save(lastInfo: LastInfo) { fun save(lastInfo: LastInfo) {
@ -46,4 +53,76 @@ object HistoryManager {
} }
}?.close() }?.close()
} }
fun getBooInfo(url : String ,callback : (BookPageInfos?)->Unit) {
openRealm()?.apply{
Blog.LOGE("get ${url}" )
Blog.LOGE("get ${this.query(BookPageInfo::class).count().find()}" )
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find().first()
if (bookPageInfo != null) {
Blog.LOGE("get ${bookPageInfo}" )
this.query(BookPageInfos::class,"bookPageUrl == $0",bookPageInfo.bookPageUrl).find().first().let {
Blog.LOGE("get ${it} , ${it?.pages}" )
callback.invoke(this.copyFromRealm(it))
}
}
}?.close()
}
fun getBooPageInfo(url : String ,callback : (BookPageInfo?)->Unit) {
openRealm()?.apply{
Blog.LOGE("get ${url}" )
Blog.LOGE("get ${this.query(BookPageInfo::class).count().find()}" )
var result = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()
if (result.size > 0) {
var bookPageInfo = result?.first()
if (bookPageInfo != null) {
callback.invoke(this.copyFromRealm(bookPageInfo))
}
}
}?.close()
}
fun getNextPage(url : String ,callback : (BookPageInfo?)->Unit) {
openRealm()?.apply{
Blog.LOGE("getNextPage ${url}" )
Blog.LOGE("getNextPage ${this.query(BookPageInfo::class).count().find()}" )
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()?.first()
Blog.LOGE("getNextPage 1 ${bookPageInfo}" )
if (bookPageInfo != null) {
Blog.LOGE("getNextPage 2 ${bookPageInfo.chapterNum}" )
Blog.LOGE("getNextPage 2 ${bookPageInfo.bookPageUrl}" )
var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.chapterNum - 1).query("bookPageUrl == $0","${bookPageInfo.bookPageUrl}").find()
if(results.size > 0) {
results.first()?.let {
Blog.LOGE("getNextPage 2 ${it.pathUrl}" )
callback.invoke(it)
}
}
}
}?.close()
}
fun getPrevPage(url : String ,callback : (BookPageInfo?)->Unit) {
openRealm()?.apply{
Blog.LOGE("getPrevPage ${url}" )
Blog.LOGE("getPrevPage ${this.query(BookPageInfo::class).count().find()}" )
var bookPageInfo = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()?.first()
Blog.LOGE("getNextPage ${bookPageInfo}" )
if (bookPageInfo != null) {
Blog.LOGE("getNextPage 2 ${bookPageInfo.chapterNum}" )
Blog.LOGE("getNextPage 2 ${bookPageInfo.bookPageUrl}" )
var results = this.query(BookPageInfo::class).query("chapterNum == $0 && bookPageUrl == $1",bookPageInfo.chapterNum + 1,"${bookPageInfo.bookPageUrl}").find()
if(results.size > 0) {
results.first()?.let {
callback.invoke(it)
}
}
}
}?.close()
}
} }

View File

@ -1,15 +1,89 @@
package com.mime.dualscreenview.data.model package com.mime.dualscreenview.data.model
import com.mime.dualscreenview.common.Blog
import io.realm.kotlin.ext.realmListOf
import io.realm.kotlin.types.RealmList
import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.RealmSet
import io.realm.kotlin.types.annotations.PrimaryKey
class BookPageInfos {
var list : ArrayList<BookPageInfo>? = null
class BookPageInfosJ : RealmObject {
var bookTitle : String = ""
var bookPageUrl : String = ""
var pages : ArrayList<BookPageInfoJ> = arrayListOf<BookPageInfoJ>()
fun getTitleArray() : ArrayList<String> { fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>() var arrayList = ArrayList<String>()
list?.forEach { arrayList.add(it.title ?: "") } pages?.forEach { arrayList.add(it.bookTitle ?: "") }
return arrayList return arrayList
} }
fun getR() : BookPageInfos{
var r = BookPageInfos()
r.bookTitle = this.bookTitle
r.bookPageUrl = this.bookPageUrl
// for (item in this.pages) {
//// Blog.LOGE("item >>> ${item}")
// r.pages.add(item.getRealm())
// }
return r
}
} }
class BookPageInfo { class BookPageInfoJ : RealmObject {
var title : String? = "" var chapterID : Int = 0
var link : String? = "" var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
var pathUrl : String? = ""
fun getRealm() : BookPageInfo {
var r = BookPageInfo()
r.chapterID = this.chapterID
r.contents = this.contents
r.bookPageUrl = this.bookPageUrl ?: ""
r.chapterTitle = this.chapterTitle
r.bookTitle = this.bookTitle ?: ""
r.chapterNum = this.chapterNum
r.lastPage = this.lastPage
r.pathUrl = this.pathUrl?.replace("'","")
return r
}
}
class BookPageInfos : RealmObject {
var bookTitle : String = ""
@PrimaryKey
var bookPageUrl : String? = ""
var pages : RealmList<BookPageInfo> = realmListOf()
fun getTitleArray() : ArrayList<String> {
var arrayList = ArrayList<String>()
pages?.forEach {
Blog.LOGE("chapterTitle >> ${it.chapterTitle} ")
arrayList.add(it.chapterTitle ?: "") }
return arrayList
}
}
class BookPageInfo : RealmObject {
var chapterID : Int = 0
var contents : String? = ""
var bookPageUrl : String? = ""
var chapterTitle : String? = ""
var bookTitle : String? = ""
var chapterNum : Int = 0
var lastPage : Int? = 0
@PrimaryKey
var pathUrl : String? = ""
} }

View File

@ -3,6 +3,8 @@ package com.mime.dualscreenview.data.model
import android.content.pm.ActivityInfo import android.content.pm.ActivityInfo
import io.realm.kotlin.types.RealmObject import io.realm.kotlin.types.RealmObject
import io.realm.kotlin.types.annotations.PrimaryKey import io.realm.kotlin.types.annotations.PrimaryKey
import java.text.SimpleDateFormat
import java.util.Date
class LastInfo() : RealmObject { class LastInfo() : RealmObject {
@ -42,6 +44,14 @@ class HistoryItem() : RealmObject {
contentsName = this@HistoryItem.contentsName contentsName = this@HistoryItem.contentsName
displayOrientation = this@HistoryItem.displayOrientation displayOrientation = this@HistoryItem.displayOrientation
} }
fun putHistory(bookPageInfo: BookPageInfo? , currentPath : String) : HistoryItem {
title = bookPageInfo?.bookTitle ?: SimpleDateFormat("YY-mm-DD-HH:mm").format(Date())
pageUrl = bookPageInfo?.pathUrl ?: ""
chapter = bookPageInfo?.chapterNum ?: 0
pageIndex = bookPageInfo?.lastPage ?: 0
contentsName = bookPageInfo?.chapterTitle ?: ""
return this
}
} }
class Bookmark() : RealmObject { class Bookmark() : RealmObject {
@PrimaryKey @PrimaryKey

View File

@ -15,7 +15,6 @@ object DefaultList {
arrayAdapter.addAll(items) arrayAdapter.addAll(items)
builderSingle.setNegativeButton("닫기", builderSingle.setNegativeButton("닫기",
DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() }) DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })
builderSingle.setAdapter(arrayAdapter, builderSingle.setAdapter(arrayAdapter,
DialogInterface.OnClickListener { dialog, position -> DialogInterface.OnClickListener { dialog, position ->
val strName = arrayAdapter.getItem(position) val strName = arrayAdapter.getItem(position)

View File

@ -18,6 +18,8 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene
private val gestureDetector: GestureDetector private val gestureDetector: GestureDetector
abstract fun onSwipeLeft() abstract fun onSwipeLeft()
abstract fun onSwipeRight() abstract fun onSwipeRight()
abstract fun onSwipeDown()
abstract fun onSwipeUp()
abstract fun onSingleTap(area : TouchArea) abstract fun onSingleTap(area : TouchArea)
override fun onTouch(v: View?, event: MotionEvent?): Boolean { override fun onTouch(v: View?, event: MotionEvent?): Boolean {
@ -34,6 +36,7 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene
return true return true
} }
override fun onSingleTapUp(e: MotionEvent): Boolean { override fun onSingleTapUp(e: MotionEvent): Boolean {
val width: Int = context?.resources?.displayMetrics?.widthPixels ?: 0 val width: Int = context?.resources?.displayMetrics?.widthPixels ?: 0
val height: Int = context?.resources?.displayMetrics?.heightPixels ?: 0 val height: Int = context?.resources?.displayMetrics?.heightPixels ?: 0
@ -53,14 +56,27 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene
return super.onSingleTapUp(e) return super.onSingleTapUp(e)
} }
override fun onFling(e1: MotionEvent, e2: MotionEvent, velocityX: Float, velocityY: Float): Boolean { override fun onFling(
val distanceX = e2.x - e1.x e1: MotionEvent,
val distanceY = e2.y - e1.y e2: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
val distanceX = e2.x - (e1?.x ?: 0f)
val distanceY = e2.y - (e1?.y ?: 0f)
if (Math.abs(distanceX) > Math.abs(distanceY) if (Math.abs(distanceX) > Math.abs(distanceY)
&& Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD
&& Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) { && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceX > 0) onSwipeRight() else onSwipeLeft() if (distanceX > 0) onSwipeRight() else onSwipeLeft()
return true return true
} else if (Math.abs(distanceY) > Math.abs(distanceX)
&& Math.abs(distanceY) > SWIPE_DISTANCE_THRESHOLD
&& Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (distanceY > 0) onSwipeDown() else onSwipeUp()
return true
} else {
} }
return false return false
} }

View File

@ -7,6 +7,7 @@ import android.graphics.Typeface
import android.os.Build import android.os.Build
import android.os.Handler import android.os.Handler
import android.util.AttributeSet import android.util.AttributeSet
import android.view.View
import android.widget.TextView import android.widget.TextView
import androidx.constraintlayout.widget.ConstraintLayout import androidx.constraintlayout.widget.ConstraintLayout
import androidx.constraintlayout.widget.Guideline import androidx.constraintlayout.widget.Guideline
@ -32,14 +33,18 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
) : super(context, attrs, defStyleAttr, defStyleRes) {initView(context)} ) : super(context, attrs, defStyleAttr, defStyleRes) {initView(context)}
var mainTextView : TextView? = null var mainTextView : TextView? = null
var sencondTextView : TextView? = null var sencondTextView : TextView? = null
var demp : View? = null
var hiddenTextView : PagedTextView? = null var hiddenTextView : PagedTextView? = null
var guideLine : Guideline? = null var guideLine : Guideline? = null
var pageList: ArrayList<CharSequence>? = null var pageList: ArrayList<CharSequence>? = null
var text : String = "" var text : String = ""
set(new) { set(new) {
Blog.LOGE("field >> ${field}")
Blog.LOGE("new >> ${new}")
field = new field = new
hiddenTextView?.text = text Blog.LOGE("field >> ${field}")
hiddenTextView?.forceLayout() hiddenTextView?.setTxtF(field)
hiddenTextView?.visibility = VISIBLE
} }
private val hanler = Handler() private val hanler = Handler()
@ -52,11 +57,23 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
inflate(context, R.layout.layout_textviewer, this) inflate(context, R.layout.layout_textviewer, this)
mainTextView = findViewById(R.id.first_view) mainTextView = findViewById(R.id.first_view)
sencondTextView = findViewById(R.id.sencond_view) sencondTextView = findViewById(R.id.sencond_view)
demp = findViewById(R.id.demp)
hiddenTextView = findViewById(R.id.hidden_view) hiddenTextView = findViewById(R.id.hidden_view)
guideLine = findViewById(R.id.center_guide)
hiddenTextView?.mPagedTextGenerateInterface = this hiddenTextView?.mPagedTextGenerateInterface = this
hanler.removeCallbacks(touchTimeover) hanler.removeCallbacks(touchTimeover)
setOnLongClickListener { v ->
mPagedTextViewInterface?.onLongClick()
return@setOnLongClickListener false
}
setOnTouchListener(object : OnSwipeTouchListener(context) { setOnTouchListener(object : OnSwipeTouchListener(context) {
override fun onSwipeUp() {
mPagedTextViewInterface?.onLongClick()
}
override fun onSwipeDown() {
mPagedTextViewInterface?.onLongClick()
}
override fun onSwipeLeft() { override fun onSwipeLeft() {
mPagedTextViewInterface?.onSwipeLeft() mPagedTextViewInterface?.onSwipeLeft()
} }
@ -74,26 +91,25 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
mPagedTextViewInterface?.onTouch(touchArea) mPagedTextViewInterface?.onTouch(touchArea)
} }
} }
}) })
} }
fun layoutChange(needDualPage: Boolean) { fun layoutChange(needDualPage: Boolean) {
Blog.LOGD(log = "layoutChange>> ${this::class.java.name}") Blog.LOGD(log = "layoutChange>> ${this::class.java.name}")
if (needDualPage) { if (needDualPage) {
findViewById<Guideline>(R.id.center_guide).updateLayoutParams<ConstraintLayout.LayoutParams> { sencondTextView?.visibility = VISIBLE
guidePercent = 0.5f demp?.visibility = VISIBLE
}
} else { } else {
findViewById<Guideline>(R.id.center_guide).updateLayoutParams<ConstraintLayout.LayoutParams> { sencondTextView?.visibility = GONE
guidePercent = 1f demp?.visibility = GONE
}
} }
} }
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) { override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
super.onLayout(changed, left, top, right, bottom) super.onLayout(changed, left, top, right, bottom)
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}") Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
if(!changed) { if(changed) {
hiddenTextView?.text = text hiddenTextView?.text = text
forceUpdateUI() forceUpdateUI()
} }
@ -121,6 +137,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
this.pageList = pageList this.pageList = pageList
setPageBy(0) setPageBy(0)
} }
hiddenTextView?.visibility = GONE
} }
fun setColorStyle(colors : Array<String>) { fun setColorStyle(colors : Array<String>) {
@ -132,7 +149,8 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
} }
// fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface) // fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface)
fun setText(replace: String) = hiddenTextView?.setText(replace) // fun setText(replace: String) = hiddenTextView?.setText(replace)
fun setTextSize(fl: Float) { fun setTextSize(fl: Float) {
hiddenTextView?.setTextSize(fl) hiddenTextView?.setTextSize(fl)
mainTextView?.setTextSize(fl) mainTextView?.setTextSize(fl)
@ -144,7 +162,7 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
} }
fun isDualPage() : Boolean { fun isDualPage() : Boolean {
return (guideLine?.layoutParams as ConstraintLayout.LayoutParams).guidePercent != 1f return sencondTextView?.visibility == VISIBLE
} }
fun setPageBy(num : Int) { fun setPageBy(num : Int) {

View File

@ -9,6 +9,8 @@ import android.text.StaticLayout
import android.util.AttributeSet import android.util.AttributeSet
import androidx.appcompat.widget.AppCompatTextView import androidx.appcompat.widget.AppCompatTextView
import com.mime.dualscreenview.common.Blog import com.mime.dualscreenview.common.Blog
import kotlinx.coroutines.MainScope
import kotlinx.coroutines.launch
import kotlin.math.min import kotlin.math.min
@ -60,13 +62,21 @@ class PagedTextView : AppCompatTextView {
} }
private fun setPageText() { private fun setPageText() {
if(pageList.size > 0) {
isPaginating = true isPaginating = true
text = pageList[pageIndex] text = pageList[pageIndex]
isPaginating = false isPaginating = false
} }
}
fun setTxtF(text: CharSequence?) {
needPaginate = true
this.setText(text , null)
}
override fun setText(text: CharSequence?, type: BufferType?) { override fun setText(text: CharSequence?, type: BufferType?) {
if (!isPaginating) { if (!isPaginating) {
needPaginate = true
originalText = text ?: "" originalText = text ?: ""
} }
super.setText(text, type) super.setText(text, type)
@ -160,12 +170,14 @@ class PagedTextView : AppCompatTextView {
} }
} }
private fun paginate() { private fun paginate() {
if (layout != null) {
MainScope().launch {
pageList.clear() pageList.clear()
Blog.LOGD(log = "paginate>> ${this::class.java.name}") Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}")
val layout = from(layout) val layout = from(layout)
val lines = min(maxLines, layout.lineCount) val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 2} else {min(maxLines, layout.lineCount)}
var startOffset = 0 var startOffset = 0
val heightWithoutPaddings = pageHeight - paddingTop - paddingBottom val heightWithoutPaddings = (pageHeight - (paddingTop + paddingBottom)) * 0.85
var height = heightWithoutPaddings var height = heightWithoutPaddings
for (i in 0 until lines) { for (i in 0 until lines) {
@ -185,6 +197,8 @@ class PagedTextView : AppCompatTextView {
} }
mPagedTextGenerateInterface?.completePagination(pageList) mPagedTextGenerateInterface?.completePagination(pageList)
} }
}
}
private fun from(layout: Layout): Layout = private fun from(layout: Layout): Layout =
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) { if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
@ -200,7 +214,7 @@ class PagedTextView : AppCompatTextView {
)) ))
} else { } else {
StaticLayout.Builder StaticLayout.Builder
.obtain(originalText, 0, originalText.length, paint, layout.width) .obtain(originalText, 0, originalText.length, paint, layout.width - (paddingLeft + paddingRight))
.setAlignment(layout.alignment) .setAlignment(layout.alignment)
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier) .setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
.setIncludePad(includeFontPadding) .setIncludePad(includeFontPadding)

View File

@ -5,4 +5,5 @@ interface PagedTextViewInterface {
fun onTimeoverTouch() fun onTimeoverTouch()
fun onSwipeLeft() fun onSwipeLeft()
fun onSwipeRight() fun onSwipeRight()
fun onLongClick()
} }

View File

@ -1,62 +1,62 @@
package com.mime.dualscreenview.view //package com.mime.dualscreenview.view
//
import android.content.Context //import android.content.Context
import android.util.AttributeSet //import android.util.AttributeSet
import com.mime.dualscreenview.R //import com.mime.dualscreenview.R
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment
import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value //import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value
//
class ScopeEditor: SideButtonTextView { //class ScopeEditor: SideButtonTextView {
constructor(context: Context) : super(context) // constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) // constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( // constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context, // context,
attrs, // attrs,
defStyleAttr // defStyleAttr
) // )
var titleArray : Array<String>? = null // var titleArray : Array<String>? = null
set(value) { // set(value) {
if(value != null && value.size < 1) { // if(value != null && value.size < 1) {
Error("titleArray는 최소 한개 이상이여야됨.") // Error("titleArray는 최소 한개 이상이여야됨.")
return // return
} // }
field = value // field = value
maxValue = field!!.size // maxValue = field!!.size
} // }
//
var maxValue : Int = 1 // var maxValue : Int = 1
set(value) { // set(value) {
if (value < 1) { // if (value < 1) {
Error("maxValue는 무조건 0보다 커야하눈뎅....") // Error("maxValue는 무조건 0보다 커야하눈뎅....")
return // return
} // }
field = value // field = value
} // }
//
override var value : Int = 14 // override var value : Int = 14
set(newValue) { // set(newValue) {
field = newValue // field = newValue
text_value.text = displayFormat.format(titleArray?.get(field) ?:"defulat") // text_value.text = displayFormat.format(titleArray?.get(field) ?:"defulat")
mValueChange?.invoke(field) // mValueChange?.invoke(field)
} // }
//
//
constructor( // constructor(
context: Context, // context: Context,
attrs: AttributeSet?, // attrs: AttributeSet?,
defStyleAttr: Int, // defStyleAttr: Int,
defStyleRes: Int // defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) // ) : super(context, attrs, defStyleAttr, defStyleRes)
//
init { // init {
inflate(context, R.layout.layout_steps_editor,this) // inflate(context, R.layout.layout_steps_editor,this)
btn_decrement.setOnClickListener { value = Math.abs(value.dec()).rem(maxValue) } // btn_decrement.setOnClickListener { value = Math.abs(value.dec()).rem(maxValue) }
btn_increment.setOnClickListener { value = value.inc().rem(maxValue) } // btn_increment.setOnClickListener { value = value.inc().rem(maxValue) }
leftButtonTitle = "<" // leftButtonTitle = "<"
rightButtonTitle = ">" // rightButtonTitle = ">"
} // }
//
//
//
} //}

View File

@ -1,70 +1,70 @@
package com.mime.dualscreenview.view //package com.mime.dualscreenview.view
//
import android.content.Context //import android.content.Context
import android.util.AttributeSet //import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout //import androidx.constraintlayout.widget.ConstraintLayout
import com.mime.dualscreenview.R //import com.mime.dualscreenview.R
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment
import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value //import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value
import java.lang.Exception //import java.lang.Exception
//
open class SideButtonTextView : ConstraintLayout { //open class SideButtonTextView : ConstraintLayout {
constructor(context: Context) : super(context) // constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) // constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( // constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context, // context,
attrs, // attrs,
defStyleAttr // defStyleAttr
) // )
//
constructor( // constructor(
context: Context, // context: Context,
attrs: AttributeSet?, // attrs: AttributeSet?,
defStyleAttr: Int, // defStyleAttr: Int,
defStyleRes: Int // defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) // ) : super(context, attrs, defStyleAttr, defStyleRes)
//
var leftButtonTitle : String = "" // var leftButtonTitle : String = ""
set(value) { // set(value) {
field = value // field = value
btn_decrement.text = field // btn_decrement.text = field
} // }
//
var rightButtonTitle : String = "" // var rightButtonTitle : String = ""
set(value) { // set(value) {
field = value // field = value
btn_increment.text = field // btn_increment.text = field
} // }
//
open var value : Int = 14 // open var value : Int = 14
set(newValue) { // set(newValue) {
field = newValue // field = newValue
text_value.text = displayFormat.format(field) // text_value.text = displayFormat.format(field)
mValueChange?.invoke(field) // mValueChange?.invoke(field)
} // }
//
var displayFormat = "글자 크기 : %d" // var displayFormat = "글자 크기 : %d"
set(newValue) { // set(newValue) {
field = newValue // field = newValue
try { // try {
text_value.text = displayFormat.format(value) // text_value.text = displayFormat.format(value)
} catch (e : Exception) { // } catch (e : Exception) {
//
} // }
} // }
//
var mValueChange : ValueChange? = null // var mValueChange : ValueChange? = null
set(newValue) { // set(newValue) {
field = newValue // field = newValue
if (newValue != null) { // if (newValue != null) {
newValue(value) // newValue(value)
} // }
} // }
//
init { // init {
// inflate(context, R.layout.layout_steps_editor,this) //// inflate(context, R.layout.layout_steps_editor,this)
// btn_decrement.setOnClickListener { value = value.dec() } //// btn_decrement.setOnClickListener { value = value.dec() }
// btn_increment.setOnClickListener { value = value.inc() } //// btn_increment.setOnClickListener { value = value.inc() }
} // }
} //}

View File

@ -1,37 +1,37 @@
package com.mime.dualscreenview.view //package com.mime.dualscreenview.view
//
import android.content.Context //import android.content.Context
import android.util.AttributeSet //import android.util.AttributeSet
import androidx.constraintlayout.widget.ConstraintLayout //import androidx.constraintlayout.widget.ConstraintLayout
import com.mime.dualscreenview.R //import com.mime.dualscreenview.R
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_decrement
import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment //import kotlinx.android.synthetic.main.layout_steps_editor.view.btn_increment
import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value //import kotlinx.android.synthetic.main.layout_steps_editor.view.text_value
import java.lang.Exception //import java.lang.Exception
//
typealias ValueChange = (Int)->Unit //typealias ValueChange = (Int)->Unit
//
class StepsEditor : SideButtonTextView { //class StepsEditor : SideButtonTextView {
constructor(context: Context) : super(context) // constructor(context: Context) : super(context)
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) // constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super( // constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
context, // context,
attrs, // attrs,
defStyleAttr // defStyleAttr
) // )
//
constructor( // constructor(
context: Context, // context: Context,
attrs: AttributeSet?, // attrs: AttributeSet?,
defStyleAttr: Int, // defStyleAttr: Int,
defStyleRes: Int // defStyleRes: Int
) : super(context, attrs, defStyleAttr, defStyleRes) // ) : super(context, attrs, defStyleAttr, defStyleRes)
//
init { // init {
inflate(context, R.layout.layout_steps_editor,this) // inflate(context, R.layout.layout_steps_editor,this)
btn_decrement.setOnClickListener { value = value.dec() } // btn_decrement.setOnClickListener { value = value.dec() }
btn_increment.setOnClickListener { value = value.inc() } // btn_increment.setOnClickListener { value = value.inc() }
leftButtonTitle = "-" // leftButtonTitle = "-"
rightButtonTitle = "+" // rightButtonTitle = "+"
} // }
} //}

View File

@ -8,6 +8,9 @@ import android.webkit.*
import com.mime.dualscreenview.common.Blog import com.mime.dualscreenview.common.Blog
import com.mime.dualscreenview.data.model.LastInfo import com.mime.dualscreenview.data.model.LastInfo
import com.mime.dualscreenview.webcontents.contentsinfo.DidFindContents import com.mime.dualscreenview.webcontents.contentsinfo.DidFindContents
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import org.json.JSONObject
open class BaseWebContentsViewer { open class BaseWebContentsViewer {
@ -16,12 +19,27 @@ open class BaseWebContentsViewer {
lateinit var webview : WebView lateinit var webview : WebView
lateinit var mainControllInterface : MainControllInterface lateinit var mainControllInterface : MainControllInterface
@JavascriptInterface
fun onBookInfo(jsonData : String) {
GlobalScope.launch {
try {
Blog.LOGE("BaseWebContentsViewer",jsonData)
val data: JSONObject = JSONObject(jsonData)
Blog.LOGE("BaseWebContentsViewer",data.toString())
mainControllInterface?.onBookInfos(jsonData)
} catch (e : Exception) {
}
}
}
constructor(webview : WebView, mainControllInterface : MainControllInterface ) { constructor(webview : WebView, mainControllInterface : MainControllInterface ) {
this.webview = webview this.webview = webview
this.mainControllInterface = mainControllInterface this.mainControllInterface = mainControllInterface
webview.webChromeClient = rootWebChromeClient webview.webChromeClient = rootWebChromeClient
webview.webViewClient = rootWebViewClient webview.webViewClient = rootWebViewClient
webview.settings.textZoom = 100 webview.settings.textZoom = 100
webview.addJavascriptInterface(this,"PAgit")
webview.settings.javaScriptEnabled = true webview.settings.javaScriptEnabled = true
webview.settings.javaScriptCanOpenWindowsAutomatically = false webview.settings.javaScriptCanOpenWindowsAutomatically = false
webview.settings.loadWithOverviewMode = true webview.settings.loadWithOverviewMode = true
@ -33,6 +51,8 @@ open class BaseWebContentsViewer {
WebView.setWebContentsDebuggingEnabled(true) WebView.setWebContentsDebuggingEnabled(true)
} }
constructor()
fun loadContents(webContents: BaseWebContents) { fun loadContents(webContents: BaseWebContents) {
currentContentsProvider = webContents currentContentsProvider = webContents
currentContentsProvider?.let { currentContentsProvider?.let {
@ -69,9 +89,9 @@ open class BaseWebContentsViewer {
if(request?.url?.toString()?.contains("gif") ?: false) { if(request?.url?.toString()?.contains("gif") ?: false) {
return WebResourceResponse("text/javascript", "UTF-8", null); return WebResourceResponse("text/javascript", "UTF-8", null);
} }
if(request?.url?.toString()?.contains(currentContentsProvider?.acccceptResourceKeyword() ?: "") == false && request?.url?.toString()?.contains(currentContentsProvider?.getLastedDoamin() ?: "") == false) { // if(request?.url?.toString()?.contains(currentContentsProvider?.acccceptResourceKeyword() ?: "") == false && request?.url?.toString()?.contains(currentContentsProvider?.getLastedDoamin() ?: "") == false) {
return WebResourceResponse("text/javascript", "UTF-8", null); // return WebResourceResponse("text/javascript", "UTF-8", null);
} // }
return super.shouldInterceptRequest(view, request) return super.shouldInterceptRequest(view, request)
} }
@ -142,6 +162,11 @@ open class BaseWebContentsViewer {
override fun onPageFinished(view: WebView?, url: String?) { override fun onPageFinished(view: WebView?, url: String?) {
super.onPageFinished(view, url) super.onPageFinished(view, url)
view?.let { view?.let {
if(url?.contains("/list/") ?: false){
findListItem {
Blog.LOGE("onPageFinished", url ?: "")
}
}
currentContentsProvider?.doOnloaded(it , { result -> currentContentsProvider?.doOnloaded(it , { result ->
result?.let { mainControllInterface.onLoadedContents(it) } result?.let { mainControllInterface.onLoadedContents(it) }
} , { } , {

View File

@ -15,5 +15,6 @@ interface MainControllInterface {
fun onLoadedContents(contents :String) fun onLoadedContents(contents :String)
fun onFindTitle(contents :String) fun onFindTitle(contents :String)
fun onBookInfos(jsonString : String)
} }

View File

@ -1,12 +1,13 @@
package com.mime.dualscreenview.webcontents 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.Booktoki
object WebContentsManger { object WebContentsManger {
val allContentsList : ArrayList<BaseWebContents> = arrayListOf(Booktoki) val allContentsList : ArrayList<BaseWebContents> = arrayListOf(Agit)
fun getBaseWebContentsBy(name : String) : BaseWebContents { fun getBaseWebContentsBy(name : String) : BaseWebContents {
var correctContents : BaseWebContents = Booktoki var correctContents : BaseWebContents = Agit
for (contents in allContentsList) { for (contents in allContentsList) {
if(name.equals(contents.getWebcontentsName())) { if(name.equals(contents.getWebcontentsName())) {
correctContents = contents correctContents = contents

View File

@ -0,0 +1,138 @@
package com.mime.dualscreenview.webcontents.contentsinfo
import com.mime.dualscreenview.webcontents.BaseWebContents
object Agit : BaseWebContents() {
override var lastNumber : Int = 664
override fun getWebcontentsName(): String {
return "Agit"
}
override fun getLastedDoamin(): String {
return String.format("https://agit%d.xyz/", lastNumber)
}
override fun getContentsList(): String {
return " var datasets = [];\n" +
" var pageNum = 0;\n" +
" var totalCount = 0;\n" +
" var currentIdx = 0;\n" +
" function getContentList() {\n" +
" \n" +
" if(document.getElementById('count_list') != undefined && totalCount <= 0) {\n" +
" totalCount = Number(document.getElementById('count_list').textContent);\n" +
" console.log(\"totalCount \" + totalCount);\n" +
" currentIdx = totalCount;\n" +
" }\n" +
" \n" +
" var bookTitle = document.getElementsByClassName('pt-2')[1].textContent;\n" +
" var bookPageUrl = new URL(location.href).pathname;\n" +
" var pages = document.getElementById('id_page_novel_c').childNodes;\n" +
" var list = document.getElementById('id_list_novel_c').childNodes;\n" +
" console.log(\"list.length >> \" + list.length);\n" +
" for (i = 0; i < list.length; i++) {\n" +
" var onclickValue = list[i].attributes['onclick'].value;\n" +
" var pageUrl = onclickValue.split('location.href=')[1].replace(';', '');\n" +
" var chapterTitle = list[i].childNodes[1].children[0].textContent;\n" +
" var chapterID = list[i].childNodes[1].getAttribute('data-wr-id-c');\n" +
" \n" +
" var data = {\n" +
" 'chapterID': Number(chapterID),\n" +
" 'idx': Number(currentIdx),\n" +
" 'pathUrl': pageUrl,\n" +
" 'bookPageUrl': bookPageUrl,\n" +
" 'chapterTitle': chapterTitle,\n" +
" 'bookTitle': bookTitle,\n" +
" };\n" +
" datasets.push(data);\n" +
" currentIdx = currentIdx - 1\n" +
" }\n" +
" \n" +
" \n" +
" \n" +
" var currentTime = 500;\n" +
" try { currentTime = new Date().valueOf() % 1000;\n" +
" \n" +
" } catch (e) {\n" +
" \n" +
" }\n" +
" \n" +
" console.log(\"pages.length >> \" + pages.length);\n" +
" console.log(\"datasets.length >> \" + datasets.length);\n" +
" console.log(\"totalCount >> \" + totalCount);\n" +
" console.log(\"pages.length >> \" + pages.length);\n" +
" \n" +
" if ((pages.length > pageNum) ||\n" +
" (totalCount > datasets.length)) {\n" +
" pageNum += 1;\n" +
" get_data_novel_list_c(pageNum);\n" +
" setTimeout(function() {\n" +
" getContentList();\n" +
" }, 2000 + currentTime);\n" +
" } else if ((pages.length == pageNum) ||\n" +
" (totalCount > 10 &&\n" +
" totalCount == datasets.length)) {\n" +
" datasets.sort((a, b) => b.idx < a.idx);\n" +
" var i = 0;\n" +
" datasets.forEach(function(item) {\n" +
" item['chapterNum'] = i;\n" +
" i = i + 1;\n" +
" } );\n" +
" \n" +
" PAgit.onBookInfo(JSON.stringify({\n" +
" 'bookTitle': bookTitle,\n" +
" 'bookPageUrl': new URL(location.href)\n" +
" .pathname,\n" +
" 'pages': datasets ,\n" +
" }));\n" +
" }\n" +
" }\n" +
" \n" +
" function wait(sec) {\n" +
" let start = Date.now(),\n" +
" now = start;\n" +
" while (now - start < sec * 1000) {\n" +
" now = Date.now();\n" +
" }\n" +
" }\n" +
" getContentList();"
}
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(\"id_wr_content\") != null ? document.getElementById(\"id_wr_content\").innerText : null"
}
override fun checkCorrectContents(contents: String): String {
return if (contents != null && !contents.isNullOrEmpty()) {
contents
} else {
"fail load"
}
}
override fun onLoadedJs(): String {
return "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();"
}
}

View File

@ -10,6 +10,7 @@
<WebView <WebView
android:id="@+id/menu_web" android:id="@+id/menu_web"
android:layout_margin="20dp"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="0dp" android:layout_height="0dp"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
@ -18,17 +19,7 @@
app:layout_constraintTop_toBottomOf="@id/textview_title" /> app:layout_constraintTop_toBottomOf="@id/textview_title" />
<com.mime.dualscreenview.view.PagedTextLayout
android:id="@+id/paged_layer"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible"
android:background="@color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/btn_setting"
app:layout_constraintTop_toBottomOf="@id/textview_title" />
<ImageButton <ImageButton
android:id="@+id/btn_home" android:id="@+id/btn_home"
@ -49,7 +40,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/main_top_height" android:layout_height="@dimen/main_top_height"
android:text="@string/app_name" android:text="@string/app_name"
android:background="#8FFF" android:background="@color/black"
android:gravity="center" android:gravity="center"
android:textSize="24sp" android:textSize="24sp"
app:layout_constraintRight_toLeftOf="@id/btn_list" app:layout_constraintRight_toLeftOf="@id/btn_list"
@ -104,7 +95,7 @@
android:tag="1" android:tag="1"
android:text="@string/display_the_second_screen" android:text="@string/display_the_second_screen"
android:visibility="visible" android:visibility="visible"
android:background="#8FFF" android:background="@color/black"
app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintHorizontal_chainStyle="spread"
@ -114,7 +105,7 @@
android:id="@+id/btn_setting" android:id="@+id/btn_setting"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="@dimen/main_top_height" android:layout_height="@dimen/main_top_height"
android:background="#8FFF" android:background="@color/black"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/btn_left" app:layout_constraintLeft_toRightOf="@+id/btn_left"
app:layout_constraintRight_toLeftOf="@+id/btn_right" app:layout_constraintRight_toLeftOf="@+id/btn_right"
@ -128,12 +119,27 @@
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
android:tag="0" android:tag="0"
android:text="@string/display_the_second_screen" android:text="@string/display_the_second_screen"
android:background="#8FFF" android:background="@color/black"
android:visibility="visible" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent" app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_chainStyle="spread" /> app:layout_constraintHorizontal_chainStyle="spread" />
<com.mime.dualscreenview.view.PagedTextLayout
android:id="@+id/paged_layer"
android:layout_margin="1dp"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:visibility="invisible"
android:background="@color/black"
android:elevation="5dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toTopOf="@id/btn_setting"
app:layout_constraintTop_toBottomOf="@id/textview_title" />
<ProgressBar <ProgressBar
android:id="@+id/progress" android:id="@+id/progress"
android:layout_width="0dp" android:layout_width="0dp"

View File

@ -1,52 +1,69 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout <RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
android:paddingTop="@dimen/main_top_height" android:layout_margin="5dp"
android:paddingBottom="@dimen/main_top_height"
android:layout_margin="0dp"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.Guideline <LinearLayout
android:id="@+id/center_guide" android:layout_margin="8dp"
android:orientation="vertical" android:layout_alignParentStart="true"
app:layout_constraintGuide_percent="0.5" android:layout_alignParentEnd="true"
android:layout_width="0dp" android:orientation="horizontal"
android:layout_height="0dp"/> android:layout_width="match_parent"
android:layout_height="match_parent">
<com.mime.dualscreenview.view.PagedTextView <com.mime.dualscreenview.view.PagedTextView
android:padding="@dimen/textview_padding" android:layout_margin="5dp"
android:padding="2dp"
android:id="@+id/hidden_view" android:id="@+id/hidden_view"
android:visibility="invisible"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@id/sencond_view"
android:layout_width="0dp"
style="@style/sss"
android:layout_height="match_parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:id="@+id/first_view"
android:padding="@dimen/textview_padding"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toLeftOf="@id/sencond_view"
android:layout_width="0dp"
style="@style/sss"
android:layout_height="match_parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:padding="@dimen/textview_padding"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:visibility="visible" android:visibility="visible"
app:layout_constraintBottom_toBottomOf="parent" android:layout_width="0dp"
app:layout_constraintLeft_toLeftOf="@id/center_guide" android:layout_weight="1"
android:includeFontPadding="false"
android:lineSpacingExtra="0dp"
style="@style/sss"
android:layout_height="match_parent"/>
<View
android:id="@+id/demp"
android:layout_margin="5dp"
android:padding="2dp"
android:layout_weight="1"
android:layout_width="0dp"
android:layout_height="match_parent"/>
</LinearLayout>
<LinearLayout
android:layout_margin="5dp"
android:layout_alignParentStart="true"
android:layout_alignParentEnd="true"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.AppCompatTextView
android:layout_margin="5dp"
android:padding="2dp"
android:gravity="center"
android:includeFontPadding="false"
android:id="@+id/first_view"
android:lineSpacingExtra="0dp"
android:layout_width="0dp"
android:layout_weight="1"
style="@style/sss"
android:layout_height="match_parent"/>
<androidx.appcompat.widget.AppCompatTextView
android:layout_margin="5dp"
android:padding="2dp"
android:includeFontPadding="false"
android:lineSpacingExtra="0dp"
android:visibility="visible"
android:id="@+id/sencond_view" android:id="@+id/sencond_view"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_weight="1"
style="@style/sss" style="@style/sss"
android:layout_height="match_parent"/> android:layout_height="match_parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</LinearLayout>
</RelativeLayout>

View File

@ -3,53 +3,53 @@
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"> xmlns:app="http://schemas.android.com/apk/res-auto">
<androidx.constraintlayout.widget.Guideline <!-- <androidx.constraintlayout.widget.Guideline-->
android:id="@+id/vertical_guide" <!-- android:id="@+id/vertical_guide"-->
android:orientation="horizontal" <!-- android:orientation="horizontal"-->
app:layout_constraintGuide_percent="0.5" <!-- app:layout_constraintGuide_percent="0.5"-->
android:layout_width="wrap_content" <!-- android:layout_width="wrap_content"-->
android:layout_height="wrap_content"/> <!-- android:layout_height="wrap_content"/>-->
<androidx.appcompat.widget.AppCompatTextView <!-- <androidx.appcompat.widget.AppCompatTextView-->
app:layout_constraintLeft_toLeftOf="parent" <!-- app:layout_constraintLeft_toLeftOf="parent"-->
app:layout_constraintRight_toRightOf="parent" <!-- app:layout_constraintRight_toRightOf="parent"-->
app:layout_constraintTop_toTopOf="parent" <!-- app:layout_constraintTop_toTopOf="parent"-->
app:layout_constraintBottom_toBottomOf="parent" <!-- app:layout_constraintBottom_toBottomOf="parent"-->
android:id="@+id/preview" <!-- android:id="@+id/preview"-->
android:text="@string/preview_text" <!-- android:text="@string/preview_text"-->
android:layout_width="0dp" <!-- android:layout_width="0dp"-->
android:layout_height="0dp"/> <!-- android:layout_height="0dp"/>-->
<ScrollView <!-- <ScrollView-->
android:id="@+id/config_setting" <!-- android:id="@+id/config_setting"-->
android:background="#99444444" <!-- android:background="#99444444"-->
app:layout_constraintLeft_toLeftOf="parent" <!-- app:layout_constraintLeft_toLeftOf="parent"-->
app:layout_constraintRight_toRightOf="parent" <!-- app:layout_constraintRight_toRightOf="parent"-->
app:layout_constraintTop_toTopOf="@id/vertical_guide" <!-- app:layout_constraintTop_toTopOf="@id/vertical_guide"-->
app:layout_constraintBottom_toBottomOf="parent" <!-- app:layout_constraintBottom_toBottomOf="parent"-->
android:layout_width="0dp" <!-- android:layout_width="0dp"-->
android:layout_height="0dp"> <!-- android:layout_height="0dp">-->
<LinearLayout <!-- <LinearLayout-->
android:orientation="vertical" <!-- android:orientation="vertical"-->
android:layout_width="match_parent" <!-- android:layout_width="match_parent"-->
android:layout_height="wrap_content"> <!-- android:layout_height="wrap_content">-->
<include layout="@layout/item_setting_title"/> <!-- <include layout="@layout/item_setting_title"/>-->
<com.mime.dualscreenview.view.StepsEditor <!-- <com.mime.dualscreenview.view.StepsEditor-->
android:id="@+id/text_size" <!-- android:id="@+id/text_size"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
<com.mime.dualscreenview.view.StepsEditor <!-- <com.mime.dualscreenview.view.StepsEditor-->
android:id="@+id/letter_space" <!-- android:id="@+id/letter_space"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
<com.mime.dualscreenview.view.StepsEditor <!-- <com.mime.dualscreenview.view.StepsEditor-->
android:id="@+id/line_space" <!-- android:id="@+id/line_space"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
<com.mime.dualscreenview.view.StepsEditor <!-- <com.mime.dualscreenview.view.StepsEditor-->
android:id="@+id/page_padding" <!-- android:id="@+id/page_padding"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
<com.mime.dualscreenview.view.ScopeEditor <!-- <com.mime.dualscreenview.view.ScopeEditor-->
android:id="@+id/page_typesface" <!-- android:id="@+id/page_typesface"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
<com.mime.dualscreenview.view.ScopeEditor <!-- <com.mime.dualscreenview.view.ScopeEditor-->
android:id="@+id/page_style" <!-- android:id="@+id/page_style"-->
style="@style/StepsEditorStyle" /> <!-- style="@style/StepsEditorStyle" />-->
</LinearLayout> <!-- </LinearLayout>-->
</ScrollView> <!-- </ScrollView>-->
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -2,8 +2,8 @@
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.DualScreenView" parent="Theme.MaterialComponents.DayNight.DarkActionBar"> <style name="Theme.DualScreenView" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item> <item name="colorPrimary">@color/black</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/black</item> <item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. --> <!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item> <item name="colorSecondary">@color/teal_200</item>

View File

@ -1,11 +1,13 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<resources> <resources xmlns:tools="http://schemas.android.com/tools">
<style name="sss"> <style name="sss">
<item name="android:statusBarColor" tools:targetApi="l">@color/black</item>
<item name="android:fontFamily">@font/kcc_sonkeechung</item> <item name="android:fontFamily">@font/kcc_sonkeechung</item>
<item name="android:textSize">14dp</item> <item name="android:textSize">14dp</item>
<item name="android:textAlignment">textStart</item> <item name="android:textAlignment">textStart</item>
</style> </style>
<style name="StepsEditorStyle"> <style name="StepsEditorStyle">
<item name="android:statusBarColor" tools:targetApi="l">@color/black</item>
<item name="android:layout_width">match_parent</item>> <item name="android:layout_width">match_parent</item>>
<item name="android:layout_height">@dimen/setting_item_height</item>> <item name="android:layout_height">@dimen/setting_item_height</item>>
</style> </style>

View File

@ -2,15 +2,15 @@
<!-- Base application theme. --> <!-- Base application theme. -->
<style name="Theme.DualScreenView" parent="Theme.MaterialComponents.NoActionBar"> <style name="Theme.DualScreenView" parent="Theme.MaterialComponents.NoActionBar">
<!-- Primary brand color. --> <!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item> <item name="colorOnSecondary">@color/black</item>
<item name="colorPrimaryVariant">@color/purple_700</item> <item name="colorPrimary">@color/black</item>
<item name="colorPrimaryVariant">@color/black</item>
<item name="colorOnPrimary">@color/white</item> <item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. --> <!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item> <item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item> <item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. --> <!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item> <item name="android:statusBarColor">?attr/colorOnSecondary</item>
<!-- Customize your theme here. --> <!-- Customize your theme here. -->
<item name="windowNoTitle">true</item> <item name="windowNoTitle">true</item>
<item name="windowActionBar">false</item> <item name="windowActionBar">false</item>