Skip to content

Commit 54433fc

Browse files
committed
fix: address PR review comments\n\n- Improved URL validation in LoginViewModel using URLUtil.\n- Added exception handling around URI constructor and network calls.\n- Cleaned up wildcard imports in UI files.\n- Ensured isLoading is reset on error.
1 parent 4a8fe5c commit 54433fc

4 files changed

Lines changed: 87 additions & 32 deletions

File tree

android/app/src/main/java/com/httpsms/ui/login/LoginActivityContent.kt

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,20 @@ import androidx.compose.foundation.layout.height
1010
import androidx.compose.foundation.layout.padding
1111
import androidx.compose.foundation.layout.size
1212
import androidx.compose.foundation.rememberScrollState
13+
import androidx.compose.foundation.text.ClickableText
1314
import androidx.compose.foundation.text.KeyboardOptions
1415
import androidx.compose.foundation.verticalScroll
15-
import androidx.compose.foundation.text.ClickableText
16+
import androidx.compose.material.icons.Icons
1617
import androidx.compose.material.icons.filled.QrCodeScanner
17-
import androidx.compose.material3.*
18+
import androidx.compose.material3.Button
19+
import androidx.compose.material3.ButtonDefaults
20+
import androidx.compose.material3.CircularProgressIndicator
21+
import androidx.compose.material3.Icon
22+
import androidx.compose.material3.IconButton
23+
import androidx.compose.material3.MaterialTheme
24+
import androidx.compose.material3.OutlinedTextField
25+
import androidx.compose.material3.Text
1826
import androidx.compose.runtime.Composable
19-
import androidx.compose.material.icons.Icons
2027
import androidx.compose.runtime.collectAsState
2128
import androidx.compose.runtime.getValue
2229
import androidx.compose.ui.Alignment

android/app/src/main/java/com/httpsms/ui/login/LoginViewModel.kt

Lines changed: 27 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import android.content.pm.PackageManager
66
import android.os.Build
77
import android.telephony.SubscriptionManager
88
import android.telephony.TelephonyManager
9+
import android.webkit.URLUtil
910
import androidx.core.content.ContextCompat
1011
import androidx.lifecycle.ViewModel
1112
import androidx.lifecycle.viewModelScope
@@ -21,6 +22,7 @@ import kotlinx.coroutines.launch
2122
import kotlinx.coroutines.withContext
2223
import timber.log.Timber
2324
import java.net.URI
25+
import java.net.URISyntaxException
2426

2527
data class LoginUiState(
2628
val apiKey: String = "",
@@ -154,39 +156,46 @@ class LoginViewModel : ViewModel() {
154156
return@launch
155157
}
156158

157-
// Simple URL validation (can be improved)
158-
if (!serverUrl.startsWith("http")) {
159+
if (!URLUtil.isValidUrl(serverUrl)) {
159160
_uiState.value = _uiState.value.copy(
160161
isLoading = false,
161162
serverUrlError = "Server URL [$serverUrl] is invalid"
162163
)
163164
return@launch
164165
}
165166

166-
if (!serverUrl.startsWith("https")) {
167+
if (!URLUtil.isHttpsUrl(serverUrl)) {
167168
_uiState.value = _uiState.value.copy(
168169
isLoading = false,
169170
serverUrlError = "Server URL [$serverUrl] must be HTTPS"
170171
)
171172
return@launch
172173
}
173174

174-
val authResult = withContext(Dispatchers.IO) {
175-
val service = HttpSmsApiService(apiKey, URI(serverUrl))
176-
val e164Phone1 = PhoneNumberValidator.formatE164(phone1, countryCode)
177-
val response1 = service.updateFcmToken(e164Phone1, Constants.SIM1, Settings.getFcmToken(context) ?: "")
178-
179-
if (response1.second != null || response1.third != null) {
180-
return@withContext Pair(response1.second, response1.third)
175+
val authResult = try {
176+
withContext(Dispatchers.IO) {
177+
val service = HttpSmsApiService(apiKey, URI(serverUrl))
178+
val e164Phone1 = PhoneNumberValidator.formatE164(phone1, countryCode)
179+
val response1 = service.updateFcmToken(e164Phone1, Constants.SIM1, Settings.getFcmToken(context) ?: "")
180+
181+
if (response1.second != null || response1.third != null) {
182+
return@withContext Pair(response1.second, response1.third)
183+
}
184+
185+
if (currentState.isDualSim) {
186+
val e164Phone2 = PhoneNumberValidator.formatE164(phone2, countryCode)
187+
val response2 = service.updateFcmToken(e164Phone2, Constants.SIM2, Settings.getFcmToken(context) ?: "")
188+
return@withContext Pair(response2.second, response2.third)
189+
}
190+
191+
Pair(null, null)
181192
}
182-
183-
if (currentState.isDualSim) {
184-
val e164Phone2 = PhoneNumberValidator.formatE164(phone2, countryCode)
185-
val response2 = service.updateFcmToken(e164Phone2, Constants.SIM2, Settings.getFcmToken(context) ?: "")
186-
return@withContext Pair(response2.second, response2.third)
187-
}
188-
189-
Pair(null, null)
193+
} catch (e: URISyntaxException) {
194+
Timber.e(e, "Invalid URI: $serverUrl")
195+
Pair(null, "Server URL [$serverUrl] is invalid")
196+
} catch (e: Exception) {
197+
Timber.e(e, "Login error")
198+
Pair(null, "An unexpected error occurred: ${e.message}")
190199
}
191200

192201
if (authResult.first != null) {

android/app/src/main/java/com/httpsms/ui/main/MainActivityContent.kt

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,31 +2,49 @@ package com.httpsms.ui.main
22

33
import android.telephony.PhoneNumberUtils
44
import androidx.compose.foundation.Image
5-
import androidx.compose.foundation.layout.*
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.IntrinsicSize
7+
import androidx.compose.foundation.layout.PaddingValues
8+
import androidx.compose.foundation.layout.Row
9+
import androidx.compose.foundation.layout.Spacer
10+
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.size
15+
import androidx.compose.foundation.layout.width
616
import androidx.compose.foundation.rememberScrollState
717
import androidx.compose.foundation.verticalScroll
818
import androidx.compose.material.icons.Icons
9-
import androidx.compose.material.icons.automirrored.filled.Logout
10-
import androidx.compose.material.icons.filled.*
11-
import androidx.compose.material3.*
19+
import androidx.compose.material.icons.filled.BatteryAlert
20+
import androidx.compose.material.icons.filled.CheckCircle
21+
import androidx.compose.material.icons.filled.Favorite
22+
import androidx.compose.material.icons.filled.Settings
23+
import androidx.compose.material3.Button
24+
import androidx.compose.material3.ButtonDefaults
25+
import androidx.compose.material3.Card
26+
import androidx.compose.material3.CardDefaults
27+
import androidx.compose.material3.Icon
28+
import androidx.compose.material3.LinearProgressIndicator
29+
import androidx.compose.material3.LocalContentColor
30+
import androidx.compose.material3.MaterialTheme
31+
import androidx.compose.material3.Text
1232
import androidx.compose.runtime.Composable
1333
import androidx.compose.runtime.collectAsState
1434
import androidx.compose.runtime.getValue
1535
import androidx.compose.ui.Alignment
1636
import androidx.compose.ui.Modifier
1737
import androidx.compose.ui.graphics.Color
18-
import androidx.compose.ui.graphics.vector.ImageVector
1938
import androidx.compose.ui.platform.LocalContext
2039
import androidx.compose.ui.res.painterResource
2140
import androidx.compose.ui.res.stringResource
22-
import androidx.compose.ui.res.vectorResource
2341
import androidx.compose.ui.text.font.FontWeight
2442
import androidx.compose.ui.unit.dp
2543
import androidx.compose.ui.unit.sp
2644
import com.httpsms.R
2745
import com.httpsms.ui.theme.Blue500
2846
import com.httpsms.ui.theme.Pink500
29-
import java.util.*
47+
import java.util.Locale
3048

3149
@Composable
3250
fun MainScreen(

android/app/src/main/java/com/httpsms/ui/settings/SettingsActivityContent.kt

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,36 @@ package com.httpsms.ui.settings
22

33
import android.app.Activity
44
import androidx.compose.foundation.isSystemInDarkTheme
5-
import androidx.compose.foundation.layout.*
5+
import androidx.compose.foundation.layout.Column
6+
import androidx.compose.foundation.layout.PaddingValues
7+
import androidx.compose.foundation.layout.Row
8+
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.fillMaxSize
10+
import androidx.compose.foundation.layout.fillMaxWidth
11+
import androidx.compose.foundation.layout.height
12+
import androidx.compose.foundation.layout.padding
13+
import androidx.compose.foundation.layout.width
614
import androidx.compose.foundation.rememberScrollState
715
import androidx.compose.foundation.verticalScroll
816
import androidx.compose.material.icons.Icons
917
import androidx.compose.material.icons.automirrored.filled.ArrowBack
1018
import androidx.compose.material.icons.automirrored.filled.Logout
11-
import androidx.compose.material.icons.filled.ArrowBack
12-
import androidx.compose.material3.*
13-
import androidx.compose.runtime.*
19+
import androidx.compose.material3.Button
20+
import androidx.compose.material3.ButtonDefaults
21+
import androidx.compose.material3.ExperimentalMaterial3Api
22+
import androidx.compose.material3.Icon
23+
import androidx.compose.material3.IconButton
24+
import androidx.compose.material3.MaterialTheme
25+
import androidx.compose.material3.OutlinedTextField
26+
import androidx.compose.material3.Scaffold
27+
import androidx.compose.material3.Switch
28+
import androidx.compose.material3.Text
29+
import androidx.compose.material3.TopAppBar
30+
import androidx.compose.material3.TopAppBarDefaults
31+
import androidx.compose.runtime.Composable
32+
import androidx.compose.runtime.SideEffect
33+
import androidx.compose.runtime.collectAsState
34+
import androidx.compose.runtime.getValue
1435
import androidx.compose.ui.Alignment
1536
import androidx.compose.ui.Modifier
1637
import androidx.compose.ui.graphics.Color

0 commit comments

Comments
 (0)