Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
99dca0b
feat: Started implementing Widgets
whyKVD Feb 26, 2026
b01941f
feat: Started working on how to display the trips in the widget
whyKVD Feb 27, 2026
dd8f581
feat: Now the widget is displayed correctly with all the data
whyKVD Mar 5, 2026
db94074
feat: Created a configuration activity for the widget
whyKVD Mar 5, 2026
05eeaa8
feat: Now the widget can be configured
whyKVD Mar 6, 2026
fe91af3
feat: Now the widget can be modified on the homescreen
whyKVD Mar 6, 2026
e54eb74
feat: Added the direction icon and other fixes
whyKVD Mar 6, 2026
c594d9c
fix: Fixed a problem gived byt the android studio linter
whyKVD Mar 6, 2026
caae9eb
feat: Now the widget can perform next and prev trip calls, still not …
whyKVD Mar 6, 2026
0423ac9
feat: All the action, next, prev and refresh are completed almost sim…
whyKVD Mar 7, 2026
5a5af71
fix: Deleted a receiver that does not exist anymore
whyKVD Mar 7, 2026
9302de5
fix: Fixed the refresh call after the loading of a trip from the cache
whyKVD Mar 7, 2026
c0cd754
feat: Added the line indication and the possibility to change the dir…
whyKVD Mar 7, 2026
dc0b68a
style: Created some seamless floatingbutton
whyKVD Mar 7, 2026
40a1cd9
feat: Configuration activity enhancement and some code cleanup
whyKVD Mar 8, 2026
4737804
feat: Started using mutablestateflow in the widget
whyKVD Mar 9, 2026
880b586
feat: Refactoring how to retrieve trip data introduced a lot of bugs
whyKVD Mar 9, 2026
cef83c0
fix: Resolved the infinite loading problem
whyKVD Mar 10, 2026
70d7985
fix: Fixed the wrong update of the tripIndex
whyKVD Mar 10, 2026
fd34527
refactoring: Added the StopLineTypeIcon and changed some tint
whyKVD Mar 11, 2026
7cc8821
refactoring: tried to decuple the state from the ui
whyKVD Mar 12, 2026
b7bf114
feat: Changed the minSdk from 21 to 23
whyKVD Mar 20, 2026
9af0879
feat: Created WidgetState and modified some models
whyKVD Mar 20, 2026
2cd1438
feat: Created a worker to update the widget
whyKVD Mar 20, 2026
dd39bee
feat: Modified the Manifest and the application file
whyKVD Mar 20, 2026
68538b7
feat: Modified the ConfigurationActivity and the Actions
whyKVD Mar 20, 2026
46039fb
style: Minor changes and some refactoring
whyKVD Mar 23, 2026
8fd2232
refactoring: General code refactoring
whyKVD Mar 25, 2026
baef5d1
refactoring: Added menu icon
whyKVD Mar 29, 2026
1dc20b4
refactoring: Deleted the unused keys
whyKVD Mar 29, 2026
5d69830
refactoring: Renamed Available to LineTripsAvailable
whyKVD Mar 29, 2026
4adf5b3
feat: Added StopTripsState
whyKVD Mar 29, 2026
d2984e2
feat: Updated the actions and created a new entry point
whyKVD Mar 29, 2026
3ad45b5
feat: Added the stopClickAction run callback
whyKVD Mar 29, 2026
f3bea5a
refactoring: Refactored the view to work better
whyKVD Mar 29, 2026
0aa2867
refactoring: Renamed the state
whyKVD Mar 29, 2026
3766b0c
refactoring: Added some loading behavior
whyKVD Apr 1, 2026
a46dd57
refactoring: Added the updating feature for the stop state
whyKVD Apr 1, 2026
f0f02c3
feat: Limited Widget worker updates
whyKVD Apr 3, 2026
9b8d954
feat: Added a show hide feature for the completed stops
whyKVD Apr 3, 2026
d0d05d8
refactoring: Deleted an unused line
whyKVD Apr 3, 2026
479785b
refactoring: Refactoring of ConfigurationActivity
whyKVD Apr 5, 2026
c8d7cd8
refactoring: More refactoring on the LineSelectionScreenWidget
whyKVD Apr 5, 2026
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
18 changes: 17 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,15 @@ plugins {
alias(libs.plugins.com.google.devtools.ksp)
alias(libs.plugins.com.google.dagger.hilt.android)
alias(libs.plugins.compose.compiler)
alias(libs.plugins.kotlin.serialization)
}

android {
compileSdk 36

defaultConfig {
applicationId "org.stypox.tridenta"
minSdk 21
minSdk 23
targetSdk 36
versionCode 60
versionName "1.5"
Expand Down Expand Up @@ -65,15 +66,25 @@ hilt {
}

dependencies {
implementation libs.androidx.work.runtime.ktx
implementation libs.androidx.hilt.common
implementation libs.androidx.hilt.work
implementation libs.androidx.hilt.compiler
coreLibraryDesugaring libs.desugar.jdk.libs

implementation libs.work

// Core
implementation libs.core.ktx
implementation libs.lifecycle.runtime.ktx
implementation libs.lifecycle.viewmodel.compose
implementation libs.okhttp
implementation libs.preference.ktx

// Serialization
implementation libs.kotlin.serialization
implementation libs.kotlin.serialization.json

// Compose and Material3
implementation libs.activity.compose
implementation libs.compose.ui
Expand All @@ -84,6 +95,11 @@ dependencies {
debugImplementation libs.compose.androidx.ui.test.manifest
implementation libs.compose.androidx.runtime.livedata
implementation libs.androidx.material3
implementation libs.glance
implementation libs.glance.appwidget
implementation libs.glance.material3
implementation libs.glance.preview
implementation libs.glance.appwidget.preview

// Navigation
implementation libs.compose.destinations.core
Expand Down
32 changes: 32 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,38 @@
android:name="android.app.shortcuts"
android:resource="@xml/shortcuts" />
</activity>
<activity
android:name=".widget.WidgetConfigurationActivity"
android:exported="true"
android:taskAffinity=""
android:excludeFromRecents="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_CONFIGURE" />
</intent-filter>
</activity>
<receiver android:name=".widget.LineTripWidgetReceiver"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>

<!-- This is used for the CoroutineWorker -->
<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<!-- If you are using androidx.startup to initialize other components -->
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>
</application>


</manifest>
22 changes: 21 additions & 1 deletion app/src/main/java/org/stypox/tridenta/TridentaApplication.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,14 @@
package org.stypox.tridenta

import android.app.Application
import android.util.Log
import androidx.hilt.work.HiltWorkerFactory
import androidx.work.Configuration
import dagger.hilt.EntryPoint
import dagger.hilt.InstallIn
import dagger.hilt.android.EntryPointAccessors
import dagger.hilt.android.HiltAndroidApp
import dagger.hilt.components.SingletonComponent
import kotlinx.coroutines.MainScope
import org.stypox.tridenta.db.LogDao
import org.stypox.tridenta.log.AppUncaughtExceptionHandler
Expand All @@ -10,7 +17,7 @@ import org.stypox.tridenta.log.setupLogger
import javax.inject.Inject

@HiltAndroidApp
class TridentaApplication : Application() {
class TridentaApplication : Application(), Configuration.Provider {

// store logger's DAO and scope here, so that they are correctly garbage collected when
// Application is destroyed (probably this is not needed, but let's be sure)
Expand All @@ -25,4 +32,17 @@ class TridentaApplication : Application() {
// cleanup old logs (we don't want the database to be cluttered with those)
clearOldLogs()
}

@EntryPoint
@InstallIn(SingletonComponent::class)
interface HiltWorkerFactoryEntryPoint {
fun workerFactory(): HiltWorkerFactory
}

override val workManagerConfiguration by lazy {Configuration.Builder()
.setWorkerFactory(
EntryPointAccessors.fromApplication(this, HiltWorkerFactoryEntryPoint::class.java).workerFactory()
)
.setMinimumLoggingLevel(Log.INFO)
.build()}
}
6 changes: 6 additions & 0 deletions app/src/main/java/org/stypox/tridenta/db/data/DbLine.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@ import androidx.room.Entity
import androidx.room.ForeignKey
import androidx.room.Ignore
import androidx.room.Index
import kotlinx.serialization.Serializable
import org.stypox.tridenta.enums.Area
import org.stypox.tridenta.enums.StopLineType
import org.stypox.tridenta.util.OffsetDateTimeSerializer
import java.time.OffsetDateTime

@Entity(
primaryKeys = ["lineId", "type"]
)
@Serializable
data class DbLine(
// some testing exposed that a line is always identified by the (lineId, type) tuple
val lineId: Int,
Expand Down Expand Up @@ -49,9 +52,12 @@ data class DbLine(
Index("lineId", "lineType")
]
)
@Serializable
data class DbNewsItem(
val serviceType: String,
@Serializable(with = OffsetDateTimeSerializer::class)
val startDate: OffsetDateTime,
@Serializable(with = OffsetDateTimeSerializer::class)
val endDate: OffsetDateTime,
val header: String,
val details: String,
Expand Down
2 changes: 2 additions & 0 deletions app/src/main/java/org/stypox/tridenta/db/data/DbStop.kt
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
package org.stypox.tridenta.db.data

import androidx.room.*
import kotlinx.serialization.Serializable
import org.stypox.tridenta.enums.CardinalPoint
import org.stypox.tridenta.enums.StopLineType

@Entity(
primaryKeys = ["stopId", "type"]
)
@Serializable
data class DbStop(
// some testing exposed that a stop is always identified by the (stopId, type) tuple
val stopId: Int,
Expand Down
3 changes: 2 additions & 1 deletion app/src/main/java/org/stypox/tridenta/repo/data/UiLine.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package org.stypox.tridenta.repo.data

import androidx.annotation.ColorInt
import kotlinx.serialization.Serializable
import org.stypox.tridenta.db.data.DbLine
import org.stypox.tridenta.db.data.DbNewsItem
import org.stypox.tridenta.enums.Area
import org.stypox.tridenta.enums.StopLineType
import java.util.regex.Pattern
import kotlin.math.min

@Serializable
data class UiLine(
val lineId: Int,
val type: StopLineType,
Expand Down
7 changes: 7 additions & 0 deletions app/src/main/java/org/stypox/tridenta/repo/data/UiTrip.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,23 @@
package org.stypox.tridenta.repo.data

import kotlinx.serialization.Serializable
import org.stypox.tridenta.db.data.DbLine
import org.stypox.tridenta.db.data.DbStop
import org.stypox.tridenta.enums.Direction
import org.stypox.tridenta.enums.StopLineType
import org.stypox.tridenta.extractor.data.ExStopTime
import org.stypox.tridenta.extractor.data.ExTrip
import org.stypox.tridenta.util.OffsetDateTimeSerializer
import java.time.OffsetDateTime

/**
* Same as [ExTrip] but with line and stop data loaded
*/
@Serializable
data class UiTrip(
val delay: Int,
val direction: Direction,
@Serializable(with = OffsetDateTimeSerializer::class)
val lastEventReceivedAt: OffsetDateTime?,
val lineId: Int, // needed for when DbLine could not be loaded, and so it is null
val line: DbLine?,
Expand All @@ -28,8 +32,11 @@ data class UiTrip(
/**
* Same as [ExStopTime] but with stop data loaded
*/
@Serializable
data class UiStopTime(
@Serializable(with = OffsetDateTimeSerializer::class)
val arrivalTime: OffsetDateTime?,
@Serializable(with = OffsetDateTimeSerializer::class)
val departureTime: OffsetDateTime?,
val stop: DbStop?,
)
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import org.stypox.tridenta.R
import org.stypox.tridenta.ui.destinations.LogsScreenDestination
import org.stypox.tridenta.destinations.LogsScreenDestination
import org.stypox.tridenta.ui.theme.TitleText


Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/stypox/tridenta/ui/error/ErrorRow.kt
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ import androidx.compose.ui.unit.dp
import com.ramcosta.composedestinations.navigation.DestinationsNavigator
import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import org.stypox.tridenta.R
import org.stypox.tridenta.ui.destinations.LogsScreenDestination
import org.stypox.tridenta.destinations.LogsScreenDestination
import org.stypox.tridenta.ui.theme.BodyText

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ import org.stypox.tridenta.repo.data.UiLine
import org.stypox.tridenta.repo.data.UiTrip
import org.stypox.tridenta.sample.SampleUiLineProvider
import org.stypox.tridenta.sample.SampleUiTripProvider
import org.stypox.tridenta.ui.destinations.LineTripsScreenDestination
import org.stypox.tridenta.destinations.LineTripsScreenDestination
import org.stypox.tridenta.ui.lines.LineShortName
import org.stypox.tridenta.ui.nav.AppBarDrawerIcon
import org.stypox.tridenta.ui.nav.AppBarFavoriteIcon
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ import org.stypox.tridenta.log.logError
import org.stypox.tridenta.repo.LineTripsRepository
import org.stypox.tridenta.repo.LinesRepository
import org.stypox.tridenta.repo.data.UiTrip
import org.stypox.tridenta.ui.navArgs
import org.stypox.tridenta.navArgs
import java.time.ZonedDateTime
import javax.inject.Inject

Expand Down Expand Up @@ -78,7 +78,7 @@ class LineTripsViewModel @Inject constructor(
mutableUiState.update { it.copy(directionFilter = newDirectionFilter) }

if (newDirectionFilter == Direction.ForwardAndBackward) {
val state = uiState.value;
val state = uiState.value
if (state.trip == null) {
// the trip can be null if there is no trip in that direction
loadIndex(state.tripIndex)
Expand All @@ -94,7 +94,7 @@ class LineTripsViewModel @Inject constructor(
}

} else {
val state = uiState.value;
val state = uiState.value
if (state.trip?.direction != newDirectionFilter) {
// we need to load another trip, since the current one has the wrong direction
loadIndex(state.tripIndex)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import org.stypox.tridenta.R
import org.stypox.tridenta.db.data.DbLine
import org.stypox.tridenta.enums.Area
import org.stypox.tridenta.sample.SampleDbLineProvider
import org.stypox.tridenta.ui.destinations.LineTripsScreenDestination
import org.stypox.tridenta.destinations.LineTripsScreenDestination
import org.stypox.tridenta.ui.error.ErrorPanel
import org.stypox.tridenta.ui.error.ErrorRow
import org.stypox.tridenta.ui.nav.AppBarDrawerIcon
Expand Down
2 changes: 1 addition & 1 deletion app/src/main/java/org/stypox/tridenta/ui/nav/Drawer.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ import org.stypox.tridenta.R
import org.stypox.tridenta.db.data.DbLine
import org.stypox.tridenta.db.data.DbStop
import org.stypox.tridenta.db.views.HistoryLineOrStop
import org.stypox.tridenta.ui.destinations.*
import org.stypox.tridenta.destinations.*
import org.stypox.tridenta.ui.lines.LineShortName
import org.stypox.tridenta.ui.theme.*

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/stypox/tridenta/ui/nav/Navigation.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,11 @@ import com.ramcosta.composedestinations.rememberNavHostEngine
import com.ramcosta.composedestinations.spec.Direction
import kotlinx.coroutines.launch
import org.stypox.tridenta.R
import org.stypox.tridenta.ui.NavGraphs
import org.stypox.tridenta.ui.destinations.LinesScreenDestination
import org.stypox.tridenta.ui.theme.HeadlineText
import org.stypox.tridenta.util.PreferenceKeys
import androidx.core.content.edit
import org.stypox.tridenta.NavGraphs
import org.stypox.tridenta.destinations.LinesScreenDestination

const val DEEP_LINK_PREFIX = "tridenta://"
const val DEEP_LINK_URL_PATTERN = DEEP_LINK_PREFIX + FULL_ROUTE_PLACEHOLDER
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ import org.stypox.tridenta.db.data.DbStop
import org.stypox.tridenta.repo.data.UiTrip
import org.stypox.tridenta.sample.SampleDbStopProvider
import org.stypox.tridenta.sample.SampleUiTripProvider
import org.stypox.tridenta.ui.destinations.LineTripsScreenDestination
import org.stypox.tridenta.destinations.LineTripsScreenDestination
import org.stypox.tridenta.ui.nav.AppBarDrawerIcon
import org.stypox.tridenta.ui.nav.AppBarFavoriteIcon
import org.stypox.tridenta.ui.nav.DEEP_LINK_URL_PATTERN
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import org.stypox.tridenta.extractor.ROME_ZONE_ID
import org.stypox.tridenta.log.logError
import org.stypox.tridenta.repo.StopTripsRepository
import org.stypox.tridenta.repo.StopsRepository
import org.stypox.tridenta.ui.navArgs
import org.stypox.tridenta.navArgs
import java.time.ZonedDateTime
import javax.inject.Inject

Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/stypox/tridenta/ui/stops/StopsScreen.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,8 +33,8 @@ import com.ramcosta.composedestinations.navigation.EmptyDestinationsNavigator
import org.stypox.tridenta.R
import org.stypox.tridenta.repo.data.UiStop
import org.stypox.tridenta.sample.SampleUiStopProvider
import org.stypox.tridenta.ui.destinations.LineTripsScreenDestination
import org.stypox.tridenta.ui.destinations.StopTripsScreenDestination
import org.stypox.tridenta.destinations.LineTripsScreenDestination
import org.stypox.tridenta.destinations.StopTripsScreenDestination
import org.stypox.tridenta.ui.error.ErrorPanel
import org.stypox.tridenta.ui.error.ErrorRow
import org.stypox.tridenta.ui.nav.AppBarDrawerIcon
Expand Down
4 changes: 2 additions & 2 deletions app/src/main/java/org/stypox/tridenta/ui/trip/TripView.kt
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import org.stypox.tridenta.repo.data.UiLine
import org.stypox.tridenta.repo.data.UiTrip
import org.stypox.tridenta.sample.SampleDbStopProvider
import org.stypox.tridenta.sample.SampleUiTripProvider
import org.stypox.tridenta.ui.destinations.LineTripsScreenDestination
import org.stypox.tridenta.ui.destinations.StopTripsScreenDestination
import org.stypox.tridenta.destinations.LineTripsScreenDestination
import org.stypox.tridenta.destinations.StopTripsScreenDestination
import org.stypox.tridenta.ui.error.ErrorPanel
import org.stypox.tridenta.ui.error.ErrorRow
import org.stypox.tridenta.ui.theme.*
Expand Down
36 changes: 36 additions & 0 deletions app/src/main/java/org/stypox/tridenta/util/SerializerUtils.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
package org.stypox.tridenta.util

import kotlinx.serialization.KSerializer
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import java.time.OffsetDateTime
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter

object ZonedDateTimeSerializer : KSerializer<ZonedDateTime> {
override val descriptor = PrimitiveSerialDescriptor("ZonedDateTime", PrimitiveKind.STRING)

override fun serialize(encoder: Encoder, value: ZonedDateTime) {
encoder.encodeString(value.toString())
}

override fun deserialize(decoder: Decoder): ZonedDateTime {
return ZonedDateTime.parse(decoder.decodeString())
}
}

object OffsetDateTimeSerializer : KSerializer<OffsetDateTime> {
override val descriptor = PrimitiveSerialDescriptor("OffsetDateTime", PrimitiveKind.STRING)

private val formatter = DateTimeFormatter.ISO_OFFSET_DATE_TIME

override fun serialize(encoder: Encoder, value: OffsetDateTime) {
encoder.encodeString(value.format(formatter))
}

override fun deserialize(decoder: Decoder): OffsetDateTime {
return OffsetDateTime.parse(decoder.decodeString(), formatter)
}
}
Loading