ReaderActivity.kt 52 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182
  1. package com.kdanmobile.reader
  2. import android.annotation.SuppressLint
  3. import android.app.Activity
  4. import android.app.Dialog
  5. import android.arch.lifecycle.Observer
  6. import android.arch.lifecycle.ViewModelProviders
  7. import android.content.Intent
  8. import android.net.Uri
  9. import android.os.Build
  10. import android.os.Bundle
  11. import android.support.constraint.ConstraintLayout
  12. import android.support.constraint.ConstraintSet
  13. import android.support.design.widget.Snackbar
  14. import android.support.v4.content.ContextCompat
  15. import android.support.v7.app.AlertDialog
  16. import android.support.v7.app.AppCompatActivity
  17. import android.util.DisplayMetrics
  18. import android.view.*
  19. import android.view.animation.AnimationUtils
  20. import android.widget.EditText
  21. import android.widget.LinearLayout
  22. import android.widget.TextView
  23. import android.widget.Toast
  24. import com.kdanmobile.kmpdfkit.globaldata.KMPDFAnnotEditMode
  25. import com.kdanmobile.kmpdfkit.pdfcommon.KMPDFReaderView
  26. import com.kdanmobile.kmpdfkit.pdfcommon.PDFInfo
  27. import com.kdanmobile.reader.Utils.applyConstraintSet
  28. import com.kdanmobile.reader.annotationattribute.AnnotationAttribute
  29. import com.kdanmobile.reader.annotationattribute.AnnotationColor
  30. import com.kdanmobile.reader.annotationattribute.InkAttribute
  31. import com.kdanmobile.reader.password.DialogPasswordActivity
  32. import com.kdanmobile.reader.screen.contextmenu.TextBoxContextMenuActionListener
  33. import com.kdanmobile.reader.screen.model.SharePrefsModel
  34. import com.kdanmobile.reader.screen.reader.mediabox.MediaBoxView
  35. import com.kdanmobile.reader.screen.reader.mediabox.shape.ShapeTabView
  36. import com.kdanmobile.reader.screen.reader.mediabox.signature.SignatureTabView
  37. import com.kdanmobile.reader.screen.reader.mediabox.stamp.StampTabView
  38. import com.kdanmobile.reader.screen.reader.mediabox.textbox.TextBoxTabView
  39. import com.kdanmobile.reader.screen.view.*
  40. import com.kdanmobile.reader.setting.ReaderSettingDialogFragment
  41. import com.kdanmobile.reader.setting.ReaderSettingListener
  42. import com.kdanmobile.reader.thumb.FileUtil
  43. import com.kdanmobile.reader.thumb.PdfThumbDialogFragment
  44. import com.kdanmobile.reader.thumb.PdfThumbFragmentListener
  45. import com.kdanmobile.reader.utils.AnimationUtil
  46. import com.kdanmobile.reader.utils.DensityUtil
  47. import com.kdanmobile.reader.utils.UriToPathUtil
  48. import com.kdanmobile.reader.view.AnnotationAttributeView
  49. import com.kdanmobile.reader.view.AnnotationAttributeWindow
  50. import kotlinx.android.synthetic.main.activity_reader.*
  51. import java.io.File
  52. import java.util.*
  53. import kotlin.properties.Delegates
  54. abstract class ReaderActivity : AppCompatActivity(), ReaderSettingListener, PdfThumbFragmentListener {
  55. /**
  56. * If return true, ReaderActivity.onBackPressed will not run
  57. */
  58. abstract fun onBackPressedWhenNothingCanClose(): Boolean
  59. abstract fun onClickShare()
  60. abstract fun onClickKdanCloud()
  61. abstract fun onClickTextReflow()
  62. abstract fun onClickFileInfo()
  63. abstract fun onClickIBonPrint()
  64. abstract fun onClickPrint()
  65. abstract fun onClickUserGuide()
  66. abstract fun provideReaderSettingDialogFragment(): ReaderSettingDialogFragment
  67. abstract fun providePdfThumbDialogFragment(): PdfThumbDialogFragment
  68. abstract fun getKdanPdfReaderFolder(): File
  69. abstract fun isIBonPrintEnabled(): Boolean
  70. open fun isBottomBarKdanCloudBtnVisible(): Boolean { return true }
  71. open fun insertToRecentDocumentList(filename: String) {}
  72. open fun saveCurrentPageIndex(filename: String, currentPage: Int) {}
  73. open fun loadCurrentPageIndex(filename: String, defaultValue: Int): Int = 0
  74. open fun onOpenedFile() { /* do nothing */ }
  75. companion object {
  76. const val KEY_FILE_ABSOLUTE = "file_absolutepath"
  77. const val REQUEST_PASSWORD = 222
  78. }
  79. protected val file: File?
  80. get() {
  81. return viewModel.file
  82. }
  83. protected var filePath: String? = null
  84. private set
  85. protected val pdfInfo: PDFInfo?
  86. get() {
  87. return viewModel.pdfInfo
  88. }
  89. protected val isPasswordProtected: Boolean
  90. get() {
  91. return viewModel.isPasswordProtected
  92. }
  93. protected val currentPageIndex: Int
  94. get() {
  95. return viewModel.pdfInfoHandler.getCurrentPage()
  96. }
  97. protected val pageCount: Int
  98. get() {
  99. return viewModel.pdfInfoHandler.getPdfPageCount()
  100. }
  101. protected val password: String
  102. get() {
  103. return viewModel.password
  104. }
  105. protected val readerModel: ReaderModel
  106. get() {
  107. return viewModel.readerModel
  108. }
  109. private lateinit var viewModel: ReaderViewModel
  110. private var isShowPasswordActivity = false
  111. // For hide/show toolbars
  112. private var isHideToolbar = false
  113. private lateinit var originConstraintSet: ConstraintSet
  114. private var menuItemBookmark: MenuItem? = null
  115. private val UI_ANIMATION_DURATION = 300L
  116. private val FRAGMENT_READER_SETTING_TAG = "ReaderSetting"
  117. private val FRAGMENT_PDF_THUMB_TAG = "PdfThumb"
  118. private var w_318: Int = 0
  119. private var w_240: Int = 0
  120. private var w_left: Int = 0
  121. private var oldLeftToolbarType = ReaderViewModel.LeftToolbarType.NONE
  122. private var snackbarMediaBox: Snackbar? = null
  123. private var fileCannotOpenDialog: AlertDialog? = null
  124. private var isHidePdfPage: Boolean by Delegates.observable(false) { property, oldValue, newValue ->
  125. if (newValue == oldValue) return@observable
  126. // println("${property.name} changed from $oldValue to $newValue")
  127. tv_readerActivity_pdfPage.clearAnimation()
  128. when (newValue) {
  129. true -> tv_readerActivity_pdfPage.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_out))
  130. false -> tv_readerActivity_pdfPage.startAnimation(AnimationUtils.loadAnimation(this, R.anim.fade_in))
  131. }
  132. }
  133. override fun onCreate(savedInstanceState: Bundle?) {
  134. super.onCreate(savedInstanceState)
  135. window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  136. setContentView(R.layout.activity_reader)
  137. setSupportActionBar(toolbar_readerActivity)
  138. isShowPasswordActivity = savedInstanceState?.getBoolean("isShowPasswordActivity") ?: false
  139. filePath = savedInstanceState?.getString("filePath")
  140. val copyFile = intent.getBooleanExtra("copyFile", true)
  141. val displayMetrics = DisplayMetrics()
  142. windowManager.defaultDisplay.getMetrics(displayMetrics)
  143. val width = Math.min(DensityUtil.getScreenWidthPx(baseContext), DensityUtil.getScreenHeightPx(baseContext))
  144. w_318 = 318 * width / 800
  145. w_240 = 240 * width / 800
  146. w_left = resources.getDimension(R.dimen.reader_left_right_toolbar_icon_width).toInt()
  147. cloneOriginConstraintSet()
  148. setupToolbar()
  149. setupRightSideToolbar()
  150. setupMediaBoxView()
  151. FileUtil.init(getKdanPdfReaderFolder())
  152. val factory = ReaderViewModelFactory()
  153. viewModel = ViewModelProviders.of(this, factory).get(ReaderViewModel::class.java)
  154. viewModel.isOpenedFileLiveData.observe(this, Observer(this::onIsOpenedFileUpdate))
  155. viewModel.fileNameLiveData.observe(this, Observer { supportActionBar?.title = it })
  156. viewModel.annotationModeLiveData.observe(this, Observer(this::onAnnotationModeUpdate))
  157. viewModel.annotationEitModeLiveData.observe(this, Observer(this::onAnnotationEditModeUpdate))
  158. viewModel.isCopyModeLiveData.observe(this, Observer (this::onIsCopyModeUpdate))
  159. viewModel.highLightAttributeLiveData.observe(this, Observer(this::onHighlightAttributeUpdate))
  160. viewModel.strikeAttributeLiveData.observe(this, Observer(this::onStrikeAttributeUpdate))
  161. viewModel.underLineAttributeLiveData.observe(this, Observer(this::onUnderlineAttributeUpdate))
  162. viewModel.inkAttributeLiveData.observe(this, Observer(this::onInkAttributeUpdate))
  163. viewModel.isOpenedFileLiveData.value?.also { isOpened ->
  164. val hasOpened = null != filePath
  165. if (isShowPasswordActivity) return@also
  166. if (isOpened) return@also
  167. filePath = if (intent.action == Intent.ACTION_VIEW) {
  168. UriToPathUtil.getInstance().getPath(applicationContext, intent.data)
  169. } else {
  170. intent.getStringExtra(KEY_FILE_ABSOLUTE)
  171. }
  172. if (!hasOpened) {
  173. val copyMode = if (copyFile) FileUtil.CopyMode.CREATE_NEW_FILE else FileUtil.CopyMode.DO_NOTHING
  174. if (!filePath.isNullOrEmpty()) {
  175. filePath = FileUtil.copyFileToKdanPdfReaderFolder(filePath as String, copyMode)
  176. } else if (intent.action == Intent.ACTION_VIEW && null != intent.data) {
  177. filePath = FileUtil.saveFileToKdanPdfReaderFolder(this, intent.data!!, copyMode)
  178. }
  179. if (!filePath.isNullOrEmpty()) {
  180. insertToRecentDocumentList(filePath as String)
  181. }
  182. }
  183. if (filePath.isNullOrEmpty()) {
  184. showFileCannotOpenDialog(getString(R.string.cannot_open_buffer))
  185. } else {
  186. val result = viewModel.openPdfFile(this@ReaderActivity, Uri.parse(filePath), password, Runnable { requestPassword() }, intent.type)
  187. if (result == ReaderViewModel.OpenFileResult.FAILED) {
  188. showFileCannotOpenDialog(getString(R.string.cannot_open_file_Path, filePath))
  189. }
  190. }
  191. }
  192. setupLeftToolbar()
  193. setupRightToolbar()
  194. setupBottomToolbar()
  195. viewModel.pageIndexLiveData.observe(this, Observer(this::onPageIndexChanged))
  196. viewModel.isPageInBookmarksLiveData.observe(this, Observer(this::onIsPageInBookmarksChanged))
  197. viewModel.isLeftToolbarOpenLiveData.observe(this, Observer(this::onLeftToolbarOpenStateChanged))
  198. viewModel.leftToolbarTypeLiveData.observe(this, Observer(this::onLeftToolbarTypeChanged))
  199. isHidePdfPage = true
  200. applySetting()
  201. setupPdfChangedListener()
  202. }
  203. private fun showFileCannotOpenDialog(title: String) {
  204. fileCannotOpenDialog = AlertDialog.Builder(this)
  205. .setTitle(title)
  206. .setCancelable(false)
  207. .setPositiveButton(getString(android.R.string.ok)) { dialog, which ->
  208. finish()
  209. }
  210. .create()
  211. fileCannotOpenDialog?.show()
  212. }
  213. override fun onDestroy() {
  214. fileCannotOpenDialog?.dismiss()
  215. super.onDestroy()
  216. }
  217. override fun onSaveInstanceState(outState: Bundle?) {
  218. super.onSaveInstanceState(outState)
  219. outState?.putBoolean("isShowPasswordActivity", isShowPasswordActivity)
  220. outState?.putString("filePath", filePath)
  221. }
  222. private fun requestPassword(isIncorrectPassword: Boolean = false) {
  223. isShowPasswordActivity = true
  224. val intent = Intent(baseContext, DialogPasswordActivity::class.java)
  225. val bundle = Bundle()
  226. bundle.putBoolean("isIncorrectPassword", isIncorrectPassword)
  227. intent.putExtras(bundle)
  228. startActivityForResult(intent, REQUEST_PASSWORD)
  229. }
  230. fun isPdf(): Boolean {
  231. var isPdf = filePath?.toLowerCase(Locale.US)?.endsWith(".pdf") ?: false
  232. // TODO this workaround should be removed in the future
  233. // workaround: password-protected pdf is not editable
  234. isPdf = isPdf && !isPasswordProtected
  235. return isPdf
  236. }
  237. final override fun onBackPressed() {
  238. when {
  239. mediaBoxView.isShown -> mediaBoxView.dismiss()
  240. onBackPressedWhenNothingCanClose() -> { /** do nothing **/ }
  241. else -> super.onBackPressed()
  242. }
  243. }
  244. override fun onCreateOptionsMenu(menu: Menu?): Boolean {
  245. menuInflater.inflate(R.menu.reader_more, menu)
  246. menuItemBookmark = menu?.findItem(R.id.item_reader_bookmark)
  247. onIsPageInBookmarksChanged(viewModel.isPageInBookmarksLiveData.value)
  248. if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
  249. menu?.findItem(R.id.item_reader_more_print)?.isVisible = false
  250. }
  251. if (!isPdf()) {
  252. menu?.apply {
  253. findItem(R.id.item_reader_more_text_reflow)?.isVisible = false
  254. findItem(R.id.item_reader_more_clear_signature)?.isVisible = false
  255. findItem(R.id.item_reader_more_file_info)?.isVisible = false
  256. findItem(R.id.item_reader_more_print)?.isVisible = false
  257. findItem(R.id.item_ibon_print)?.isVisible = false
  258. }
  259. menuItemBookmark?.isVisible = false
  260. }
  261. if (!isIBonPrintEnabled()) {
  262. menu?.findItem(R.id.item_ibon_print)?.isVisible = false
  263. }
  264. return true
  265. }
  266. @SuppressLint("RestrictedApi")
  267. override fun onPrepareOptionsPanel(view: View?, menu: Menu?): Boolean {
  268. /** Force show action menu item icon **/
  269. menu?.also {
  270. if ("MenuBuilder" != it::javaClass.get().simpleName) return@also
  271. try {
  272. val method = it.javaClass.getDeclaredMethod("setOptionalIconsVisible", java.lang.Boolean.TYPE)
  273. method.isAccessible = true
  274. method.invoke(it, true)
  275. } catch (e: Exception) {
  276. // Do nothing
  277. }
  278. }
  279. return super.onPrepareOptionsPanel(view, menu)
  280. }
  281. protected fun getPageText(pageIndex: Int) = viewModel.getPageText(pageIndex)
  282. private fun cloneOriginConstraintSet() {
  283. if (!isBelowKitkat()) {
  284. originConstraintSet = ConstraintSet().apply {
  285. clone(constrainLayout_readerActivity_root)
  286. }
  287. }
  288. }
  289. private fun onIsCopyModeUpdate(isCopyMode: Boolean?) {
  290. if (isCopyMode == null) return
  291. when (isCopyMode) {
  292. true -> hideTopLeftBottomToolbars()
  293. false -> showAllToolbars()
  294. }
  295. }
  296. private fun onHighlightAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  297. if (annotationAttribute == null) return
  298. view_readerActivity_highLightStroke.setBackgroundColor(annotationAttribute.color)
  299. }
  300. private fun onStrikeAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  301. if (annotationAttribute == null) return
  302. view_readerActivity_strikeStroke.setBackgroundColor(annotationAttribute.color)
  303. }
  304. private fun onUnderlineAttributeUpdate(annotationAttribute: AnnotationAttribute?) {
  305. if (annotationAttribute == null) return
  306. view_readerActivity_underlineStroke.setBackgroundColor(annotationAttribute.color)
  307. }
  308. private fun onInkAttributeUpdate(inkAttribute: InkAttribute?) {
  309. if (inkAttribute == null) return
  310. val color = inkAttribute.color
  311. AnnotationColor.values().forEach {
  312. if (ContextCompat.getColor(this, it.colorResId) == color) {
  313. val drawableResId = when (it) {
  314. AnnotationColor.Color1 -> R.drawable.ic_reader_right_toolbar_ink_color1
  315. AnnotationColor.Color2 -> R.drawable.ic_reader_right_toolbar_ink_color2
  316. AnnotationColor.Color3 -> R.drawable.ic_reader_right_toolbar_ink_color3
  317. AnnotationColor.Color4 -> R.drawable.ic_reader_right_toolbar_ink_color4
  318. AnnotationColor.Color5 -> R.drawable.ic_reader_right_toolbar_ink_color5
  319. AnnotationColor.Color6 -> R.drawable.ic_reader_right_toolbar_ink_color6
  320. AnnotationColor.Color7 -> R.drawable.ic_reader_right_toolbar_ink_color7
  321. AnnotationColor.Color8 -> R.drawable.ic_reader_right_toolbar_ink_color8
  322. AnnotationColor.Color9 -> R.drawable.ic_reader_right_toolbar_ink_color9
  323. AnnotationColor.Color10 -> R.drawable.ic_reader_right_toolbar_ink_color10
  324. }
  325. iv_readerActivity_ink.setImageResource(drawableResId)
  326. return
  327. }
  328. }
  329. }
  330. private fun onAnnotationModeUpdate(annotationMode: ReaderViewModel.AnnotationMode?) {
  331. if (annotationMode == null) return
  332. if (viewModel.isCrop) return
  333. val map = HashMap<ReaderViewModel.AnnotationMode, View>().apply {
  334. put(ReaderViewModel.AnnotationMode.Highlight, iv_readerActivity_highLight)
  335. put(ReaderViewModel.AnnotationMode.Strike, iv_readerActivity_strike)
  336. put(ReaderViewModel.AnnotationMode.Underline, iv_readerActivity_underline)
  337. put(ReaderViewModel.AnnotationMode.Ink, iv_readerActivity_ink)
  338. }
  339. map.forEach {
  340. if (it.key == annotationMode) {
  341. val color = ContextCompat.getColor(this, R.color.reader_right_toolbar_selected_bg)
  342. it.value.setBackgroundColor(color)
  343. } else {
  344. it.value.setBackgroundDrawable(null)
  345. }
  346. }
  347. when (annotationMode == ReaderViewModel.AnnotationMode.None) {
  348. true -> showAllToolbars()
  349. false -> hideTopLeftBottomToolbars()
  350. }
  351. readerModel.onPdfChangedListener?.onPageUpdated(arrayListOf(currentPageIndex))
  352. }
  353. private fun onAnnotationEditModeUpdate(mode: KMPDFAnnotEditMode.Mode?) {
  354. when (mode) {
  355. KMPDFAnnotEditMode.Mode.NULL -> {
  356. showAllToolbars()
  357. isHideToolbar = false
  358. snackbarMediaBox?.dismiss()
  359. snackbarMediaBox = null
  360. }
  361. KMPDFAnnotEditMode.Mode.SIGN_MODIFY -> {
  362. hideAllToolbars()
  363. isHideToolbar = true
  364. }
  365. KMPDFAnnotEditMode.Mode.FREETEXT_MODIFY, KMPDFAnnotEditMode.Mode.STAMP_MODIFY, KMPDFAnnotEditMode.Mode.SHAPE_MODIFY -> {
  366. hideAllToolbars()
  367. isHideToolbar = true
  368. snackbarMediaBox?.dismiss()
  369. snackbarMediaBox = null
  370. }
  371. else -> {}
  372. }
  373. isHidePdfPage = true
  374. readerModel.onPdfChangedListener?.onPageUpdated(arrayListOf(currentPageIndex))
  375. }
  376. private fun onIsOpenedFileUpdate(isOpened: Boolean?) {
  377. if (isOpened == null) return
  378. val container = viewGroup_readerActivity_container
  379. container.removeAllViews()
  380. if (!isOpened) return
  381. val context = this
  382. val readerView = object : KMPDFReaderView(context) {
  383. @SuppressLint("ClickableViewAccessibility")
  384. override fun onTouchEvent(motionEvent: MotionEvent): Boolean {
  385. if (motionEvent.action == MotionEvent.ACTION_UP) {
  386. if (viewModel.isCopyModeLiveData.value == true) {
  387. if (viewModel.copySelection()) {
  388. val context = this@ReaderActivity
  389. Toast.makeText(context, R.string.reader_copy_text_success, Toast.LENGTH_SHORT).show()
  390. }
  391. }
  392. }
  393. return super.onTouchEvent(motionEvent)
  394. }
  395. override fun onTapMainDocArea() {
  396. super.onTapMainDocArea()
  397. when (isHideToolbar) {
  398. true -> {
  399. showAllToolbars()
  400. viewModel.clearSelection()
  401. }
  402. false -> hideAllToolbars()
  403. }
  404. isHideToolbar = !isHideToolbar
  405. }
  406. override fun onMoveToChild(pageIndex: Int) {
  407. super.onMoveToChild(pageIndex)
  408. viewModel.setPageIndex(pageIndex)
  409. }
  410. override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {
  411. val isEditMode = viewModel.annotationModeLiveData.value != ReaderViewModel.AnnotationMode.None
  412. val isCopyMode = viewModel.isCopyModeLiveData.value != false
  413. if (!isEditMode && !isCopyMode && !isHideToolbar) {
  414. hideAllToolbars()
  415. isHideToolbar = true
  416. }
  417. isHidePdfPage = isEditMode || isCopyMode
  418. return super.onScroll(e1, e2, distanceX, distanceY)
  419. }
  420. }
  421. viewModel.setReaderView(readerView)
  422. if (!filePath.isNullOrEmpty()) {
  423. val defaultValue = viewModel.pageIndexLiveData.value ?: 0
  424. val pageIndex = loadCurrentPageIndex(filePath as String, defaultValue)
  425. viewModel.pdfInfoHandler.setCurrentPage(pageIndex)
  426. viewModel.fileNameLiveData.postValue(File(filePath as String).name)
  427. }
  428. initTextBoxContextMenuActions()
  429. container.addView(readerView)
  430. val model = SharePrefsModel(this)
  431. onReadModeChanged(model.readMode.value ?: 0)
  432. if (model.isCropModeEnable.value == true) {
  433. readerView.post {
  434. onCropModeEnableChanged(true)
  435. }
  436. }
  437. onOpenedFile()
  438. }
  439. private fun initTextBoxContextMenuActions() {
  440. viewModel.setTextBoxContextMenuActions(object : TextBoxContextMenuActionListener {
  441. override fun onDelete(): Boolean {
  442. viewModel.deleteSelectedTextBox()
  443. return true
  444. }
  445. override fun onEditStyle(): Boolean {
  446. mediaBoxView.showTextBoxStyleView()
  447. viewModel.editSelectedTextBoxStyle()
  448. return true
  449. }
  450. override fun onEditText(): Boolean {
  451. hideAllToolbars()
  452. isHideToolbar = true
  453. viewModel.editSelectedTextBoxText()
  454. return true
  455. }
  456. override fun onCopy(): Boolean {
  457. viewModel.copySelectedTextBox()
  458. return true
  459. }
  460. })
  461. }
  462. override fun onStop() {
  463. viewModel.saveModifyingAnnotation()
  464. viewModel.temporarySave()
  465. if (!filePath.isNullOrEmpty()) {
  466. saveCurrentPageIndex(filePath as String, currentPageIndex)
  467. }
  468. super.onStop()
  469. }
  470. override fun onResume() {
  471. super.onResume()
  472. viewModel.restoreAnnotationEditMode()
  473. }
  474. private fun onPageIndexChanged(pageIndex: Int?) {
  475. pageIndex?.also {
  476. viewModel.setBookmarkDisplay(pageIndex)
  477. readerModel.onPdfChangedListener?.onPageSelected(pageIndex)
  478. tv_readerActivity_pdfPage.post {
  479. tv_readerActivity_pdfPage.text="${(pageIndex) + 1}/${viewModel.pdfInfoHandler.getPdfPageCount()}"
  480. }
  481. }
  482. }
  483. private fun onIsPageInBookmarksChanged(isPageInBookmarks: Boolean?) {
  484. isPageInBookmarks?.let {
  485. if (it) {
  486. menuItemBookmark?.icon = ContextCompat.getDrawable(this, R.drawable.ic_bookmark_fill)
  487. } else {
  488. menuItemBookmark?.icon = ContextCompat.getDrawable(this, R.drawable.ic_bookmark_border)
  489. }
  490. }
  491. }
  492. private fun isBelowKitkat(): Boolean {
  493. return true
  494. // return Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT
  495. }
  496. private fun showAllToolbars() {
  497. if (isBelowKitkat()) {
  498. val duration = ((1 - toolbar_readerActivity.alpha) * UI_ANIMATION_DURATION).toLong()
  499. AnimationUtil.showViewFromTopToBottom(toolbar_readerActivity, duration)
  500. AnimationUtil.showViewFromBottomToTop(viewGroup_readerActivity_bottomToolbar, duration)
  501. AnimationUtil.showViewFromLeftToRight(viewGroup_readerActivity_leftToolbar, duration)
  502. AnimationUtil.showViewFromRightToLeft(viewGroup_readerActivity_rightToolbar, duration)
  503. } else {
  504. constrainLayout_readerActivity_root.applyConstraintSet(originConstraintSet, UI_ANIMATION_DURATION)
  505. }
  506. isHidePdfPage = true
  507. }
  508. private fun hideAllToolbars() {
  509. if (isBelowKitkat()) {
  510. val duration = (toolbar_readerActivity.alpha * UI_ANIMATION_DURATION).toLong()
  511. AnimationUtil.hideViewFromBottomToTop(toolbar_readerActivity, duration)
  512. AnimationUtil.hideViewFromTopToBottom(viewGroup_readerActivity_bottomToolbar, duration)
  513. AnimationUtil.hideViewFromRightToLeft(viewGroup_readerActivity_leftToolbar, duration)
  514. AnimationUtil.hideViewFromLeftToRight(viewGroup_readerActivity_rightToolbar, duration)
  515. hideSearchViewSoftKeyboard()
  516. } else {
  517. constrainLayout_readerActivity_root.applyConstraintSet(this, R.layout.activity_reader_hide_all, UI_ANIMATION_DURATION)
  518. }
  519. }
  520. private fun hideTopLeftBottomToolbars() {
  521. if (isBelowKitkat()) {
  522. val duration = (toolbar_readerActivity.alpha * UI_ANIMATION_DURATION).toLong()
  523. AnimationUtil.hideViewFromBottomToTop(toolbar_readerActivity, duration)
  524. AnimationUtil.hideViewFromTopToBottom(viewGroup_readerActivity_bottomToolbar, duration)
  525. AnimationUtil.hideViewFromRightToLeft(viewGroup_readerActivity_leftToolbar, duration)
  526. hideSearchViewSoftKeyboard()
  527. } else {
  528. constrainLayout_readerActivity_root.applyConstraintSet(this, R.layout.activity_reader_hide_top_left_bottom, UI_ANIMATION_DURATION)
  529. }
  530. }
  531. private fun setupPdfChangedListener() {
  532. readerModel.onPdfChangedListener = object : OnPdfChangedListener {
  533. override fun onPageCreated(pages: List<Int>) {
  534. TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
  535. }
  536. override fun onPageDeleted(pages: List<Int>) {
  537. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  538. if (view is LeftToolbarView) {
  539. view.updateContent()
  540. view.onScrollToContent(currentPageIndex, true)
  541. }
  542. }
  543. override fun onPageSelected(pageIndex: Int) {
  544. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  545. if (view is LeftToolbarView) {
  546. view.onScrollToContent(currentPageIndex, true)
  547. }
  548. }
  549. override fun onPageUpdated(pages: List<Int>) {
  550. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  551. if (view is LeftToolbarView) {
  552. view.updateContent()
  553. view.onScrollToContent(currentPageIndex, true)
  554. }
  555. }
  556. }
  557. }
  558. private fun updateBookmarkView() {
  559. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  560. if (view is BookmarkView) {
  561. view.updateContent()
  562. view.onScrollToContent(currentPageIndex, true)
  563. }
  564. }
  565. private fun setupToolbar() {
  566. toolbar_readerActivity.setNavigationOnClickListener { finish() }
  567. toolbar_readerActivity.setOnMenuItemClickListener {
  568. when (it.itemId) {
  569. R.id.item_reader_bookmark -> onClickBookmark()
  570. R.id.item_reader_more_text_reflow -> onClickTextReflow()
  571. R.id.item_reader_more_file_info -> onClickFileInfo()
  572. R.id.item_ibon_print -> onClickIBonPrint()
  573. R.id.item_reader_more_print -> onClickPrint()
  574. R.id.item_reader_more_user_guide -> onClickUserGuide()
  575. R.id.item_reader_more_clear_signature -> onClickClearSignature()
  576. }
  577. return@setOnMenuItemClickListener true
  578. }
  579. }
  580. private fun onClickBookmark() {
  581. viewModel.isPageInBookmarksLiveData.value?.let {
  582. if (!it) {
  583. showAddBookmarkDialog()
  584. } else {
  585. showDeleteBookmarkDialog()
  586. }
  587. }
  588. }
  589. private fun onClickClearSignature() {
  590. AlertDialog.Builder(this)
  591. .setMessage(R.string.reader_clear_signature_dialog_msg)
  592. .setPositiveButton(android.R.string.yes) { _, _ -> viewModel.clearSignature() }
  593. .setNegativeButton(android.R.string.no) { _, _ -> /* do nothing */ }
  594. .show()
  595. }
  596. private fun showAddBookmarkDialog() {
  597. val alertDialogBuilder = AlertDialog.Builder(this)
  598. val editText = EditText(this)
  599. val layoutParams =
  600. LinearLayout.LayoutParams(LinearLayout.LayoutParams.MATCH_PARENT, LinearLayout.LayoutParams.MATCH_PARENT)
  601. editText.layoutParams = layoutParams
  602. val defaultTitle = getString(R.string.dialogAddBookmark_page) + " " + (viewModel.pdfInfoHandler.getCurrentPage() + 1)
  603. editText.setText(defaultTitle, TextView.BufferType.EDITABLE)
  604. editText.setSelection(0, defaultTitle.length)
  605. alertDialogBuilder.setTitle(getString(R.string.reader_alert_dialog_title_add_bookmark))
  606. alertDialogBuilder.setView(editText)
  607. alertDialogBuilder.setPositiveButton(getString(R.string.reader_alert_dialog_button_confirm)) { dialog, which ->
  608. viewModel.addBookmark(editText.text.toString())
  609. updateBookmarkView()
  610. }
  611. alertDialogBuilder.setNegativeButton(getString(R.string.reader_alert_dialog_button_cancel)) { dialog, which ->
  612. }
  613. alertDialogBuilder.create().show()
  614. editText.requestFocus()
  615. }
  616. private fun getBookmarkTitle(page: Int): String {
  617. val bookmarks = viewModel.bookmarkHandler.getBookmarks()
  618. for (bookmark in bookmarks) {
  619. if (bookmark.pageNum == page) {
  620. return bookmark.title
  621. }
  622. }
  623. return ""
  624. }
  625. private fun showDeleteBookmarkDialog() {
  626. val alertDialogBuilder = AlertDialog.Builder(this)
  627. alertDialogBuilder.setTitle(getString(R.string.reader_alert_dialog_title_delete_bookmark))
  628. val bookmarkTitle = getBookmarkTitle(viewModel.pdfInfoHandler.getCurrentPage())
  629. val message = String.format(getString(R.string.reader_alert_dialog_message_delete_bookmark), bookmarkTitle)
  630. alertDialogBuilder.setMessage(message)
  631. alertDialogBuilder.setPositiveButton(getString(R.string.reader_alert_dialog_button_confirm)) { dialog, which ->
  632. viewModel.deleteBookmark()
  633. updateBookmarkView()
  634. }
  635. alertDialogBuilder.setNegativeButton(getString(R.string.reader_alert_dialog_button_cancel)) { dialog, which ->
  636. }
  637. alertDialogBuilder.create().show()
  638. }
  639. private fun hideSearchViewSoftKeyboard() {
  640. val view = linearLayout_readerActivity_leftToolbarContainer.getChildAt(0)
  641. if (view is SearchView) {
  642. view.hideSoftKeyboard()
  643. }
  644. }
  645. private fun setupLeftToolbar() {
  646. viewGroup_readerActivity_leftToolbar.setScroll(false)
  647. setLeftToolbarWidth(w_240)
  648. viewGroup_readerActivity_leftToolbar.smoothScrollTo(w_240, 0, 0)
  649. val child = layoutInflater.inflate(R.layout.view_thumbnail, null)
  650. linearLayout_readerActivity_leftToolbarContainer.addView(child)
  651. fun onClickLeftToolbarItem(leftToolbarType: ReaderViewModel.LeftToolbarType) {
  652. viewModel.setLeftToolbarType(leftToolbarType)
  653. updateLeftToolbarOpenState(leftToolbarType)
  654. }
  655. iv_readerActivity_thumbnail.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.THUMBNAIL) }
  656. iv_readerActivity_bookmark.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.BOOKMARK) }
  657. iv_readerActivity_outline.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.OUTLINE) }
  658. iv_readerActivity_search.setOnClickListener { onClickLeftToolbarItem(ReaderViewModel.LeftToolbarType.SEARCH) }
  659. if (!isPdf()) {
  660. iv_readerActivity_bookmark.visibility = View.GONE
  661. if (!isPasswordProtected) iv_readerActivity_outline.visibility = View.GONE
  662. }
  663. }
  664. override fun onReadModeChanged(readMode: Int) {
  665. viewModel.readMode = when (readMode) {
  666. ReadingModeSelectView.modeDay -> ReaderViewModel.ReadMode.READ_MODE_DAY
  667. ReadingModeSelectView.modeNight -> ReaderViewModel.ReadMode.READ_MODE_NIGHT
  668. ReadingModeSelectView.modeSoft -> ReaderViewModel.ReadMode.READ_MODE_SOFT
  669. ReadingModeSelectView.modeChromeWhite -> ReaderViewModel.ReadMode.MODE_CHROME_WHITE
  670. ReadingModeSelectView.modeEtonBlue -> ReaderViewModel.ReadMode.MODE_ETON_BLUE
  671. ReadingModeSelectView.modeWhiteLilac -> ReaderViewModel.ReadMode.MODE_WHITE_LILAC
  672. else -> ReaderViewModel.ReadMode.READ_MODE_DAY
  673. }
  674. }
  675. override fun onCropModeEnableChanged(enable: Boolean) {
  676. viewModel.isCrop = enable
  677. val buttons = arrayOf(iv_readerActivity_highLight, iv_readerActivity_strike, iv_readerActivity_underline, iv_readerActivity_ink, ib_readerActivity_bottomToolbarMediaBox)
  678. if (enable) {
  679. viewModel.stopAnnotationMode()
  680. val color = ContextCompat.getColor(baseContext, R.color.reader_right_toolbar_disabled_bg)
  681. for (button in buttons) {
  682. button.isEnabled = false
  683. button.setBackgroundColor(color)
  684. }
  685. } else {
  686. for (button in buttons) {
  687. button.isEnabled = true
  688. button.setBackgroundDrawable(null)
  689. }
  690. }
  691. }
  692. override fun onShowStateBarEnableChanged(enable: Boolean, dialog: Dialog?) {
  693. when (enable) {
  694. true -> {
  695. dialog?.window?.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
  696. window.clearFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN)
  697. }
  698. false -> {
  699. dialog?.window?.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  700. window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN)
  701. }
  702. }
  703. }
  704. override fun onTurnPageDirectionChanged(direction: Int) {
  705. viewModel.viewDirection = when (direction == 0) {
  706. true -> ReaderViewModel.ViewDirection.VerticalSinglePageContinues
  707. false -> ReaderViewModel.ViewDirection.HorizontalSinglePage
  708. }
  709. }
  710. override fun onShowTurnPageBtnEnableChanged(enable: Boolean) {
  711. when (enable) {
  712. true -> {
  713. ib_readerActivity_bottomToolbarPrevious.visibility = View.VISIBLE
  714. ib_readerActivity_bottomToolbarNext.visibility = View.VISIBLE
  715. }
  716. false -> {
  717. ib_readerActivity_bottomToolbarPrevious.visibility = View.GONE
  718. ib_readerActivity_bottomToolbarNext.visibility = View.GONE
  719. }
  720. }
  721. }
  722. override fun onLockScreenSleepEnableChanged(enable: Boolean) {
  723. when (enable) {
  724. true -> window.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  725. false -> window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
  726. }
  727. }
  728. override fun onShowCommentToolEnableChanged(enable: Boolean) {
  729. }
  730. override fun onShowBOTAToolEnableChanged(enable: Boolean) {
  731. }
  732. private fun setupRightSideToolbar() {
  733. iv_readerActivity_setting.setOnClickListener {
  734. val settingDialog = provideReaderSettingDialogFragment()
  735. settingDialog.show(supportFragmentManager, FRAGMENT_READER_SETTING_TAG)
  736. }
  737. }
  738. private fun applySetting() {
  739. val model = SharePrefsModel(this)
  740. onShowStateBarEnableChanged(model.isShowStateBarEnable.value ?: false, null)
  741. onTurnPageDirectionChanged(model.turnPageDirection.value ?: 0)
  742. onShowTurnPageBtnEnableChanged(model.isShowTurnPageBtnEnable.value ?: false)
  743. onLockScreenSleepEnableChanged(model.isLockScreenSleepEnable.value ?: false)
  744. onShowCommentToolEnableChanged(model.isShowCommentToolEnable.value ?: false)
  745. onShowBOTAToolEnableChanged(model.isShowBOTAToolEnable.value ?: false)
  746. }
  747. override fun isShowStateBar(): Boolean {
  748. return SharePrefsModel(this).isShowStateBarEnable.value ?: false
  749. }
  750. private fun setupBottomToolbar() {
  751. ib_readerActivity_bottomToolbarMediaBox.setOnClickListener { mediaBoxView.show() }
  752. ib_readerActivity_bottomToolbarViewAll.setOnClickListener {
  753. onClickBottomThumb1()
  754. }
  755. ib_readerActivity_bottomToolbarPrevious.setOnClickListener {
  756. val handler = viewModel.pdfInfoHandler
  757. val pageIndex = handler.getCurrentPage()
  758. val previousPageIndex = Math.max(pageIndex - 1, 0)
  759. handler.setCurrentPage(previousPageIndex)
  760. }
  761. ib_readerActivity_bottomToolbarNext.setOnClickListener {
  762. val handler = viewModel.pdfInfoHandler
  763. val pageIndex = handler.getCurrentPage()
  764. val nextPageIndex = Math.min(pageIndex + 1, handler.getPdfPageCount() - 1)
  765. handler.setCurrentPage(nextPageIndex)
  766. }
  767. ib_readerActivity_bottomToolbarKdanCloud.visibility = if (isBottomBarKdanCloudBtnVisible()) {
  768. View.VISIBLE
  769. } else {
  770. View.GONE
  771. }
  772. ib_readerActivity_bottomToolbarKdanCloud.setOnClickListener {
  773. onClickKdanCloud()
  774. }
  775. ib_readerActivity_bottomToolbarShare.setOnClickListener {
  776. onClickShare()
  777. }
  778. if (!isPdf()) {
  779. ib_readerActivity_bottomToolbarMediaBox.visibility = View.GONE
  780. }
  781. }
  782. private fun setupMediaBoxView() {
  783. fun showSnackbar(title: String, btnText: String) {
  784. snackbarMediaBox = Snackbar.make(mediaBoxView, title, Snackbar.LENGTH_INDEFINITE)
  785. .setAction(btnText) {
  786. viewModel.clearSelection()
  787. mediaBoxView.post {
  788. mediaBoxView.show()
  789. snackbarMediaBox?.dismiss()
  790. snackbarMediaBox = null
  791. }
  792. }
  793. snackbarMediaBox?.setActionTextColor(ContextCompat.getColor(this, R.color.bright_blue))
  794. snackbarMediaBox?.show()
  795. }
  796. mediaBoxView.apply {
  797. onShowListener = Runnable {
  798. onMediaBoxShown()
  799. snackbarMediaBox?.dismiss()
  800. snackbarMediaBox = null
  801. }
  802. onDismissListener = Runnable {
  803. onMediaBoxDismissed()
  804. snackbarMediaBox?.dismiss()
  805. snackbarMediaBox = null
  806. }
  807. onClickAddButtonListener = object : MediaBoxView.OnClickHeaderButtonListener {
  808. override fun onClickTextBoxAddButton(textBoxTabView: TextBoxTabView) {
  809. dismiss(false)
  810. viewModel.setTextBoxAttribute(textBoxTabView.getTextBoxAttribute())
  811. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_textBox), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  812. }
  813. override fun onClickTextBoxStyleApplyButton(textBoxTabView: TextBoxTabView) {
  814. dismiss(false)
  815. viewModel.setTextBoxAttribute(textBoxTabView.getTextBoxAttribute(), true)
  816. }
  817. override fun onClickSignatureAddButton(signatureTabView: SignatureTabView) {
  818. dismiss(false)
  819. viewModel.setSignatureAttribute(signatureTabView.getSignatureAttribute())
  820. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_signature), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  821. }
  822. override fun onClickStampAddButton(stampTabView: StampTabView) {
  823. dismiss(false)
  824. viewModel.setStampAttribute(stampTabView.getStampAttribute())
  825. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_stamp), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  826. }
  827. override fun onClickShapeAddButton(shapeTabView: ShapeTabView) {
  828. dismiss(false)
  829. viewModel.setShapeAttribute(shapeTabView.getShapeAttribute())
  830. showSnackbar(resources.getString(R.string.reader_mediaBox_snakebar_shape), resources.getString(R.string.reader_mediaBox_snakebar_undo))
  831. }
  832. }
  833. }
  834. }
  835. private fun setupRightToolbar() {
  836. viewGroup_readerActivity_rightToolbar.setScroll(false)
  837. iv_readerActivity_highLight.apply {
  838. setOnClickListener { viewModel.onClickHighlightBtn() }
  839. setOnLongClickListener { btn ->
  840. viewModel.onLongClickHighlightBtn()
  841. val context = this@ReaderActivity
  842. AnnotationAttributeWindow(context, true).also { window ->
  843. viewModel.highLightAttributeLiveData.value?.let { attr ->
  844. window.annotationAttributeView.annotationAttribute = attr
  845. }
  846. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  847. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  848. viewModel.setHighLightAttributes(annotationAttributeView.annotationAttribute)
  849. }
  850. }
  851. val contentView = window.contentView.apply {
  852. val w = Utils.makeDropDownMeasureSpec(window.width)
  853. val y = Utils.makeDropDownMeasureSpec(window.height)
  854. measure(w, y)
  855. }
  856. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  857. val xOff = (-contentView.measuredWidth - space).toInt()
  858. val yOff = -btn.height
  859. window.showAsDropDown(btn, xOff, yOff)
  860. }
  861. return@setOnLongClickListener true
  862. }
  863. }
  864. iv_readerActivity_strike.apply {
  865. setOnClickListener { viewModel.onClickStrikeBtn() }
  866. setOnLongClickListener { btn ->
  867. viewModel.onLongClickStrikeBtn()
  868. val context = this@ReaderActivity
  869. AnnotationAttributeWindow(context, true).also { window ->
  870. viewModel.strikeAttributeLiveData.value?.let { attr ->
  871. window.annotationAttributeView.annotationAttribute = attr
  872. }
  873. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  874. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  875. viewModel.setStrikeOutAttributes(annotationAttributeView.annotationAttribute)
  876. }
  877. }
  878. val contentView = window.contentView.apply {
  879. val w = Utils.makeDropDownMeasureSpec(window.width)
  880. val y = Utils.makeDropDownMeasureSpec(window.height)
  881. measure(w, y)
  882. }
  883. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  884. val xOff = (-contentView.measuredWidth - space).toInt()
  885. val yOff = -btn.height
  886. window.showAsDropDown(btn, xOff, yOff)
  887. }
  888. return@setOnLongClickListener true
  889. }
  890. }
  891. iv_readerActivity_underline.apply {
  892. setOnClickListener { viewModel.onClickUnderlineBtn() }
  893. setOnLongClickListener { btn ->
  894. viewModel.onLongClickUnderlineBtn()
  895. val context = this@ReaderActivity
  896. AnnotationAttributeWindow(context, true).also { window ->
  897. viewModel.underLineAttributeLiveData.value?.let { attr ->
  898. window.annotationAttributeView.annotationAttribute = attr
  899. }
  900. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  901. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  902. viewModel.setUnderLineAttributes(annotationAttributeView.annotationAttribute)
  903. }
  904. }
  905. val contentView = window.contentView.apply {
  906. val w = Utils.makeDropDownMeasureSpec(window.width)
  907. val y = Utils.makeDropDownMeasureSpec(window.height)
  908. measure(w, y)
  909. }
  910. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  911. val xOff = (-contentView.measuredWidth - space).toInt()
  912. val yOff = -btn.height
  913. window.showAsDropDown(btn, xOff, yOff)
  914. }
  915. return@setOnLongClickListener true
  916. }
  917. }
  918. iv_readerActivity_ink.apply {
  919. setOnClickListener { viewModel.onClickInkBtn() }
  920. setOnLongClickListener { btn ->
  921. viewModel.onLongClickInkBtn()
  922. val context = this@ReaderActivity
  923. AnnotationAttributeWindow(context, false).also { window ->
  924. viewModel.inkAttributeLiveData.value?.let { attr ->
  925. window.annotationAttributeView.inkAttribute = attr
  926. }
  927. window.annotationAttributeView.onChangeListener = object : AnnotationAttributeView.OnChangeListener {
  928. override fun onChange(annotationAttributeView: AnnotationAttributeView) {
  929. viewModel.setInkAttributes(annotationAttributeView.inkAttribute)
  930. }
  931. }
  932. val contentView = window.contentView.apply {
  933. val w = Utils.makeDropDownMeasureSpec(window.width)
  934. val y = Utils.makeDropDownMeasureSpec(window.height)
  935. measure(w, y)
  936. }
  937. val space = resources.getDimension(R.dimen.reader_annotation_property_setting_window_right_toolbar_space)
  938. val xOff = (-contentView.measuredWidth - space).toInt()
  939. val yOff = -contentView.measuredHeight
  940. window.showAsDropDown(btn, xOff, yOff)
  941. }
  942. return@setOnLongClickListener true
  943. }
  944. }
  945. if (!isPdf()) {
  946. iv_readerActivity_highLight.visibility = View.GONE
  947. iv_readerActivity_strike.visibility = View.GONE
  948. iv_readerActivity_underline.visibility = View.GONE
  949. iv_readerActivity_ink.visibility = View.GONE
  950. view_readerActivity_highLightStroke.visibility = View.GONE
  951. view_readerActivity_strikeStroke.visibility = View.GONE
  952. view_readerActivity_underlineStroke.visibility = View.GONE
  953. }
  954. }
  955. private fun setLeftToolbarWidth(width: Int) {
  956. var params = viewGroup_readerActivity_leftToolbar.layoutParams as ConstraintLayout.LayoutParams
  957. params.width = width + w_left
  958. params.height = 0
  959. viewGroup_readerActivity_leftToolbar.layoutParams = params
  960. params = linearLayout_readerActivity_leftToolbarContainer.layoutParams as ConstraintLayout.LayoutParams
  961. params.width = width
  962. linearLayout_readerActivity_leftToolbarContainer.layoutParams = params
  963. }
  964. private fun updateLeftToolbarOpenState(type: ReaderViewModel.LeftToolbarType) {
  965. val isLeftToolbarOpen = viewModel.isLeftToolbarOpenLiveData.value ?: false
  966. viewModel.setIsLeftToolbarOpen(!isLeftToolbarOpen || oldLeftToolbarType != type)
  967. cloneOriginConstraintSet()
  968. }
  969. private fun onMediaBoxShown() {
  970. hideAllToolbars()
  971. isHideToolbar = true
  972. }
  973. private fun onMediaBoxDismissed() {
  974. showAllToolbars()
  975. isHideToolbar = false
  976. viewModel.clearSelection()
  977. }
  978. private fun setLeftToolbarContentView(leftToolbarType: ReaderViewModel.LeftToolbarType) {
  979. if (oldLeftToolbarType != leftToolbarType) {
  980. linearLayout_readerActivity_leftToolbarContainer.removeAllViews()
  981. val view = when (leftToolbarType) {
  982. ReaderViewModel.LeftToolbarType.NONE,
  983. ReaderViewModel.LeftToolbarType.THUMBNAIL -> {
  984. val thumbnailView = ThumbnailView(this)
  985. thumbnailView.setHandlers(viewModel.pdfInfoHandler, viewModel.thumbnailHandler)
  986. thumbnailView
  987. }
  988. ReaderViewModel.LeftToolbarType.BOOKMARK -> {
  989. val bookmarkView = BookmarkView(this)
  990. bookmarkView.setHandlers(viewModel.pdfInfoHandler, viewModel.thumbnailHandler, viewModel.bookmarkHandler)
  991. bookmarkView
  992. }
  993. ReaderViewModel.LeftToolbarType.OUTLINE -> {
  994. val outlineView = OutlineView(this)
  995. outlineView.setHandlers(viewModel.pdfInfoHandler, viewModel.outlineHandler)
  996. outlineView
  997. }
  998. ReaderViewModel.LeftToolbarType.SEARCH -> {
  999. val searchView = SearchView(this)
  1000. searchView.setHandlers(viewModel.pdfInfoHandler, viewModel.searchHandler)
  1001. searchView
  1002. }
  1003. }
  1004. linearLayout_readerActivity_leftToolbarContainer.addView(view as View)
  1005. oldLeftToolbarType = leftToolbarType
  1006. }
  1007. }
  1008. private fun getLeftToolbarContentWidth(): Int {
  1009. return when (viewModel.leftToolbarTypeLiveData.value == ReaderViewModel.LeftToolbarType.THUMBNAIL) {
  1010. true -> w_240
  1011. false -> w_318
  1012. }
  1013. }
  1014. private fun onLeftToolbarTypeChanged(leftToolbarType: ReaderViewModel.LeftToolbarType?) {
  1015. updateLeftToolbarIcons()
  1016. setLeftToolbarWidth(getLeftToolbarContentWidth())
  1017. cloneOriginConstraintSet()
  1018. if (leftToolbarType != null) {
  1019. setLeftToolbarContentView(leftToolbarType)
  1020. }
  1021. }
  1022. private fun onLeftToolbarOpenStateChanged(open: Boolean?) {
  1023. updateLeftToolbarIcons()
  1024. when (open == true) {
  1025. true -> viewGroup_readerActivity_leftToolbar.smoothScrollTo(0, 0, UI_ANIMATION_DURATION.toInt())
  1026. false -> {
  1027. viewGroup_readerActivity_leftToolbar.smoothScrollTo(getLeftToolbarContentWidth(), 0, UI_ANIMATION_DURATION.toInt())
  1028. hideSearchViewSoftKeyboard()
  1029. }
  1030. }
  1031. }
  1032. private fun updateLeftToolbarIcons() {
  1033. iv_readerActivity_thumbnail.setImageResource(R.drawable.ic_left_toolbar_thumbnails)
  1034. iv_readerActivity_bookmark.setImageResource(R.drawable.ic_left_toolbar_bookmarks)
  1035. iv_readerActivity_outline.setImageResource(R.drawable.ic_left_toolbar_outline)
  1036. iv_readerActivity_search.setImageResource(R.drawable.ic_left_toolbar_search)
  1037. if (viewModel.isLeftToolbarOpenLiveData.value == true) {
  1038. when (viewModel.leftToolbarTypeLiveData.value) {
  1039. ReaderViewModel.LeftToolbarType.NONE -> {}
  1040. ReaderViewModel.LeftToolbarType.THUMBNAIL -> iv_readerActivity_thumbnail.setImageResource(R.drawable.ic_left_toolbar_thumbnails_selected)
  1041. ReaderViewModel.LeftToolbarType.BOOKMARK -> iv_readerActivity_bookmark.setImageResource(R.drawable.ic_left_toolbar_bookmarks_selected)
  1042. ReaderViewModel.LeftToolbarType.OUTLINE -> iv_readerActivity_outline.setImageResource(R.drawable.ic_left_toolbar_outline_selected)
  1043. ReaderViewModel.LeftToolbarType.SEARCH -> iv_readerActivity_search.setImageResource(R.drawable.ic_left_toolbar_search_selected)
  1044. }
  1045. }
  1046. }
  1047. private fun onClickBottomThumb1() {
  1048. viewModel.transferReaderModel()
  1049. val thumbDialog = providePdfThumbDialogFragment()
  1050. thumbDialog.show(supportFragmentManager, FRAGMENT_PDF_THUMB_TAG)
  1051. }
  1052. override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
  1053. super.onActivityResult(requestCode, resultCode, data)
  1054. if (resultCode == Activity.RESULT_OK){
  1055. when (requestCode) {
  1056. REQUEST_PASSWORD -> {
  1057. val password = data?.getStringExtra("password") ?: ""
  1058. if (password.isEmpty()) {
  1059. finish()
  1060. } else {
  1061. viewModel.isOpenedFileLiveData.value?.also { isOpened ->
  1062. if (isOpened) return@also
  1063. val result = viewModel.openPdfFile(this@ReaderActivity, Uri.parse(filePath), password, Runnable { requestPassword(true) }, intent.type)
  1064. if (result == ReaderViewModel.OpenFileResult.FAILED) {
  1065. showFileCannotOpenDialog(getString(R.string.cannot_open_file_Path, filePath))
  1066. }
  1067. }
  1068. }
  1069. }
  1070. }
  1071. }
  1072. }
  1073. }