@june24/expo-pdf-reader 0.1.20 → 0.1.21

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -89,6 +89,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
89
89
  private val onTextPress = ViewEvent<Map<String, Any>>("onTextPress", this, null)
90
90
 
91
91
  private var pageHeights = mutableListOf<Int>()
92
+ private var rowHeights = mutableListOf<Int>()
92
93
  private var pageWidthsPdf = mutableListOf<Float>()
93
94
  private var pageHeightsPdf = mutableListOf<Float>()
94
95
  private var pageViews = mutableListOf<ImageView?>()
@@ -552,13 +553,38 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
552
553
  notifyAnnotationChange()
553
554
  }
554
555
 
556
+ private fun isTwoUpMode(): Boolean = displayMode == "twoUp" || displayMode == "twoUpContinuous"
557
+
555
558
  private fun marginBetweenPages(): Int = if (displayMode == "single") 0 else 16
556
559
 
560
+ private fun getFrameForPage(pageIndex: Int): FrameLayout? {
561
+ if (pageIndex !in pageHeights.indices) return null
562
+ return if (isTwoUpMode()) {
563
+ val row = pageIndex / 2
564
+ val col = pageIndex % 2
565
+ if (row >= container.childCount) null
566
+ else (container.getChildAt(row) as? LinearLayout)?.getChildAt(col) as? FrameLayout
567
+ } else {
568
+ container.getChildAt(pageIndex) as? FrameLayout
569
+ }
570
+ }
571
+
557
572
  private fun scrollToPage(pageIndex: Int) {
558
573
  if (pageHeights.isEmpty()) return
559
- var offset = 0
560
- for (i in 0 until pageIndex.coerceIn(0, pageHeights.size - 1)) {
561
- offset += pageHeights[i] + marginBetweenPages()
574
+ val idx = pageIndex.coerceIn(0, pageHeights.size - 1)
575
+ val gap = marginBetweenPages()
576
+ val offset = if (isTwoUpMode() && rowHeights.isNotEmpty()) {
577
+ var sum = 0
578
+ for (r in 0 until idx / 2) {
579
+ sum += rowHeights[r] + gap
580
+ }
581
+ sum
582
+ } else {
583
+ var sum = 0
584
+ for (i in 0 until idx) {
585
+ sum += pageHeights[i] + gap
586
+ }
587
+ sum
562
588
  }
563
589
  scrollView.post { scrollView.smoothScrollTo(0, offset) }
564
590
  }
@@ -598,6 +624,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
598
624
  fileDescriptor?.close()
599
625
  fileDescriptor = null
600
626
  pageHeights.clear()
627
+ rowHeights.clear()
601
628
  pageWidthsPdf.clear()
602
629
  pageHeightsPdf.clear()
603
630
  pageViews.clear()
@@ -632,20 +659,16 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
632
659
  updateVisiblePages()
633
660
  return
634
661
  }
635
- val viewHeight = height.coerceAtLeast(1)
636
662
  val viewWidth = width.coerceAtLeast(1)
637
- val isSingle = displayMode == "single"
663
+ val isTwoUp = displayMode == "twoUp" || displayMode == "twoUpContinuous"
664
+ val effectiveWidth = if (isTwoUp) viewWidth / 2 else viewWidth
638
665
  scope.launch {
639
- val w = viewWidth
666
+ val w = effectiveWidth
640
667
  val result = withContext(Dispatchers.Default) {
641
668
  (0 until renderer.pageCount).map { i ->
642
669
  val page = renderer.openPage(i)
643
670
  try {
644
- val pageH = if (isSingle) {
645
- viewHeight
646
- } else {
647
- (w.toFloat() * page.height / page.width).toInt()
648
- }
671
+ val pageH = (w.toFloat() * page.height / page.width).toInt()
649
672
  Triple(
650
673
  i,
651
674
  pageH,
@@ -659,6 +682,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
659
682
  if (!isActive) return@launch
660
683
  withContext(Dispatchers.Main) {
661
684
  pageHeights.clear()
685
+ rowHeights.clear()
662
686
  pageWidthsPdf.clear()
663
687
  pageHeightsPdf.clear()
664
688
  for ((_, h, pdfSize) in result) {
@@ -666,6 +690,14 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
666
690
  pageWidthsPdf.add(pdfSize.first)
667
691
  pageHeightsPdf.add(pdfSize.second)
668
692
  }
693
+ if (isTwoUp) {
694
+ val rowCount = (renderer.pageCount + 1) / 2
695
+ for (r in 0 until rowCount) {
696
+ val h0 = pageHeights.getOrElse(2 * r) { 0 }
697
+ val h1 = pageHeights.getOrElse(2 * r + 1) { 0 }
698
+ rowHeights.add(maxOf(h0, h1))
699
+ }
700
+ }
669
701
  ensurePlaceholders(renderer)
670
702
  scrollToPage(initialPage.coerceIn(0, (renderer.pageCount - 1).coerceAtLeast(0)))
671
703
  updateVisiblePages()
@@ -682,31 +714,76 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
682
714
  while (pageAnnotations.size < pageCount) {
683
715
  pageAnnotations.add(mutableListOf())
684
716
  }
685
- for (i in 0 until pageCount) {
686
- val frame = FrameLayout(context).apply {
687
- layoutParams = LinearLayout.LayoutParams(
688
- LinearLayout.LayoutParams.MATCH_PARENT,
689
- pageHeights[i]
690
- ).apply { setMargins(0, 0, 0, marginBetween) }
691
- setBackgroundColor(Color.LTGRAY)
717
+ if (isTwoUpMode() && rowHeights.isNotEmpty()) {
718
+ val rowCount = rowHeights.size
719
+ for (r in 0 until rowCount) {
720
+ val rowLayout = LinearLayout(context).apply {
721
+ orientation = LinearLayout.HORIZONTAL
722
+ layoutParams = LinearLayout.LayoutParams(
723
+ LinearLayout.LayoutParams.MATCH_PARENT,
724
+ rowHeights[r]
725
+ ).apply { setMargins(0, 0, 0, marginBetween) }
726
+ }
727
+ for (col in 0..1) {
728
+ val i = 2 * r + col
729
+ if (i >= pageCount) break
730
+ val frame = FrameLayout(context).apply {
731
+ layoutParams = LinearLayout.LayoutParams(
732
+ 0,
733
+ LinearLayout.LayoutParams.MATCH_PARENT,
734
+ 1f
735
+ ).apply { setMargins(0, 0, if (col == 0) 8 else 0, 0) }
736
+ setBackgroundColor(Color.LTGRAY)
737
+ }
738
+ val overlay = AnnotationOverlayView(context, i).apply {
739
+ layoutParams = FrameLayout.LayoutParams(
740
+ FrameLayout.LayoutParams.MATCH_PARENT,
741
+ FrameLayout.LayoutParams.MATCH_PARENT
742
+ )
743
+ }
744
+ frame.addView(overlay)
745
+ rowLayout.addView(frame)
746
+ overlayViews[i] = overlay
747
+ }
748
+ container.addView(rowLayout)
692
749
  }
693
- val overlay = AnnotationOverlayView(context, i).apply {
694
- layoutParams = FrameLayout.LayoutParams(
695
- FrameLayout.LayoutParams.MATCH_PARENT,
696
- FrameLayout.LayoutParams.MATCH_PARENT
697
- )
750
+ } else {
751
+ for (i in 0 until pageCount) {
752
+ val frame = FrameLayout(context).apply {
753
+ layoutParams = LinearLayout.LayoutParams(
754
+ LinearLayout.LayoutParams.MATCH_PARENT,
755
+ pageHeights[i]
756
+ ).apply { setMargins(0, 0, 0, marginBetween) }
757
+ setBackgroundColor(Color.LTGRAY)
758
+ }
759
+ val overlay = AnnotationOverlayView(context, i).apply {
760
+ layoutParams = FrameLayout.LayoutParams(
761
+ FrameLayout.LayoutParams.MATCH_PARENT,
762
+ FrameLayout.LayoutParams.MATCH_PARENT
763
+ )
764
+ }
765
+ frame.addView(overlay)
766
+ container.addView(frame)
767
+ overlayViews[i] = overlay
698
768
  }
699
- frame.addView(overlay)
700
- container.addView(frame)
701
- overlayViews[i] = overlay
702
769
  }
703
770
  }
704
771
 
705
772
  private fun currentPageFromScroll(): Int {
706
773
  if (pageHeights.isEmpty()) return 0
707
774
  val scrollY = scrollView.scrollY
708
- var offset = 0
709
775
  val gap = marginBetweenPages()
776
+ if (isTwoUpMode() && rowHeights.isNotEmpty()) {
777
+ var offset = 0
778
+ for (r in rowHeights.indices) {
779
+ val rowH = rowHeights[r]
780
+ if (scrollY < offset + rowH / 2) return (2 * r).coerceAtMost(pageHeights.size - 1)
781
+ if (scrollY < offset + rowH) return (2 * r + 1).coerceAtMost(pageHeights.size - 1)
782
+ offset += rowH + gap
783
+ }
784
+ return (pageHeights.size - 1).coerceAtLeast(0)
785
+ }
786
+ var offset = 0
710
787
  for (i in pageHeights.indices) {
711
788
  if (scrollY < offset + pageHeights[i] / 2) return i
712
789
  offset += pageHeights[i] + gap
@@ -723,7 +800,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
723
800
  for (i in pageViews.indices) {
724
801
  if (i in from..to) continue
725
802
  val iv = pageViews.getOrNull(i) ?: continue
726
- val frame = container.getChildAt(i) as? FrameLayout ?: continue
803
+ val frame = getFrameForPage(i) ?: continue
727
804
  val bmp = (iv.drawable as? BitmapDrawable)?.bitmap
728
805
  iv.setImageBitmap(null)
729
806
  bmp?.recycle()
@@ -740,11 +817,10 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
740
817
 
741
818
  private fun renderPageToView(pageIndex: Int) {
742
819
  val renderer = pdfRenderer ?: return
743
- val frame = container.getChildAt(pageIndex) as? FrameLayout ?: return
744
- // Frame always has overlay; only skip if we already have an ImageView for this page
820
+ val frame = getFrameForPage(pageIndex) ?: return
745
821
  if (pageViews.getOrNull(pageIndex) != null) return
746
822
  val page = renderer.openPage(pageIndex)
747
- val w = width.coerceAtLeast(1)
823
+ val w = if (isTwoUpMode()) (width / 2).coerceAtLeast(1) else width.coerceAtLeast(1)
748
824
  val h = pageHeights[pageIndex]
749
825
  val bitmap = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888)
750
826
  page.render(bitmap, null, null, PdfRenderer.Page.RENDER_MODE_FOR_DISPLAY)
@@ -766,18 +842,7 @@ class ExpoPdfReaderView(context: Context, appContext: AppContext) : ExpoView(con
766
842
 
767
843
  private fun notifyPageChange() {
768
844
  if (pageHeights.isEmpty()) return
769
- val scrollY = scrollView.scrollY
770
- var offset = 0
771
- var detectedPage = 0
772
- val gap = marginBetweenPages()
773
- for (i in pageHeights.indices) {
774
- if (scrollY < offset + pageHeights[i] / 2) {
775
- detectedPage = i
776
- break
777
- }
778
- offset += pageHeights[i] + gap
779
- detectedPage = i
780
- }
845
+ val detectedPage = currentPageFromScroll()
781
846
  if (detectedPage != lastEmittedPageIndex) {
782
847
  lastEmittedPageIndex = detectedPage
783
848
  onPageChange(mapOf(
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@june24/expo-pdf-reader",
3
- "version": "0.1.20",
3
+ "version": "0.1.21",
4
4
  "description": "A PDF reader for Expo apps with annotation and zoom controls",
5
5
  "homepage": "git@gitlab.com:june_241/expo-pdf-reader.git",
6
6
  "main": "build/index.js",