Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,9 @@
<activity
android:name=".activity.VITEventsActivity"
android:exported="false" />
<activity
android:name=".activity.MaintenanceActivity"
android:exported="false" />
<activity
android:name=".activity.NavigationActivity"
android:exported="false" />
Expand Down
47 changes: 35 additions & 12 deletions app/src/main/java/com/dscvit/vitty/activity/AuthActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import android.view.View
import android.widget.Toast
import androidx.activity.result.ActivityResultLauncher
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.OnBackPressedCallback
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.edit
import androidx.databinding.DataBindingUtil
Expand All @@ -24,6 +25,7 @@ import com.dscvit.vitty.util.Constants.TOKEN
import com.dscvit.vitty.util.Constants.UID
import com.dscvit.vitty.util.Constants.USER_INFO
import com.dscvit.vitty.util.NotificationPermissionHelper
import com.dscvit.vitty.util.MaintenanceChecker
import com.google.android.gms.auth.api.signin.GoogleSignIn
import com.google.android.gms.auth.api.signin.GoogleSignInAccount
import com.google.android.gms.auth.api.signin.GoogleSignInClient
Expand Down Expand Up @@ -62,6 +64,22 @@ class AuthActivity : AppCompatActivity() {

configureGoogleSignIn()
setupUI()
setupBackPressedHandler()
}

private fun setupBackPressedHandler() {
val callback = object : OnBackPressedCallback(true) {
override fun handleOnBackPressed() {
binding.apply {
if (introPager.currentItem == 0 || loginClick) {
finish()
} else {
introPager.currentItem--
}
}
}
}
onBackPressedDispatcher.addCallback(this, callback)
}

private fun setupNotificationPermissionLauncher() {
Expand Down Expand Up @@ -266,8 +284,9 @@ class AuthActivity : AppCompatActivity() {
val email = firebaseAuth.currentUser?.email
Timber.d("Firebase authentication successful - uid: $uid, email: $email")
saveInfo(acct.idToken, uid)
authViewModel.signInAndGetTimeTable("", "", uid ?: "", "")
leadToNextPage()

// Quick maintenance check for new login
checkMaintenanceBeforeProceed()
} else {
Timber.e("Firebase authentication failed: ${authResult.exception?.message}")
logoutFailed()
Expand All @@ -278,6 +297,20 @@ class AuthActivity : AppCompatActivity() {
}
}

private fun checkMaintenanceBeforeProceed() {
MaintenanceChecker.checkMaintenanceStatusAsync(this) { isUnderMaintenance ->
if (isUnderMaintenance) {
binding.loadingView.visibility = View.GONE
val intent = Intent(this, MaintenanceActivity::class.java)
startActivity(intent)
finish()
} else {
authViewModel.signInAndGetTimeTable("", "", firebaseAuth.currentUser?.uid ?: "", "")
leadToNextPage()
}
}
}

private fun leadToNextPage() {
authViewModel.signInResponse.observe(this) {
if (it != null) {
Expand Down Expand Up @@ -323,14 +356,4 @@ class AuthActivity : AppCompatActivity() {
}
}
}

override fun onBackPressed() {
binding.apply {
if (introPager.currentItem == 0 || loginClick) {
super.onBackPressed()
} else {
introPager.currentItem--
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
package com.dscvit.vitty.activity

import android.content.Intent
import android.os.Bundle
import androidx.compose.ui.platform.ViewCompositionStrategy
import androidx.databinding.DataBindingUtil
import androidx.fragment.app.FragmentActivity
import com.dscvit.vitty.R
import com.dscvit.vitty.databinding.ActivityMaintenanceBinding
import com.dscvit.vitty.theme.VittyTheme
import com.dscvit.vitty.ui.maintenance.MaintenanceScreen
import com.dscvit.vitty.util.MaintenanceChecker

class MaintenanceActivity : FragmentActivity() {

private lateinit var binding: ActivityMaintenanceBinding

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

binding = DataBindingUtil.setContentView(this, R.layout.activity_maintenance)

binding.composeView.apply {
setViewCompositionStrategy(
ViewCompositionStrategy.DisposeOnLifecycleDestroyed(this@MaintenanceActivity)
)
setContent {
VittyTheme {
MaintenanceScreen(
onRetryClick = { retryConnection() },
onExitClick = { exitApp() }
)
}
}
}
}

private fun retryConnection() {
MaintenanceChecker.checkMaintenanceStatusAsync(this) { isUnderMaintenance ->
if (!isUnderMaintenance) {
val intent = Intent(this, InstructionsActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
startActivity(intent)
finish()
}
}
}

private fun exitApp() {
finishAffinity()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ import retrofit2.http.Path
import retrofit2.http.Query

interface APICommunity {
@GET("/")
fun checkServerStatus(): Call<String>

@Headers("Content-Type: application/json")
@POST("/api/v3/auth/check-username")
fun checkUsername(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1050,4 +1050,30 @@ class APICommunityRestClient {
},
)
}

fun checkServerStatus(
retrofitServerStatusListener: RetrofitServerStatusListener,
) {
mApiUser = retrofit.create<APICommunity>(APICommunity::class.java)
val apiServerStatusCall = mApiUser!!.checkServerStatus()
apiServerStatusCall.enqueue(
object : Callback<String> {
override fun onResponse(
call: Call<String>,
response: Response<String>,
) {
Timber.d("ServerStatus: ${response.body()}")
retrofitServerStatusListener.onSuccess(call, response.body(), response.isSuccessful)
}

override fun onFailure(
call: Call<String>,
t: Throwable,
) {
Timber.d("ServerStatusError: ${t.message}")
retrofitServerStatusListener.onError(call, t)
}
},
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -169,3 +169,15 @@ interface RetrofitActiveFriendsListener {
t: Throwable,
)
}

interface RetrofitServerStatusListener {
fun onSuccess(
call: Call<String>,
response: String?,
isSuccessful: Boolean
)
fun onError(
call: Call<String>,
t: Throwable
)
}
34 changes: 32 additions & 2 deletions app/src/main/java/com/dscvit/vitty/ui/main/MainComposeApp.kt
Original file line number Diff line number Diff line change
Expand Up @@ -103,8 +103,10 @@ import com.dscvit.vitty.ui.schedule.ScheduleViewModel
import com.dscvit.vitty.util.Analytics
import com.dscvit.vitty.util.Constants
import com.dscvit.vitty.util.LogoutHelper
import com.dscvit.vitty.util.MaintenanceChecker
import com.dscvit.vitty.util.SemesterUtils
import com.dscvit.vitty.util.UtilFunctions
import com.dscvit.vitty.ui.maintenance.MaintenanceBannerDialog
import com.google.gson.Gson
import com.google.gson.reflect.TypeToken
import java.net.URLDecoder
Expand All @@ -113,6 +115,7 @@ import java.nio.charset.StandardCharsets
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import timber.log.Timber

@Composable
fun MainComposeApp() {
Expand All @@ -129,6 +132,9 @@ fun MainComposeApp() {

var campus by remember { mutableStateOf(prefs.getString(Constants.COMMUNITY_CAMPUS, "") ?: "") }
var showCampusDialog by remember { mutableStateOf(campus.isEmpty()) }

// Maintenance banner state
var showMaintenanceBanner by remember { mutableStateOf(false) }

DisposableEffect(Unit) {
val listener =
Expand Down Expand Up @@ -208,13 +214,24 @@ fun MainComposeApp() {
}
}

LaunchedEffect(Unit) {
if (UtilFunctions.isNetworkAvailable(context)) {
MaintenanceChecker.checkMaintenanceStatusAsync(context) { isUnderMaintenance ->
Timber.d("Dialog check result: isUnderMaintenance=%s", isUnderMaintenance)
showMaintenanceBanner = isUnderMaintenance
}
} else {
Timber.d("No network available")
}
}

VittyTheme {
ModalNavigationDrawer(
drawerState = drawerState,
drawerContent = {
DrawerContent(
navController = navController,
onCloseDrawer = { scope.launch { drawerState.close() } },
onCloseDrawer = { scope.launch { drawerState.close() } }
)
},
) {
Expand Down Expand Up @@ -866,6 +883,19 @@ fun MainComposeApp() {
onDismiss = { showCampusDialog = false },
)
}

// Maintenance Banner Dialog
MaintenanceBannerDialog(
isVisible = showMaintenanceBanner,
onDismiss = {
showMaintenanceBanner = false
},
onRetryClick = {
MaintenanceChecker.checkMaintenanceStatusAsync(context) { isUnderMaintenance ->
showMaintenanceBanner = isUnderMaintenance
}
}
)
}
}
}
Expand Down Expand Up @@ -1091,7 +1121,7 @@ fun NavigationItem(
@Composable
fun DrawerContent(
navController: NavHostController,
onCloseDrawer: () -> Unit,
onCloseDrawer: () -> Unit
) {
val context = LocalContext.current
val prefs = remember { context.getSharedPreferences(Constants.USER_INFO, 0) }
Expand Down
Loading
Loading