Skip to content

Commit 464c9a2

Browse files
authored
Develop (#92)
[mage-1505] 1) Fix app crash when clicking "profile" when location access has not been previously granted [mage-1504] 1) Add proper back button handling to dismiss nav drawer and bottom sheets when they're open. 2) Correct back click handling for SignupActivity. 3) Add back click handling for ServerUrlScreen when it is launched from clicking a button on ServerUrlActivity. [mage-1514] 1) Fix issues with app logo display [mage-1506] 1) Fix dialog window leak in ObservationEditActivity [mage-1444] 1) Add "how to" view pager to server selection page
1 parent f7449d6 commit 464c9a2

35 files changed

+707
-73
lines changed

mage/build.gradle

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,8 +89,8 @@ android {
8989

9090
defaultConfig {
9191
applicationId "mil.nga.giat.mage"
92-
versionCode 1953
93-
versionName '7.2.5'
92+
versionCode 1954
93+
versionName '7.2.6'
9494
minSdkVersion 27
9595
targetSdkVersion 34
9696
multiDexEnabled true

mage/src/main/AndroidManifest.xml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
tools:replace="android:allowBackup"
3434
android:icon="@drawable/ic_launcher"
3535
android:label="@string/app_name"
36-
android:logo="@drawable/ic_wand_white_50dp"
3736
android:supportsRtl="true"
3837
android:theme="@style/AppTheme"
3938
android:requestLegacyExternalStorage="true"

mage/src/main/java/mil/nga/giat/mage/LandingActivity.kt

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ import android.view.MenuItem
1212
import android.view.View
1313
import android.widget.ImageView
1414
import android.widget.TextView
15+
import androidx.activity.OnBackPressedCallback
1516
import androidx.activity.result.ActivityResult
1617
import androidx.activity.result.contract.ActivityResultContracts
1718
import androidx.appcompat.app.AppCompatActivity
@@ -208,6 +209,8 @@ class LandingActivity : AppCompatActivity(), NavigationView.OnNavigationItemSele
208209
)
209210
}
210211

212+
addBackClickHandler()
213+
211214
// Check if MAGE was launched with a local file
212215
val openPath = intent.getStringExtra(EXTRA_OPEN_FILE_PATH)
213216
openPath?.let { handleOpenFilePath(it) }
@@ -292,6 +295,25 @@ class LandingActivity : AppCompatActivity(), NavigationView.OnNavigationItemSele
292295
}
293296
}
294297

298+
private fun addBackClickHandler() {
299+
val onBackPressedCallback = object : OnBackPressedCallback(true) {
300+
override fun handleOnBackPressed() {
301+
if (binding?.drawerLayout?.isDrawerOpen(GravityCompat.START) == true) {
302+
//close drawer when it's open
303+
binding?.drawerLayout?.closeDrawer(GravityCompat.START)
304+
} else {
305+
//drawer is not open, allow default back behavior by disabling this callback and re-triggering the back press
306+
isEnabled = false
307+
onBackPressedDispatcher.onBackPressed()
308+
isEnabled = true //re-enable for next time
309+
}
310+
}
311+
}
312+
313+
//add back handler
314+
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
315+
}
316+
295317
private fun setFeeds(feeds: List<Feed>) {
296318
val menu = binding!!.navigation.menu
297319
val feedsMenu: Menu? = menu.findItem(R.id.feeds_item).subMenu

mage/src/main/java/mil/nga/giat/mage/login/LoginActivity.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ import mil.nga.giat.mage.map.cache.CacheProvider
5151
import mil.nga.giat.mage.sdk.Compatibility.Companion.isServerVersion5
5252
import mil.nga.giat.mage.sdk.preferences.PreferenceHelper
5353
import mil.nga.giat.mage.sdk.utils.MediaUtility
54+
import mil.nga.giat.mage.utils.IntentConstants
5455
import org.apache.commons.lang3.StringUtils
5556
import org.json.JSONException
5657
import org.json.JSONObject
@@ -153,7 +154,7 @@ class LoginActivity : AppCompatActivity() {
153154
changeServerURL()
154155
return
155156
}
156-
findViewById<View>(R.id.server_url).setOnClickListener { changeServerURL() }
157+
findViewById<View>(R.id.server_url).setOnClickListener { changeServerURL(true) }
157158
serverUrlText.text = serverUrl
158159

159160
// Setup login based on last api pull
@@ -357,8 +358,9 @@ class LoginActivity : AppCompatActivity() {
357358
}
358359
}
359360

360-
private fun changeServerURL() {
361+
private fun changeServerURL(launchedFromButtonClick: Boolean = false) {
361362
val intent = Intent(this, ServerUrlActivity::class.java)
363+
intent.putExtra(IntentConstants.LAUNCHED_FROM_BUTTON_CLICK, launchedFromButtonClick)
362364
startActivity(intent)
363365
finish()
364366
}

mage/src/main/java/mil/nga/giat/mage/login/ServerUrlActivity.kt

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,34 @@ package mil.nga.giat.mage.login
22

33
import android.content.Intent
44
import android.os.Bundle
5+
import androidx.activity.compose.BackHandler
56
import androidx.activity.compose.setContent
67
import androidx.appcompat.app.AppCompatActivity
78
import dagger.hilt.android.AndroidEntryPoint
89
import mil.nga.giat.mage.ui.theme.MageTheme3
9-
import mil.nga.giat.mage.ui.setup.ServerUrlScreen
10+
import mil.nga.giat.mage.ui.setup.TopLevelServerUrlScreen
11+
import mil.nga.giat.mage.utils.IntentConstants
1012

1113
@AndroidEntryPoint
1214
class ServerUrlActivity : AppCompatActivity() {
1315
override fun onCreate(savedInstanceState: Bundle?) {
1416
super.onCreate(savedInstanceState)
1517

18+
val launchedFromLogin = intent.getBooleanExtra(IntentConstants.LAUNCHED_FROM_BUTTON_CLICK, false)
19+
20+
val onDone = {
21+
val intent = Intent(this, LoginActivity::class.java)
22+
startActivity(intent)
23+
finish()
24+
}
25+
1626
setContent {
1727
MageTheme3 {
18-
ServerUrlScreen(
19-
onDone = {
20-
val intent = Intent(this, LoginActivity::class.java)
21-
startActivity(intent)
22-
finish()
23-
},
24-
onCancel = {
25-
val intent = Intent(this, LoginActivity::class.java)
26-
startActivity(intent)
27-
finish()
28-
}
29-
)
28+
TopLevelServerUrlScreen(onDone)
29+
}
30+
31+
if (launchedFromLogin) {
32+
BackHandler { onDone() }
3033
}
3134
}
3235
}

mage/src/main/java/mil/nga/giat/mage/login/SignupActivity.kt

Lines changed: 17 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,12 @@ import android.util.Patterns
1111
import android.view.KeyEvent
1212
import android.view.View
1313
import android.view.inputmethod.InputMethodManager
14+
import androidx.activity.OnBackPressedCallback
1415
import androidx.appcompat.app.AlertDialog
1516
import androidx.appcompat.app.AppCompatActivity
1617
import androidx.core.content.ContextCompat
1718
import androidx.core.graphics.ColorUtils
19+
import androidx.core.view.GravityCompat
1820
import androidx.lifecycle.ViewModelProvider
1921
import dagger.hilt.android.AndroidEntryPoint
2022
import mil.nga.giat.mage.R
@@ -38,7 +40,7 @@ open class SignupActivity : AppCompatActivity() {
3840
setContentView(binding.root)
3941

4042
binding.signupButton.setOnClickListener { signup() }
41-
binding.cancelButton.setOnClickListener { cancel() }
43+
binding.cancelButton.setOnClickListener { done() }
4244
binding.refreshCaptcha.setOnClickListener { getCaptcha() }
4345

4446
binding.signupUsername.setOnFocusChangeListener { _: View, hasFocus: Boolean ->
@@ -74,19 +76,28 @@ open class SignupActivity : AppCompatActivity() {
7476
}
7577
}
7678

79+
addBackClickHandler()
80+
7781
viewModel = ViewModelProvider(this).get(SignupViewModel::class.java)
7882
viewModel.signupState.observe(this) { state: SignupState -> onSignupState(state) }
7983
viewModel.signupStatus.observe(this) { status: SignupStatus? -> onSignup(status) }
8084
viewModel.captcha.observe(this) { captcha: String? -> onCaptcha(captcha) }
8185
viewModel.captchaState.observe(this) { state: CaptchaState -> onCaptchaState(state) }
8286
}
8387

84-
protected fun onSignupState(state: SignupState) {
85-
if (state == SignupState.CANCEL) {
86-
done()
87-
} else {
88-
toggleMask(state === SignupState.LOADING)
88+
private fun addBackClickHandler() {
89+
val onBackPressedCallback = object : OnBackPressedCallback(true) {
90+
override fun handleOnBackPressed() {
91+
done()
92+
}
8993
}
94+
95+
//add back handler
96+
onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
97+
}
98+
99+
protected fun onSignupState(state: SignupState) {
100+
toggleMask(state === SignupState.LOADING)
90101
}
91102

92103
private fun onCaptchaState(state: CaptchaState) {
@@ -191,10 +202,6 @@ open class SignupActivity : AppCompatActivity() {
191202
viewModel.getCaptcha(binding.signupUsername.text.toString(), backgroundColor())
192203
}
193204

194-
private fun cancel() {
195-
viewModel.cancel()
196-
}
197-
198205
protected fun hideKeyboard() {
199206
val view: View = findViewById(android.R.id.content)
200207
val imm = getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager

mage/src/main/java/mil/nga/giat/mage/login/SignupViewModel.kt

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ open class SignupViewModel @Inject constructor(
2222
}
2323

2424
enum class SignupState {
25-
COMPLETE, LOADING, CANCEL
25+
COMPLETE, LOADING
2626
}
2727

2828
enum class SignupError {
@@ -98,8 +98,4 @@ open class SignupViewModel @Inject constructor(
9898
_signupState.value = SignupState.COMPLETE
9999
}
100100
}
101-
102-
fun cancel() {
103-
_signupState.value = SignupState.CANCEL
104-
}
105101
}

mage/src/main/java/mil/nga/giat/mage/map/MapFragment.kt

Lines changed: 28 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ import android.view.ViewGroup.MarginLayoutParams
2626
import android.view.ViewGroup.VISIBLE
2727
import android.view.inputmethod.InputMethodManager
2828
import android.widget.Toast
29+
import androidx.activity.OnBackPressedCallback
2930
import androidx.appcompat.app.AlertDialog
3031
import androidx.appcompat.app.AppCompatActivity
3132
import androidx.compose.foundation.layout.Column
@@ -136,7 +137,6 @@ import mil.nga.giat.mage.sdk.exceptions.UserException
136137
import mil.nga.giat.mage.search.GeocoderResult
137138
import mil.nga.giat.mage.search.SearchResponseType
138139
import mil.nga.giat.mage.ui.search.PlacenameSearch
139-
import mil.nga.giat.mage.ui.map.MapSearchViewModel
140140
import mil.nga.giat.mage.ui.sheet.DragHandle
141141
import mil.nga.giat.mage.ui.theme.MageTheme3
142142
import mil.nga.giat.mage.utils.googleMapsUri
@@ -424,6 +424,33 @@ class MapFragment : Fragment(),
424424
}
425425
}
426426
}
427+
428+
addBackClickHandler()
429+
}
430+
431+
private fun addBackClickHandler() {
432+
val onBackPressedCallback = object : OnBackPressedCallback(true) {
433+
override fun handleOnBackPressed() {
434+
if (searchBottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
435+
searchBottomSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
436+
searchBottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
437+
}
438+
else if (featureBottomSheetBehavior.state == BottomSheetBehavior.STATE_EXPANDED ||
439+
featureBottomSheetBehavior.state == BottomSheetBehavior.STATE_COLLAPSED) {
440+
viewModel.deselectFeature()
441+
featureBottomSheetBehavior.state = BottomSheetBehavior.STATE_HIDDEN
442+
}
443+
else {
444+
//if no bottom sheets are consuming the back press, allow default back behavior by disabling this callback and re-triggering the back press
445+
isEnabled = false
446+
requireActivity().onBackPressedDispatcher.onBackPressed()
447+
isEnabled = true //re-enable for next time
448+
}
449+
}
450+
}
451+
452+
//add back handler
453+
requireActivity().onBackPressedDispatcher.addCallback(viewLifecycleOwner, onBackPressedCallback)
427454
}
428455

429456
private fun onObservationAction(action: Any) {

mage/src/main/java/mil/nga/giat/mage/observation/edit/ObservationEditActivity.kt

Lines changed: 22 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ open class ObservationEditActivity : AppCompatActivity() {
8686
private var defaultMapLatLng = LatLng(0.0, 0.0)
8787
private var defaultMapZoom: Float = 0f
8888

89+
private var discardChangesDialog: AlertDialog? = null
90+
8991
@Inject lateinit var eventLocalDataSource: EventLocalDataSource
9092

9193
private val requestImagePermission = registerForActivityResult(
@@ -226,11 +228,21 @@ open class ObservationEditActivity : AppCompatActivity() {
226228
}
227229

228230
private fun cancel() {
229-
AlertDialog.Builder(this)
231+
discardChangesDialog?.dismiss()
232+
233+
discardChangesDialog = AlertDialog.Builder(this)
230234
.setTitle("Discard Changes")
231235
.setMessage(R.string.cancel_edit)
232-
.setPositiveButton(R.string.discard_changes) { _, _ -> finish() }
233-
.setNegativeButton(R.string.no, null)
236+
.setPositiveButton(R.string.discard_changes) { dialog, _ ->
237+
dialog.dismiss()
238+
finish()
239+
}
240+
.setNegativeButton(R.string.no) { dialog, _ ->
241+
dialog.dismiss()
242+
}
243+
.setOnDismissListener{
244+
discardChangesDialog = null
245+
}
234246
.show()
235247
}
236248

@@ -483,6 +495,13 @@ open class ObservationEditActivity : AppCompatActivity() {
483495
dialog.show(supportFragmentManager, "DIALOG_FORM_REORDER")
484496
}
485497

498+
override fun onStop() {
499+
super.onStop()
500+
//dismiss the dialog if it's showing and the activity is stopping, to prevent window leaks
501+
discardChangesDialog?.dismiss()
502+
discardChangesDialog = null
503+
}
504+
486505
companion object {
487506
private val LOG_NAME = ObservationEditActivity::class.java.name
488507

mage/src/main/java/mil/nga/giat/mage/profile/ProfileActivity.java

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@
5353

5454
import java.io.File;
5555
import java.io.IOException;
56+
import java.util.Date;
5657
import java.util.List;
5758
import java.util.Locale;
5859
import java.util.UUID;
@@ -358,14 +359,9 @@ public void onMapAndViewReady(GoogleMap map) {
358359
map.setMapStyle(MapStyleOptions.loadRawResourceStyle(getApplicationContext(), R.raw.map_theme_night));
359360
}
360361

361-
if (latLng != null) {
362-
Marker marker = map.addMarker(new MarkerOptions()
363-
.position(latLng)
364-
.visible(false));
365-
366-
if (location != null) {
367-
marker.setTag(location.getId());
368-
}
362+
if (latLng != null && location != null) {
363+
Marker marker = map.addMarker(new MarkerOptions().position(latLng).visible(false));
364+
marker.setTag(location.getId());
369365

370366
LocationAgeTransformation transformation = new LocationAgeTransformation(application, location.getTimestamp().getTime());
371367

@@ -383,11 +379,11 @@ public void onMapAndViewReady(GoogleMap map) {
383379

384380
int color = transformation.locationColor();
385381
map.addCircle(new CircleOptions()
386-
.center(latLng)
387-
.radius(accuracy)
388-
.fillColor(ColorUtils.setAlphaComponent(color, (int) (256 * .20)))
389-
.strokeColor(ColorUtils.setAlphaComponent(color, (int) (256 * .87)))
390-
.strokeWidth(2.0f));
382+
.center(latLng)
383+
.radius(accuracy)
384+
.fillColor(ColorUtils.setAlphaComponent(color, (int) (256 * .20)))
385+
.strokeColor(ColorUtils.setAlphaComponent(color, (int) (256 * .87)))
386+
.strokeWidth(2.0f));
391387

392388
double latitudePadding = (accuracy / 111325);
393389
LatLngBounds bounds = new LatLngBounds(

0 commit comments

Comments
 (0)