Skip to content

Commit

Permalink
✨ Year in review - #TräwellingWrapped (#451)
Browse files Browse the repository at this point in the history
  • Loading branch information
jheubuch authored Dec 4, 2024
1 parent b0d42c1 commit 6ecfd77
Show file tree
Hide file tree
Showing 15 changed files with 1,170 additions and 6 deletions.
4 changes: 4 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@
android:name=".ui.info.InfoActivity"
android:exported="false" />

<activity
android:name=".ui.wrapped.WrappedActivity"
android:exported="false" />

<meta-data
android:name="io.sentry.dsn"
android:value="${SENTRY_DSN}" />
Expand Down
9 changes: 9 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 @@ -27,6 +27,7 @@ import de.hbch.traewelling.api.models.user.TrustedUser
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 de.hbch.traewelling.api.models.wrapped.YearInReviewData
import okhttp3.OkHttpClient
import retrofit2.Call
import retrofit2.Response
Expand Down Expand Up @@ -348,6 +349,11 @@ interface ReportService {
): Response<Unit>
}

interface WrappedService {
@GET("year-in-review")
suspend fun getYearInReview(): Response<YearInReviewData>
}

object TraewellingApi {
var jwt: String = ""

Expand All @@ -372,6 +378,9 @@ object TraewellingApi {
val reportService: ReportService by lazy {
trwlRetrofit.create(ReportService::class.java)
}
val wrappedService: WrappedService by lazy {
trwlRetrofit.create(WrappedService::class.java)
}
}

object WebhookRelayApi {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ data class User(

data class LightUser(
@SerializedName("id") val id: Int,
@SerializedName("displayName") val name: String,
@SerializedName("displayName", alternate = ["name"]) val name: String,
@SerializedName("username") val username: String,
@SerializedName("profilePicture") val avatarUrl: String,
@SerializedName("mastodonUrl") val mastodonUrl: String?
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
package de.hbch.traewelling.api.models.wrapped

import com.google.gson.annotations.SerializedName
import de.hbch.traewelling.api.models.station.Station
import de.hbch.traewelling.api.models.status.Status
import de.hbch.traewelling.api.models.user.LightUser

data class YearInReviewData(
val user: LightUser,
val count: Int,
val distance: YearInReviewSumStats,
val duration: YearInReviewSumStats,
val totalDelay: Int,
val operators: TopBy,
val lines: TopBy,
val longestTrips: LongestTrips,
@SerializedName("fastestTrips") val fastestTrip: Status,
@SerializedName("slowestTrips") val slowestTrip: Status,
@SerializedName("mostDelayedArrivals") val mostDelayedArrival: Status,
val topDestinations: List<TopStation>,
val lonelyStations: List<TopStation>,
val mostLikedStatuses: List<MostLikedStatus>
)

data class YearInReviewSumStats(
val total: Long,
val averagePerDay: Float
)

data class TopByDistance(
val operator: String,
val distance: Long,
val line: String?
)

data class TopByDuration(
val operator: String,
val duration: Long,
val line: String?
)

data class TopBy(
val count: Int?,
val topByDistance: TopByDistance,
val topByDuration: TopByDuration
)

data class LongestTrips(
val distance: Status,
val duration: Status
)

data class TopStation(
val count: Int,
val station: Station
)

data class MostLikedStatus(
val likeCount: Int,
val status: Status
)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package de.hbch.traewelling.shared

import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import io.getunleash.UnleashClient

class FeatureFlags private constructor() {
Expand All @@ -12,12 +14,17 @@ class FeatureFlags private constructor() {

private var unleashClient: UnleashClient? = null

private var _wrappedActive = MutableLiveData(false)
val wrappedActive: LiveData<Boolean> get() = _wrappedActive

fun init(client: UnleashClient) {
unleashClient = client
unleashClient?.startPolling()
}

fun flagsUpdated() {
unleashClient?.let { }
unleashClient?.let {
_wrappedActive.postValue(it.isEnabled("WrappedActive", false))
}
}
}
2 changes: 1 addition & 1 deletion app/src/main/kotlin/de/hbch/traewelling/theme/Type.kt
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import de.hbch.traewelling.R
val RalewayFont = Font(R.font.raleway)
val TwindexxFont = Font(R.font.ae_matrix16_btmodern_standard)
val Raleway = FontFamily(RalewayFont)
val Twindexx = FontFamily(TwindexxFont)
val BTModern = FontFamily(TwindexxFont)

val DefaultTypography = Typography()
val AppTypography = Typography(
Expand Down
14 changes: 14 additions & 0 deletions app/src/main/kotlin/de/hbch/traewelling/ui/dashboard/Dashboard.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,9 +21,11 @@ import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import androidx.lifecycle.viewmodel.compose.viewModel
import de.hbch.traewelling.api.models.status.Status
import de.hbch.traewelling.shared.FeatureFlags
import de.hbch.traewelling.shared.LoggedInUserViewModel
import de.hbch.traewelling.ui.include.cardSearchStation.CardSearch
import de.hbch.traewelling.ui.include.status.CheckInCardViewModel
import de.hbch.traewelling.ui.wrapped.WrappedTeaser
import de.hbch.traewelling.util.OnBottomReached
import de.hbch.traewelling.util.checkInList
import kotlinx.coroutines.launch
Expand Down Expand Up @@ -55,6 +57,9 @@ fun Dashboard(
)
val checkInListState = rememberLazyListState()

val featureFlags = remember { FeatureFlags.getInstance() }
val wrappedActive by featureFlags.wrappedActive.observeAsState(false)

checkInListState.OnBottomReached {
if (dashboardViewModel.checkIns.size > 0) {
dashboardViewModel.loadCheckIns(++currentPage)
Expand Down Expand Up @@ -91,6 +96,15 @@ fun Dashboard(
}
)
}

if (wrappedActive) {
item {
WrappedTeaser(
modifier = Modifier.fillMaxWidth()
)
}
}

checkInList(
checkIns,
checkInCardViewModel,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import de.hbch.traewelling.api.models.station.Station
import de.hbch.traewelling.api.models.user.User
import de.hbch.traewelling.theme.LocalColorScheme
import de.hbch.traewelling.theme.LocalFont
import de.hbch.traewelling.theme.Twindexx
import de.hbch.traewelling.theme.BTModern
import de.hbch.traewelling.ui.search.Search
import de.hbch.traewelling.util.getGreeting

Expand All @@ -42,7 +42,7 @@ fun CardSearch(
text = getGreeting(),
style = LocalFont.current.headlineLarge,
modifier = Modifier.padding(8.dp),
fontFamily = Twindexx,
fontFamily = BTModern,
color = LocalColorScheme.current.primary
)
Search(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import android.net.Uri
import android.os.Bundle
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.enableEdgeToEdge
import androidx.browser.customtabs.CustomTabsIntent
import de.hbch.traewelling.BuildConfig
import de.hbch.traewelling.theme.MainTheme
Expand All @@ -13,7 +14,7 @@ class InfoActivity : ComponentActivity() {

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

enableEdgeToEdge()
setContent {
MainTheme {
InfoScreen(
Expand Down
Loading

0 comments on commit 6ecfd77

Please sign in to comment.