From 8483f8d42cdbcf95c48223f328c6bbbe905a3673 Mon Sep 17 00:00:00 2001 From: inthewaves <26474149+inthewaves@users.noreply.github.com> Date: Mon, 13 Jan 2025 23:02:18 -0800 Subject: [PATCH] OutlineListFragment: validate node id argument --- .../pdfviewer/outline/OutlineFragment.kt | 5 +++-- .../pdfviewer/outline/OutlineListFragment.kt | 19 +++++++++++++++---- .../pdfviewer/viewModel/OutlineViewModel.kt | 2 ++ 3 files changed, 20 insertions(+), 6 deletions(-) diff --git a/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineFragment.kt b/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineFragment.kt index df6a6a29..6a2f56c7 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineFragment.kt +++ b/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineFragment.kt @@ -10,8 +10,8 @@ import android.widget.TextView import androidx.core.os.bundleOf import androidx.fragment.app.Fragment import androidx.fragment.app.FragmentContainerView +import androidx.fragment.app.activityViewModels import androidx.fragment.app.viewModels -import app.grapheneos.pdfviewer.PdfViewer import app.grapheneos.pdfviewer.R import app.grapheneos.pdfviewer.applySystemBarMargins import app.grapheneos.pdfviewer.databinding.OutlineFragmentBinding @@ -26,6 +26,7 @@ class OutlineFragment : Fragment() { private lateinit var topBar: MaterialToolbar private lateinit var listContainer: FragmentContainerView + private val activityViewModel by activityViewModels() private val viewModel by viewModels() private fun dismissOutlineFragment(pageNumber: Int? = null) { @@ -84,7 +85,6 @@ class OutlineFragment : Fragment() { val docTitle = arguments?.getString(ARG_DOC_TITLE_KEY, "") ?: "" - val activityViewModel = (requireActivity() as PdfViewer).viewModel activityViewModel.requestOutlineIfNotAvailable() activityViewModel.outline.observe(viewLifecycleOwner) { outlineState -> if (outlineState is PdfViewModel.OutlineStatus.Loaded) { @@ -122,6 +122,7 @@ class OutlineFragment : Fragment() { is OutlineViewModel.Action.ViewChildren -> { val parent = action.parent val fragment = OutlineListFragment.makeInstance(parent.id) + // could be replaced with androidx.navigation if (childFragmentManager.findFragmentByTag(parent.id.toString()) == null) { listContainer.visibility = View.VISIBLE childFragmentManager.beginTransaction() diff --git a/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineListFragment.kt b/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineListFragment.kt index 52b89b64..bb0f223a 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineListFragment.kt +++ b/app/src/main/java/app/grapheneos/pdfviewer/outline/OutlineListFragment.kt @@ -1,6 +1,7 @@ package app.grapheneos.pdfviewer.outline import android.os.Bundle +import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup @@ -18,8 +19,8 @@ import com.google.android.material.divider.MaterialDividerItemDecoration class OutlineListViewModel : ViewModel() { val outlineContents = MutableLiveData?>(null) - fun updateOutlineContents(contents: List) { - if (outlineContents.value == null) { + fun updateOutlineContents(contents: List?) { + if (contents != null && outlineContents.value == null) { outlineContents.value = contents } } @@ -48,9 +49,18 @@ class OutlineListFragment : Fragment() { list.addItemDecoration(dividerItemDecoration) list.layoutManager = layoutManager + val parentNodeId = arguments?.getInt(ARG_OUTLINE_ID, -2) ?: -2 + outlineViewModel.currentChild.observe(viewLifecycleOwner) { child -> - if (child != null) { - viewModel.updateOutlineContents(child.children) + val contents = if (child?.id == parentNodeId) { + child.children + } else { + outlineViewModel.findNodeOrNull(parentNodeId)?.children + } + viewModel.updateOutlineContents(contents) + if (contents == null) { + Log.d(TAG, "unable to find child with id $parentNodeId") + outlineViewModel.submitAction(OutlineViewModel.Action.Back) } } @@ -70,6 +80,7 @@ class OutlineListFragment : Fragment() { } companion object { + private const val TAG = "OutlineListFragment" private const val ARG_OUTLINE_ID = "outlinenodeid" fun makeInstance(outlineId: Int) = OutlineListFragment().apply { diff --git a/app/src/main/java/app/grapheneos/pdfviewer/viewModel/OutlineViewModel.kt b/app/src/main/java/app/grapheneos/pdfviewer/viewModel/OutlineViewModel.kt index 640bde52..574df2d9 100644 --- a/app/src/main/java/app/grapheneos/pdfviewer/viewModel/OutlineViewModel.kt +++ b/app/src/main/java/app/grapheneos/pdfviewer/viewModel/OutlineViewModel.kt @@ -44,6 +44,8 @@ class OutlineViewModel : ViewModel() { val currentChild = MutableLiveData(null) + fun findNodeOrNull(id: Int): OutlineNode? = outlineStack.find { it.id == id } + fun getSubtitleString() = outlineStack.lastOrNull()?.title?.trim() ?: docTitle private var docTitle = ""