Skip to content

Commit

Permalink
✨ Add profile editing (#407)
Browse files Browse the repository at this point in the history
  • Loading branch information
jheubuch authored Aug 13, 2024
1 parent bdd5894 commit 6d94fc7
Show file tree
Hide file tree
Showing 15 changed files with 743 additions and 106 deletions.
10 changes: 10 additions & 0 deletions app/src/main/kotlin/de/hbch/traewelling/api/ApiService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,9 @@ import de.hbch.traewelling.api.models.status.*
import de.hbch.traewelling.api.models.status.Tag
import de.hbch.traewelling.api.models.trip.HafasTrainTrip
import de.hbch.traewelling.api.models.trip.HafasTripPage
import de.hbch.traewelling.api.models.user.SaveUserSettings
import de.hbch.traewelling.api.models.user.User
import de.hbch.traewelling.api.models.user.UserSettings
import de.hbch.traewelling.api.models.webhook.WebhookUserCreateRequest
import okhttp3.OkHttpClient
import retrofit2.Call
Expand Down Expand Up @@ -264,6 +266,14 @@ interface UserService {
fun unmuteUser(
@Path("id") userId: Int
): Call<Data<Unit>>

@GET("settings/profile")
suspend fun getUserSettings(): Response<Data<UserSettings>>

@PUT("settings/profile")
suspend fun saveUserSettings(
@Body settings: SaveUserSettings
): Response<Data<UserSettings>>
}

interface WebhookRelayService {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,16 @@ class LogInterceptor : Interceptor {
val requestBody = buffer.readUtf8()
buffer.close()

val responseCopy = response.newBuilder().build()

val additionalInfo = mapOf(
Pair("path", path),
Pair("code", response.code.toString()),
Pair("responseBody", response.body?.string() ?: "no body"),
Pair("code", responseCopy.code.toString()),
// Pair("responseBody", responseCopy.body?.string() ?: "no body"),
Pair("requestBody", requestBody)
)

Logger.captureMessage("[${response.code}] $path", additionalInfo)
Logger.captureMessage("[${responseCopy.code}] $path", additionalInfo)
}
return response
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package de.hbch.traewelling.api.models.status

import com.google.gson.annotations.SerializedName
import de.hbch.traewelling.R
import de.hbch.traewelling.providers.checkin.CheckInRequest
import java.time.ZonedDateTime

Expand All @@ -25,3 +26,24 @@ data class TrwlCheckInResponse(
@SerializedName("alsoOnThisConnection") val coTravellers: List<Status>,
@SerializedName("points") val points: StatusPoints
)

enum class AllowedPersonsToCheckIn {
@SerializedName("forbidden")
FORBIDDEN {
override val icon = R.drawable.ic_cancel
override val title = R.string.nobody
},
@SerializedName("friends")
FRIENDS {
override val icon = R.drawable.ic_group
override val title = R.string.friends
},
@SerializedName("list")
TRUSTED_USERS {
override val icon = R.drawable.ic_authorized
override val title = R.string.trusted
};

abstract val icon: Int
abstract val title: Int
}
Original file line number Diff line number Diff line change
Expand Up @@ -157,10 +157,12 @@ enum class StatusVisibility() {
ONLY_AUTHENTICATED {
override val icon = R.drawable.ic_authorized
override val title = R.string.visibility_only_authenticated
override val isMastodonVisibility = false
};

abstract val icon: Int
abstract val title: Int
open val isMastodonVisibility: Boolean = true
}

enum class StatusBusiness(val business: Int) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package de.hbch.traewelling.api.models.user

import com.google.gson.annotations.SerializedName
import de.hbch.traewelling.api.models.status.AllowedPersonsToCheckIn
import de.hbch.traewelling.api.models.status.StatusVisibility

data class UserSettings(
val username: String,
val displayName: String,
val profilePicture: String,
val privateProfile: Boolean,
val defaultStatusVisibility: StatusVisibility,
val privacyHideDays: Int,
val email: String,
@SerializedName("mastodon") val mastodonUrl: String?,
val mastodonVisibility: StatusVisibility?,
@SerializedName("friendCheckin") val allowedPersonsToCheckIn: AllowedPersonsToCheckIn,
val likesEnabled: Boolean,
val pointsEnabled: Boolean
)

data class SaveUserSettings(
val username: String,
val displayName: String,
val privateProfile: Boolean,
val defaultStatusVisibility: Int,
val privacyHideDays: Int?,
val mastodonVisibility: Int,
@SerializedName("friendCheckin") val allowedPersonsToCheckIn: AllowedPersonsToCheckIn,
val likesEnabled: Boolean,
val pointsEnabled: Boolean
)
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,11 @@ object Settings : Destination {
override val route = "settings"
}

object ProfileEdit : Destination {
override val label = R.string.edit_profile
override val route = "edit-profile"
}

val SCREENS = listOf(
Dashboard,
EnRoute,
Expand All @@ -173,7 +178,8 @@ val SCREENS = listOf(
CheckIn,
CheckInResult,
StatusDetails,
Settings
Settings,
ProfileEdit
)

val BOTTOM_NAVIGATION = listOf(
Expand Down
13 changes: 12 additions & 1 deletion app/src/main/kotlin/de/hbch/traewelling/navigation/NavHost.kt
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ import de.hbch.traewelling.ui.settings.Settings
import de.hbch.traewelling.ui.statistics.DailyStatistics
import de.hbch.traewelling.ui.statistics.Statistics
import de.hbch.traewelling.ui.statusDetail.StatusDetail
import de.hbch.traewelling.ui.user.EditProfile
import de.hbch.traewelling.ui.user.Profile
import de.hbch.traewelling.util.HOME
import de.hbch.traewelling.util.popBackStackAndNavigate
Expand Down Expand Up @@ -263,11 +264,21 @@ fun TraewelldroidNavHost(
navController.navigate("daily-statistics/$formatted")
},
userSelectedAction = navToUserProfile,
joinConnection = navToJoinConnection
joinConnection = navToJoinConnection,
editProfile = {
navController.navigate(ProfileEdit.route) {
launchSingleTop = true
}
}
)

onResetFloatingActionButton()
}
composable(ProfileEdit.route) {
EditProfile(
snackbarHostState = snackbarHostState
)
}
composable(
DailyStatistics.route,
deepLinks = DailyStatistics.deepLinks
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,14 @@ import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import com.jcloquell.androidsecurestorage.SecureStorage
import de.hbch.traewelling.api.TraewellingApi
import de.hbch.traewelling.api.models.Data
import de.hbch.traewelling.api.models.user.SaveUserSettings
import de.hbch.traewelling.api.models.user.UserSettings
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import retrofit2.Response

class SettingsViewModel : ViewModel() {

Expand All @@ -17,6 +25,9 @@ class SettingsViewModel : ViewModel() {
private val _displayDivergentStop = MutableLiveData(true)
val displayDivergentStop: LiveData<Boolean> get() = _displayDivergentStop

private val _userSettings = MutableLiveData<UserSettings?>(null)
val userSettings: LiveData<UserSettings?> get() = _userSettings

fun loadSettings(context: Context) {
val secureStorage = SecureStorage(context)

Expand All @@ -29,6 +40,11 @@ class SettingsViewModel : ViewModel() {
_displayDivergentStop.postValue(
secureStorage.getObject(SharedValues.SS_DISPLAY_DIVERGENT_STOP, Boolean::class.java) ?: true
)

val coroutineScope = CoroutineScope(Dispatchers.IO)
coroutineScope.launch {
getUserSettings()
}
}

fun updateDisplayTagsInCard(context: Context, state: Boolean) {
Expand All @@ -48,4 +64,30 @@ class SettingsViewModel : ViewModel() {
secureStorage.storeObject(SharedValues.SS_DISPLAY_DIVERGENT_STOP, state)
_displayDivergentStop.postValue(state)
}

suspend fun getUserSettings() {
val settings = try {
val response = TraewellingApi.userService.getUserSettings()
if (response.isSuccessful) {
response.body()?.data
} else {
null
}
} catch (_: Exception) {
null
}
_userSettings.postValue(settings)
}

suspend fun saveUserSettings(settings: SaveUserSettings): Response<Data<UserSettings>>? {
return try {
val response = TraewellingApi.userService.saveUserSettings(settings)
if (response.isSuccessful) {
_userSettings.postValue(response.body()?.data)
}
response
} catch (ex: Exception) {
null
}
}
}
Loading

0 comments on commit 6d94fc7

Please sign in to comment.