Compare commits
No commits in common. "main" and "proto" have entirely different histories.
63
.gitignore
vendored
63
.gitignore
vendored
@ -1,15 +1,50 @@
|
|||||||
*.iml
|
# These are some examples of commonly ignored file patterns.
|
||||||
.gradle
|
# You should customize this list as applicable to your project.
|
||||||
/local.properties
|
# Learn more about .gitignore:
|
||||||
/.idea/caches
|
# https://www.atlassian.com/git/tutorials/saving-changes/gitignore
|
||||||
/.idea/libraries
|
|
||||||
/.idea/modules.xml
|
# Node artifact files
|
||||||
/.idea/workspace.xml
|
node_modules/
|
||||||
/.idea/navEditor.xml
|
dist/
|
||||||
/.idea/assetWizardSettings.xml
|
|
||||||
|
# Compiled Java class files
|
||||||
|
*.class
|
||||||
|
|
||||||
|
# Compiled Python bytecode
|
||||||
|
*.py[cod]
|
||||||
|
|
||||||
|
# Log files
|
||||||
|
*.log
|
||||||
|
|
||||||
|
# Package files
|
||||||
|
*.jar
|
||||||
|
|
||||||
|
# Maven
|
||||||
|
target/
|
||||||
|
dist/
|
||||||
|
|
||||||
|
# JetBrains IDE
|
||||||
|
.idea/
|
||||||
|
|
||||||
|
# Unit test reports
|
||||||
|
TEST*.xml
|
||||||
|
|
||||||
|
# Generated by MacOS
|
||||||
.DS_Store
|
.DS_Store
|
||||||
/build
|
|
||||||
/captures
|
# Generated by Windows
|
||||||
.externalNativeBuild
|
Thumbs.db
|
||||||
.cxx
|
|
||||||
local.properties
|
# Applications
|
||||||
|
*.app
|
||||||
|
*.exe
|
||||||
|
*.war
|
||||||
|
|
||||||
|
# Large media files
|
||||||
|
*.mp4
|
||||||
|
*.tiff
|
||||||
|
*.avi
|
||||||
|
*.flv
|
||||||
|
*.mov
|
||||||
|
*.wmv
|
||||||
|
|
||||||
|
|||||||
11
README.md
11
README.md
@ -1,11 +0,0 @@
|
|||||||
# tokkiz
|
|
||||||
|
|
||||||
|
|
||||||
resource from {
|
|
||||||
https://www.flaticon.com/search/2?word=rotate&color=black&shape=fill
|
|
||||||
}
|
|
||||||
한글 폰트 from {
|
|
||||||
https://gongu.copyright.or.kr/gongu/bbs/B0000018/list.do?menuNo=200195
|
|
||||||
https://noonnu.cc/font_page/1075
|
|
||||||
}
|
|
||||||
|
|
||||||
1
app/.gitignore
vendored
1
app/.gitignore
vendored
@ -1 +0,0 @@
|
|||||||
/build
|
|
||||||
Binary file not shown.
@ -1,74 +0,0 @@
|
|||||||
plugins {
|
|
||||||
id 'com.android.application'
|
|
||||||
id 'org.jetbrains.kotlin.android'
|
|
||||||
id 'io.realm.kotlin'
|
|
||||||
// id 'kotlin-android-extensions'
|
|
||||||
}
|
|
||||||
|
|
||||||
android {
|
|
||||||
namespace 'com.mime.dualscreenview'
|
|
||||||
compileSdk 34
|
|
||||||
|
|
||||||
defaultConfig {
|
|
||||||
applicationId "com.mime.dualscreenview"
|
|
||||||
minSdk 24
|
|
||||||
targetSdk 34
|
|
||||||
versionCode 1
|
|
||||||
versionName "1.0"
|
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
|
||||||
}
|
|
||||||
signingConfigs {
|
|
||||||
|
|
||||||
debug {
|
|
||||||
storeFile = file("./bs_debug.keystore")
|
|
||||||
storePassword = "android"
|
|
||||||
keyAlias = "androiddebugkey"
|
|
||||||
keyPassword = "android"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
buildTypes {
|
|
||||||
release {
|
|
||||||
minifyEnabled false
|
|
||||||
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
packagingOptions {
|
|
||||||
exclude 'resources.arsc'
|
|
||||||
exclude 'AndroidManifest.xml'
|
|
||||||
}
|
|
||||||
compileOptions {
|
|
||||||
sourceCompatibility JavaVersion.VERSION_1_8
|
|
||||||
targetCompatibility JavaVersion.VERSION_1_8
|
|
||||||
}
|
|
||||||
kotlinOptions {
|
|
||||||
jvmTarget = '1.8'
|
|
||||||
}
|
|
||||||
buildFeatures {
|
|
||||||
dataBinding true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
dependencies {
|
|
||||||
|
|
||||||
implementation 'androidx.core:core-ktx:1.13.1'
|
|
||||||
implementation 'androidx.collection:collection-ktx:1.4.3'
|
|
||||||
|
|
||||||
implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.1'
|
|
||||||
|
|
||||||
implementation 'androidx.appcompat:appcompat:1.7.0'
|
|
||||||
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
|
|
||||||
|
|
||||||
implementation 'com.google.android.material:material:1.12.0'
|
|
||||||
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'
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// testImplementation 'junit:junit:4.13.2'
|
|
||||||
|
|
||||||
}
|
|
||||||
21
app/proguard-rules.pro
vendored
21
app/proguard-rules.pro
vendored
@ -1,21 +0,0 @@
|
|||||||
# Add project specific ProGuard rules here.
|
|
||||||
# You can control the set of applied configuration files using the
|
|
||||||
# proguardFiles setting in build.gradle.
|
|
||||||
#
|
|
||||||
# For more details, see
|
|
||||||
# http://developer.android.com/guide/developing/tools/proguard.html
|
|
||||||
|
|
||||||
# If your project uses WebView with JS, uncomment the following
|
|
||||||
# and specify the fully qualified class name to the JavaScript interface
|
|
||||||
# class:
|
|
||||||
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
|
||||||
# public *;
|
|
||||||
#}
|
|
||||||
|
|
||||||
# Uncomment this to preserve the line number information for
|
|
||||||
# debugging stack traces.
|
|
||||||
#-keepattributes SourceFile,LineNumberTable
|
|
||||||
|
|
||||||
# If you keep the line number information, uncomment this to
|
|
||||||
# hide the original source file name.
|
|
||||||
#-renamesourcefileattribute SourceFile
|
|
||||||
@ -1,44 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools">
|
|
||||||
|
|
||||||
<uses-permission android:name="android.permission.INTERNET"/>
|
|
||||||
|
|
||||||
<application
|
|
||||||
android:allowBackup="false"
|
|
||||||
android:name=".BaseAppication"
|
|
||||||
android:dataExtractionRules="@xml/data_extraction_rules"
|
|
||||||
android:fullBackupContent="@xml/backup_rules"
|
|
||||||
android:icon="@mipmap/ic_launcher"
|
|
||||||
android:label="@string/app_name"
|
|
||||||
android:usesCleartextTraffic="true"
|
|
||||||
android:roundIcon="@mipmap/ic_launcher_round"
|
|
||||||
android:supportsRtl="true"
|
|
||||||
android:largeHeap="true"
|
|
||||||
android:theme="@style/Theme.DualScreenView"
|
|
||||||
tools:targetApi="31" >
|
|
||||||
|
|
||||||
<activity
|
|
||||||
android:name=".activity.Intro"
|
|
||||||
android:launchMode="singleTask"
|
|
||||||
android:configChanges="keyboardHidden|orientation|screenSize"
|
|
||||||
android:exported="true">
|
|
||||||
<intent-filter>
|
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
|
||||||
<action android:name="android.intent.action.VIEW" />
|
|
||||||
<category android:name="android.intent.category.LAUNCHER" />
|
|
||||||
</intent-filter>
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:name=".activity.Main"
|
|
||||||
android:exported="false">
|
|
||||||
</activity>
|
|
||||||
<activity
|
|
||||||
android:launchMode="singleInstance"
|
|
||||||
android:name=".activity.Settings"
|
|
||||||
android:exported="false"
|
|
||||||
/>
|
|
||||||
</application>
|
|
||||||
|
|
||||||
</manifest>
|
|
||||||
@ -1,12 +0,0 @@
|
|||||||
package com.mime.dualscreenview
|
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import com.mime.dualscreenview.common.PrefManager
|
|
||||||
import io.realm.kotlin.Realm
|
|
||||||
|
|
||||||
class BaseAppication : Application() {
|
|
||||||
override fun onCreate() {
|
|
||||||
super.onCreate()
|
|
||||||
PrefManager.init(this)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,181 +0,0 @@
|
|||||||
package com.mime.dualscreenview.activity
|
|
||||||
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.os.Message
|
|
||||||
import android.text.SpannableStringBuilder
|
|
||||||
import android.text.style.RelativeSizeSpan
|
|
||||||
import android.view.Gravity
|
|
||||||
import android.view.KeyEvent
|
|
||||||
import android.view.KeyEvent.KEYCODE_BACK
|
|
||||||
import android.view.KeyEvent.KEYCODE_MEDIA_FAST_FORWARD
|
|
||||||
import android.view.KeyEvent.KEYCODE_MEDIA_NEXT
|
|
||||||
import android.view.KeyEvent.KEYCODE_MEDIA_PREVIOUS
|
|
||||||
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
|
|
||||||
import com.mime.dualscreenview.data.HistoryManager
|
|
||||||
import com.mime.dualscreenview.data.model.HistoryItem
|
|
||||||
import com.mime.dualscreenview.data.model.LastInfo
|
|
||||||
import io.realm.kotlin.Realm
|
|
||||||
import io.realm.kotlin.RealmConfiguration
|
|
||||||
import io.realm.kotlin.types.BaseRealmObject
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
|
|
||||||
open class Base : AppCompatActivity() {
|
|
||||||
|
|
||||||
inner class BaseHandler(looper : Looper = Looper.getMainLooper()) : Handler() {
|
|
||||||
override fun handleMessage(msg: Message) {
|
|
||||||
super.handleMessage(msg)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val baseHandler = BaseHandler()
|
|
||||||
var didBackPress = false
|
|
||||||
|
|
||||||
val onBackPressRunnable = Runnable {
|
|
||||||
didBackPress = false
|
|
||||||
}
|
|
||||||
|
|
||||||
val backPressString = arrayOf(
|
|
||||||
"이퓨 워너 백투웹?\n플리즈~\n한번더 뒤로가기!!",
|
|
||||||
"이퓨 워너 종료?\n플리즈~\n한번더 뒤로가기!~!",
|
|
||||||
)
|
|
||||||
fun firstBackPress() {
|
|
||||||
didBackPress = true
|
|
||||||
val origin = "이퓨 워너 종료?\n플리즈~ 한번더 뒤로가기!~!"
|
|
||||||
val biggerText = SpannableStringBuilder(origin)
|
|
||||||
biggerText.setSpan(RelativeSizeSpan(1.6f), 0, origin.length, 0)
|
|
||||||
Toast.makeText(baseContext,biggerText,Toast.LENGTH_LONG).apply {
|
|
||||||
setGravity(Gravity.CENTER, 0, 0)
|
|
||||||
}.show()
|
|
||||||
baseHandler.postDelayed(onBackPressRunnable,1500L)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
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}")
|
|
||||||
return when(keyCode) {
|
|
||||||
KEYCODE_VOLUME_DOWN -> { true }
|
|
||||||
KEYCODE_VOLUME_UP -> { true }
|
|
||||||
KEYCODE_VOLUME_MUTE -> { true }
|
|
||||||
KEYCODE_MEDIA_FAST_FORWARD -> { true }
|
|
||||||
KEYCODE_MEDIA_REWIND -> { true }
|
|
||||||
KEYCODE_MEDIA_PREVIOUS -> { true }
|
|
||||||
KEYCODE_MEDIA_NEXT -> { true }
|
|
||||||
KEYCODE_BACK -> { false }
|
|
||||||
else -> {
|
|
||||||
super.onKeyDown(keyCode, event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onKeyUp(keyCode: Int, event: KeyEvent?): Boolean {
|
|
||||||
Blog.LOGD(log = "keyCode : ${keyCode}, event : ${event}")
|
|
||||||
return when(keyCode) {
|
|
||||||
KEYCODE_VOLUME_DOWN -> {
|
|
||||||
onKeyClick(keyCode)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
KEYCODE_VOLUME_UP -> {
|
|
||||||
onKeyClick(keyCode)
|
|
||||||
true
|
|
||||||
}
|
|
||||||
KEYCODE_VOLUME_MUTE -> {
|
|
||||||
onKeyClick(keyCode)
|
|
||||||
true }
|
|
||||||
KEYCODE_BACK -> {
|
|
||||||
// onBackPressed()
|
|
||||||
this.onBackPressed()
|
|
||||||
false
|
|
||||||
}
|
|
||||||
KEYCODE_MEDIA_FAST_FORWARD -> { true }
|
|
||||||
KEYCODE_MEDIA_REWIND -> { true }
|
|
||||||
KEYCODE_MEDIA_PREVIOUS -> { true }
|
|
||||||
KEYCODE_MEDIA_NEXT -> { true }
|
|
||||||
else -> {
|
|
||||||
super.onKeyDown(keyCode, event)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onKeyClick(keyCode: Int) : Boolean {
|
|
||||||
when(keyCode) {
|
|
||||||
KEYCODE_VOLUME_DOWN -> {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
KEYCODE_VOLUME_UP -> {
|
|
||||||
true
|
|
||||||
}
|
|
||||||
KEYCODE_VOLUME_MUTE -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
KEYCODE_MEDIA_FAST_FORWARD -> { true }
|
|
||||||
KEYCODE_MEDIA_REWIND -> { true }
|
|
||||||
KEYCODE_MEDIA_PREVIOUS -> { true }
|
|
||||||
KEYCODE_MEDIA_NEXT -> { true }
|
|
||||||
else -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
fun openRealm() : Realm = HistoryManager.openRealm
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,981 +0,0 @@
|
|||||||
package com.mime.dualscreenview.activity
|
|
||||||
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.content.Intent
|
|
||||||
import android.content.pm.ActivityInfo
|
|
||||||
import android.content.res.Configuration
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.net.Uri
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import android.os.Handler
|
|
||||||
import android.os.Looper
|
|
||||||
import android.os.Message
|
|
||||||
import android.text.InputType
|
|
||||||
import android.text.SpannableStringBuilder
|
|
||||||
import android.text.style.RelativeSizeSpan
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.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
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import android.widget.EditText
|
|
||||||
import android.widget.ProgressBar
|
|
||||||
import android.widget.TextView
|
|
||||||
import android.widget.Toast
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
import androidx.core.net.toUri
|
|
||||||
import com.google.gson.Gson
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
import com.mime.dualscreenview.common.Blog
|
|
||||||
import com.mime.dualscreenview.common.PairArray
|
|
||||||
import com.mime.dualscreenview.common.PrefManager
|
|
||||||
import com.mime.dualscreenview.common.colorz
|
|
||||||
import com.mime.dualscreenview.common.getIndex
|
|
||||||
import com.mime.dualscreenview.common.typesfacez
|
|
||||||
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.BookPageInfosJ
|
|
||||||
import com.mime.dualscreenview.data.model.HistoryItem
|
|
||||||
import com.mime.dualscreenview.data.model.LastInfo
|
|
||||||
import com.mime.dualscreenview.data.model.ReaderConfig
|
|
||||||
import com.mime.dualscreenview.databinding.IntroBinding
|
|
||||||
import com.mime.dualscreenview.dialog.DefaultList
|
|
||||||
import com.mime.dualscreenview.view.PagedTextLayout
|
|
||||||
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.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
|
|
||||||
import kotlin.random.Random
|
|
||||||
|
|
||||||
|
|
||||||
class Intro : Base() , MainControllInterface, PagedTextViewInterface {
|
|
||||||
|
|
||||||
private lateinit var mBaseWebContentsViewer : BaseWebContentsViewer
|
|
||||||
var lastInfo : LastInfo? = null
|
|
||||||
lateinit var paged_layer : PagedTextLayout
|
|
||||||
lateinit var textview_title : TextView
|
|
||||||
var currentBooinfo : BookPageInfo? = null
|
|
||||||
|
|
||||||
val handle = object : Handler(Looper.getMainLooper()) {
|
|
||||||
override fun handleMessage(msg: Message) {
|
|
||||||
if (msg.what == 0 ) {
|
|
||||||
(msg.obj as? ReaderConfig)?.let {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getCurrentUrl() : String {
|
|
||||||
var currentPath = currentBooinfo?.pathUrl ?: mBaseWebContentsViewer.webview.url?.toUri()?.path ?: ""
|
|
||||||
var domain = PrefManager.getLastDomain()
|
|
||||||
return domain.plus(if (currentPath.length > 4) currentPath else "")
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onConfigurationChanged(newConfig: Configuration) {
|
|
||||||
super.onConfigurationChanged(newConfig)
|
|
||||||
Blog.LOGD(log= "onConfigurationChanged ${this::class.java.name} >> newConfig ${newConfig}")
|
|
||||||
mBaseWebContentsViewer.webview.reload()
|
|
||||||
}
|
|
||||||
|
|
||||||
var contentsSaver : WebView? = null
|
|
||||||
lateinit var binding : IntroBinding
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
Blog.LOGD(log= "onCreate ${this::class.java.name} >> savedInstanceState ${savedInstanceState}")
|
|
||||||
binding = IntroBinding.inflate(layoutInflater)
|
|
||||||
setContentView(binding.root)
|
|
||||||
binding.menuWeb.let {
|
|
||||||
it.setOnLongClickListener {
|
|
||||||
onTouch(TouchArea.Center)
|
|
||||||
return@setOnLongClickListener false
|
|
||||||
}
|
|
||||||
mBaseWebContentsViewer = BaseWebContentsViewer(it,this)
|
|
||||||
}
|
|
||||||
|
|
||||||
paged_layer = binding.pagedLayer
|
|
||||||
textview_title = binding.textviewTitle
|
|
||||||
|
|
||||||
binding.btnList.setOnClickListener { v ->
|
|
||||||
mBaseWebContentsViewer?.webview?.url?.let {
|
|
||||||
Uri.parse(it).path?.let {
|
|
||||||
HistoryManager.getBookInfos(it, {
|
|
||||||
it?.let {
|
|
||||||
it.pages.sortBy { it.pathUrl }
|
|
||||||
showList(it)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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
|
|
||||||
contentsSaver?.settings?.loadWithOverviewMode = true
|
|
||||||
contentsSaver?.settings?.setPluginState(WebSettings.PluginState.ON)
|
|
||||||
contentsSaver?.settings?.domStorageEnabled = true
|
|
||||||
contentsSaver?.clearCache(true);
|
|
||||||
contentsSaver?.clearHistory();
|
|
||||||
contentsSaver?.clearSslPreferences();
|
|
||||||
}
|
|
||||||
|
|
||||||
// findViewById<View>(R.id.btn_rotate).setOnClickListener { v->
|
|
||||||
// switcvhOrient()
|
|
||||||
// }
|
|
||||||
|
|
||||||
binding.btnSetting.setOnClickListener { v->
|
|
||||||
startActivity(Intent(this@Intro, Settings::class.java))
|
|
||||||
}
|
|
||||||
binding.btnHistory.setOnClickListener { v->
|
|
||||||
var realm = openRealm()
|
|
||||||
realm.query<HistoryItem>().find().let {
|
|
||||||
showHistory(realm.copyFromRealm(it))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.btnHome.setOnClickListener { v->
|
|
||||||
paged_layer.visibility = GONE
|
|
||||||
mBaseWebContentsViewer.loadContents(NewtokiOne)
|
|
||||||
}
|
|
||||||
|
|
||||||
loadLastInfo()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadLastInfo(){
|
|
||||||
val realm = openRealm()
|
|
||||||
try { lastInfo = realm.query<LastInfo>().find().last()?.copyFromRealm()
|
|
||||||
try {
|
|
||||||
if (lastInfo != null) {
|
|
||||||
HistoryManager.getBookPageInfo(Uri.parse(lastInfo!!.pageUrl!!).path!!) {
|
|
||||||
it?.let {
|
|
||||||
currentBooinfo = it
|
|
||||||
paged_layer.visibility = VISIBLE
|
|
||||||
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!!))
|
|
||||||
} else {
|
|
||||||
Blog.LOGE("HistoryManager.getNextPage(${NewtokiOne.getLastedDoamin()})")
|
|
||||||
mBaseWebContentsViewer.webview.loadUrl(NewtokiOne.getLastedDoamin() + it?.pathUrl!!)
|
|
||||||
}
|
|
||||||
it?.pathUrl?.let {
|
|
||||||
HistoryManager.getBookInfos(it) {
|
|
||||||
saveItem(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
HistoryManager.openRealm.query<ReaderConfig>()?.find()?.let {
|
|
||||||
if (it.size > 0) {
|
|
||||||
realm.copyFromRealm(it.first()).let {
|
|
||||||
applyReaderConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
paged_layer.text = it!!.contents!!
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}catch (e1 : Exception){
|
|
||||||
|
|
||||||
}} catch (e : Exception) { }
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun reloadLastInfo() {
|
|
||||||
val configuration: Configuration = getResources().getConfiguration()
|
|
||||||
if(lastInfo != null && lastInfo?.displayOrientation != configuration.orientation) {
|
|
||||||
// findViewById<View>(R.id.btn_rotate).performClick()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBookInfos(aInfos: BookPageInfos) {
|
|
||||||
Blog.LOGE("onBookInfos(aInfos: ${aInfos})")
|
|
||||||
runOnUiThread {
|
|
||||||
showList(aInfos)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBookInfos(jsonString: String) {
|
|
||||||
Blog.LOGE("onBookInfos" , "jsonString >> ${jsonString}")
|
|
||||||
val realm = openRealm()
|
|
||||||
var infos : BookPageInfos? = null
|
|
||||||
realm.writeBlocking {
|
|
||||||
try {
|
|
||||||
var infosj : BookPageInfosJ? = null
|
|
||||||
infosj = Gson().fromJson(jsonString, BookPageInfosJ::class.java)
|
|
||||||
HistoryManager.getBookInfos(infosj.bookPageUrl!!){
|
|
||||||
if (it != null) {
|
|
||||||
|
|
||||||
infos = copyToRealm(it!!, UpdatePolicy.ALL)
|
|
||||||
for (item in infosj.pages) {
|
|
||||||
if (infos!!.hasItem(item.getRealm()) == false) {
|
|
||||||
infos!!.pages.add(item.getRealm())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (infos != null) {
|
|
||||||
infos = this.copyFromRealm(infos!!)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
infos = infosj?.getR()
|
|
||||||
if (infos != null) {
|
|
||||||
infos = copyToRealm(infos!!, UpdatePolicy.ALL)
|
|
||||||
for (item in infosj.pages) {
|
|
||||||
infos?.pages?.add(item.getRealm())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (infos != null) {
|
|
||||||
infos = this.copyFromRealm(infos!!)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} catch (e :Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
} finally {
|
|
||||||
infos?.bookPageUrl?.let {
|
|
||||||
HistoryManager.getBookInfos(it){
|
|
||||||
it?.let {
|
|
||||||
Blog.LOGE(s(), "onBookInfos it >> ${it}")
|
|
||||||
runOnUiThread {
|
|
||||||
showList(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun s() = "onBookInfos"
|
|
||||||
|
|
||||||
fun reloadTo(lastInfo: LastInfo?) {
|
|
||||||
findViewById<WebView>(R.id.menu_web)?.postDelayed({
|
|
||||||
if (lastInfo != null) {
|
|
||||||
mBaseWebContentsViewer.loadLastInfo(lastInfo!!)
|
|
||||||
} else {
|
|
||||||
mBaseWebContentsViewer.loadContents(NewtokiOne)
|
|
||||||
}
|
|
||||||
},200L)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStart() {
|
|
||||||
super.onStart()
|
|
||||||
proceedLastPage()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun proceedLastPage() {
|
|
||||||
var realm = HistoryManager.openRealm
|
|
||||||
realm.query<ReaderConfig>()?.find()?.let {
|
|
||||||
if (it.size > 0) {
|
|
||||||
realm.copyFromRealm(it.first())?.let {
|
|
||||||
var msg = handle.obtainMessage()
|
|
||||||
msg.what = 0
|
|
||||||
msg.obj = it
|
|
||||||
handle.sendMessageDelayed(msg, 200)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
reloadLastInfo()
|
|
||||||
reloadTo(lastInfo)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun switcvhOrient(){
|
|
||||||
// val configuration: Configuration = getResources().getConfiguration()
|
|
||||||
// setRequestedOrientation(
|
|
||||||
// if(configuration.orientation == ActivityInfo.SCREEN_ORIENTATION_PORTRAIT) { ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE }
|
|
||||||
// else {ActivityInfo.SCREEN_ORIENTATION_PORTRAIT}
|
|
||||||
// )
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showHistory(infos: List<HistoryItem>) {
|
|
||||||
|
|
||||||
val builderSingle: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
|
|
||||||
builderSingle.setTitle("${currentTitle} : ${currentChapter} -> Select One ")
|
|
||||||
val arrayAdapter =
|
|
||||||
ArrayAdapter<String>(this@Intro, android.R.layout.select_dialog_singlechoice)
|
|
||||||
for (item in infos) {
|
|
||||||
arrayAdapter.addAll(item.title)
|
|
||||||
}
|
|
||||||
|
|
||||||
builderSingle.setNegativeButton("cancel",
|
|
||||||
DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() })
|
|
||||||
|
|
||||||
builderSingle.setAdapter(arrayAdapter,
|
|
||||||
DialogInterface.OnClickListener { dialog, which ->
|
|
||||||
val strName = arrayAdapter.getItem(which)
|
|
||||||
val item = infos.get(which)
|
|
||||||
val builderInner: AlertDialog.Builder = AlertDialog.Builder(this@Intro)
|
|
||||||
builderInner.setMessage(strName)
|
|
||||||
builderInner.setTitle("${infos.get(which).title}로 이동 고고!?")
|
|
||||||
builderInner.setPositiveButton("Ok",
|
|
||||||
DialogInterface.OnClickListener {
|
|
||||||
dialog, which ->
|
|
||||||
contentsLoad(item.pageUrl)
|
|
||||||
dialog.dismiss()
|
|
||||||
})
|
|
||||||
builderInner.setNeutralButton("삭제",
|
|
||||||
DialogInterface.OnClickListener {
|
|
||||||
dialog, which ->
|
|
||||||
var realm = openRealm()
|
|
||||||
realm?.writeBlocking {
|
|
||||||
this.query<HistoryItem>().query("title == '${item.title}'").find()?.last()?.let{
|
|
||||||
this.delete(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dialog.dismiss()
|
|
||||||
})
|
|
||||||
builderInner.setNegativeButton("취소",
|
|
||||||
DialogInterface.OnClickListener {
|
|
||||||
dialog, which ->
|
|
||||||
dialog.dismiss()
|
|
||||||
})
|
|
||||||
builderInner.show()
|
|
||||||
})
|
|
||||||
var ddddd= builderSingle.create()
|
|
||||||
ddddd.setOnShowListener { d->
|
|
||||||
(d as? AlertDialog)?.let{
|
|
||||||
it.listView?.setSelection(currentChapter)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ddddd.show()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun showList(infos: 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.chapterID }
|
|
||||||
|
|
||||||
DefaultList.showDefaultList(
|
|
||||||
this@Intro,
|
|
||||||
"현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라",
|
|
||||||
items,
|
|
||||||
currentChapter,
|
|
||||||
{ position ->
|
|
||||||
return@showDefaultList items?.get(position)?.chapterTitle ?: ""
|
|
||||||
},
|
|
||||||
{ position ->
|
|
||||||
items?.get(position)?.let { moveTo(it) }
|
|
||||||
}, { state ->
|
|
||||||
if (state < 0 ) {
|
|
||||||
saveItem(infos)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val String.cleanTextContent: String
|
|
||||||
get() {
|
|
||||||
// strips off all non-ASCII characters
|
|
||||||
var text = this
|
|
||||||
text = text.replace("[^\\x00-\\x7F]".toRegex(), "")
|
|
||||||
|
|
||||||
// erases all the ASCII control characters
|
|
||||||
text = text.replace("[\\p{Cntrl}&&[^\r\n\t]]".toRegex(), "")
|
|
||||||
|
|
||||||
// removes non-printable characters from Unicode
|
|
||||||
text = text.replace("\\p{C}".toRegex(), "")
|
|
||||||
return text.trim()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var saveClient = object : WebViewClient() {
|
|
||||||
override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) {
|
|
||||||
super.onPageStarted(view, url, favicon)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
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 {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, 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}")
|
|
||||||
}
|
|
||||||
}.apply {
|
|
||||||
HistoryManager.getBookInfos(it) { saveItem(it)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var saveTarget : ArrayList<BookPageInfo> = arrayListOf()
|
|
||||||
private fun saveItem(infos: BookPageInfos?) {
|
|
||||||
Blog.LOGE("saveItem >>> infos?.pages ${infos?.pages?.size ?: 0}")
|
|
||||||
var savedCount = Math.abs(Random(System.currentTimeMillis()).nextLong().rem(9) + 6L)
|
|
||||||
Blog.LOGE("saveItem >>> targetCount = ${savedCount}")
|
|
||||||
|
|
||||||
infos?.pages?.reversed()?.forEach {
|
|
||||||
if ((it.contents?.length ?: 0) > 10) {
|
|
||||||
} else {
|
|
||||||
if (savedCount.toInt() > 0) {
|
|
||||||
saveTarget.add(it)
|
|
||||||
savedCount = savedCount - 1L
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (savedCount > 0) {
|
|
||||||
HistoryManager.openRealm.query<BookPageInfo>().find().forEach {
|
|
||||||
if ((it.contents?.length ?: 0) > 10) {
|
|
||||||
} else if(savedCount.toInt() > 0) {
|
|
||||||
saveTarget.add(HistoryManager.openRealm.copyFromRealm(it))
|
|
||||||
savedCount = savedCount - 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
Blog.LOGE("saveItem >>> saveTarget ${saveTarget.count()}")
|
|
||||||
try {
|
|
||||||
saveTarget.removeFirst().let {
|
|
||||||
Blog.LOGE("saveItem >>> ${it.pathUrl}")
|
|
||||||
runOnUiThread {
|
|
||||||
mBaseWebContentsViewer.webview.url?.let { currentUrl ->
|
|
||||||
currentUrl.replace(Uri.parse(currentUrl).path ?: "", it.pathUrl ?: "")
|
|
||||||
?.let { targetUrl ->
|
|
||||||
Blog.LOGE("targetUrl >>> ${targetUrl}")
|
|
||||||
contentsSaver?.loadUrl(targetUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch ( e : Exception) {
|
|
||||||
e.printStackTrace()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun moveTo(item: BookPageInfo?) {
|
|
||||||
item?.pathUrl?.let { newPath ->
|
|
||||||
if (item.contents?.length ?: 0 > 10) {
|
|
||||||
paged_layer.text = item!!.contents!!
|
|
||||||
paged_layer.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
mBaseWebContentsViewer?.webview?.url?.let { currentUrl ->
|
|
||||||
Uri.parse(currentUrl)?.path?.let {
|
|
||||||
currentUrl.replace(it, newPath)?.let {
|
|
||||||
mBaseWebContentsViewer?.webview?.loadUrl(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// fun showStyleList() {
|
|
||||||
// var mStylez = Stylez(this@Intro)
|
|
||||||
// mStylez.styleSelectInterface = object : StyleSelectInterface {
|
|
||||||
// override fun onSelectStyle(bgColor: String, textColor: String) {
|
|
||||||
// paged_layer?.setColorStyle(arrayOf(textColor,bgColor))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// mStylez.show()
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
override fun onDestroy() {
|
|
||||||
|
|
||||||
super.onDestroy()
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var onNextClickAction: GotoSomeWhere? = null
|
|
||||||
override fun showNextBtn(find : Boolean , onClickAction: GotoSomeWhere) {
|
|
||||||
onNextClickAction = onClickAction
|
|
||||||
findViewById<ImageFilterButton>(R.id.btn_right)?.let{
|
|
||||||
it.setOnClickListener {
|
|
||||||
actionNextEvent()
|
|
||||||
}
|
|
||||||
it.visibility= if(find) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun moveToNext(pathUrl : String?) {
|
|
||||||
if (pathUrl != null && pathUrl.length > 6) {
|
|
||||||
HistoryManager.getNextPage(pathUrl!!) {
|
|
||||||
if(it != null && it!!.pathUrl?.length ?: 0 > 6) {contentsLoad(it.pathUrl!!)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
fun moveToPrev(pathUrl : String?) {
|
|
||||||
if (pathUrl != null && pathUrl.length > 6) {
|
|
||||||
HistoryManager.getPrevPage(pathUrl!!) {
|
|
||||||
if(it != null && it!!.pathUrl?.length ?: 0 > 6) {contentsLoad(it.pathUrl!!)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun contentsLoad(pathUrl : String) {
|
|
||||||
HistoryManager.getBookPageInfo(pathUrl) {
|
|
||||||
Blog.LOGE("contentsLoad :::: pathUrl >> ${pathUrl}")
|
|
||||||
it?.pathUrl?.let {
|
|
||||||
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
|
|
||||||
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(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")) {
|
|
||||||
paged_layer.visibility = GONE
|
|
||||||
mBaseWebContentsViewer.webview.loadUrl(lastInfo!!.pageUrl!!.replace(Uri.parse(lastInfo!!.pageUrl)!!.path!!,it?.pathUrl!!))
|
|
||||||
} else {
|
|
||||||
paged_layer.visibility = GONE
|
|
||||||
mBaseWebContentsViewer.webview.loadUrl(NewtokiOne.getLastedDoamin() + it?.pathUrl!!)
|
|
||||||
}
|
|
||||||
HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun actionNextEvent(fast : Boolean = false) {
|
|
||||||
if (paged_layer != null && paged_layer!!.visibility == View.VISIBLE && paged_layer!!.size() > 0 && (paged_layer!!.current() < paged_layer!!.size() - 1) ) {
|
|
||||||
paged_layer!!.doNext(fast)
|
|
||||||
updateLastInfo(paged_layer!!)
|
|
||||||
} else {
|
|
||||||
moveToNext(currentBooinfo?.pathUrl ?: mBaseWebContentsViewer.webview.url?.toUri()?.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var onPrevClickAction: GotoSomeWhere? = null
|
|
||||||
override fun showPrevBtn(find : Boolean, onClickAction: GotoSomeWhere) {
|
|
||||||
onPrevClickAction = onClickAction
|
|
||||||
findViewById<ImageFilterButton>(R.id.btn_left)?.let{
|
|
||||||
it.setOnClickListener {
|
|
||||||
actionPrevEvent()
|
|
||||||
}
|
|
||||||
it.visibility= if(find) VISIBLE else GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun applyReaderConfig() {
|
|
||||||
var realm = HistoryManager.openRealm
|
|
||||||
realm.query<ReaderConfig>()?.find()?.let {
|
|
||||||
if (it.size > 0) {
|
|
||||||
realm.copyFromRealm(it.first())?.let {
|
|
||||||
runOnUiThread {
|
|
||||||
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)
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun actionPrevEvent(fast : Boolean = false) {
|
|
||||||
if (paged_layer != null && paged_layer!!.visibility == View.VISIBLE && paged_layer!!.size() > 0 && paged_layer!!.current() > 0 ) {
|
|
||||||
paged_layer!!.doPrev(fast)
|
|
||||||
updateLastInfo(paged_layer!!)
|
|
||||||
} else {
|
|
||||||
moveToPrev(currentBooinfo?.pathUrl ?: mBaseWebContentsViewer.webview.url?.toUri()?.path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBackPressed() {
|
|
||||||
|
|
||||||
// super.onBackPressed()
|
|
||||||
var layer = findViewById<PagedTextLayout>(R.id.paged_layer)
|
|
||||||
|
|
||||||
// if (!didBackPress) {
|
|
||||||
// firstBackPress()
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
if (layer != null && layer.visibility == View.VISIBLE) {
|
|
||||||
didBackPress = false
|
|
||||||
layer.visibility = GONE
|
|
||||||
onTouch(TouchArea.Center)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mBaseWebContentsViewer.webview.canGoBack()) {
|
|
||||||
mBaseWebContentsViewer.webview.goBack()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!didBackPress) {
|
|
||||||
firstBackPress()
|
|
||||||
return
|
|
||||||
} else {
|
|
||||||
finishAffinity()
|
|
||||||
didBackPress = false
|
|
||||||
// super.onBackPressed()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun showAlert(alert: String) {
|
|
||||||
Log.i(TAG,"showAlert >> " + alert)
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
|
||||||
override fun onLoadedContents(aContents: String) {
|
|
||||||
paged_layer.apply {
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Log.i(TAG,"onLoadedContents >> " + aContents)
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentTitle : String = ""
|
|
||||||
var currentChapter : Int = 0
|
|
||||||
|
|
||||||
override fun onFindTitle(contents: String) {
|
|
||||||
textview_title.text = contents
|
|
||||||
textview_title.setOnClickListener {
|
|
||||||
val builder = AlertDialog.Builder(this)
|
|
||||||
builder.setTitle("Title")
|
|
||||||
val input = EditText(this)
|
|
||||||
input.setText(mBaseWebContentsViewer?.webview?.url ?: "")
|
|
||||||
input.inputType = InputType.TYPE_CLASS_TEXT
|
|
||||||
builder.setView(input)
|
|
||||||
builder.setPositiveButton(
|
|
||||||
"OK"
|
|
||||||
) { dialog, which ->
|
|
||||||
var m_Text = input.text.toString()
|
|
||||||
mBaseWebContentsViewer?.webview?.loadUrl(m_Text.trim())
|
|
||||||
}
|
|
||||||
builder.setNegativeButton(
|
|
||||||
"Cancel"
|
|
||||||
) { dialog, which -> dialog.cancel() }
|
|
||||||
builder.show()
|
|
||||||
}
|
|
||||||
var testRegex = """[^0-9]""".toRegex();
|
|
||||||
Blog.LOGI(TAG,"onFindTitle >> " + contents + " ::: ${testRegex.replace(contents,"")}")
|
|
||||||
if(contents.contains("-")) {
|
|
||||||
currentTitle = contents.split("-")[0]
|
|
||||||
try {
|
|
||||||
currentChapter = testRegex.replace(contents.split("-")[1],"").toInt()
|
|
||||||
} catch (e : Exception) {
|
|
||||||
currentChapter = 0
|
|
||||||
}
|
|
||||||
} else if(testRegex.replace(contents,"").length > 0){
|
|
||||||
currentChapter = testRegex.replace(contents,"").toInt()
|
|
||||||
currentTitle = contents.split(testRegex.replace(contents,""))[0]
|
|
||||||
} else {
|
|
||||||
val dateFormat = "yyyyMMdd-HH"
|
|
||||||
val date = Date(currentTimeMillis())
|
|
||||||
val simpleDateFormat = SimpleDateFormat(dateFormat)
|
|
||||||
currentTitle = simpleDateFormat.format(date)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onStartLoad() {
|
|
||||||
findViewById<ProgressBar>(R.id.progress).visibility = VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun completePageLoad(lastInfo: LastInfo) {
|
|
||||||
val configuration: Configuration = getResources().getConfiguration()
|
|
||||||
|
|
||||||
if(this.lastInfo == null || !(this.lastInfo?.pageUrl.equals(lastInfo?.pageUrl)) || this.lastInfo?.displayOrientation != configuration?.orientation) {
|
|
||||||
lastInfo.displayOrientation = configuration?.orientation ?: ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
saveLastInfo(lastInfo)
|
|
||||||
}
|
|
||||||
binding.progress.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun saveLastInfo(lastInfo: LastInfo) {
|
|
||||||
val realm = openRealm()
|
|
||||||
if((realm.query<LastInfo>()?.count()?.find() ?: 0) > 0) {
|
|
||||||
realm.writeBlocking {
|
|
||||||
this.query<LastInfo>()?.find()?.last()?.let{
|
|
||||||
it.pageUrl = lastInfo.pageUrl
|
|
||||||
it.title = currentTitle
|
|
||||||
it.chapter = currentChapter
|
|
||||||
it.pageIndex = lastInfo.pageIndex
|
|
||||||
it.contentsName = lastInfo.contentsName
|
|
||||||
it.displayOrientation = lastInfo.displayOrientation
|
|
||||||
this@Intro.lastInfo = copyFromRealm(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
realm.writeBlocking {
|
|
||||||
copyToRealm(lastInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Blog.LOGD(log ="Successfully opened realm: ${realm.configuration.name}")
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun updateLastInfo(pagedTextLayout: PagedTextLayout) {
|
|
||||||
val configuration: Configuration = getResources().getConfiguration()
|
|
||||||
val realm = openRealm()
|
|
||||||
realm.writeBlocking {
|
|
||||||
this.query<LastInfo>()?.find()?.last()?.let{
|
|
||||||
it.displayOrientation = configuration.orientation
|
|
||||||
it.title = currentTitle
|
|
||||||
// it.pageUrl = currentBooinfo?.pathUrl ?: mBaseWebContentsViewer.webview.url?.toUri()?.path ?: ""
|
|
||||||
it.chapter = currentChapter
|
|
||||||
it.pageIndex = pagedTextLayout.current()
|
|
||||||
this@Intro.lastInfo = copyFromRealm(it)
|
|
||||||
}
|
|
||||||
if (currentTitle.length > 0 && currentChapter > 0) {
|
|
||||||
this@Intro.lastInfo?.makeHistoryItem()?.let{
|
|
||||||
copyToRealm(it, UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Blog.LOGD(log ="Successfully opened realm: ${realm.configuration.name}")
|
|
||||||
|
|
||||||
}
|
|
||||||
override fun onKeyClick(keyCode: Int): Boolean {
|
|
||||||
when(keyCode) {
|
|
||||||
KeyEvent.KEYCODE_VOLUME_DOWN ->{actionNextEvent()}
|
|
||||||
KeyEvent.KEYCODE_VOLUME_UP ->{actionPrevEvent()}
|
|
||||||
KeyEvent.KEYCODE_VOLUME_MUTE -> {actionNextEvent()}
|
|
||||||
|
|
||||||
}
|
|
||||||
return super.onKeyClick(keyCode)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onTouch(touchArea: TouchArea) {
|
|
||||||
Blog.LOGD(log="onTouch ${touchArea}")
|
|
||||||
when (touchArea) {
|
|
||||||
TouchArea.Center-> {
|
|
||||||
findViewById<View>(R.id.btn_right).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_left).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_setting).visibility = VISIBLE
|
|
||||||
|
|
||||||
textview_title.visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_home).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_list).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_history).visibility = VISIBLE
|
|
||||||
// findViewById<View>(R.id.btn_rotate).visibility = VISIBLE
|
|
||||||
|
|
||||||
}
|
|
||||||
TouchArea.Right -> {
|
|
||||||
actionNextEvent()
|
|
||||||
}
|
|
||||||
TouchArea.Left-> {
|
|
||||||
actionPrevEvent()
|
|
||||||
}
|
|
||||||
TouchArea.DoubleRight -> {
|
|
||||||
actionNextEvent(true)
|
|
||||||
}
|
|
||||||
TouchArea.DoubleLeft -> {
|
|
||||||
actionPrevEvent(true)
|
|
||||||
}
|
|
||||||
else -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLongClick() {
|
|
||||||
Blog.LOGD(log="onLongClick")
|
|
||||||
|
|
||||||
}
|
|
||||||
override fun onSwipeLeft(count : Int) {
|
|
||||||
Blog.LOGD(log="onSwipeLeft ${count}")
|
|
||||||
actionNextEvent(count > 1)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeRight(count : Int) {
|
|
||||||
Blog.LOGD(log="onSwipeRight ${count}")
|
|
||||||
actionPrevEvent(count > 1)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeUp(touchCount: Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeDown(touchCount: Int) {
|
|
||||||
if (touchCount == 2) {
|
|
||||||
if (paged_layer?.visibility == VISIBLE) {
|
|
||||||
paged_layer?.visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_right).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_left).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_setting).visibility = VISIBLE
|
|
||||||
|
|
||||||
textview_title.visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_home).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_list).visibility = VISIBLE
|
|
||||||
findViewById<View>(R.id.btn_history).visibility = VISIBLE
|
|
||||||
// findViewById<View>(R.id.btn_rotate).visibility = VISIBLE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onTimeoverTouch() {
|
|
||||||
Blog.LOGD(log="onTimeoverTouch")
|
|
||||||
findViewById<View>(R.id.btn_right).visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_left).visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_setting).visibility = GONE
|
|
||||||
|
|
||||||
textview_title.visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_home).visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_list).visibility = GONE
|
|
||||||
findViewById<View>(R.id.btn_history).visibility = GONE
|
|
||||||
// findViewById<View>(R.id.btn_rotate).visibility = GONE
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
private const val TAG = "DualScreenStatus"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,8 +0,0 @@
|
|||||||
package com.mime.dualscreenview.activity
|
|
||||||
|
|
||||||
import android.app.Activity
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
|
||||||
|
|
||||||
class Main : Base() {
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,123 +0,0 @@
|
|||||||
package com.mime.dualscreenview.activity
|
|
||||||
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
|
||||||
import androidx.annotation.RequiresApi
|
|
||||||
import androidx.databinding.DataBindingUtil
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
import com.mime.dualscreenview.common.PairArray
|
|
||||||
import com.mime.dualscreenview.common.colorz
|
|
||||||
import com.mime.dualscreenview.common.getIndex
|
|
||||||
import com.mime.dualscreenview.common.typesfacez
|
|
||||||
import com.mime.dualscreenview.data.HistoryManager
|
|
||||||
import com.mime.dualscreenview.data.model.ReaderConfig
|
|
||||||
import com.mime.dualscreenview.databinding.SettingsBinding
|
|
||||||
import io.realm.kotlin.UpdatePolicy
|
|
||||||
import io.realm.kotlin.ext.query
|
|
||||||
|
|
||||||
class Settings : Base() {
|
|
||||||
|
|
||||||
lateinit var binding : SettingsBinding
|
|
||||||
var readerConfig : ReaderConfig? = null
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
super.onCreate(savedInstanceState)
|
|
||||||
binding = DataBindingUtil.setContentView(this, R.layout.settings)
|
|
||||||
// setContentView(R.layout.settings)
|
|
||||||
var realm = HistoryManager.openRealm
|
|
||||||
realm.writeBlocking {
|
|
||||||
this.query<ReaderConfig>()?.find()?.let {
|
|
||||||
if (it.size > 0) {
|
|
||||||
readerConfig = copyFromRealm(it.first())
|
|
||||||
} else {
|
|
||||||
readerConfig = ReaderConfig()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
|
||||||
override fun onResume() {
|
|
||||||
super.onResume()
|
|
||||||
binding.textSize.displayFormat = "글자 크기 : %d"
|
|
||||||
binding.textSize.value = readerConfig?.textSize ?: 14
|
|
||||||
binding.textSize.mValueChange = {
|
|
||||||
binding.preview.textSize = it.toFloat() ;
|
|
||||||
if (readerConfig?.textSize != it) {
|
|
||||||
readerConfig?.textSize = it
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.pagePadding.displayFormat = "페이지 여백 : %d"
|
|
||||||
binding.pagePadding.value = readerConfig?.padding ?: 5
|
|
||||||
binding.pagePadding.mValueChange = {
|
|
||||||
binding.preview.setPadding(it,it,it,it) ;
|
|
||||||
if (readerConfig?.padding != it) {
|
|
||||||
readerConfig?.padding = it
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.letterSpace.displayFormat = "자간 : %d"
|
|
||||||
binding.letterSpace.value = readerConfig?.letterSpace ?: 1
|
|
||||||
binding.letterSpace.mValueChange = {
|
|
||||||
binding.preview.letterSpacing = it.times(0.01).toFloat() ;
|
|
||||||
if (readerConfig?.letterSpace != it) {
|
|
||||||
readerConfig?.letterSpace = it
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
binding.lineSpace.displayFormat = "행간 : %d"
|
|
||||||
binding.lineSpace.value = readerConfig?.lineSpace ?: 1
|
|
||||||
binding.lineSpace.mValueChange = {
|
|
||||||
binding.preview.setLineSpacing(1f, 1f.plus(it.times(0.01f))) ;
|
|
||||||
if (readerConfig?.lineSpace != it) {
|
|
||||||
readerConfig?.lineSpace = it
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
binding.pageTypesface.displayFormat = "폰트 : %s"
|
|
||||||
binding.pageTypesface.titleArray = typesfacez.map { it.first }.toTypedArray()
|
|
||||||
binding.pageTypesface.value = getIndex(typesfacez as PairArray<Any>,readerConfig?.font ?: "")
|
|
||||||
binding.pageTypesface.mValueChange = {
|
|
||||||
val pair = typesfacez.get(it)
|
|
||||||
binding.preview.setTypeface(resources.getFont(pair.second))
|
|
||||||
if (readerConfig?.font != pair.first) {
|
|
||||||
readerConfig?.font = pair.first ?: ""
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
binding.pageStyle.displayFormat = "스타일 : %s"
|
|
||||||
binding.pageStyle.titleArray = colorz.map { it.first }.toTypedArray()
|
|
||||||
binding.pageStyle.value = readerConfig?.style ?: 0
|
|
||||||
binding.pageStyle.mValueChange = {
|
|
||||||
val pair = colorz.get(it)
|
|
||||||
binding.preview.setBackgroundColor(Color.parseColor(pair.second.last()))
|
|
||||||
binding.preview.setTextColor(Color.parseColor(pair.second.first()))
|
|
||||||
if (readerConfig?.style != it) {
|
|
||||||
readerConfig?.style = it ?: 0
|
|
||||||
configSave()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun configSave() {
|
|
||||||
var realm = HistoryManager.openRealm
|
|
||||||
realm.writeBlocking {
|
|
||||||
copyToRealm(readerConfig!!, UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,54 +0,0 @@
|
|||||||
package com.mime.dualscreenview.common
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import com.mime.dualscreenview.BuildConfig
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
|
|
||||||
object Blog {
|
|
||||||
val DEFAULT_TAG = "MyEBook_TAG"
|
|
||||||
enum class BLogType {
|
|
||||||
D,I,E
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGD(tag : String = DEFAULT_TAG, log: String){
|
|
||||||
LOG(BLogType.D,tag,log)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGI(tag : String = DEFAULT_TAG, log: String){
|
|
||||||
LOG(BLogType.I,tag,log)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGE(tag : String = DEFAULT_TAG, log: Throwable){
|
|
||||||
LOG(BLogType.E,tag,log.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGE(tag : String = DEFAULT_TAG, log: Exception){
|
|
||||||
LOG(BLogType.E,tag,log.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGE(tag : String = DEFAULT_TAG, log: String){
|
|
||||||
LOG(BLogType.E,tag,log)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun LOGE(log: String){
|
|
||||||
LOG(BLogType.E,DEFAULT_TAG,log)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun LOG(type : BLogType, tag : String, log : String) {
|
|
||||||
if (BuildConfig.DEBUG || BuildConfig.BUILD_TYPE.contains("debug")) {
|
|
||||||
when(type) {
|
|
||||||
BLogType.D -> {
|
|
||||||
Log.d(tag,log)
|
|
||||||
}
|
|
||||||
BLogType.I -> {
|
|
||||||
Log.i(tag,log)
|
|
||||||
}
|
|
||||||
BLogType.E -> {
|
|
||||||
Log.e(tag,log)
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,84 +0,0 @@
|
|||||||
package com.mime.dualscreenview.common
|
|
||||||
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
|
|
||||||
typealias PairArray<T> = Array<Pair<String,T>>
|
|
||||||
val colorz : PairArray<Array<String>> = arrayOf<Pair<String,Array<String>>>(
|
|
||||||
Pair("color set 01",arrayOf<String>("#E1F5FE", "#263238")),
|
|
||||||
Pair("color set 02",arrayOf<String>("#F0F4C3", "#37474F")),
|
|
||||||
Pair("color set 03",arrayOf<String>("#ECEFF1", "#455A64")),
|
|
||||||
Pair("color set 04",arrayOf<String>("#E0F7FA", "#263238")),
|
|
||||||
Pair("color set 05",arrayOf<String>("#F5F5F5", "#263238")),
|
|
||||||
Pair("color set 06",arrayOf<String>("#ECEFF1", "#263238")),
|
|
||||||
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 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),
|
|
||||||
Pair("정선 아리랑 뿌리", R.font.jsarirang_ppuri),
|
|
||||||
Pair("정선 동강 레귤러", R.font.jsdongkang_regular),
|
|
||||||
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")
|
|
||||||
fun PairArray<Any>.getIndex(key : String) = getIndex(this, key)
|
|
||||||
fun getIndex(collection : PairArray<Any>, key : String) : Int {
|
|
||||||
var index = 0
|
|
||||||
var returns = 0
|
|
||||||
for (item in collection) {
|
|
||||||
if(item.first.equals(key)) {
|
|
||||||
returns = index
|
|
||||||
}
|
|
||||||
index = index.inc()
|
|
||||||
}
|
|
||||||
return returns
|
|
||||||
}
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
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_"
|
|
||||||
private val domainKey = "Last_Domain_"
|
|
||||||
private lateinit var main : SharedPreferences
|
|
||||||
fun init(context: Context) {
|
|
||||||
main = context.getSharedPreferences(mainName,Context.MODE_PRIVATE)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save(key : String, value : String?) {
|
|
||||||
main.edit().putString(key,value).apply()
|
|
||||||
}
|
|
||||||
fun load(key : String) : String? {
|
|
||||||
return main.getString(key, "")
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getLastDomain() : String {
|
|
||||||
return main.getString(domainKey, NewtokiOne.getLastedDoamin()) ?: NewtokiOne.getLastedDoamin()
|
|
||||||
}
|
|
||||||
fun putLastDomain(domain : String) {
|
|
||||||
Blog.LOGE("domain >>> ${domain}")
|
|
||||||
main.edit().putString(domainKey,domain).apply()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,168 +0,0 @@
|
|||||||
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.LastInfo
|
|
||||||
import com.mime.dualscreenview.data.model.ReaderConfig
|
|
||||||
import io.realm.kotlin.Realm
|
|
||||||
import io.realm.kotlin.RealmConfiguration
|
|
||||||
import io.realm.kotlin.UpdatePolicy
|
|
||||||
import io.realm.kotlin.types.BaseRealmObject
|
|
||||||
import io.realm.kotlin.types.TypedRealmObject
|
|
||||||
import kotlin.reflect.KClass
|
|
||||||
|
|
||||||
object HistoryManager {
|
|
||||||
val clazz : Set<KClass<out BaseRealmObject>> = setOf(LastInfo::class, HistoryItem::class, ReaderConfig::class, BookPageInfos::class, BookPageInfo::class)
|
|
||||||
val schemaVersion : Long = 5
|
|
||||||
|
|
||||||
|
|
||||||
val openRealm : Realm = Realm.open(RealmConfiguration.Builder(clazz as Set<KClass<out TypedRealmObject>>)
|
|
||||||
.schemaVersion(schemaVersion)
|
|
||||||
.deleteRealmIfMigrationNeeded()
|
|
||||||
.build())
|
|
||||||
|
|
||||||
fun save(lastInfo: LastInfo) {
|
|
||||||
openRealm.apply{
|
|
||||||
this.writeBlocking {
|
|
||||||
copyToRealm(lastInfo, UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save(historyItem: HistoryItem) {
|
|
||||||
openRealm.apply{
|
|
||||||
this.writeBlocking {
|
|
||||||
copyToRealm(historyItem, UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun requestLastInfo(callback : (LastInfo)->Unit) {
|
|
||||||
openRealm.apply{
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun save(config : ReaderConfig) {
|
|
||||||
openRealm.apply{
|
|
||||||
this.writeBlocking {
|
|
||||||
copyToRealm(config,UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBookInfos(aUrl : String, callback : (BookPageInfos?)->Unit) {
|
|
||||||
var url : String = aUrl
|
|
||||||
openRealm.apply{
|
|
||||||
if (url.startsWith("//")) {
|
|
||||||
while (url.startsWith("//")) {
|
|
||||||
url = url.replace("//","/").trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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}" )
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBookPageInfo(aUrl : String, callback : (BookPageInfo?)->Unit) {
|
|
||||||
var url : String = aUrl
|
|
||||||
openRealm.apply{
|
|
||||||
if (url.startsWith("//")) {
|
|
||||||
while (url.startsWith("//")) {
|
|
||||||
url = url.replace("//","/").trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var result = this.query(BookPageInfo::class).query("pathUrl == $0","${url}").find()
|
|
||||||
if (result.size > 0) {
|
|
||||||
var bookPageInfo = result?.first()
|
|
||||||
if (bookPageInfo != null) {
|
|
||||||
callback.invoke(bookPageInfo)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getBooPageInfoContentsSave(aUrl : String, contents : String) {
|
|
||||||
var url : String = aUrl
|
|
||||||
openRealm.writeBlocking {
|
|
||||||
Blog.LOGE("getBooPageInfoContentsSave ${url}")
|
|
||||||
val result = query(BookPageInfo::class).query("pathUrl == $0", "${url}").find()
|
|
||||||
if (result.size > 0) {
|
|
||||||
result.first().contents = contents
|
|
||||||
copyToRealm(result.first(), UpdatePolicy.ALL)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun getNextPage(aUrl : String ,callback : (BookPageInfo?)->Unit) {
|
|
||||||
var url : String = aUrl
|
|
||||||
openRealm.apply{
|
|
||||||
if (url.startsWith("//")) {
|
|
||||||
while (url.startsWith("//")) {
|
|
||||||
url = url.replace("//","/").trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var bookPageInfo =
|
|
||||||
this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
|
|
||||||
if (bookPageInfo.size > 0) {
|
|
||||||
Blog.LOGE("getNextPage 2 => chapterNum : ${bookPageInfo.first().chapterNum} , bookPageInfo.bookPageUrl : ${bookPageInfo.first().bookPageUrl}" )
|
|
||||||
var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum + 1).query("bookPageUrl == $0","${bookPageInfo.first().bookPageUrl}").find()
|
|
||||||
if(results.size > 0) {
|
|
||||||
results.first().let {
|
|
||||||
Blog.LOGE("getNextPage 2 nextBook pathUrl : ${it.pathUrl}" )
|
|
||||||
callback.invoke(it)
|
|
||||||
}
|
|
||||||
} else {callback.invoke(null)}
|
|
||||||
} else {callback.invoke(null)}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getPrevPage(aUrl : String ,callback : (BookPageInfo?)->Unit) {
|
|
||||||
var url : String = aUrl
|
|
||||||
openRealm.apply{
|
|
||||||
Blog.LOGE("getPrevPage ${url}" )
|
|
||||||
if (url.startsWith("//")) {
|
|
||||||
while (url.startsWith("//")) {
|
|
||||||
url = url.replace("//","/").trim()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
Blog.LOGE("getPrevPage ${url}" )
|
|
||||||
var bookPageInfo =
|
|
||||||
this.query(BookPageInfo::class).query("pathUrl == $0", url).find()
|
|
||||||
Blog.LOGE("getPrevPage ${bookPageInfo}" )
|
|
||||||
if (bookPageInfo.size > 0) {
|
|
||||||
Blog.LOGE("getPrevPage 2 ${bookPageInfo?.first()?.chapterNum}" )
|
|
||||||
Blog.LOGE("getPrevPage 2 ${bookPageInfo?.first()?.bookPageUrl}" )
|
|
||||||
var results = this.query(BookPageInfo::class).query("chapterNum == $0",bookPageInfo.first().chapterNum - 1).query("bookPageUrl == $0","${bookPageInfo.first().bookPageUrl}").find()
|
|
||||||
if(results.size > 0) {
|
|
||||||
results.first()?.let {
|
|
||||||
callback.invoke(it)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback.invoke(null)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
callback.invoke(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,121 +0,0 @@
|
|||||||
package com.mime.dualscreenview.data.model
|
|
||||||
|
|
||||||
import io.realm.kotlin.ext.realmListOf
|
|
||||||
import io.realm.kotlin.types.RealmList
|
|
||||||
import io.realm.kotlin.types.RealmObject
|
|
||||||
import io.realm.kotlin.types.annotations.Ignore
|
|
||||||
import io.realm.kotlin.types.annotations.PrimaryKey
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class BookPageInfosJ {
|
|
||||||
var bookTitle : String = ""
|
|
||||||
var bookPageUrl : String = ""
|
|
||||||
|
|
||||||
var pages : ArrayList<BookPageInfoJ> = arrayListOf<BookPageInfoJ>()
|
|
||||||
|
|
||||||
fun getTitleArray() : ArrayList<String> {
|
|
||||||
var arrayList = ArrayList<String>()
|
|
||||||
pages.forEach { arrayList.add(it.bookTitle ?: "") }
|
|
||||||
return arrayList
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getR() : BookPageInfos{
|
|
||||||
var r = BookPageInfos()
|
|
||||||
r.bookTitle = this.bookTitle
|
|
||||||
r.bookPageUrl = this.bookPageUrl
|
|
||||||
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class BookPageInfoJ {
|
|
||||||
var chapterID : Int = 0
|
|
||||||
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 {
|
|
||||||
arrayList.add(it.getTitleItem())}
|
|
||||||
return arrayList
|
|
||||||
}
|
|
||||||
|
|
||||||
fun sort() {
|
|
||||||
val comparator : Comparator<BookPageInfo> = compareBy { it.chapterID }
|
|
||||||
pages.sortWith(comparator)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun hasItem(item: BookPageInfo) : Boolean {
|
|
||||||
var hasItem = false
|
|
||||||
for (c in pages) {
|
|
||||||
if (!hasItem) {
|
|
||||||
hasItem = c.pathUrl.equals(item.pathUrl)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return hasItem
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
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? = ""
|
|
||||||
|
|
||||||
fun getTitleItem() : String {
|
|
||||||
var result = StringBuilder()
|
|
||||||
result.append(if ((contents?.length ?: 0) > 10) {
|
|
||||||
"S:[0] "
|
|
||||||
} else {
|
|
||||||
"[X] "
|
|
||||||
})
|
|
||||||
|
|
||||||
result.append(chapterTitle?: "")
|
|
||||||
|
|
||||||
result.append(if ((lastPage ?: 0) > 0) {
|
|
||||||
" [0] "
|
|
||||||
} else {
|
|
||||||
" [X] "
|
|
||||||
})
|
|
||||||
|
|
||||||
return result.toString()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,61 +0,0 @@
|
|||||||
package com.mime.dualscreenview.data.model
|
|
||||||
|
|
||||||
import android.content.pm.ActivityInfo
|
|
||||||
import io.realm.kotlin.types.RealmObject
|
|
||||||
import io.realm.kotlin.types.annotations.PrimaryKey
|
|
||||||
import java.text.SimpleDateFormat
|
|
||||||
import java.util.Date
|
|
||||||
|
|
||||||
|
|
||||||
class LastInfo : RealmObject {
|
|
||||||
@PrimaryKey
|
|
||||||
var _id : String = "UniqLastId"
|
|
||||||
var pageUrl : String = ""
|
|
||||||
var title : String = ""
|
|
||||||
var chapter : Int = 0
|
|
||||||
var pageIndex : Int = 0
|
|
||||||
var contentsName : String = ""
|
|
||||||
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
|
|
||||||
fun makeHistoryItem() : HistoryItem = HistoryItem().apply {
|
|
||||||
title = this@LastInfo.title
|
|
||||||
pageUrl = this@LastInfo.pageUrl
|
|
||||||
chapter = this@LastInfo.chapter
|
|
||||||
pageIndex = this@LastInfo.pageIndex
|
|
||||||
contentsName = this@LastInfo.contentsName
|
|
||||||
displayOrientation = this@LastInfo.displayOrientation
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class HistoryItem : RealmObject {
|
|
||||||
@PrimaryKey
|
|
||||||
var title : String = ""
|
|
||||||
var pageUrl : String = ""
|
|
||||||
var chapter : Int = 0
|
|
||||||
var pageIndex : Int = 0
|
|
||||||
var contentsName : String = ""
|
|
||||||
var displayOrientation : Int = ActivityInfo.SCREEN_ORIENTATION_PORTRAIT
|
|
||||||
|
|
||||||
fun makeLastInfo() = LastInfo().apply{
|
|
||||||
_id = "UniqLastId"
|
|
||||||
title = this@HistoryItem.title
|
|
||||||
pageUrl = this@HistoryItem.pageUrl
|
|
||||||
chapter = this@HistoryItem.chapter
|
|
||||||
pageIndex = this@HistoryItem.pageIndex
|
|
||||||
contentsName = this@HistoryItem.contentsName
|
|
||||||
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 {
|
|
||||||
@PrimaryKey
|
|
||||||
var pageUrl : String = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
@ -1,17 +0,0 @@
|
|||||||
package com.mime.dualscreenview.data.model
|
|
||||||
|
|
||||||
import io.realm.kotlin.types.RealmObject
|
|
||||||
import io.realm.kotlin.types.annotations.PrimaryKey
|
|
||||||
|
|
||||||
class ReaderConfig : RealmObject {
|
|
||||||
@PrimaryKey
|
|
||||||
var id : String? = "ReaderConfig"
|
|
||||||
var textSize : Int? = 14
|
|
||||||
var textColor : String? = "#FFFFFF"
|
|
||||||
var bgColor : String? = "#000000"
|
|
||||||
var style : Int? = 0
|
|
||||||
var lineSpace : Int? = 1
|
|
||||||
var letterSpace : Int? = 1
|
|
||||||
var font : String? = ""
|
|
||||||
var padding : Int? = 5
|
|
||||||
}
|
|
||||||
@ -1,55 +0,0 @@
|
|||||||
package com.mime.dualscreenview.dialog
|
|
||||||
|
|
||||||
import android.R
|
|
||||||
import android.content.Context
|
|
||||||
import android.content.DialogInterface
|
|
||||||
import android.widget.ArrayAdapter
|
|
||||||
import androidx.appcompat.app.AlertDialog
|
|
||||||
import com.mime.dualscreenview.data.model.BookPageInfo
|
|
||||||
|
|
||||||
object DefaultList {
|
|
||||||
fun showDefaultList(context: Context, title : String, items : Collection<BookPageInfo>, firstPosition : Int, choosedTitle : (Int)->String, chooedPositive : (Int)->Unit, saveCalback : (Int)->Unit ) {
|
|
||||||
val builderSingle: AlertDialog.Builder = AlertDialog.Builder(context)
|
|
||||||
builderSingle.setTitle(title)
|
|
||||||
val arrayAdapter =
|
|
||||||
ArrayAdapter<String>(context, R.layout.select_dialog_singlechoice)
|
|
||||||
for (item in items) {
|
|
||||||
arrayAdapter.add(item.getTitleItem())
|
|
||||||
}
|
|
||||||
builderSingle.setNeutralButton("전체 저장") { dialog, which ->
|
|
||||||
saveCalback.invoke(-1)
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
builderSingle.setNegativeButton("닫기",
|
|
||||||
DialogInterface.OnClickListener { dialog, which ->
|
|
||||||
dialog.dismiss() })
|
|
||||||
builderSingle.setAdapter(arrayAdapter,
|
|
||||||
DialogInterface.OnClickListener { dialog, position ->
|
|
||||||
val strName = arrayAdapter.getItem(position)
|
|
||||||
val builderInner: AlertDialog.Builder = AlertDialog.Builder(context)
|
|
||||||
builderInner.setMessage(strName)
|
|
||||||
builderInner.setTitle(choosedTitle.invoke(position))
|
|
||||||
builderInner.setNegativeButton("닫기") { dialog, which ->
|
|
||||||
|
|
||||||
}
|
|
||||||
// builderInner.setNeutralButton("자동 저장") { dialog, which ->
|
|
||||||
// saveCalback.invoke(position)
|
|
||||||
// }
|
|
||||||
builderInner.setPositiveButton("이동"){ dialog, which ->
|
|
||||||
chooedPositive.invoke(position)
|
|
||||||
dialog.dismiss()
|
|
||||||
}
|
|
||||||
builderInner.show().apply {
|
|
||||||
DialogManager.add(this)
|
|
||||||
}
|
|
||||||
})
|
|
||||||
builderSingle.create()?.apply{
|
|
||||||
setOnShowListener { d->
|
|
||||||
(d as? AlertDialog)?.let{
|
|
||||||
it.listView?.setSelection(firstPosition)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
DialogManager.add(this)
|
|
||||||
}?.show()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,19 +0,0 @@
|
|||||||
package com.mime.dualscreenview.dialog
|
|
||||||
|
|
||||||
import android.app.Dialog
|
|
||||||
import androidx.activity.ComponentDialog
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
object DialogManager {
|
|
||||||
val dialogs = arrayListOf<ComponentDialog>()
|
|
||||||
fun add(item : ComponentDialog) = dialogs.add(item)
|
|
||||||
fun closeAll() {
|
|
||||||
for (dialog in dialogs) {
|
|
||||||
try {
|
|
||||||
dialog?.dismiss()
|
|
||||||
} catch(e : Exception) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,97 +0,0 @@
|
|||||||
//package com.mime.dualscreenview.dialog
|
|
||||||
//
|
|
||||||
//import android.app.Dialog
|
|
||||||
//import android.content.Context
|
|
||||||
//import android.content.DialogInterface
|
|
||||||
//import android.graphics.Color
|
|
||||||
//import android.os.Bundle
|
|
||||||
//import android.view.LayoutInflater
|
|
||||||
//import android.view.View
|
|
||||||
//import android.view.ViewGroup
|
|
||||||
//import android.view.Window
|
|
||||||
//import android.widget.TextView
|
|
||||||
//import androidx.recyclerview.widget.GridLayoutManager
|
|
||||||
//import androidx.recyclerview.widget.RecyclerView
|
|
||||||
//import com.mime.dualscreenview.R
|
|
||||||
//import kotlin.random.Random
|
|
||||||
//
|
|
||||||
//interface StyleSelectInterface {
|
|
||||||
// fun onSelectStyle(bgColor : String, textColor : String)
|
|
||||||
//}
|
|
||||||
//class Stylez : Dialog {
|
|
||||||
// constructor(context: Context) : super(context) {initView(context)}
|
|
||||||
// constructor(context: Context, themeResId: Int) : super(context, themeResId) {initView(context)}
|
|
||||||
// constructor(
|
|
||||||
// context: Context,
|
|
||||||
// cancelable: Boolean,
|
|
||||||
// cancelListener: DialogInterface.OnCancelListener?
|
|
||||||
// ) : super(context, cancelable, cancelListener) {initView(context)}
|
|
||||||
//
|
|
||||||
// var styleSelectInterface : StyleSelectInterface? = null
|
|
||||||
//
|
|
||||||
// fun initView(context: Context) {
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onCreate(savedInstanceState: Bundle?) {
|
|
||||||
// super.onCreate(savedInstanceState)
|
|
||||||
// this.requestWindowFeature(Window.FEATURE_NO_TITLE);
|
|
||||||
// setCancelable(true)
|
|
||||||
// setContentView(R.layout.dialog_stylesz)
|
|
||||||
// val recyclerView: RecyclerView = findViewById(R.id.stylez_recyclerview)
|
|
||||||
// val adapterRe = AdapterRe(context, colorz)
|
|
||||||
// recyclerView.adapter = adapterRe
|
|
||||||
// recyclerView.layoutManager =
|
|
||||||
// GridLayoutManager(context, 2, GridLayoutManager.VERTICAL, false)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inner class AdapterRe(ctx: Context, myImageNameList: Array<Array<String>>) :
|
|
||||||
// RecyclerView.Adapter<StylezViewHolder>() {
|
|
||||||
// private val inflater: LayoutInflater
|
|
||||||
// private val myImageNameList: Array<Array<String>>
|
|
||||||
// private val ctx : Context
|
|
||||||
// init {
|
|
||||||
// inflater = LayoutInflater.from(ctx)
|
|
||||||
// this.ctx = ctx
|
|
||||||
// this.myImageNameList = myImageNameList
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onCreateViewHolder (
|
|
||||||
// parent: ViewGroup,
|
|
||||||
// viewType: Int
|
|
||||||
// ): StylezViewHolder {
|
|
||||||
// val view: View = inflater.inflate(R.layout.item_colorz, parent, false)
|
|
||||||
// return StylezViewHolder(view)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onBindViewHolder(holder: StylezViewHolder, position: Int) {
|
|
||||||
// var colorz = myImageNameList.get(position)
|
|
||||||
// var sampleTextz = ctx.resources.getStringArray(R.array.sample_textz)
|
|
||||||
// holder?.setStyle(bgColor = colorz.get(1), textColor = colorz.get(0),sampleTextz.get(Random.nextInt(9876) % sampleTextz.size))
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// override fun getItemCount(): Int {
|
|
||||||
// return myImageNameList.size
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// inner class StylezViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
|
|
||||||
// var textView: TextView
|
|
||||||
// var bg : View
|
|
||||||
// init {
|
|
||||||
// textView = itemView.findViewById(R.id.textview_sample)
|
|
||||||
// bg = itemView.findViewById(R.id.bg_sample)
|
|
||||||
// }
|
|
||||||
// fun setStyle(bgColor : String, textColor : String, sampleText : String ) {
|
|
||||||
// bg.setBackgroundColor(Color.parseColor(bgColor))
|
|
||||||
// textView.setTextColor(Color.parseColor(textColor))
|
|
||||||
// textView.text = sampleText
|
|
||||||
// itemView?.setOnClickListener { v ->
|
|
||||||
// styleSelectInterface?.onSelectStyle(bgColor,textColor)
|
|
||||||
// dismiss()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,815 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.os.SystemClock
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.GestureDetector
|
|
||||||
import android.view.MotionEvent
|
|
||||||
import android.view.View
|
|
||||||
import android.view.View.OnTouchListener
|
|
||||||
import com.mime.dualscreenview.common.Blog
|
|
||||||
import com.mime.dualscreenview.view.GestureAnalyser.GestureType
|
|
||||||
import kotlin.math.abs
|
|
||||||
import kotlin.math.pow
|
|
||||||
import kotlin.math.sqrt
|
|
||||||
|
|
||||||
|
|
||||||
enum class TouchArea {
|
|
||||||
Left,Center,Right, DoubleLeft, DoubleRight
|
|
||||||
}
|
|
||||||
|
|
||||||
class GestureAnalyser @JvmOverloads constructor(
|
|
||||||
swipeSlopeIntolerance: Int = 3,
|
|
||||||
doubleTapMaxDelayMillis: Int = 500,
|
|
||||||
doubleTapMaxDownMillis: Int = 100
|
|
||||||
) {
|
|
||||||
private val initialX = DoubleArray(5)
|
|
||||||
private val initialY = DoubleArray(5)
|
|
||||||
private val finalX = DoubleArray(5)
|
|
||||||
private val finalY = DoubleArray(5)
|
|
||||||
private val currentX = DoubleArray(5)
|
|
||||||
private val currentY = DoubleArray(5)
|
|
||||||
private val delX = DoubleArray(5)
|
|
||||||
private val delY = DoubleArray(5)
|
|
||||||
|
|
||||||
private var numFingers = 0
|
|
||||||
private var initialT: Long = 0
|
|
||||||
private var finalT: Long = 0
|
|
||||||
private var currentT: Long = 0
|
|
||||||
|
|
||||||
private var prevInitialT: Long = 0
|
|
||||||
private var prevFinalT: Long = 0
|
|
||||||
|
|
||||||
private var swipeSlopeIntolerance = 3
|
|
||||||
|
|
||||||
private val doubleTapMaxDelayMillis: Long
|
|
||||||
private val doubleTapMaxDownMillis: Long
|
|
||||||
|
|
||||||
init {
|
|
||||||
this.swipeSlopeIntolerance = swipeSlopeIntolerance
|
|
||||||
this.doubleTapMaxDownMillis = doubleTapMaxDownMillis.toLong()
|
|
||||||
this.doubleTapMaxDelayMillis = doubleTapMaxDelayMillis.toLong()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun trackGesture(ev: MotionEvent) {
|
|
||||||
val n = ev.pointerCount
|
|
||||||
for (i in 0 until n) {
|
|
||||||
initialX[i] = ev.getX(i).toDouble()
|
|
||||||
initialY[i] = ev.getY(i).toDouble()
|
|
||||||
}
|
|
||||||
numFingers = n
|
|
||||||
initialT = SystemClock.uptimeMillis()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun untrackGesture() {
|
|
||||||
numFingers = 0
|
|
||||||
prevFinalT = SystemClock.uptimeMillis()
|
|
||||||
prevInitialT = initialT
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getGesture(ev: MotionEvent): GestureType {
|
|
||||||
var averageDistance = 0.0
|
|
||||||
for (i in 0 until numFingers) {
|
|
||||||
finalX[i] = ev.getX(i).toDouble()
|
|
||||||
finalY[i] = ev.getY(i).toDouble()
|
|
||||||
delX[i] = finalX[i] - initialX[i]
|
|
||||||
delY[i] = finalY[i] - initialY[i]
|
|
||||||
|
|
||||||
averageDistance += sqrt(
|
|
||||||
(finalX[i] - initialX[i]).pow(2.0) + (finalY[i] - initialY[i]).pow(
|
|
||||||
2.0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
averageDistance /= numFingers.toDouble()
|
|
||||||
|
|
||||||
finalT = SystemClock.uptimeMillis()
|
|
||||||
val gt = GestureType()
|
|
||||||
gt.gestureFlag = calcGesture()
|
|
||||||
gt.gestureDuration = finalT - initialT
|
|
||||||
gt.gestureDistance = averageDistance
|
|
||||||
return gt
|
|
||||||
}
|
|
||||||
|
|
||||||
fun getOngoingGesture(ev: MotionEvent): Int {
|
|
||||||
for (i in 0 until numFingers) {
|
|
||||||
currentX[i] = ev.getX(i).toDouble()
|
|
||||||
currentY[i] = ev.getY(i).toDouble()
|
|
||||||
delX[i] = finalX[i] - initialX[i]
|
|
||||||
delY[i] = finalY[i] - initialY[i]
|
|
||||||
}
|
|
||||||
currentT = SystemClock.uptimeMillis()
|
|
||||||
return calcGesture()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun calcGesture(): Int {
|
|
||||||
if (isDoubleTap) {
|
|
||||||
return DOUBLE_TAP_1
|
|
||||||
}
|
|
||||||
|
|
||||||
if (numFingers == 1) {
|
|
||||||
if ((-(delY[0])) > (swipeSlopeIntolerance * (abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_1_UP
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((delY[0])) > (swipeSlopeIntolerance * (abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_1_DOWN
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((-(delX[0])) > (swipeSlopeIntolerance * (abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_1_LEFT
|
|
||||||
}
|
|
||||||
|
|
||||||
if (((delX[0])) > (swipeSlopeIntolerance * (abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_1_RIGHT
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numFingers == 2) {
|
|
||||||
if (((-delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
))) && ((-delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_2_UP
|
|
||||||
}
|
|
||||||
if (((delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
))) && ((delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_2_DOWN
|
|
||||||
}
|
|
||||||
if (((-delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
))) && ((-delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_2_LEFT
|
|
||||||
}
|
|
||||||
if (((delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
))) && ((delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_2_RIGHT
|
|
||||||
}
|
|
||||||
if (finalFingDist(0, 1) > 2 * (initialFingDist(0, 1))) {
|
|
||||||
return UNPINCH_2
|
|
||||||
}
|
|
||||||
if (finalFingDist(0, 1) < 0.5 * (initialFingDist(0, 1))) {
|
|
||||||
return PINCH_2
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numFingers == 3) {
|
|
||||||
if (((-delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
&& ((-delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
&& ((-delY[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[2]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_3_UP
|
|
||||||
}
|
|
||||||
if (((delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
&& ((delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
&& ((delY[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[2]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_3_DOWN
|
|
||||||
}
|
|
||||||
if (((-delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
&& ((-delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
&& ((-delX[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[2]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_3_LEFT
|
|
||||||
}
|
|
||||||
if (((delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
&& ((delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
&& ((delX[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[2]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_3_RIGHT
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((finalFingDist(0, 1) > 1.75 * (initialFingDist(0, 1)))
|
|
||||||
&& (finalFingDist(1, 2) > 1.75 * (initialFingDist(1, 2)))
|
|
||||||
&& (finalFingDist(2, 0) > 1.75 * (initialFingDist(2, 0)))
|
|
||||||
) {
|
|
||||||
return UNPINCH_3
|
|
||||||
}
|
|
||||||
if ((finalFingDist(0, 1) < 0.66 * (initialFingDist(0, 1)))
|
|
||||||
&& (finalFingDist(1, 2) < 0.66 * (initialFingDist(1, 2)))
|
|
||||||
&& (finalFingDist(2, 0) < 0.66 * (initialFingDist(2, 0)))
|
|
||||||
) {
|
|
||||||
return PINCH_3
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (numFingers == 4) {
|
|
||||||
if (((-delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
&& ((-delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
&& ((-delY[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[2]
|
|
||||||
)))
|
|
||||||
&& ((-delY[3]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[3]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_4_UP
|
|
||||||
}
|
|
||||||
if (((delY[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[0]
|
|
||||||
)))
|
|
||||||
&& ((delY[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[1]
|
|
||||||
)))
|
|
||||||
&& ((delY[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[2]
|
|
||||||
)))
|
|
||||||
&& ((delY[3]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delX[3]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_4_DOWN
|
|
||||||
}
|
|
||||||
if (((-delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
&& ((-delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
&& ((-delX[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[2]
|
|
||||||
)))
|
|
||||||
&& ((-delX[3]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[3]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_4_LEFT
|
|
||||||
}
|
|
||||||
if (((delX[0]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[0]
|
|
||||||
)))
|
|
||||||
&& ((delX[1]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[1]
|
|
||||||
)))
|
|
||||||
&& ((delX[2]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[2]
|
|
||||||
)))
|
|
||||||
&& ((delX[3]) > (swipeSlopeIntolerance * abs(
|
|
||||||
delY[3]
|
|
||||||
)))
|
|
||||||
) {
|
|
||||||
return SWIPE_4_RIGHT
|
|
||||||
}
|
|
||||||
if ((finalFingDist(0, 1) > 1.5 * (initialFingDist(0, 1)))
|
|
||||||
&& (finalFingDist(1, 2) > 1.5 * (initialFingDist(1, 2)))
|
|
||||||
&& (finalFingDist(2, 3) > 1.5 * (initialFingDist(2, 3)))
|
|
||||||
&& (finalFingDist(3, 0) > 1.5 * (initialFingDist(3, 0)))
|
|
||||||
) {
|
|
||||||
return UNPINCH_4
|
|
||||||
}
|
|
||||||
if ((finalFingDist(0, 1) < 0.8 * (initialFingDist(0, 1)))
|
|
||||||
&& (finalFingDist(1, 2) < 0.8 * (initialFingDist(1, 2)))
|
|
||||||
&& (finalFingDist(2, 3) < 0.8 * (initialFingDist(2, 3)))
|
|
||||||
&& (finalFingDist(3, 0) < 0.8 * (initialFingDist(3, 0)))
|
|
||||||
) {
|
|
||||||
return PINCH_4
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun initialFingDist(fingNum1: Int, fingNum2: Int): Double {
|
|
||||||
return sqrt(
|
|
||||||
(initialX[fingNum1] - initialX[fingNum2]).pow(2.0) + (initialY[fingNum1] - initialY[fingNum2]).pow(
|
|
||||||
2.0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun finalFingDist(fingNum1: Int, fingNum2: Int): Double {
|
|
||||||
return sqrt(
|
|
||||||
(finalX[fingNum1] - finalX[fingNum2]).pow(2.0) + (finalY[fingNum1] - finalY[fingNum2]).pow(
|
|
||||||
2.0
|
|
||||||
)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
val isDoubleTap: Boolean
|
|
||||||
get() = if (initialT - prevFinalT < doubleTapMaxDelayMillis && finalT - initialT < doubleTapMaxDownMillis && prevFinalT - prevInitialT < doubleTapMaxDownMillis) {
|
|
||||||
true
|
|
||||||
} else {
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
inner class GestureType {
|
|
||||||
var gestureFlag: Int = 0
|
|
||||||
var gestureDuration: Long = 0
|
|
||||||
|
|
||||||
var gestureDistance: Double = 0.0
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val DEBUG: Boolean = true
|
|
||||||
|
|
||||||
// Finished gestures flags
|
|
||||||
const val SWIPE_1_UP: Int = 11
|
|
||||||
const val SWIPE_1_DOWN: Int = 12
|
|
||||||
const val SWIPE_1_LEFT: Int = 13
|
|
||||||
const val SWIPE_1_RIGHT: Int = 14
|
|
||||||
const val SWIPE_2_UP: Int = 21
|
|
||||||
const val SWIPE_2_DOWN: Int = 22
|
|
||||||
const val SWIPE_2_LEFT: Int = 23
|
|
||||||
const val SWIPE_2_RIGHT: Int = 24
|
|
||||||
const val SWIPE_3_UP: Int = 31
|
|
||||||
const val SWIPE_3_DOWN: Int = 32
|
|
||||||
const val SWIPE_3_LEFT: Int = 33
|
|
||||||
const val SWIPE_3_RIGHT: Int = 34
|
|
||||||
const val SWIPE_4_UP: Int = 41
|
|
||||||
const val SWIPE_4_DOWN: Int = 42
|
|
||||||
const val SWIPE_4_LEFT: Int = 43
|
|
||||||
const val SWIPE_4_RIGHT: Int = 44
|
|
||||||
const val PINCH_2: Int = 25
|
|
||||||
const val UNPINCH_2: Int = 26
|
|
||||||
const val PINCH_3: Int = 35
|
|
||||||
const val UNPINCH_3: Int = 36
|
|
||||||
const val PINCH_4: Int = 45
|
|
||||||
const val UNPINCH_4: Int = 46
|
|
||||||
|
|
||||||
const val DOUBLE_TAP_1: Int = 107
|
|
||||||
|
|
||||||
//Ongoing gesture flags
|
|
||||||
const val SWIPING_1_UP: Int = 101
|
|
||||||
const val SWIPING_1_DOWN: Int = 102
|
|
||||||
const val SWIPING_1_LEFT: Int = 103
|
|
||||||
const val SWIPING_1_RIGHT: Int = 104
|
|
||||||
const val SWIPING_2_UP: Int = 201
|
|
||||||
const val SWIPING_2_DOWN: Int = 202
|
|
||||||
const val SWIPING_2_LEFT: Int = 203
|
|
||||||
const val SWIPING_2_RIGHT: Int = 204
|
|
||||||
const val PINCHING: Int = 205
|
|
||||||
const val UNPINCHING: Int = 206
|
|
||||||
private const val TAG = "GestureAnalyser"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class SimpleFingerGestures : OnTouchListener {
|
|
||||||
private var debug = true
|
|
||||||
var consumeTouchEvents: Boolean = false
|
|
||||||
|
|
||||||
protected var tracking: BooleanArray = booleanArrayOf(false, false, false, false, false)
|
|
||||||
private var ga: GestureAnalyser
|
|
||||||
private var onFingerGestureListener: OnFingerGestureListener? = null
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Constructor that creates an internal [in.championswimmer.sfg.lib.GestureAnalyser] object as well
|
|
||||||
*/
|
|
||||||
constructor() {
|
|
||||||
ga = GestureAnalyser()
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
swipeSlopeIntolerance: Int,
|
|
||||||
doubleTapMaxDelayMillis: Int,
|
|
||||||
doubleTapMaxDownMillis: Int
|
|
||||||
) {
|
|
||||||
ga = GestureAnalyser(swipeSlopeIntolerance, doubleTapMaxDelayMillis, doubleTapMaxDownMillis)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setDebug(debug: Boolean) {
|
|
||||||
this.debug = debug
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor(omfgl: OnFingerGestureListener?) {
|
|
||||||
ga = GestureAnalyser()
|
|
||||||
setOnFingerGestureListener(omfgl)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Register a callback to be invoked when multi-finger gestures take place
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* <br></br>
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* For the callbacks implemented via this, check the interface [in.championswimmer.sfg.lib.SimpleFingerGestures.OnFingerGestureListener]
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* @param omfgl The callback that will run
|
|
||||||
*/
|
|
||||||
fun setOnFingerGestureListener(omfgl: OnFingerGestureListener?) {
|
|
||||||
onFingerGestureListener = omfgl
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
override fun onTouch(view: View, ev: MotionEvent): Boolean {
|
|
||||||
if (debug) Log.d(TAG, "onTouch")
|
|
||||||
when (ev.action and MotionEvent.ACTION_MASK) {
|
|
||||||
MotionEvent.ACTION_DOWN -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_DOWN")
|
|
||||||
startTracking(0)
|
|
||||||
ga.trackGesture(ev)
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionEvent.ACTION_UP -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_UP")
|
|
||||||
if (tracking[0]) {
|
|
||||||
doCallBack(ga.getGesture(ev))
|
|
||||||
}
|
|
||||||
stopTracking(0)
|
|
||||||
ga.untrackGesture()
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionEvent.ACTION_POINTER_DOWN -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_POINTER_DOWN" + " " + "num" + ev.pointerCount)
|
|
||||||
startTracking(ev.pointerCount - 1)
|
|
||||||
ga.trackGesture(ev)
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionEvent.ACTION_POINTER_UP -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_POINTER_UP" + " " + "num" + ev.pointerCount)
|
|
||||||
if (tracking[1]) {
|
|
||||||
doCallBack(ga.getGesture(ev))
|
|
||||||
}
|
|
||||||
stopTracking(ev.pointerCount - 1)
|
|
||||||
ga.untrackGesture()
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionEvent.ACTION_CANCEL -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_CANCEL")
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
MotionEvent.ACTION_MOVE -> {
|
|
||||||
if (debug) Log.d(TAG, "ACTION_MOVE")
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return consumeTouchEvents
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun doCallBack(mGt: GestureType) {
|
|
||||||
when (mGt.gestureFlag) {
|
|
||||||
GestureAnalyser.SWIPE_1_UP -> onFingerGestureListener!!.onSwipeUp(
|
|
||||||
1,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_1_DOWN -> onFingerGestureListener!!.onSwipeDown(
|
|
||||||
1,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_1_LEFT -> onFingerGestureListener!!.onSwipeLeft(
|
|
||||||
1,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_1_RIGHT -> onFingerGestureListener!!.onSwipeRight(
|
|
||||||
1,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_2_UP -> onFingerGestureListener!!.onSwipeUp(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_2_DOWN -> onFingerGestureListener!!.onSwipeDown(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_2_LEFT -> onFingerGestureListener!!.onSwipeLeft(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_2_RIGHT -> onFingerGestureListener!!.onSwipeRight(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.PINCH_2 -> onFingerGestureListener!!.onPinch(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.UNPINCH_2 -> onFingerGestureListener!!.onUnpinch(
|
|
||||||
2,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_3_UP -> onFingerGestureListener!!.onSwipeUp(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_3_DOWN -> onFingerGestureListener!!.onSwipeDown(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_3_LEFT -> onFingerGestureListener!!.onSwipeLeft(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_3_RIGHT -> onFingerGestureListener!!.onSwipeRight(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.PINCH_3 -> onFingerGestureListener!!.onPinch(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.UNPINCH_3 -> onFingerGestureListener!!.onUnpinch(
|
|
||||||
3,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_4_UP -> onFingerGestureListener!!.onSwipeUp(
|
|
||||||
4,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_4_DOWN -> onFingerGestureListener!!.onSwipeDown(
|
|
||||||
4,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_4_LEFT -> onFingerGestureListener!!.onSwipeLeft(
|
|
||||||
4,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.SWIPE_4_RIGHT -> onFingerGestureListener!!.onSwipeRight(
|
|
||||||
4,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.PINCH_4 -> onFingerGestureListener!!.onPinch(
|
|
||||||
4,
|
|
||||||
mGt.gestureDuration,
|
|
||||||
mGt.gestureDistance
|
|
||||||
)
|
|
||||||
|
|
||||||
GestureAnalyser.UNPINCH_4 -> {
|
|
||||||
onFingerGestureListener!!.onUnpinch(4, mGt.gestureDuration, mGt.gestureDistance)
|
|
||||||
onFingerGestureListener!!.onDoubleTap(1)
|
|
||||||
}
|
|
||||||
|
|
||||||
GestureAnalyser.DOUBLE_TAP_1 -> onFingerGestureListener!!.onDoubleTap(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun startTracking(nthPointer: Int) {
|
|
||||||
for (i in 0..nthPointer) {
|
|
||||||
tracking[i] = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun stopTracking(nthPointer: Int) {
|
|
||||||
for (i in nthPointer until tracking.size) {
|
|
||||||
tracking[i] = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Interface definition for the callback to be invoked when 2-finger gestures are performed
|
|
||||||
*/
|
|
||||||
interface OnFingerGestureListener {
|
|
||||||
/**
|
|
||||||
* Called when user swipes **up** with two fingers
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onSwipeUp(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user swipes **down** with two fingers
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onSwipeDown(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user swipes **left** with two fingers
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onSwipeLeft(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user swipes **right** with two fingers
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onSwipeRight(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user **pinches** with two fingers (bring together)
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onPinch(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Called when user **un-pinches** with two fingers (take apart)
|
|
||||||
*
|
|
||||||
* @param fingers number of fingers involved in this gesture
|
|
||||||
* @param gestureDuration duration in milliSeconds
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
fun onUnpinch(fingers: Int, gestureDuration: Long, gestureDistance: Double): Boolean
|
|
||||||
|
|
||||||
fun onDoubleTap(fingers: Int): Boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
// Will see if these need to be used. For now just returning duration in milliS
|
|
||||||
const val GESTURE_SPEED_SLOW: Long = 1500
|
|
||||||
const val GESTURE_SPEED_MEDIUM: Long = 1000
|
|
||||||
const val GESTURE_SPEED_FAST: Long = 500
|
|
||||||
private const val TAG = "SimpleFingerGestures"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListener {
|
|
||||||
// companion object {
|
|
||||||
// private const val SWIPE_DISTANCE_THRESHOLD = 100
|
|
||||||
// private const val SWIPE_VELOCITY_THRESHOLD = 100
|
|
||||||
// }
|
|
||||||
// private val gestureDetector: GestureDetector
|
|
||||||
// abstract fun onSwipeLeft()
|
|
||||||
// abstract fun onSwipeRight()
|
|
||||||
// abstract fun onSwipeDown()
|
|
||||||
// abstract fun onSwipeUp()
|
|
||||||
// abstract fun onSingleTap(area : TouchArea)
|
|
||||||
// abstract fun onDoubleTap(area : TouchArea)
|
|
||||||
//
|
|
||||||
// override fun onTouch(v: View?, event: MotionEvent?): Boolean {
|
|
||||||
// if (event == null) {
|
|
||||||
// return false
|
|
||||||
// }
|
|
||||||
// return gestureDetector.onTouchEvent(event!!)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//
|
|
||||||
// private inner class GestureListener : GestureDetector.SimpleOnGestureListener() {
|
|
||||||
//
|
|
||||||
// override fun onDown(e: MotionEvent): Boolean {
|
|
||||||
// return true
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onDoubleTapEvent(e: MotionEvent): Boolean {
|
|
||||||
// val width: Int = context?.resources?.displayMetrics?.widthPixels ?: 0
|
|
||||||
// val height: Int = context?.resources?.displayMetrics?.heightPixels ?: 0
|
|
||||||
// var touchArea : TouchArea = TouchArea.Center
|
|
||||||
// if(width > 0 && height > 0) {
|
|
||||||
// val centerAreaSize = width * 0.4
|
|
||||||
// var sideAreaSize = (width - centerAreaSize) * 0.5
|
|
||||||
// if(e.x < sideAreaSize) {
|
|
||||||
// touchArea = TouchArea.DoubleLeft
|
|
||||||
// } else if(e.x > sideAreaSize && e.x < width - sideAreaSize) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// touchArea = TouchArea.DoubleRight
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// onDoubleTap(touchArea)
|
|
||||||
// return super.onDoubleTapEvent(e)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSingleTapConfirmed(e: MotionEvent): Boolean {
|
|
||||||
// val width: Int = context?.resources?.displayMetrics?.widthPixels ?: 0
|
|
||||||
// val height: Int = context?.resources?.displayMetrics?.heightPixels ?: 0
|
|
||||||
// var touchArea : TouchArea = TouchArea.Center
|
|
||||||
// if(width > 0 && height > 0) {
|
|
||||||
// val centerAreaSize = width * 0.4
|
|
||||||
// var sideAreaSize = (width - centerAreaSize) * 0.5
|
|
||||||
// if(e.x < sideAreaSize) {
|
|
||||||
// touchArea = TouchArea.Left
|
|
||||||
// } else if(e.x > sideAreaSize && e.x < width - sideAreaSize) {
|
|
||||||
//
|
|
||||||
// } else {
|
|
||||||
// touchArea = TouchArea.Right
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// onSingleTap(touchArea)
|
|
||||||
// return super.onSingleTapConfirmed(e)
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//// override fun onSingleTapUp(e: MotionEvent): Boolean {
|
|
||||||
////
|
|
||||||
//// return super.onSingleTapUp(e)
|
|
||||||
//// }
|
|
||||||
//
|
|
||||||
// override fun onFling(
|
|
||||||
// e1: MotionEvent?,
|
|
||||||
// e2: MotionEvent,
|
|
||||||
// velocityX: Float,
|
|
||||||
// velocityY: Float
|
|
||||||
// ): Boolean {
|
|
||||||
//Blog.LOGE("e1.pointerCount >> ${e1?.pointerCount}")
|
|
||||||
// Blog.LOGE("e2.pointerCount >> ${e2.pointerCount}")
|
|
||||||
// val distanceX = e2.x - (e1?.x ?: 0f)
|
|
||||||
// val distanceY = e2.y - (e1?.y ?: 0f)
|
|
||||||
// if (Math.abs(distanceX) > Math.abs(distanceY)
|
|
||||||
// && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD
|
|
||||||
// && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
|
|
||||||
// if (distanceX > 0) onSwipeRight() else onSwipeLeft()
|
|
||||||
// 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
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// init {
|
|
||||||
// gestureDetector = GestureDetector(context, GestureListener())
|
|
||||||
// }
|
|
||||||
//}
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
interface PagedTextGenerateInterface {
|
|
||||||
fun completePagination(pageList: ArrayList<CharSequence>)
|
|
||||||
}
|
|
||||||
@ -1,319 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Color
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Handler
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.view.View
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
import androidx.constraintlayout.widget.Guideline
|
|
||||||
import androidx.core.view.doOnLayout
|
|
||||||
import androidx.core.view.updateLayoutParams
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
import com.mime.dualscreenview.common.Blog
|
|
||||||
|
|
||||||
class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface {
|
|
||||||
constructor(context: Context) : super(context) {initView(context)}
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs) {initView(context)}
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
||||||
context,
|
|
||||||
attrs,
|
|
||||||
defStyleAttr
|
|
||||||
) {initView(context)}
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet?,
|
|
||||||
defStyleAttr: Int,
|
|
||||||
defStyleRes: Int
|
|
||||||
) : super(context, attrs, defStyleAttr, defStyleRes) {initView(context)}
|
|
||||||
var mainTextView : TextView? = null
|
|
||||||
var sencondTextView : TextView? = null
|
|
||||||
var demp : View? = null
|
|
||||||
var hiddenTextView : PagedTextView? = null
|
|
||||||
var guideLine : Guideline? = null
|
|
||||||
var pageList: ArrayList<CharSequence>? = null
|
|
||||||
var summaryText : String = ""
|
|
||||||
var text : String = ""
|
|
||||||
set(new) {
|
|
||||||
Blog.LOGE("field >> ${field}")
|
|
||||||
Blog.LOGE("new >> ${new}")
|
|
||||||
field = new
|
|
||||||
val summary = new.replace(" " ,"").replace("\n" ,"").substring(0,Math.min(30,new.length))
|
|
||||||
if (summary.equals(summaryText)) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
Blog.LOGE("field >> ${field}")
|
|
||||||
hiddenTextView?.setTxtF(field)
|
|
||||||
hiddenTextView?.visibility = VISIBLE
|
|
||||||
}
|
|
||||||
summaryText = summary
|
|
||||||
}
|
|
||||||
|
|
||||||
private val hanler = Handler()
|
|
||||||
var mPagedTextViewInterface : PagedTextViewInterface? = null
|
|
||||||
val touchTimeover = Runnable {
|
|
||||||
mPagedTextViewInterface?.onTimeoverTouch()
|
|
||||||
}
|
|
||||||
|
|
||||||
var currentPageTextView : TextView? = null
|
|
||||||
fun initView(context: Context) {
|
|
||||||
inflate(context, R.layout.layout_textviewer, this)
|
|
||||||
mainTextView = findViewById(R.id.first_view)
|
|
||||||
sencondTextView = findViewById(R.id.sencond_view)
|
|
||||||
demp = findViewById(R.id.demp)
|
|
||||||
currentPageTextView = findViewById(R.id.current_page)
|
|
||||||
|
|
||||||
hiddenTextView = findViewById(R.id.hidden_view)
|
|
||||||
hiddenTextView?.mPagedTextGenerateInterface = this
|
|
||||||
currentPageTextView?.text = ""
|
|
||||||
hanler.removeCallbacks(touchTimeover)
|
|
||||||
setOnLongClickListener { v ->
|
|
||||||
mPagedTextViewInterface?.onLongClick()
|
|
||||||
return@setOnLongClickListener false
|
|
||||||
}
|
|
||||||
|
|
||||||
setOnTouchListener(SimpleFingerGestures(omfgl = object : SimpleFingerGestures.OnFingerGestureListener{
|
|
||||||
override fun onSwipeUp(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
mPagedTextViewInterface?.onSwipeUp(fingers)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeDown(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
mPagedTextViewInterface?.onSwipeDown(fingers)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeLeft(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
mPagedTextViewInterface?.onSwipeLeft(fingers)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSwipeRight(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
mPagedTextViewInterface?.onSwipeRight(fingers)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onPinch(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onUnpinch(
|
|
||||||
fingers: Int,
|
|
||||||
gestureDuration: Long,
|
|
||||||
gestureDistance: Double
|
|
||||||
): Boolean {
|
|
||||||
mPagedTextViewInterface?.onLongClick()
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onDoubleTap(fingers: Int): Boolean {
|
|
||||||
hanler.removeCallbacks(touchTimeover)
|
|
||||||
mPagedTextViewInterface?.onTouch(TouchArea.Center)
|
|
||||||
hanler?.postDelayed(touchTimeover, 3000L)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}))
|
|
||||||
// {
|
|
||||||
// override fun onSwipeUp() {
|
|
||||||
// mPagedTextViewInterface?.onLongClick()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSwipeDown() {
|
|
||||||
// mPagedTextViewInterface?.onLongClick()
|
|
||||||
// }
|
|
||||||
// override fun onSwipeLeft() {
|
|
||||||
// mPagedTextViewInterface?.onSwipeLeft()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSwipeRight() {
|
|
||||||
// mPagedTextViewInterface?.onSwipeRight()
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onSingleTap(touchArea: TouchArea) {
|
|
||||||
// if(TouchArea.Center.equals(touchArea)) {
|
|
||||||
// hanler.removeCallbacks(touchTimeover)
|
|
||||||
// mPagedTextViewInterface?.onTouch(touchArea)
|
|
||||||
// hanler?.postDelayed(touchTimeover, 3000L)
|
|
||||||
// } else {
|
|
||||||
// mPagedTextViewInterface?.onTouch(touchArea)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// override fun onDoubleTap(area: TouchArea) {
|
|
||||||
// if(TouchArea.Center.equals(area)) {
|
|
||||||
//// hanler.removeCallbacks(touchTimeover)
|
|
||||||
//// mPagedTextViewInterface?.onTouch(area)
|
|
||||||
//// hanler?.postDelayed(touchTimeover, 3000L)
|
|
||||||
// } else {
|
|
||||||
// mPagedTextViewInterface?.onTouch(area)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// })
|
|
||||||
}
|
|
||||||
|
|
||||||
fun layoutChange(needDualPage: Boolean) {
|
|
||||||
Blog.LOGD(log = "layoutChange>> ${this::class.java.name}")
|
|
||||||
if (needDualPage) {
|
|
||||||
sencondTextView?.visibility = VISIBLE
|
|
||||||
demp?.visibility = VISIBLE
|
|
||||||
} else {
|
|
||||||
sencondTextView?.visibility = GONE
|
|
||||||
demp?.visibility = GONE
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
|
||||||
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
|
|
||||||
if(changed) {
|
|
||||||
hiddenTextView?.text = text
|
|
||||||
forceUpdateUI()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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}")
|
|
||||||
if (w != oldw || oldh != h) {
|
|
||||||
postDelayed(Runnable {
|
|
||||||
layoutChange(w > (h * 0.7f))
|
|
||||||
|
|
||||||
},20)
|
|
||||||
}else {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
var currentPage = 0
|
|
||||||
override fun completePagination(pageList: ArrayList<CharSequence>) {
|
|
||||||
Blog.LOGD(log = "completePagination>> ${this::class.java.name} >> pageList ${pageList}")
|
|
||||||
if(text.length > 0 && pageList!= null && pageList.size == 0) {
|
|
||||||
|
|
||||||
} else {
|
|
||||||
this.pageList = pageList
|
|
||||||
setPageBy(0)
|
|
||||||
}
|
|
||||||
hiddenTextView?.visibility = GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setColorStyle(colors : Array<String>) {
|
|
||||||
setBackgroundColor(Color.parseColor(colors.get(1)))
|
|
||||||
mainTextView?.setBackgroundColor(Color.parseColor(colors.get(1)))
|
|
||||||
sencondTextView?.setBackgroundColor(Color.parseColor(colors.get(1)))
|
|
||||||
mainTextView?.setTextColor(Color.parseColor(colors.get(0)))
|
|
||||||
sencondTextView?.setTextColor(Color.parseColor(colors.get(0)))
|
|
||||||
}
|
|
||||||
|
|
||||||
// fun setPagedTextViewInterface(pagedTextViewInterface: PagedTextViewInterface) = hiddenTextView?.setPagedTextViewInterface(pagedTextViewInterface)
|
|
||||||
// fun setText(replace: String) = hiddenTextView?.setText(replace)
|
|
||||||
|
|
||||||
fun setTextSize(fl: Float) {
|
|
||||||
hiddenTextView?.setTextSize(fl)
|
|
||||||
mainTextView?.setTextSize(fl)
|
|
||||||
sencondTextView?.setTextSize(fl)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun next(page : Int) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
fun isDualPage() : Boolean {
|
|
||||||
return sencondTextView?.visibility == VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setPageBy(num : Int) {
|
|
||||||
currentPage = num
|
|
||||||
var realPage = if(isDualPage()) currentPage * 2 else currentPage
|
|
||||||
Blog.LOGE("realPage = if(${pageList?.size} ?: 0 > ${realPage}) { realPage} else { ${(pageList?.size ?: 0) - 1 }}")
|
|
||||||
realPage = if(pageList?.size ?: 0 > realPage) { realPage} else { (pageList?.size ?: 0) - 1 }
|
|
||||||
currentPageTextView?.text = "${realPage + 1 }/${ pageList?.size ?: 0 + 1}"
|
|
||||||
|
|
||||||
mainTextView?.text = pageList?.get(realPage) ?: "NONE"
|
|
||||||
if(isDualPage()) {
|
|
||||||
realPage = realPage.inc()
|
|
||||||
sencondTextView?.text = if(pageList?.size ?: 0 > realPage) { pageList?.get(realPage)} else { "끝"}
|
|
||||||
} else {
|
|
||||||
sencondTextView?.text = ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun size(): Int = if(isDualPage()) Math.round((hiddenTextView?.size() ?:0) * 0.5f) else hiddenTextView?.size() ?: 0
|
|
||||||
fun getFastPageCount() = if(isDualPage()) 3 else 6
|
|
||||||
fun current(): Int = currentPage
|
|
||||||
fun doNext(fast : Boolean = false) {
|
|
||||||
if (fast) {
|
|
||||||
setPageBy(if((currentPage + getFastPageCount()) >= 0) {
|
|
||||||
currentPage + getFastPageCount()
|
|
||||||
} else {size()})
|
|
||||||
} else {
|
|
||||||
setPageBy(currentPage.inc())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doPrev(fast : Boolean = false) {
|
|
||||||
if (fast) {
|
|
||||||
setPageBy(if((currentPage - getFastPageCount()) >= 0) {
|
|
||||||
currentPage - getFastPageCount()
|
|
||||||
} else {0})
|
|
||||||
} else {
|
|
||||||
setPageBy(if(currentPage > 0 )currentPage.dec() else 0)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun forceUpdateUI() {
|
|
||||||
hiddenTextView?.doUpdate()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
hiddenTextView?.setPadding(left,top,right, bottom)
|
|
||||||
mainTextView?.setPadding(left,top,right, bottom)
|
|
||||||
sencondTextView?.setPadding(left,top,right, bottom)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun setTypeface(tf: Typeface?) {
|
|
||||||
hiddenTextView?.setTypeface(tf)
|
|
||||||
mainTextView?.setTypeface(tf)
|
|
||||||
sencondTextView?.setTypeface(tf)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
fun setLetterSpacing(letterSpacing: Float) {
|
|
||||||
hiddenTextView?.letterSpacing = letterSpacing.times(0.01f)
|
|
||||||
mainTextView?.letterSpacing = letterSpacing.times(0.01f)
|
|
||||||
sencondTextView?.letterSpacing = letterSpacing.times(0.01f)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
fun setLineSpacing(mult: Float) {
|
|
||||||
hiddenTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
|
||||||
mainTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
|
||||||
sencondTextView?.setLineSpacing(1f, 1f.plus(mult.times(0.01f)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@ -1,263 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.annotation.TargetApi
|
|
||||||
import android.content.Context
|
|
||||||
import android.graphics.Typeface
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.Layout
|
|
||||||
import android.text.StaticLayout
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.util.TypedValue
|
|
||||||
import androidx.appcompat.widget.AppCompatTextView
|
|
||||||
import androidx.core.view.marginBottom
|
|
||||||
import androidx.core.view.marginLeft
|
|
||||||
import androidx.core.view.marginRight
|
|
||||||
import androidx.core.view.marginTop
|
|
||||||
import com.mime.dualscreenview.common.Blog
|
|
||||||
import kotlinx.coroutines.MainScope
|
|
||||||
import kotlinx.coroutines.launch
|
|
||||||
import kotlin.math.min
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PagedTextView : AppCompatTextView {
|
|
||||||
|
|
||||||
private var needPaginate = false
|
|
||||||
private var isPaginating = false
|
|
||||||
private val pageList = arrayListOf<CharSequence>()
|
|
||||||
private var pageIndex: Int = 0
|
|
||||||
private var pageHeight: Int = 0
|
|
||||||
private var originalText: CharSequence = ""
|
|
||||||
|
|
||||||
var mPagedTextGenerateInterface : PagedTextGenerateInterface? = null
|
|
||||||
|
|
||||||
|
|
||||||
constructor(context: Context?) : super(context!!){initView(context)}
|
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?) : super(context!!, attrs){initView(context)}
|
|
||||||
|
|
||||||
constructor(context: Context?, attrs: AttributeSet?, defStyleAttr: Int) : super(context!!, attrs, defStyleAttr){initView(context)}
|
|
||||||
|
|
||||||
fun initView(context: Context?){
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fun size(): Int = pageList.size
|
|
||||||
fun current() : Int = pageIndex
|
|
||||||
|
|
||||||
fun doPrev() {
|
|
||||||
if (pageIndex > 0 )
|
|
||||||
pageIndex = pageIndex - 1
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doNext() {
|
|
||||||
if (pageIndex < pageList.size)
|
|
||||||
pageIndex = pageIndex + 1
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
fun next(index: Int) {
|
|
||||||
pageIndex = index
|
|
||||||
setPageText()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun setPageText() {
|
|
||||||
if(pageList.size > 0) {
|
|
||||||
isPaginating = true
|
|
||||||
text = pageList[pageIndex]
|
|
||||||
isPaginating = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun setTxtF(text: CharSequence?) {
|
|
||||||
needPaginate = true
|
|
||||||
this.setText(text , null)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setText(text: CharSequence?, type: BufferType?) {
|
|
||||||
if (!isPaginating) {
|
|
||||||
needPaginate = true
|
|
||||||
originalText = text ?: ""
|
|
||||||
}
|
|
||||||
super.setText(text, type)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
override fun setTextSize(size: Float) {
|
|
||||||
setTextSize(TypedValue.COMPLEX_UNIT_SP, size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTextSize(unit: Int, size: Float) {
|
|
||||||
super.setTextSize(unit, size)
|
|
||||||
paint.textSize = TypedValue.applyDimension(unit, size, context.resources.getDisplayMetrics())
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPadding(left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.setPadding(left, top, right, bottom)
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setPaddingRelative(start: Int, top: Int, end: Int, bottom: Int) {
|
|
||||||
super.setPaddingRelative(start, top, end, bottom)
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTextScaleX(size: Float) {
|
|
||||||
if (size != textScaleX) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setTextScaleX(size)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setTypeface(tf: Typeface?) {
|
|
||||||
if (typeface != null && tf != typeface) {
|
|
||||||
needPaginate = true
|
|
||||||
paint.typeface = tf
|
|
||||||
}
|
|
||||||
super.setTypeface(tf)
|
|
||||||
}
|
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
|
||||||
override fun setLetterSpacing(letterSpacing: Float) {
|
|
||||||
if (letterSpacing != this.letterSpacing) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setLetterSpacing(letterSpacing)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setHorizontallyScrolling(whether: Boolean) {
|
|
||||||
super.setHorizontallyScrolling(false)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLineSpacing(add: Float, mult: Float) {
|
|
||||||
if (add != lineSpacingExtra || mult != lineSpacingMultiplier) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
super.setLineSpacing(add, mult)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setMaxLines(maxLines: Int) {
|
|
||||||
if (maxLines != this.maxLines) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
|
|
||||||
super.setMaxLines(maxLines)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun setLines(lines: Int) {
|
|
||||||
super.setLines(lines)
|
|
||||||
|
|
||||||
if (lines != this.lineCount) {
|
|
||||||
needPaginate = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onSizeChanged(w: Int, h: Int, oldw: Int, oldh: Int) {
|
|
||||||
super.onSizeChanged(w, h, oldw, oldh)
|
|
||||||
Blog.LOGD(log = "onSizeChanged>> ${this::class.java.name}")
|
|
||||||
pageHeight = ((h - (marginTop + marginBottom + paddingTop + paddingBottom)) * 1f).toInt()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onLayout(changed: Boolean, left: Int, top: Int, right: Int, bottom: Int) {
|
|
||||||
super.onLayout(changed, left, top, right, bottom)
|
|
||||||
Blog.LOGD(log = "onLayout>> ${this::class.java.name} changed >> ${changed}")
|
|
||||||
if (changed || needPaginate) {
|
|
||||||
paginate()
|
|
||||||
setPageText()
|
|
||||||
needPaginate = false
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
fun doUpdate() {
|
|
||||||
if (needPaginate && layout != null) {
|
|
||||||
paginate()
|
|
||||||
setPageText()
|
|
||||||
needPaginate = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
private fun paginate() {
|
|
||||||
if (layout != null) {
|
|
||||||
MainScope().launch {
|
|
||||||
pageList.clear()
|
|
||||||
Blog.LOGD(log = "paginate>> ${this::class.java.name} && ${layout.text}")
|
|
||||||
val layout = from(layout)
|
|
||||||
val lines = if(min(maxLines, layout.lineCount) > 10) {min(maxLines, layout.lineCount) - 1} else {min(maxLines, layout.lineCount)}
|
|
||||||
var startOffset = 0
|
|
||||||
val heightWithoutPaddings = pageHeight //- (marginTop + marginBottom + paddingTop + paddingBottom)
|
|
||||||
var height = heightWithoutPaddings
|
|
||||||
|
|
||||||
for (i in 0 until lines) {
|
|
||||||
if (height < layout.getLineBottom(i)) {
|
|
||||||
pageList.add(
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineStart(i))
|
|
||||||
)
|
|
||||||
startOffset = layout.getLineStart(i)
|
|
||||||
height = layout.getLineTop(i) + heightWithoutPaddings
|
|
||||||
}
|
|
||||||
|
|
||||||
if (i == lines - 1) {
|
|
||||||
pageList.add(
|
|
||||||
if(layout.lineCount > i) {
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineEnd(i + 1))
|
|
||||||
} else {
|
|
||||||
layout.text.subSequence(startOffset, layout.getLineEnd(i))
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
mPagedTextGenerateInterface?.completePagination(pageList)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun from(layout: Layout): Layout =
|
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
|
|
||||||
@Suppress("DEPRECATION")
|
|
||||||
(StaticLayout(
|
|
||||||
originalText,
|
|
||||||
paint,
|
|
||||||
layout.width,
|
|
||||||
layout.alignment,
|
|
||||||
lineSpacingMultiplier,
|
|
||||||
lineSpacingExtra,
|
|
||||||
includeFontPadding
|
|
||||||
))
|
|
||||||
} else {
|
|
||||||
StaticLayout.Builder
|
|
||||||
.obtain(originalText, 0, originalText.length, paint, ((layout.width - (paddingLeft + paddingRight + marginLeft + marginRight) * 0.85f)).toInt())
|
|
||||||
.setAlignment(layout.alignment)
|
|
||||||
.setLineSpacing(lineSpacingExtra, lineSpacingMultiplier)
|
|
||||||
.setIncludePad(includeFontPadding)
|
|
||||||
.setUseLineSpacingFromFallbacks()
|
|
||||||
.setBreakStrategy(breakStrategy)
|
|
||||||
.setHyphenationFrequency(hyphenationFrequency)
|
|
||||||
// .setJustificationMode()
|
|
||||||
.setMaxLines(maxLines)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticLayout.Builder.setUseLineSpacingFromFallbacks(): StaticLayout.Builder {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
||||||
this.setUseLineSpacingFromFallbacks(isFallbackLineSpacing)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun StaticLayout.Builder.setJustificationMode(): StaticLayout.Builder {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
this.setJustificationMode(justificationMode)
|
|
||||||
}
|
|
||||||
|
|
||||||
return this
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,11 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
interface PagedTextViewInterface {
|
|
||||||
fun onTouch(touchArea: TouchArea)
|
|
||||||
fun onTimeoverTouch()
|
|
||||||
fun onSwipeLeft(touchCount : Int)
|
|
||||||
fun onSwipeRight(touchCount : Int)
|
|
||||||
fun onSwipeDown(touchCount : Int)
|
|
||||||
fun onSwipeUp(touchCount : Int)
|
|
||||||
fun onLongClick()
|
|
||||||
}
|
|
||||||
@ -1,64 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.widget.Button
|
|
||||||
import androidx.appcompat.widget.AppCompatButton
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
|
|
||||||
class ScopeEditor: SideButtonTextView {
|
|
||||||
constructor(context: Context) : super(context)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
||||||
context,
|
|
||||||
attrs,
|
|
||||||
defStyleAttr
|
|
||||||
)
|
|
||||||
var titleArray : Array<String>? = null
|
|
||||||
set(value) {
|
|
||||||
if(value != null && value.size < 1) {
|
|
||||||
Error("titleArray는 최소 한개 이상이여야됨.")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
maxValue = field!!.size
|
|
||||||
}
|
|
||||||
|
|
||||||
var maxValue : Int = 1
|
|
||||||
set(value) {
|
|
||||||
if (value < 1) {
|
|
||||||
Error("maxValue는 무조건 0보다 커야하눈뎅....")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
field = value
|
|
||||||
}
|
|
||||||
|
|
||||||
override var value : Int = 14
|
|
||||||
set(newValue) {
|
|
||||||
field = newValue
|
|
||||||
text_value?.text = displayFormat.format(titleArray?.get(field) ?:"defulat")
|
|
||||||
mValueChange?.invoke(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet?,
|
|
||||||
defStyleAttr: Int,
|
|
||||||
defStyleRes: Int
|
|
||||||
) : super(context, attrs, defStyleAttr, defStyleRes)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
init {
|
|
||||||
// super.i
|
|
||||||
// inflate(context, R.layout.layout_steps_editor,this)
|
|
||||||
btn_decrement?.setOnClickListener { value = Math.abs(value.dec()).rem(maxValue) }
|
|
||||||
btn_increment?.setOnClickListener { value = value.inc().rem(maxValue) }
|
|
||||||
leftButtonTitle = "<"
|
|
||||||
rightButtonTitle = ">"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,78 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import android.widget.Button
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.appcompat.widget.AppCompatButton
|
|
||||||
import androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
|
|
||||||
import java.lang.Exception
|
|
||||||
|
|
||||||
open class SideButtonTextView : ConstraintLayout {
|
|
||||||
constructor(context: Context) : super(context)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
||||||
context,
|
|
||||||
attrs,
|
|
||||||
defStyleAttr
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet?,
|
|
||||||
defStyleAttr: Int,
|
|
||||||
defStyleRes: Int
|
|
||||||
) : super(context, attrs, defStyleAttr, defStyleRes)
|
|
||||||
|
|
||||||
var leftButtonTitle : String = ""
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
btn_decrement?.text = field
|
|
||||||
}
|
|
||||||
|
|
||||||
var rightButtonTitle : String = ""
|
|
||||||
set(value) {
|
|
||||||
field = value
|
|
||||||
btn_increment?.text = field
|
|
||||||
}
|
|
||||||
|
|
||||||
open var value : Int = 14
|
|
||||||
set(newValue) {
|
|
||||||
field = newValue
|
|
||||||
text_value?.text = displayFormat.format(field)
|
|
||||||
mValueChange?.invoke(field)
|
|
||||||
}
|
|
||||||
|
|
||||||
var displayFormat = "글자 크기 : %d"
|
|
||||||
set(newValue) {
|
|
||||||
field = newValue
|
|
||||||
try {
|
|
||||||
text_value?.text = displayFormat.format(value)
|
|
||||||
} catch (e : Exception) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mValueChange : ValueChange? = null
|
|
||||||
set(newValue) {
|
|
||||||
field = newValue
|
|
||||||
if (newValue != null) {
|
|
||||||
newValue(value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var btn_decrement : AppCompatButton? = null
|
|
||||||
var btn_increment : AppCompatButton? = null
|
|
||||||
var text_value : TextView? = null
|
|
||||||
|
|
||||||
init {
|
|
||||||
inflate(context, R.layout.layout_steps_editor,this)
|
|
||||||
btn_increment = findViewById(R.id.btn_increment)
|
|
||||||
btn_decrement = findViewById(R.id.btn_decrement)
|
|
||||||
text_value = findViewById(R.id.text_value)
|
|
||||||
btn_decrement?.setOnClickListener { value = value.dec() }
|
|
||||||
btn_increment?.setOnClickListener { value = value.inc() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,32 +0,0 @@
|
|||||||
package com.mime.dualscreenview.view
|
|
||||||
|
|
||||||
import android.content.Context
|
|
||||||
import android.util.AttributeSet
|
|
||||||
import com.mime.dualscreenview.R
|
|
||||||
|
|
||||||
typealias ValueChange = (Int)->Unit
|
|
||||||
|
|
||||||
class StepsEditor : SideButtonTextView {
|
|
||||||
constructor(context: Context) : super(context)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?) : super(context, attrs)
|
|
||||||
constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(
|
|
||||||
context,
|
|
||||||
attrs,
|
|
||||||
defStyleAttr
|
|
||||||
)
|
|
||||||
|
|
||||||
constructor(
|
|
||||||
context: Context,
|
|
||||||
attrs: AttributeSet?,
|
|
||||||
defStyleAttr: Int,
|
|
||||||
defStyleRes: Int
|
|
||||||
) : super(context, attrs, defStyleAttr, defStyleRes)
|
|
||||||
|
|
||||||
init {
|
|
||||||
// inflate(context, R.layout.layout_steps_editor,this)
|
|
||||||
btn_decrement?.setOnClickListener { value = value.dec() }
|
|
||||||
btn_increment?.setOnClickListener { value = value.inc() }
|
|
||||||
leftButtonTitle = "-"
|
|
||||||
rightButtonTitle = "+"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,81 +0,0 @@
|
|||||||
package com.mime.dualscreenview.webcontents
|
|
||||||
|
|
||||||
import android.util.Log
|
|
||||||
import android.webkit.*
|
|
||||||
import com.mime.dualscreenview.webcontents.contentsinfo.ActionByBool
|
|
||||||
import com.mime.dualscreenview.webcontents.contentsinfo.ContentsInfoInterface
|
|
||||||
import com.mime.dualscreenview.webcontents.contentsinfo.DidFindContents
|
|
||||||
|
|
||||||
|
|
||||||
abstract class BaseWebContents : ContentsInfoInterface {
|
|
||||||
open var lastNumber : Int = 221
|
|
||||||
var completeAction : ActionByBool? = null
|
|
||||||
// val definedActionCount = 5
|
|
||||||
// var completeActionCount = 0
|
|
||||||
// set(value) {
|
|
||||||
// field = value
|
|
||||||
// if(field == definedActionCount && completeAction != null) {
|
|
||||||
// completeAction?.invoke(true)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
fun findListItem(webview: WebView, callBakItems : DidFindContents) {
|
|
||||||
webview.evaluateJavascript(getContentsList()) { result ->
|
|
||||||
callBakItems.invoke(result)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun doOnloaded(webview: WebView, findContents : DidFindContents, completeAction : ActionByBool) {
|
|
||||||
// completeActionCount = 0
|
|
||||||
this.completeAction = completeAction
|
|
||||||
// webview.evaluateJavascript(getTitleJs()) { result : String? ->
|
|
||||||
// result?.let { resultString ->
|
|
||||||
// findTitle.invoke(resultString)
|
|
||||||
// }
|
|
||||||
// completeActionCount = completeActionCount + 1
|
|
||||||
// }
|
|
||||||
webview.evaluateJavascript(getFindContentsJs()) { result : String? ->
|
|
||||||
result?.let { resultString ->
|
|
||||||
checkCorrectContents(resultString)?.let { contents ->
|
|
||||||
if(resultString != null && !"null".equals(resultString) && !resultString.isNullOrEmpty()) {
|
|
||||||
findContents.invoke(contents)
|
|
||||||
} else {
|
|
||||||
findContents.invoke(null)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} ?: findContents.invoke(null)
|
|
||||||
// completeActionCount = completeActionCount + 1
|
|
||||||
}
|
|
||||||
// webview.evaluateJavascript("document.getElementById('${getNextButtonJs()}')") { result : String? ->
|
|
||||||
// result?.let { resultString ->
|
|
||||||
// Log.e("BaseWebContents", "getNextButtonJs() >> ${resultString}")
|
|
||||||
// if(resultString != null && !"null".equals(resultString)) {
|
|
||||||
// findNextButton.invoke(resultString)
|
|
||||||
// } else {
|
|
||||||
// findNextButton.invoke(null)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// completeActionCount = completeActionCount + 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
|
|
||||||
// webview.evaluateJavascript("document.getElementById('${getPrevButtonJs()}')") { result : String? ->
|
|
||||||
// result?.let { resultString ->
|
|
||||||
// Log.e("BaseWebContents", "getPrevButtonJs() >> ${resultString}")
|
|
||||||
// if(resultString != null && !"null".equals(resultString)) {
|
|
||||||
// findPrevButton.invoke(resultString)
|
|
||||||
// }else {
|
|
||||||
// findPrevButton.invoke(null)
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// completeActionCount = completeActionCount + 1
|
|
||||||
// }
|
|
||||||
|
|
||||||
webview.evaluateJavascript(onLoadedJs()) {
|
|
||||||
Log.e("BaseWebContents", "onLoadedJs() >> ${it}")
|
|
||||||
// completeActionCount = completeActionCount + 1
|
|
||||||
}
|
|
||||||
completeAction?.invoke(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,251 +0,0 @@
|
|||||||
package com.mime.dualscreenview.webcontents
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint
|
|
||||||
import android.app.AlertDialog
|
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.net.Uri
|
|
||||||
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 {
|
|
||||||
|
|
||||||
var currentContentsProvider : BaseWebContents? = null
|
|
||||||
lateinit var webview : WebView
|
|
||||||
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) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressLint("JavascriptInterface")
|
|
||||||
constructor(webview : WebView, mainControllInterface : MainControllInterface ) {
|
|
||||||
this.webview = webview
|
|
||||||
this.mainControllInterface = mainControllInterface
|
|
||||||
webview.webChromeClient = rootWebChromeClient
|
|
||||||
webview.webViewClient = rootWebViewClient
|
|
||||||
webview.settings.textZoom = 100
|
|
||||||
webview.addJavascriptInterface(this,"PAgit")
|
|
||||||
webview.settings.javaScriptEnabled = true
|
|
||||||
webview.settings.javaScriptCanOpenWindowsAutomatically = false
|
|
||||||
webview.settings.loadWithOverviewMode = true
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
|
|
||||||
constructor()
|
|
||||||
|
|
||||||
fun loadContents(webContents: BaseWebContents) {
|
|
||||||
currentContentsProvider = webContents
|
|
||||||
currentContentsProvider?.let {
|
|
||||||
webview.loadUrl(it.getLastedDoamin())
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
val rootWebChromeClient = object : WebChromeClient() {
|
|
||||||
override fun onProgressChanged(view: WebView?, newProgress: Int) {
|
|
||||||
super.onProgressChanged(view, newProgress)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun findListItem(callBakItems : DidFindContents) {
|
|
||||||
currentContentsProvider?.findListItem(webview,callBakItems)
|
|
||||||
}
|
|
||||||
|
|
||||||
fun loadLastInfo(lastInfo: LastInfo) {
|
|
||||||
lastInfo?.let { last ->
|
|
||||||
currentContentsProvider = WebContentsManger.getBaseWebContentsBy(last.contentsName)
|
|
||||||
if (last.pageUrl.startsWith("https://")) {
|
|
||||||
webview.loadUrl(last.pageUrl)
|
|
||||||
} else {
|
|
||||||
try {
|
|
||||||
webview.loadUrl(PrefManager.getLastDomain().plus(last.pageUrl))
|
|
||||||
} catch (e : Exception) {
|
|
||||||
webview.loadUrl(PrefManager.getLastDomain())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
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) {
|
|
||||||
// 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)
|
|
||||||
mainControllInterface?.onStartLoad()
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onReceivedSslError(
|
|
||||||
view: WebView?,
|
|
||||||
handler: SslErrorHandler?,
|
|
||||||
error: SslError?
|
|
||||||
) {
|
|
||||||
// super.onReceivedSslError(view, handler, error)
|
|
||||||
Blog.LOGE(log= "onReceivedSslError >> ${error}")
|
|
||||||
handler?.proceed()
|
|
||||||
}
|
|
||||||
override fun onReceivedHttpError(
|
|
||||||
view: WebView?,
|
|
||||||
request: WebResourceRequest?,
|
|
||||||
errorResponse: WebResourceResponse?
|
|
||||||
) {
|
|
||||||
Blog.LOGE(log= "onReceivedHttpError >> ${errorResponse}")
|
|
||||||
// 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))
|
|
||||||
}
|
|
||||||
|
|
||||||
if(url?.contains("/list/") ?: false && url?.contains("agit") ?: false){
|
|
||||||
findListItem {
|
|
||||||
Blog.LOGE("onPageFinished", url ?: "")
|
|
||||||
}
|
|
||||||
} else if (url?.contains("booktoki") ?: false){
|
|
||||||
// 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 ->
|
|
||||||
if(complete) {
|
|
||||||
mainControllInterface?.completePageLoad(LastInfo().apply {
|
|
||||||
this.pageUrl = url?.toUri()?.path ?: currentContentsProvider?.getLastedDoamin() ?: ""
|
|
||||||
this.contentsName = currentContentsProvider?.getWebcontentsName() ?: ""
|
|
||||||
this.pageIndex = 0
|
|
||||||
})
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var finishedUrl : String = ""
|
|
||||||
inner class BookHelper {
|
|
||||||
@JavascriptInterface
|
|
||||||
fun sendValueFromHtml(string: String) {
|
|
||||||
|
|
||||||
Jsoup.parse(string)?.let { html ->
|
|
||||||
|
|
||||||
val toon_intro = html.getElementById("toon_intro")
|
|
||||||
val view_padding = html.getElementsByClass("view-padding")
|
|
||||||
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 = html.getElementById("list_type")
|
|
||||||
if (listParent != null) {
|
|
||||||
listParent.getElementsByClass("row").forEach { bookitem ->
|
|
||||||
// Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: bookItemInfo ${bookitem}")
|
|
||||||
try {
|
|
||||||
val bookPageInfo = BookPageInfo()
|
|
||||||
bookPageInfo.bookTitle = bookPageInfos.bookTitle
|
|
||||||
bookPageInfo.chapterNum = bookitem.getElementsByClass("cell_num").getT().toInt()
|
|
||||||
bookPageInfo.chapterID = bookitem.getElementsByClass("cell_num").getT().toInt()
|
|
||||||
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 = 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 {
|
|
||||||
HistoryManager.getBooPageInfoContentsSave(it, contents)
|
|
||||||
mainControllInterface.onLoadedContents(contents)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: ${html.title()}")
|
|
||||||
Blog.LOGE("finishedUrl >>> ${finishedUrl} :::: whole body ${html}")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun Elements.getT() = if (size > 0) get(0).text() else ""
|
|
||||||
@ -1,5 +0,0 @@
|
|||||||
//package com.mime.dualscreenview.webcontents
|
|
||||||
//
|
|
||||||
//typealias ActionByBool = (Boolean) -> Unit
|
|
||||||
//typealias DidFindContents = (String?) -> Unit
|
|
||||||
//typealias GotoSomeWhere = () -> Unit
|
|
||||||
@ -1,22 +0,0 @@
|
|||||||
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
|
|
||||||
|
|
||||||
interface MainControllInterface {
|
|
||||||
fun onStartLoad()
|
|
||||||
fun completePageLoad(apply: LastInfo)
|
|
||||||
|
|
||||||
fun showNextBtn(finnd : Boolean, onClickAction: GotoSomeWhere)
|
|
||||||
fun showPrevBtn(finnd : Boolean,onClickAction: GotoSomeWhere)
|
|
||||||
|
|
||||||
fun showAlert(alert :String)
|
|
||||||
|
|
||||||
fun onLoadedContents(contents :String)
|
|
||||||
fun onFindTitle(contents :String)
|
|
||||||
|
|
||||||
fun onBookInfos(jsonString : String)
|
|
||||||
fun onBookInfos(infos : BookPageInfos)
|
|
||||||
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
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(NewtokiOne)
|
|
||||||
|
|
||||||
fun getBaseWebContentsBy(name : String) : BaseWebContents {
|
|
||||||
var correctContents : BaseWebContents = Booktoki
|
|
||||||
for (contents in allContentsList) {
|
|
||||||
if(name.equals(contents.getWebcontentsName())) {
|
|
||||||
correctContents = contents
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return correctContents
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,138 +0,0 @@
|
|||||||
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();"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
package com.mime.dualscreenview.webcontents.contentsinfo
|
|
||||||
|
|
||||||
import com.mime.dualscreenview.webcontents.BaseWebContents
|
|
||||||
|
|
||||||
object Booktoki : BaseWebContents() {
|
|
||||||
|
|
||||||
override var lastNumber : Int = 351
|
|
||||||
|
|
||||||
override fun getWebcontentsName(): String {
|
|
||||||
return "Booktoki"
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getLastedDoamin(): String {
|
|
||||||
return String.format("https://booktoki%d.com/", lastNumber)
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +0,0 @@
|
|||||||
package com.mime.dualscreenview.webcontents.contentsinfo
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
typealias ActionByBool = (Boolean) -> Unit
|
|
||||||
typealias DidFindContents = (String?) -> Unit
|
|
||||||
typealias GotoSomeWhere = () -> Unit
|
|
||||||
|
|
||||||
interface ContentsInfoInterface {
|
|
||||||
fun getWebcontentsName() : String
|
|
||||||
fun getNextButtonJs() : String
|
|
||||||
fun getPrevButtonJs() : String
|
|
||||||
fun getTitleJs() : String
|
|
||||||
fun getFindContentsJs() : String
|
|
||||||
fun checkCorrectContents(contents: String) : String
|
|
||||||
fun getLastedDoamin() : String
|
|
||||||
fun onLoadedJs() : String
|
|
||||||
fun acccceptResourceKeyword() : String
|
|
||||||
fun getContentsList() : String
|
|
||||||
}
|
|
||||||
@ -1,95 +0,0 @@
|
|||||||
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.one"
|
|
||||||
}
|
|
||||||
|
|
||||||
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 ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,18 +0,0 @@
|
|||||||
|
|
||||||
function getList() {
|
|
||||||
var children = document.getElementsByClassName('list-body')[0].children
|
|
||||||
var maxCount = children.length
|
|
||||||
const contentsArray = []
|
|
||||||
for (i= 0; i < maxCount; i++) {
|
|
||||||
children[i].getElementsByClassName('wr-num')
|
|
||||||
contentsArray.push(
|
|
||||||
{
|
|
||||||
'title' : children[i].text ,
|
|
||||||
'link' : children[i].value
|
|
||||||
}
|
|
||||||
)
|
|
||||||
}
|
|
||||||
contentsArray.reverse()
|
|
||||||
return {'list' :contentsArray}
|
|
||||||
}
|
|
||||||
getList()
|
|
||||||
@ -1,30 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:aapt="http://schemas.android.com/aapt"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
|
|
||||||
<aapt:attr name="android:fillColor">
|
|
||||||
<gradient
|
|
||||||
android:endX="85.84757"
|
|
||||||
android:endY="92.4963"
|
|
||||||
android:startX="42.9492"
|
|
||||||
android:startY="49.59793"
|
|
||||||
android:type="linear">
|
|
||||||
<item
|
|
||||||
android:color="#44000000"
|
|
||||||
android:offset="0.0" />
|
|
||||||
<item
|
|
||||||
android:color="#00000000"
|
|
||||||
android:offset="1.0" />
|
|
||||||
</gradient>
|
|
||||||
</aapt:attr>
|
|
||||||
</path>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFF"
|
|
||||||
android:fillType="nonZero"
|
|
||||||
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
|
|
||||||
android:strokeWidth="1"
|
|
||||||
android:strokeColor="#00000000" />
|
|
||||||
</vector>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M17.921,1.505a1.5,1.5 0,0 1,-0.44 1.06L9.809,10.237a2.5,2.5 0,0 0,0 3.536l7.662,7.662a1.5,1.5 0,0 1,-2.121 2.121L7.688,15.9a5.506,5.506 0,0 1,0 -7.779L15.36,0.444a1.5,1.5 0,0 1,2.561 1.061Z"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M6.079,22.5a1.5,1.5 0,0 1,0.44 -1.06l7.672,-7.672a2.5,2.5 0,0 0,0 -3.536L6.529,2.565A1.5,1.5 0,0 1,8.65 0.444l7.662,7.661a5.506,5.506 0,0 1,0 7.779L8.64,23.556A1.5,1.5 0,0 1,6.079 22.5Z"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M2.849,23.55a2.954,2.954 0,0 0,3.266 -0.644L12,17.053l5.885,5.853a2.956,2.956 0,0 0,2.1 0.881,3.05 3.05,0 0,0 1.17,-0.237A2.953,2.953 0,0 0,23 20.779V5a5.006,5.006 0,0 0,-5 -5H6A5.006,5.006 0,0 0,1 5V20.779A2.953,2.953 0,0 0,2.849 23.55Z"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
|
|
||||||
<item android:id="@android:id/background">
|
|
||||||
<shape
|
|
||||||
android:innerRadiusRatio="2.71"
|
|
||||||
android:thicknessRatio="7.6"
|
|
||||||
android:shape="ring"
|
|
||||||
android:useLevel="false"
|
|
||||||
android:type="sweep">
|
|
||||||
<solid android:color="#9E9E9E" />
|
|
||||||
</shape>
|
|
||||||
</item>
|
|
||||||
|
|
||||||
<item android:id="@android:id/progress">
|
|
||||||
<rotate
|
|
||||||
android:fromDegrees="270"
|
|
||||||
android:toDegrees="270">
|
|
||||||
<shape
|
|
||||||
android:innerRadiusRatio="2.71"
|
|
||||||
android:thicknessRatio="7.6"
|
|
||||||
android:shape="ring"
|
|
||||||
android:angle="0"
|
|
||||||
android:type="sweep">
|
|
||||||
</shape>
|
|
||||||
</rotate>
|
|
||||||
</item>
|
|
||||||
</layer-list>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 13 KiB |
@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="512"
|
|
||||||
android:viewportHeight="512">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M256,319.84c-35.35,0 -64,28.65 -64,64v128h128v-128C320,348.49 291.35,319.84 256,319.84z"/>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M362.67,383.84v128H448c35.35,0 64,-28.65 64,-64V253.26c0,-11.08 -4.3,-21.73 -12.01,-29.7l-181.29,-195.99c-31.99,-34.61 -85.98,-36.74 -120.59,-4.75c-1.64,1.52 -3.23,3.1 -4.75,4.75L12.4,223.5C4.45,231.5 -0,242.31 0,253.58v194.26c0,35.35 28.65,64 64,64h85.33v-128c0.4,-58.17 47.37,-105.68 104.07,-107.04C312.01,275.38 362.22,323.7 362.67,383.84z"/>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M256,319.84c-35.35,0 -64,28.65 -64,64v128h128v-128C320,348.49 291.35,319.84 256,319.84z"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,170 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="108dp"
|
|
||||||
android:height="108dp"
|
|
||||||
android:viewportWidth="108"
|
|
||||||
android:viewportHeight="108">
|
|
||||||
<path
|
|
||||||
android:fillColor="#3DDC84"
|
|
||||||
android:pathData="M0,0h108v108h-108z" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M9,0L9,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,0L19,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,0L29,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,0L39,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,0L49,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,0L59,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,0L69,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,0L79,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M89,0L89,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M99,0L99,108"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,9L108,9"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,19L108,19"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,29L108,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,39L108,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,49L108,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,59L108,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,69L108,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,79L108,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,89L108,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M0,99L108,99"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,29L89,29"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,39L89,39"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,49L89,49"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,59L89,59"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,69L89,69"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M19,79L89,79"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M29,19L29,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M39,19L39,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M49,19L49,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M59,19L59,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M69,19L69,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
<path
|
|
||||||
android:fillColor="#00000000"
|
|
||||||
android:pathData="M79,19L79,89"
|
|
||||||
android:strokeWidth="0.8"
|
|
||||||
android:strokeColor="#33FFFFFF" />
|
|
||||||
</vector>
|
|
||||||
Binary file not shown.
|
Before Width: | Height: | Size: 7.5 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 7.5 KiB |
@ -1,15 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="24"
|
|
||||||
android:viewportHeight="24">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M22.713,4.077A2.993,2.993 0,0 0,20.41 3H4.242L4.2,2.649A3,3 0,0 0,1.222 0H1A1,1 0,0 0,1 2h0.222a1,1 0,0 1,0.993 0.883l1.376,11.7A5,5 0,0 0,8.557 19H19a1,1 0,0 0,0 -2H8.557a3,3 0,0 1,-2.82 -2h11.92a5,5 0,0 0,4.921 -4.113l0.785,-4.354A2.994,2.994 0,0 0,22.713 4.077Z"/>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M7,22m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M17,22m-2,0a2,2 0,1 1,4 0a2,2 0,1 1,-4 0"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,9 +0,0 @@
|
|||||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:width="512dp"
|
|
||||||
android:height="512dp"
|
|
||||||
android:viewportWidth="512"
|
|
||||||
android:viewportHeight="512">
|
|
||||||
<path
|
|
||||||
android:fillColor="#FFFFFFFF"
|
|
||||||
android:pathData="M34.28,384c17.65,30.63 56.78,41.15 87.4,23.5c0.02,-0.01 0.04,-0.02 0.06,-0.04l9.49,-5.48c17.92,15.33 38.52,27.22 60.76,35.07V448c0,35.35 28.65,64 64,64s64,-28.65 64,-64v-10.94c22.24,-7.86 42.84,-19.77 60.76,-35.12l9.54,5.5c30.63,17.67 69.79,7.17 87.47,-23.47c17.67,-30.63 7.17,-69.79 -23.47,-87.47l0,0l-9.47,-5.46c4.26,-23.2 4.26,-46.99 0,-70.19l9.47,-5.46c30.63,-17.67 41.14,-56.83 23.47,-87.47c-17.67,-30.63 -56.83,-41.14 -87.47,-23.47l-9.49,5.48C362.86,94.64 342.25,82.77 320,74.94V64c0,-35.35 -28.65,-64 -64,-64s-64,28.65 -64,64v10.94c-22.24,7.86 -42.84,19.77 -60.76,35.12l-9.54,-5.53C91.07,86.86 51.91,97.37 34.24,128s-7.17,69.79 23.47,87.47l0,0l9.47,5.46c-4.26,23.2 -4.26,46.99 0,70.19l-9.47,5.46C27.16,314.3 16.69,353.38 34.28,384zM256,170.67c47.13,0 85.33,38.21 85.33,85.33S303.13,341.33 256,341.33S170.67,303.13 170.67,256S208.87,170.67 256,170.67z"/>
|
|
||||||
</vector>
|
|
||||||
@ -1,6 +0,0 @@
|
|||||||
<?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.
Binary file not shown.
Binary file not shown.
@ -1,24 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
android:layout_width="320dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_height="420dp"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/style_dialog_title"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:gravity="center"
|
|
||||||
android:layout_height="@dimen/main_top_height"/>
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/style_dialog_title"
|
|
||||||
android:id="@+id/stylez_recyclerview"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"/>
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
@ -1,182 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<layout>
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:id="@+id/intro_bg"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".activity.Intro">
|
|
||||||
|
|
||||||
<WebView
|
|
||||||
android:id="@+id/hidden_web"
|
|
||||||
android:layout_margin="60dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"/>
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<WebView
|
|
||||||
android:id="@+id/menu_web"
|
|
||||||
android:layout_margin="20dp"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintBottom_toTopOf="@id/btn_left"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/textview_title" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:id="@+id/btn_home"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/home"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
tools:ignore="MissingConstraints" />
|
|
||||||
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/textview_title"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:text="@string/app_name"
|
|
||||||
android:gravity="center"
|
|
||||||
android:textSize="24sp"
|
|
||||||
app:layout_constraintRight_toLeftOf="@id/btn_list"
|
|
||||||
app:layout_constraintLeft_toRightOf="@id/btn_home"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:id="@+id/btn_list"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="centerInside"
|
|
||||||
android:src="@drawable/bookmark"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintLeft_toRightOf="@id/textview_title"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/btn_history"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<!-- <androidx.constraintlayout.utils.widget.ImageFilterButton-->
|
|
||||||
<!-- android:id="@+id/btn_rotate"-->
|
|
||||||
<!-- android:layout_width="wrap_content"-->
|
|
||||||
<!-- android:layout_height="@dimen/main_top_height"-->
|
|
||||||
<!-- android:adjustViewBounds="true"-->
|
|
||||||
<!-- android:scaleType="centerInside"-->
|
|
||||||
<!-- android:visibility="gone"-->
|
|
||||||
<!-- android:src="@drawable/rotation"-->
|
|
||||||
<!-- android:background="#8FFF"-->
|
|
||||||
<!-- app:layout_constraintTop_toTopOf="parent"-->
|
|
||||||
<!-- app:layout_constraintLeft_toRightOf="@id/btn_list"-->
|
|
||||||
<!-- app:layout_constraintRight_toLeftOf="@+id/btn_history"-->
|
|
||||||
<!-- app:layout_constraintHorizontal_chainStyle="spread_inside"-->
|
|
||||||
<!-- />-->
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:id="@+id/btn_history"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:src="@drawable/saved"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread_inside"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:id="@+id/btn_left"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:tag="1"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
|
|
||||||
android:text="@string/display_the_second_screen"
|
|
||||||
android:visibility="visible"
|
|
||||||
android:src="@drawable/angle_left"
|
|
||||||
app:layout_constraintLeft_toLeftOf="parent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:id="@+id/btn_setting"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:src="@drawable/settings"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintLeft_toRightOf="@+id/btn_left"
|
|
||||||
app:layout_constraintRight_toLeftOf="@+id/btn_right"
|
|
||||||
app:layout_constraintHorizontal_chainStyle="spread"
|
|
||||||
/>
|
|
||||||
|
|
||||||
<androidx.constraintlayout.utils.widget.ImageFilterButton
|
|
||||||
android:id="@+id/btn_right"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="@dimen/main_top_height"
|
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:tag="0"
|
|
||||||
android:background="@android:color/transparent"
|
|
||||||
android:src="@drawable/angle_right"
|
|
||||||
android:adjustViewBounds="true"
|
|
||||||
android:scaleType="fitCenter"
|
|
||||||
android:visibility="visible"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintRight_toRightOf="parent"
|
|
||||||
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="gone"
|
|
||||||
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
|
|
||||||
android:id="@+id/progress"
|
|
||||||
android:layout_width="0dp"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
android:layout_gravity="center"
|
|
||||||
android:layout_marginTop="48dp"
|
|
||||||
android:indeterminate="false"
|
|
||||||
android:max="100"
|
|
||||||
android:progressBackgroundTint="#FBE7C6"
|
|
||||||
android:progressDrawable="@drawable/circle_progressbar"
|
|
||||||
android:progressTint="#edbf41"
|
|
||||||
android:visibility="gone"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
||||||
</layout>
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user