218 lines
8.3 KiB
Kotlin
218 lines
8.3 KiB
Kotlin
/*
|
|
* TrackFragment.kt
|
|
* Implements the TrackFragment fragment
|
|
* A TrackFragment displays a previously recorded track
|
|
*
|
|
* This file is part of
|
|
* TRACKBOOK - Movement Recorder for Android
|
|
*
|
|
* Copyright (c) 2016-20 - Y20K.org
|
|
* Licensed under the MIT-License
|
|
* http://opensource.org/licenses/MIT
|
|
*
|
|
* Trackbook uses osmdroid - OpenStreetMap-Tools for Android
|
|
* https://github.com/osmdroid/osmdroid
|
|
*/
|
|
|
|
|
|
package org.y20k.trackbook
|
|
|
|
|
|
import YesNoDialog
|
|
import android.app.Activity
|
|
import android.content.Context
|
|
import android.content.Intent
|
|
import android.content.pm.PackageManager
|
|
import android.net.Uri
|
|
import android.os.Bundle
|
|
import android.os.Vibrator
|
|
import android.view.LayoutInflater
|
|
import android.view.View
|
|
import android.view.ViewGroup
|
|
import android.widget.Toast
|
|
import androidx.core.content.FileProvider
|
|
import androidx.core.net.toFile
|
|
import androidx.core.os.bundleOf
|
|
import androidx.fragment.app.Fragment
|
|
import androidx.navigation.fragment.findNavController
|
|
import kotlinx.coroutines.GlobalScope
|
|
import kotlinx.coroutines.launch
|
|
import org.y20k.trackbook.core.Track
|
|
import org.y20k.trackbook.dialogs.RenameTrackDialog
|
|
import org.y20k.trackbook.helpers.FileHelper
|
|
import org.y20k.trackbook.helpers.LogHelper
|
|
import org.y20k.trackbook.helpers.MapOverlay
|
|
import org.y20k.trackbook.helpers.TrackHelper
|
|
import org.y20k.trackbook.ui.TrackFragmentLayoutHolder
|
|
|
|
|
|
class TrackFragment : Fragment(), RenameTrackDialog.RenameTrackListener, YesNoDialog.YesNoDialogListener, MapOverlay.MarkerListener {
|
|
|
|
/* Define log tag */
|
|
private val TAG: String = LogHelper.makeLogTag(TrackFragment::class.java)
|
|
|
|
|
|
/* Main class variables */
|
|
private lateinit var layout: TrackFragmentLayoutHolder
|
|
private lateinit var track: Track
|
|
|
|
|
|
/* Overrides onCreate from Fragment */
|
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
super.onCreate(savedInstanceState)
|
|
// get track
|
|
val fileUriString: String = arguments?.getString(Keys.ARG_TRACK_FILE_URI, String()) ?: String()
|
|
if (fileUriString.isNotBlank()) {
|
|
track = FileHelper.readTrack(activity as Context, Uri.parse(fileUriString))
|
|
} else {
|
|
track = Track()
|
|
}
|
|
}
|
|
|
|
|
|
/* Overrides onCreateView from Fragment */
|
|
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? {
|
|
// initialize layout
|
|
layout = TrackFragmentLayoutHolder(activity as Context, this as MapOverlay.MarkerListener, inflater, container, track)
|
|
|
|
// set up share button
|
|
layout.shareButton.setOnClickListener {
|
|
openSaveGpxDialog()
|
|
}
|
|
layout.shareButton.setOnLongClickListener {
|
|
val v = (activity as Context).getSystemService(Context.VIBRATOR_SERVICE) as Vibrator
|
|
v.vibrate(50)
|
|
shareGpxTrack()
|
|
return@setOnLongClickListener true
|
|
}
|
|
// set up delete button
|
|
layout.deleteButton.setOnClickListener {
|
|
val dialogMessage: String = "${getString(R.string.dialog_yes_no_message_delete_recording)}\n\n- ${layout.trackNameView.text}"
|
|
YesNoDialog(this@TrackFragment as YesNoDialog.YesNoDialogListener).show(context = activity as Context, type = Keys.DIALOG_DELETE_TRACK, messageString = dialogMessage, yesButton = R.string.dialog_yes_no_positive_button_delete_recording)
|
|
}
|
|
// set up rename button
|
|
layout.editButton.setOnClickListener {
|
|
RenameTrackDialog(this as RenameTrackDialog.RenameTrackListener).show(activity as Context, layout.trackNameView.text.toString())
|
|
}
|
|
|
|
return layout.rootView
|
|
}
|
|
|
|
|
|
/* Overrides onResume from Fragment */
|
|
override fun onResume() {
|
|
super.onResume()
|
|
// update zoom level and map center
|
|
layout.updateMapView()
|
|
}
|
|
|
|
|
|
/* Overrides onPause from Fragment */
|
|
override fun onPause() {
|
|
super.onPause()
|
|
// save zoom level and map center
|
|
layout.saveViewStateToTrack()
|
|
}
|
|
|
|
|
|
/* Overrides onActivityResult from Fragment */
|
|
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
|
when (requestCode) {
|
|
// save GPX file to result file location
|
|
Keys.REQUEST_SAVE_GPX -> {
|
|
if (resultCode == Activity.RESULT_OK && data != null) {
|
|
val sourceUri: Uri = Uri.parse(track.gpxUriString)
|
|
val targetUri: Uri? = data.data
|
|
if (targetUri != null) {
|
|
// copy file async (= fire & forget - no return value needed)
|
|
GlobalScope.launch { FileHelper.saveCopyOfFileSuspended( activity as Context, originalFileUri = sourceUri, targetFileUri = targetUri) }
|
|
Toast.makeText(activity as Context, R.string.toast_message_save_gpx, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
}
|
|
// let activity handle result
|
|
else -> super.onActivityResult(requestCode, resultCode, data)
|
|
}
|
|
}
|
|
|
|
|
|
/* Overrides onRenameTrackDialog from RenameTrackDialog */
|
|
override fun onRenameTrackDialog(textInput: String) {
|
|
// rename track async (= fire & forget - no return value needed)
|
|
GlobalScope.launch { FileHelper.renameTrackSuspended(activity as Context, layout.track, textInput) }
|
|
// update name in layout
|
|
layout.track.name = textInput
|
|
layout.trackNameView.text = textInput
|
|
}
|
|
|
|
|
|
/* Overrides onYesNoDialog from YesNoDialogListener */
|
|
override fun onYesNoDialog(type: Int, dialogResult: Boolean, payload: Int, payloadString: String) {
|
|
when (type) {
|
|
Keys.DIALOG_DELETE_TRACK -> {
|
|
when (dialogResult) {
|
|
// user tapped remove track
|
|
true -> {
|
|
// switch to TracklistFragment and remove track there
|
|
val trackId: Long = arguments?.getLong(Keys.ARG_TRACK_ID, -1L) ?: -1L
|
|
val bundle: Bundle = bundleOf(Keys.ARG_TRACK_ID to trackId)
|
|
findNavController().navigate(R.id.tracklist_fragment, bundle)
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/* Overrides onMarkerTapped from MarkerListener */
|
|
override fun onMarkerTapped(latitude: Double, longitude: Double) {
|
|
super.onMarkerTapped(latitude, longitude)
|
|
// update track display
|
|
track = TrackHelper.toggleStarred(activity as Context, track, latitude, longitude)
|
|
layout.updateTrackOverlay(track)
|
|
// save track
|
|
GlobalScope.launch {
|
|
FileHelper.saveTrackSuspended(track, true)
|
|
}
|
|
}
|
|
|
|
|
|
/* Opens up a file picker to select the save location */
|
|
private fun openSaveGpxDialog() {
|
|
val intent = Intent(Intent.ACTION_CREATE_DOCUMENT).apply {
|
|
addCategory(Intent.CATEGORY_OPENABLE)
|
|
type = Keys.MIME_TYPE_GPX
|
|
putExtra(Intent.EXTRA_TITLE, FileHelper.getGpxFileName(track))
|
|
}
|
|
// file gets saved in onActivityResult
|
|
val packageManager: PackageManager? = activity?.packageManager
|
|
if (packageManager != null && intent.resolveActivity(packageManager) != null) {
|
|
startActivityForResult(intent, Keys.REQUEST_SAVE_GPX)
|
|
} else {
|
|
Toast.makeText(activity as Context, R.string.toast_message_install_file_helper, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
|
|
|
|
/* Share track as GPX via share sheet */
|
|
private fun shareGpxTrack() {
|
|
val gpxFile = Uri.parse(layout.track.gpxUriString).toFile()
|
|
val gpxShareUri = FileProvider.getUriForFile(this.activity as Context, "${requireActivity().applicationContext.packageName}.provider", gpxFile)
|
|
val shareIntent: Intent = Intent.createChooser(Intent().apply {
|
|
action = Intent.ACTION_SEND
|
|
data = gpxShareUri
|
|
type = Keys.MIME_TYPE_GPX
|
|
flags = Intent.FLAG_GRANT_READ_URI_PERMISSION
|
|
putExtra(Intent.EXTRA_STREAM, gpxShareUri)
|
|
}, null)
|
|
|
|
// show share sheet - if file helper is available
|
|
val packageManager: PackageManager? = activity?.packageManager
|
|
if (packageManager != null && shareIntent.resolveActivity(packageManager) != null) {
|
|
startActivity(shareIntent)
|
|
} else {
|
|
Toast.makeText(activity, R.string.toast_message_install_file_helper, Toast.LENGTH_LONG).show()
|
|
}
|
|
}
|
|
|
|
}
|