mirror of
https://github.com/commons-app/apps-android-commons.git
synced 2025-10-26 20:33:53 +01:00
fixed indexOutOfBoundsException by safely handling saved state and index in onViewCreated (#6404)
This commit is contained in:
parent
a6aaa5d078
commit
dc80e07ffd
1 changed files with 59 additions and 47 deletions
|
|
@ -119,8 +119,8 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
|
|
||||||
private var basicKvStore: BasicKvStore? = null
|
private var basicKvStore: BasicKvStore? = null
|
||||||
private val keyForShowingAlertDialog = "isNoNetworkAlertDialogShowing"
|
private val keyForShowingAlertDialog = "isNoNetworkAlertDialogShowing"
|
||||||
private var uploadableFile: UploadableFile? = null
|
internal var uploadableFile: UploadableFile? = null
|
||||||
private var place: Place? = null
|
internal var place: Place? = null
|
||||||
private lateinit var uploadMediaDetailAdapter: UploadMediaDetailAdapter
|
private lateinit var uploadMediaDetailAdapter: UploadMediaDetailAdapter
|
||||||
var indexOfFragment = 0
|
var indexOfFragment = 0
|
||||||
var isExpanded = true
|
var isExpanded = true
|
||||||
|
|
@ -142,19 +142,24 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun setImageToBeUploaded(
|
|
||||||
uploadableFile: UploadableFile?, place: Place?, inAppPictureLocation: LatLng?
|
|
||||||
) {
|
|
||||||
this.uploadableFile = uploadableFile
|
|
||||||
this.place = place
|
|
||||||
this.inAppPictureLocation = inAppPictureLocation
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateView(
|
override fun onCreateView(
|
||||||
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?
|
||||||
): View {
|
): View {
|
||||||
_binding = FragmentUploadMediaDetailFragmentBinding.inflate(inflater, container, false)
|
_binding = FragmentUploadMediaDetailFragmentBinding.inflate(inflater, container, false)
|
||||||
_binding!!.mediaDetailCardView.handleKeyboardInsets()
|
_binding!!.mediaDetailCardView.handleKeyboardInsets()
|
||||||
|
// intialise the adapter early to prevent uninitialized access
|
||||||
|
uploadMediaDetailAdapter = UploadMediaDetailAdapter(
|
||||||
|
this,
|
||||||
|
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "")!!,
|
||||||
|
recentLanguagesDao, voiceInputResultLauncher
|
||||||
|
)
|
||||||
|
uploadMediaDetailAdapter.callback =
|
||||||
|
UploadMediaDetailAdapter.Callback { titleStringID: Int, messageStringId: Int ->
|
||||||
|
showInfoAlert(titleStringID, messageStringId)
|
||||||
|
}
|
||||||
|
uploadMediaDetailAdapter.eventListener = this
|
||||||
|
binding.rvDescriptions.layoutManager = LinearLayoutManager(context)
|
||||||
|
binding.rvDescriptions.adapter = uploadMediaDetailAdapter
|
||||||
return binding.root
|
return binding.root
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -163,20 +168,48 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
|
|
||||||
basicKvStore = BasicKvStore(requireActivity(), "CurrentUploadImageQualities")
|
basicKvStore = BasicKvStore(requireActivity(), "CurrentUploadImageQualities")
|
||||||
|
|
||||||
if (fragmentCallback != null) {
|
// restoree adapter items from savedInstanceState if available
|
||||||
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
|
|
||||||
initializeFragment()
|
|
||||||
}
|
|
||||||
|
|
||||||
if (savedInstanceState != null) {
|
if (savedInstanceState != null) {
|
||||||
if (uploadMediaDetailAdapter.items.isEmpty() && fragmentCallback != null) {
|
val savedItems = savedInstanceState.getParcelableArrayList<UploadMediaDetail>(UPLOAD_MEDIA_DETAILS)
|
||||||
uploadMediaDetailAdapter.items = savedInstanceState.getParcelableArrayList(UPLOAD_MEDIA_DETAILS)!!
|
Timber.d("Restoring state: savedItems size = %s", savedItems?.size ?: "null")
|
||||||
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.items, indexOfFragment)
|
if (savedItems != null && savedItems.isNotEmpty()) {
|
||||||
|
uploadMediaDetailAdapter.items = savedItems
|
||||||
|
// only call setUploadMediaDetails if indexOfFragment is valid
|
||||||
|
if (fragmentCallback != null) {
|
||||||
|
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
|
||||||
|
if (indexOfFragment >= 0) {
|
||||||
|
presenter.setUploadMediaDetails(uploadMediaDetailAdapter.items, indexOfFragment)
|
||||||
|
Timber.d("Restored and set upload media details for index %d", indexOfFragment)
|
||||||
|
} else {
|
||||||
|
Timber.w("Invalid indexOfFragment %d, skipping setUploadMediaDetails", indexOfFragment)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Timber.w("fragmentCallback is null, skipping setUploadMediaDetails")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// initialize with a default UploadMediaDetail if saved state is empty or null
|
||||||
|
uploadMediaDetailAdapter.items = mutableListOf(UploadMediaDetail())
|
||||||
|
Timber.d("Initialized default UploadMediaDetail due to empty or null savedItems")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// intitialise with a default UploadMediaDetail for fresh fragment
|
||||||
|
if (uploadMediaDetailAdapter.items.isEmpty()) {
|
||||||
|
uploadMediaDetailAdapter.items = mutableListOf(UploadMediaDetail())
|
||||||
|
Timber.d("Initialized default UploadMediaDetail for new fragment")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (fragmentCallback != null) {
|
||||||
|
indexOfFragment = fragmentCallback!!.getIndexInViewFlipper(this)
|
||||||
|
Timber.d("Fragment callback present, indexOfFragment = %d", indexOfFragment)
|
||||||
|
initializeFragment()
|
||||||
|
} else {
|
||||||
|
Timber.w("Fragment callback is null, skipping initializeFragment")
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (!presenter.getImageQuality(indexOfFragment, inAppPictureLocation, requireActivity())) {
|
if (indexOfFragment >= 0 && !presenter.getImageQuality(indexOfFragment, inAppPictureLocation, requireActivity())) {
|
||||||
|
Timber.d("Image quality check failed, redirecting to MainActivity")
|
||||||
startActivityWithFlags(
|
startActivityWithFlags(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
MainActivity::class.java,
|
MainActivity::class.java,
|
||||||
|
|
@ -184,11 +217,12 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
Intent.FLAG_ACTIVITY_SINGLE_TOP
|
Intent.FLAG_ACTIVITY_SINGLE_TOP
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} catch (_: Exception) {
|
} catch (e: Exception) {
|
||||||
|
Timber.e(e, "Error during image quality check")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun initializeFragment() {
|
internal fun initializeFragment() {
|
||||||
if (_binding == null) {
|
if (_binding == null) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
@ -206,7 +240,6 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
presenter.setupBasicKvStoreFactory { BasicKvStore(requireActivity(), it) }
|
presenter.setupBasicKvStoreFactory { BasicKvStore(requireActivity(), it) }
|
||||||
|
|
||||||
presenter.receiveImage(uploadableFile, place, inAppPictureLocation)
|
presenter.receiveImage(uploadableFile, place, inAppPictureLocation)
|
||||||
initRecyclerView()
|
|
||||||
|
|
||||||
with (binding){
|
with (binding){
|
||||||
if (indexOfFragment == 0) {
|
if (indexOfFragment == 0) {
|
||||||
|
|
@ -265,24 +298,6 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* init the description recycler veiw and caption recyclerview
|
|
||||||
*/
|
|
||||||
private fun initRecyclerView() {
|
|
||||||
uploadMediaDetailAdapter = UploadMediaDetailAdapter(
|
|
||||||
this,
|
|
||||||
defaultKvStore.getString(Prefs.DESCRIPTION_LANGUAGE, "")!!,
|
|
||||||
recentLanguagesDao, voiceInputResultLauncher
|
|
||||||
)
|
|
||||||
uploadMediaDetailAdapter.callback =
|
|
||||||
UploadMediaDetailAdapter.Callback { titleStringID: Int, messageStringId: Int ->
|
|
||||||
showInfoAlert(titleStringID, messageStringId)
|
|
||||||
}
|
|
||||||
uploadMediaDetailAdapter.eventListener = this
|
|
||||||
binding.rvDescriptions.layoutManager = LinearLayoutManager(context)
|
|
||||||
binding.rvDescriptions.adapter = uploadMediaDetailAdapter
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun showInfoAlert(titleStringID: Int, messageStringId: Int) {
|
private fun showInfoAlert(titleStringID: Int, messageStringId: Int) {
|
||||||
showAlertDialog(
|
showAlertDialog(
|
||||||
requireActivity(),
|
requireActivity(),
|
||||||
|
|
@ -590,16 +605,14 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
var defaultLongitude = -122.431297
|
var defaultLongitude = -122.431297
|
||||||
var defaultZoom = 16.0
|
var defaultZoom = 16.0
|
||||||
|
|
||||||
val locationPickerIntent: Intent
|
|
||||||
|
|
||||||
/* Retrieve image location from EXIF if present or
|
/* Retrieve image location from EXIF if present or
|
||||||
check if user has provided location while using the in-app camera.
|
check if user has provided location while using the in-app camera.
|
||||||
Use location of last UploadItem if none of them is available */
|
Use location of last UploadItem if none of them is available */
|
||||||
|
val locationPickerIntent: Intent
|
||||||
if (uploadItem.gpsCoords != null && uploadItem.gpsCoords!!
|
if (uploadItem.gpsCoords != null && uploadItem.gpsCoords!!
|
||||||
.decLatitude != 0.0 && uploadItem.gpsCoords!!.decLongitude != 0.0
|
.decLatitude != 0.0 && uploadItem.gpsCoords!!.decLongitude != 0.0
|
||||||
) {
|
) {
|
||||||
defaultLatitude = uploadItem.gpsCoords!!
|
defaultLatitude = uploadItem.gpsCoords!!.decLatitude
|
||||||
.decLatitude
|
|
||||||
defaultLongitude = uploadItem.gpsCoords!!.decLongitude
|
defaultLongitude = uploadItem.gpsCoords!!.decLongitude
|
||||||
defaultZoom = uploadItem.gpsCoords!!.zoomLevel
|
defaultZoom = uploadItem.gpsCoords!!.zoomLevel
|
||||||
|
|
||||||
|
|
@ -615,8 +628,7 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
defaultLongitude = locationLatLng[1].toDouble()
|
defaultLongitude = locationLatLng[1].toDouble()
|
||||||
}
|
}
|
||||||
if (defaultKvStore.getString(LAST_ZOOM) != null) {
|
if (defaultKvStore.getString(LAST_ZOOM) != null) {
|
||||||
defaultZoom = defaultKvStore.getString(LAST_ZOOM)!!
|
defaultZoom = defaultKvStore.getString(LAST_ZOOM)!!.toDouble()
|
||||||
.toDouble()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
locationPickerIntent = LocationPicker.IntentBuilder()
|
locationPickerIntent = LocationPicker.IntentBuilder()
|
||||||
|
|
@ -907,4 +919,4 @@ class UploadMediaDetailFragment : UploadBaseFragment(), UploadMediaDetailsContra
|
||||||
const val UPLOADABLE_FILE: String = "uploadable_file"
|
const val UPLOADABLE_FILE: String = "uploadable_file"
|
||||||
const val UPLOAD_MEDIA_DETAILS: String = "upload_media_detail_adapter"
|
const val UPLOAD_MEDIA_DETAILS: String = "upload_media_detail_adapter"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue