diff --git a/app/build.gradle b/app/build.gradle index af5e468..045bacd 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -52,7 +52,7 @@ dependencies { implementation 'com.google.android.material:material:1.8.0' implementation 'com.google.code.gson:gson:2.10.1' - implementation files('libs/DualScreen.jar') +// implementation files('libs/DualScreen.jar') implementation 'io.realm.kotlin:library-base:1.6.0' diff --git a/app/src/main/java/com/mime/dualscreenview/activity/Intro.kt b/app/src/main/java/com/mime/dualscreenview/activity/Intro.kt index 62fb0e8..d1c9244 100644 --- a/app/src/main/java/com/mime/dualscreenview/activity/Intro.kt +++ b/app/src/main/java/com/mime/dualscreenview/activity/Intro.kt @@ -1,13 +1,9 @@ package com.mime.dualscreenview.activity -import android.app.ActivityOptions -import android.content.Context import android.content.DialogInterface -import android.content.Intent import android.content.pm.ActivityInfo import android.content.res.Configuration -import android.graphics.Color -import android.hardware.display.DisplayManager +import android.graphics.Bitmap import android.net.Uri import android.os.Build import android.os.Bundle @@ -18,13 +14,14 @@ import android.util.Log import android.view.KeyEvent import android.view.View import android.view.View.* +import android.webkit.WebSettings import android.webkit.WebView +import android.webkit.WebViewClient import android.widget.ArrayAdapter import android.widget.EditText import android.widget.ImageButton import android.widget.ProgressBar import android.widget.TextView -import android.widget.Toast import androidx.annotation.RequiresApi import androidx.appcompat.app.AlertDialog import androidx.appcompat.widget.AppCompatButton @@ -49,16 +46,14 @@ import com.mime.dualscreenview.view.TouchArea import com.mime.dualscreenview.webcontents.BaseWebContentsViewer import com.mime.dualscreenview.webcontents.MainControllInterface import com.mime.dualscreenview.webcontents.contentsinfo.Agit -import com.mime.dualscreenview.webcontents.contentsinfo.Booktoki import com.mime.dualscreenview.webcontents.contentsinfo.GotoSomeWhere -import io.realm.kotlin.Realm import io.realm.kotlin.UpdatePolicy import io.realm.kotlin.ext.copyFromRealm import io.realm.kotlin.ext.query -import io.realm.kotlin.query.find import java.lang.System.currentTimeMillis import java.text.SimpleDateFormat import java.util.Date +import kotlin.random.Random class Intro : Base() , MainControllInterface, PagedTextViewInterface { @@ -72,6 +67,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { var lastInfo : LastInfo? = null lateinit var paged_layer : PagedTextLayout lateinit var textview_title : TextView + var currentBooinfo : BookPageInfo? = null val handle = object : Handler() { override fun handleMessage(msg: Message) { // super.handleMessage(msg) @@ -79,7 +75,6 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { (msg.obj as? ReaderConfig)?.let { } - } } } @@ -89,12 +84,19 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { Blog.LOGD(log= "onConfigurationChanged ${this::class.java.name} >> newConfig ${newConfig}") mBaseWebContentsViewer.webview.reload() } + + var contentsSaver : WebView? = null override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) Blog.LOGD(log= "onCreate ${this::class.java.name} >> savedInstanceState ${savedInstanceState}") setContentView(R.layout.intro) - - mBaseWebContentsViewer = BaseWebContentsViewer(findViewById(R.id.menu_web),this) + findViewById(R.id.menu_web)?.let { + it.setOnLongClickListener { + onTouch(TouchArea.Center) + return@setOnLongClickListener false + } + mBaseWebContentsViewer = BaseWebContentsViewer(it,this) + } paged_layer =findViewById(R.id.paged_layer) textview_title =findViewById(R.id.textview_title) @@ -108,6 +110,19 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { } } } + findViewById(R.id.hidden_web)?.let { v-> + contentsSaver = v + contentsSaver?.webViewClient = saveClient + 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(R.id.btn_rotate).setOnClickListener { v-> switcvhOrient() @@ -178,7 +193,9 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { realm.close() infos?.let { Blog.LOGE("onBookInfos" , "onBookInfos it >> ${it}") - showList(it) + runOnUiThread { + showList(it) + } } @@ -276,15 +293,115 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { } fun showList(infos: BookPageInfos) { - DefaultList.showDefaultList(this@Intro,"현제는 ${currentTitle} - ${currentChapter} -> 다른화를 골라",infos.getTitleArray().reversed(),currentChapter, { position -> - return@showDefaultList infos.pages?.get(position)?.chapterTitle ?: "" - },{position -> - infos.pages?.reversed()?.get(position)?.let{moveTo(it)} - }) + if (infos != null) { + DefaultList.showDefaultList( + this@Intro, + "현제는 ${currentTitle} - ${(infos.pages.size ?: 0) - currentChapter} -> 다른화를 골라", + infos.getTitleArray(), + currentChapter, + { position -> + return@showDefaultList infos.pages?.get(position)?.chapterTitle ?: "" + }, + { position -> + infos.pages?.get(position)?.let { moveTo(it) } + }, { state -> + if (state < 0 ) { + saveItem(infos) + } + }) + } + } + var isLoading = false + var saveClient = object : WebViewClient() { + override fun onPageStarted(view: WebView?, url: String?, favicon: Bitmap?) { + super.onPageStarted(view, url, favicon) + isLoading = true + Blog.LOGE("saveClient >>> ${isLoading} ${url}") + } + override fun onPageFinished(webView: WebView?, url: String?) { + super.onPageFinished(webView, url) + isLoading = false + var ramdomTimeSec = 1000L + Random(System.currentTimeMillis()).nextLong().rem(1999) + Blog.LOGE("ramdomTime >>> ${ramdomTimeSec}") + webView?.postDelayed( { + Blog.LOGE("saveClient >>> ${isLoading} ${url}") + var findContents = Agit.getFindContentsJs() + Blog.LOGE("saveClient find >>> ${findContents}") + Random(System.currentTimeMillis()).nextLong().rem(999) + webView?.evaluateJavascript(findContents){ result: String? -> + Blog.LOGE("saveClient result >>> ${result}") + result?.let { string: String -> + Blog.LOGE("saveClient contents >>> ${string}") + if (string.length > 10) { + Blog.LOGE("saveClient it.length >>> ${string.length}") + var contents = string.replace("\\\"", "\"") + contents = + (contents.replace("\\n", System.getProperty("line.separator"))) + Blog.LOGE("saveClient contents >>> ${contents}") + Uri.parse(url)?.let { + it.path?.let { + HistoryManager.getBooPageInfo(it) { + HistoryManager.openRealm().apply { + this.writeBlocking { + it?.contents = contents + if (it != null) { + copyToRealm(it, UpdatePolicy.ALL) + } + } + }.close() + } + } + } + } + var ramdomTime = 10000L + Random(System.currentTimeMillis()).nextLong().rem(3999) + Blog.LOGE("ramdomTime >>> ${ramdomTime}") + contentsSaver?.postDelayed( { saveItem(null) }, ramdomTime) + } + }},ramdomTimeSec) + } + } + + var saveTarget : ArrayList = arrayListOf() + private fun saveItem(infos: BookPageInfos?) { + Blog.LOGE("saveItem >>> infos?.pages ${infos?.pages?.size ?: 0}") + var savedCount = Random(System.currentTimeMillis()).nextLong().rem(19) + 6L + infos?.pages?.reversed()?.forEach { + if (it.contents?.length ?: 0 > 10) { + } else { + if (saveTarget.size < savedCount.toInt()) { + saveTarget.add(it) + } + } + } + + Blog.LOGE("saveItem >>> saveTarget ${saveTarget.count()}") + if (isLoading == false) { + 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 { @@ -324,15 +441,20 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { } } - fun actionNextEvent() { + 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() + paged_layer!!.doNext(fast) updateLastInfo(paged_layer!!) }else { Uri.parse(mBaseWebContentsViewer.webview.url)?.let { it.path?.let { HistoryManager.getNextPage(it) { Blog.LOGE("HistoryManager.getNextPage(${it})") + if (it?.contents?.length ?: 0 > 10) { + currentBooinfo = it + paged_layer.text = it!!.contents!! + paged_layer.visibility = VISIBLE + } if(it?.pathUrl?.length ?: 0 > 0) { HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!)) Blog.LOGE("HistoryManager.getNextPage(${it?.pathUrl})") @@ -345,6 +467,11 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { mBaseWebContentsViewer.webview.loadUrl(Agit.getLastedDoamin() + it?.pathUrl!!) paged_layer?.visibility = GONE } + it?.pathUrl?.let { + HistoryManager.getBooInfo(it) { + saveItem(it) + } + } } } } @@ -366,14 +493,20 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { } - fun actionPrevEvent() { + 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() + paged_layer!!.doPrev(fast) updateLastInfo(paged_layer!!) } else { Uri.parse(mBaseWebContentsViewer.webview.url)?.let { it.path?.let { HistoryManager.getPrevPage(it) { + if (it?.contents?.length ?: 0 > 10) { + currentBooinfo = it + paged_layer.text = it!!.contents!! + paged_layer.visibility = VISIBLE + } + if(it?.pathUrl?.length ?: 0 > 0) { HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!)) if (lastInfo?.pageUrl?.length ?: 0 > 0 && lastInfo?.pageUrl!!.startsWith("http")) { @@ -393,10 +526,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { super.onBackPressed() var layer = findViewById(R.id.paged_layer) - if (!didBackPress) { - firstBackPress() - return - } +// if (!didBackPress) { +// firstBackPress() +// return +// } if (layer != null && layer.visibility == View.VISIBLE) { didBackPress = false @@ -413,9 +546,10 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { if (!didBackPress) { firstBackPress() return + } else { + finish() + didBackPress = false } - finish() - didBackPress = false } @@ -428,6 +562,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { paged_layer.apply { if (aContents != null) { var contents = aContents.replace("\\\"","\"") + text = (contents.replace("\\n", System.getProperty("line.separator"))) visibility = VISIBLE mPagedTextViewInterface = this@Intro var realm = HistoryManager.openRealm() @@ -455,8 +590,8 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { - text = (contents.replace("\\n", System.getProperty("line.separator"))) - if(lastInfo != null && lastInfo!!.pageUrl.equals(mBaseWebContentsViewer.webview.url)) { +// text = (contents.replace("\\n", System.getProperty("line.separator"))) + if(lastInfo != null && mBaseWebContentsViewer.webview.url?.endsWith(lastInfo!!.pageUrl) ?: false) { this@Intro.findViewById(R.id.progress)?.visibility = VISIBLE paged_layer?.postDelayed({ next(lastInfo!!.pageIndex) @@ -466,16 +601,28 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { },1000) } forceUpdateUI() - HistoryManager.getBooPageInfo(mBaseWebContentsViewer.webview.url!!){ - HistoryManager.openRealm().apply { - this.writeBlocking { - it?.contents = contents - if (it != null) { - copyToRealm(it, UpdatePolicy.ALL) + mBaseWebContentsViewer.webview.url?.let { + Uri.parse(it)?.let { + it.path?.let { + HistoryManager.getBooPageInfo(it){ + currentBooinfo = it + HistoryManager.openRealm().apply { + this.writeBlocking { + it?.chapterTitle?.let { + onFindTitle(it) + } + currentChapter = it?.chapterNum ?: 0 + currentPage = it?.chapterNum ?: 0 + it?.contents = contents + if (it != null) { + copyToRealm(it, UpdatePolicy.ALL) + } + } + }.close() + HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!)) } } - }.close() - HistoryManager.save(historyItem = HistoryItem().putHistory(it,mBaseWebContentsViewer.webview.url!!)) + } } } } @@ -596,7 +743,7 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { } override fun onTouch(touchArea: TouchArea) { - Blog.LOGD(log="onTouch") + Blog.LOGD(log="onTouch ${touchArea}") when (touchArea) { TouchArea.Center-> { findViewById(R.id.btn_right).visibility = VISIBLE @@ -616,6 +763,12 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { TouchArea.Left-> { actionPrevEvent() } + TouchArea.DoubleRight -> { + actionNextEvent(true) + } + TouchArea.DoubleLeft -> { + actionPrevEvent(true) + } else -> { } @@ -626,20 +779,39 @@ class Intro : Base() , MainControllInterface, PagedTextViewInterface { override fun onLongClick() { Blog.LOGD(log="onLongClick") - if (paged_layer?.visibility == VISIBLE) { - paged_layer?.visibility = GONE + + } + 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(R.id.btn_right).visibility = VISIBLE + findViewById(R.id.btn_left).visibility = VISIBLE + findViewById(R.id.btn_setting).visibility = VISIBLE + + textview_title.visibility = VISIBLE + findViewById(R.id.btn_home).visibility = VISIBLE + findViewById(R.id.btn_list).visibility = VISIBLE + findViewById(R.id.btn_history).visibility = VISIBLE + findViewById(R.id.btn_rotate).visibility = VISIBLE + } } } - override fun onSwipeLeft() { - Blog.LOGD(log="onSwipeLeft") - actionNextEvent() - - } - - override fun onSwipeRight() { - Blog.LOGD(log="onSwipeRight") - actionPrevEvent() - } override fun onTimeoverTouch() { diff --git a/app/src/main/java/com/mime/dualscreenview/data/model/BookPageInfo.kt b/app/src/main/java/com/mime/dualscreenview/data/model/BookPageInfo.kt index 8326176..6fafb52 100644 --- a/app/src/main/java/com/mime/dualscreenview/data/model/BookPageInfo.kt +++ b/app/src/main/java/com/mime/dualscreenview/data/model/BookPageInfo.kt @@ -65,8 +65,8 @@ class BookPageInfos : RealmObject { var arrayList = ArrayList() pages?.forEach { - Blog.LOGE("chapterTitle >> ${it.chapterTitle} ") - arrayList.add(it.chapterTitle ?: "") } +// Blog.LOGE("chapterTitle >> ${it.getTitleItem()} ") + arrayList.add(it.getTitleItem())} return arrayList } @@ -85,5 +85,22 @@ class BookPageInfo : RealmObject { @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() + } } \ No newline at end of file diff --git a/app/src/main/java/com/mime/dualscreenview/dialog/DefaultList.kt b/app/src/main/java/com/mime/dualscreenview/dialog/DefaultList.kt index 63beec2..257ca76 100644 --- a/app/src/main/java/com/mime/dualscreenview/dialog/DefaultList.kt +++ b/app/src/main/java/com/mime/dualscreenview/dialog/DefaultList.kt @@ -7,20 +7,31 @@ import android.widget.ArrayAdapter import androidx.appcompat.app.AlertDialog object DefaultList { - fun showDefaultList(context: Context,title : String, items : Collection, firstPosition : Int, choosedTitle : (Int)->String, chooedPositive : (Int)->Unit) { + fun showDefaultList(context: Context,title : String, items : Collection, firstPosition : Int, choosedTitle : (Int)->String, chooedPositive : (Int)->Unit, saveCalback : (Int)->Unit ) { val builderSingle: AlertDialog.Builder = AlertDialog.Builder(context) builderSingle.setTitle(title) val arrayAdapter = ArrayAdapter(context, R.layout.select_dialog_singlechoice) arrayAdapter.addAll(items) + builderSingle.setNeutralButton("전체 저장") { dialog, which -> + saveCalback.invoke(-1) + dialog.dismiss() + } builderSingle.setNegativeButton("닫기", - DialogInterface.OnClickListener { dialog, which -> dialog.dismiss() }) + 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() diff --git a/app/src/main/java/com/mime/dualscreenview/view/OnSwipeTouchListener.kt b/app/src/main/java/com/mime/dualscreenview/view/OnSwipeTouchListener.kt index 2dea9ed..85f0f16 100644 --- a/app/src/main/java/com/mime/dualscreenview/view/OnSwipeTouchListener.kt +++ b/app/src/main/java/com/mime/dualscreenview/view/OnSwipeTouchListener.kt @@ -1,13 +1,716 @@ 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 + 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 + * + * + *

+ * + * + * 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 { @@ -21,6 +724,7 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene 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) { @@ -36,8 +740,26 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene 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) { - override fun onSingleTapUp(e: MotionEvent): Boolean { + } 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 @@ -53,16 +775,22 @@ abstract class OnSwipeTouchListener(val context: Context?) : View.OnTouchListene } } onSingleTap(touchArea) - return super.onSingleTapUp(e) + 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) diff --git a/app/src/main/java/com/mime/dualscreenview/view/PagedTextLayout.kt b/app/src/main/java/com/mime/dualscreenview/view/PagedTextLayout.kt index e0bae9e..e6a6c03 100644 --- a/app/src/main/java/com/mime/dualscreenview/view/PagedTextLayout.kt +++ b/app/src/main/java/com/mime/dualscreenview/view/PagedTextLayout.kt @@ -53,46 +53,120 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { 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(object : OnSwipeTouchListener(context) { - override fun onSwipeUp() { + 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 onSwipeDown() { - mPagedTextViewInterface?.onLongClick() + override fun onDoubleTap(fingers: Int): Boolean { + hanler.removeCallbacks(touchTimeover) + mPagedTextViewInterface?.onTouch(TouchArea.Center) + hanler?.postDelayed(touchTimeover, 3000L) + return false } - 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 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) { @@ -168,6 +242,10 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { 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() @@ -178,13 +256,26 @@ class PagedTextLayout : ConstraintLayout , PagedTextGenerateInterface { } 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() { - setPageBy(currentPage.inc()) + fun doNext(fast : Boolean = false) { + if (fast) { + setPageBy(if((currentPage + getFastPageCount()) >= 0) { + currentPage + getFastPageCount() + } else {size()}) + } else { + setPageBy(currentPage.inc()) + } } - fun doPrev() { - setPageBy(currentPage.dec()) + 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() { diff --git a/app/src/main/java/com/mime/dualscreenview/view/PagedTextViewInterface.kt b/app/src/main/java/com/mime/dualscreenview/view/PagedTextViewInterface.kt index 9b661f3..42dc26b 100644 --- a/app/src/main/java/com/mime/dualscreenview/view/PagedTextViewInterface.kt +++ b/app/src/main/java/com/mime/dualscreenview/view/PagedTextViewInterface.kt @@ -3,7 +3,9 @@ package com.mime.dualscreenview.view interface PagedTextViewInterface { fun onTouch(touchArea: TouchArea) fun onTimeoverTouch() - fun onSwipeLeft() - fun onSwipeRight() + fun onSwipeLeft(touchCount : Int) + fun onSwipeRight(touchCount : Int) + fun onSwipeDown(touchCount : Int) + fun onSwipeUp(touchCount : Int) fun onLongClick() } \ No newline at end of file diff --git a/app/src/main/java/com/mime/dualscreenview/webcontents/BaseWebContentsViewer.kt b/app/src/main/java/com/mime/dualscreenview/webcontents/BaseWebContentsViewer.kt index 200ce74..e72c466 100644 --- a/app/src/main/java/com/mime/dualscreenview/webcontents/BaseWebContentsViewer.kt +++ b/app/src/main/java/com/mime/dualscreenview/webcontents/BaseWebContentsViewer.kt @@ -6,6 +6,7 @@ import android.net.http.SslError import android.util.Log import android.webkit.* import com.mime.dualscreenview.common.Blog +import com.mime.dualscreenview.data.HistoryManager import com.mime.dualscreenview.data.model.LastInfo import com.mime.dualscreenview.webcontents.contentsinfo.DidFindContents import kotlinx.coroutines.GlobalScope @@ -72,9 +73,19 @@ open class BaseWebContentsViewer { } fun loadLastInfo(lastInfo: LastInfo) { - lastInfo?.let { - currentContentsProvider = WebContentsManger.getBaseWebContentsBy(it.contentsName) - webview.loadUrl(it.pageUrl) + lastInfo?.let { last -> + currentContentsProvider = WebContentsManger.getBaseWebContentsBy(last.contentsName) +// HistoryManager.getBooPageInfo(last.pageUrl,{ page -> +// if(page != null){ +// if(page.contents?.length ?: 0 > 0) { +// mainControllInterface?.onLoadedContents(page.contents!!) +// } else { +// webview.loadUrl(last.pageUrl) +// } +// } else { + webview.loadUrl(last.pageUrl) +// } +// }) } } diff --git a/app/src/main/java/com/mime/dualscreenview/webcontents/contentsinfo/Agit.kt b/app/src/main/java/com/mime/dualscreenview/webcontents/contentsinfo/Agit.kt index 30c93c6..5e93a6b 100644 --- a/app/src/main/java/com/mime/dualscreenview/webcontents/contentsinfo/Agit.kt +++ b/app/src/main/java/com/mime/dualscreenview/webcontents/contentsinfo/Agit.kt @@ -117,7 +117,7 @@ object Agit : BaseWebContents() { } override fun getFindContentsJs(): String { - return "document.getElementById(\"id_wr_content\") != null ? document.getElementById(\"id_wr_content\").innerText : null" + return "document.getElementById('id_wr_content') != null ? document.getElementById('id_wr_content').innerText : null" } override fun checkCorrectContents(contents: String): String { diff --git a/app/src/main/res/layout/intro.xml b/app/src/main/res/layout/intro.xml index 09acd97..bc6c1c6 100644 --- a/app/src/main/res/layout/intro.xml +++ b/app/src/main/res/layout/intro.xml @@ -7,6 +7,15 @@ android:layout_height="match_parent" tools:context=".activity.Intro"> + + \ No newline at end of file diff --git a/app/src/main/res/layout/layout_textviewer.xml b/app/src/main/res/layout/layout_textviewer.xml index 86e04df..7ed74c3 100644 --- a/app/src/main/res/layout/layout_textviewer.xml +++ b/app/src/main/res/layout/layout_textviewer.xml @@ -7,7 +7,7 @@ xmlns:app="http://schemas.android.com/apk/res-auto"> - - + \ No newline at end of file diff --git a/gradlew b/gradlew index 1b6c787..1aa94a4 100755 --- a/gradlew +++ b/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,13 +80,11 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} - -# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' +# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036) +APP_HOME=$( cd "${APP_HOME:-./}" > /dev/null && pwd -P ) || exit # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD=maximum @@ -133,22 +131,29 @@ location of your Java installation." fi else JAVACMD=java - which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. + if ! command -v java >/dev/null 2>&1 + then + die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. Please set the JAVA_HOME variable in your environment to match the location of your Java installation." + fi fi # Increase the maximum file descriptors if we can. if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC2039,SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac @@ -193,11 +198,15 @@ if "$cygwin" || "$msys" ; then done fi -# Collect all arguments for the java command; -# * $DEFAULT_JVM_OPTS, $JAVA_OPTS, and $GRADLE_OPTS can contain fragments of -# shell script including quotes and variable substitutions, so put them in -# double quotes to make sure that they get re-expanded; and -# * put everything else in single quotes, so that it's not re-expanded. + +# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' + +# Collect all arguments for the java command: +# * DEFAULT_JVM_OPTS, JAVA_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments, +# and any embedded shellness will be escaped. +# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be +# treated as '${Hostname}' itself on the command line. set -- \ "-Dorg.gradle.appname=$APP_BASE_NAME" \ @@ -205,6 +214,12 @@ set -- \ org.gradle.wrapper.GradleWrapperMain \ "$@" +# Stop when "xargs" is not available. +if ! command -v xargs >/dev/null 2>&1 +then + die "xargs is not available" +fi + # Use "xargs" to parse quoted args. # # With -n1 it outputs one arg per line, with the quotes and backslashes removed. diff --git a/gradlew.bat b/gradlew.bat index ac1b06f..6689b85 100644 --- a/gradlew.bat +++ b/gradlew.bat @@ -14,7 +14,7 @@ @rem limitations under the License. @rem -@if "%DEBUG%" == "" @echo off +@if "%DEBUG%"=="" @echo off @rem ########################################################################## @rem @rem Gradle startup script for Windows @@ -25,7 +25,8 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 -if "%DIRNAME%" == "" set DIRNAME=. +if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% @@ -40,7 +41,7 @@ if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto execute +if %ERRORLEVEL% equ 0 goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -75,13 +76,15 @@ set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar :end @rem End local scope for the variables with windows NT shell -if "%ERRORLEVEL%"=="0" goto mainEnd +if %ERRORLEVEL% equ 0 goto mainEnd :fail rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem the _cmd.exe /c_ return code! -if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 -exit /b 1 +set EXIT_CODE=%ERRORLEVEL% +if %EXIT_CODE% equ 0 set EXIT_CODE=1 +if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE% +exit /b %EXIT_CODE% :mainEnd if "%OS%"=="Windows_NT" endlocal diff --git a/settings.gradle b/settings.gradle index 27f5736..1f15064 100644 --- a/settings.gradle +++ b/settings.gradle @@ -12,5 +12,5 @@ dependencyResolutionManagement { mavenCentral() } } -rootProject.name = "DualScreenView" +rootProject.name = "Bum's App" include ':app'