From 8bd9ebd7a274d87ada203a000ea70994699ef52e Mon Sep 17 00:00:00 2001 From: Daniel Bertoldi Date: Wed, 18 Jun 2025 16:36:18 -0300 Subject: [PATCH] Sync and Dispaly Venue Map --- .../ui/BottomNavigationView.kt | 4 +- .../ui/venue/VenueView.kt | 47 ++++++++++++++---- shared/build.gradle.kts | 1 + .../droidcon/domain/entity/Conference.kt | 3 +- .../impl/SqlDelightConferenceRepository.kt | 4 ++ .../domain/service/impl/DefaultSyncService.kt | 7 ++- .../domain/service/impl/dto/ConferencesDto.kt | 2 +- .../co/touchlab/droidcon/db/Conference.sq | 13 ++--- .../src/commonMain/sqldelight/databases/2.db | Bin 0 -> 77824 bytes .../commonMain/sqldelight/migrations/1.sqm | 1 + 10 files changed, 62 insertions(+), 20 deletions(-) create mode 100644 shared/src/commonMain/sqldelight/databases/2.db create mode 100644 shared/src/commonMain/sqldelight/migrations/1.sqm diff --git a/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/BottomNavigationView.kt b/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/BottomNavigationView.kt index 018763d6..62873f5e 100644 --- a/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/BottomNavigationView.kt +++ b/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/BottomNavigationView.kt @@ -64,7 +64,7 @@ internal fun BottomNavigationView(viewModel: ApplicationViewModel, currentConfer when (selectedTab) { ApplicationViewModel.Tab.Schedule -> SessionListView( viewModel = viewModel.schedule, - title = currentConference?.name ?: "Schedule", + title = currentConference.name, emptyText = "Sessions could not be loaded.", ) @@ -74,7 +74,7 @@ internal fun BottomNavigationView(viewModel: ApplicationViewModel, currentConfer emptyText = "Add sessions to your agenda from session detail in schedule.", ) - ApplicationViewModel.Tab.Venue -> VenueView() + ApplicationViewModel.Tab.Venue -> VenueView(currentConference) ApplicationViewModel.Tab.Sponsors -> SponsorsView(viewModel.sponsors) ApplicationViewModel.Tab.Settings -> SettingsView(viewModel.settings) } diff --git a/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/venue/VenueView.kt b/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/venue/VenueView.kt index 475b0026..bbda3f35 100644 --- a/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/venue/VenueView.kt +++ b/shared-ui/src/commonMain/kotlin/co.touchlab.droidcon/ui/venue/VenueView.kt @@ -1,28 +1,57 @@ package co.touchlab.droidcon.ui.venue +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.padding +import androidx.compose.material3.CircularProgressIndicator import androidx.compose.material3.Scaffold +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.collectAsState +import androidx.compose.runtime.getValue +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import co.touchlab.droidcon.domain.entity.Conference +import coil3.compose.AsyncImagePainter +import coil3.compose.rememberAsyncImagePainter import com.github.panpf.zoomimage.ZoomImage -import droidcon.shared_ui.generated.resources.venue_map_1 -import org.jetbrains.compose.resources.painterResource @Composable -fun VenueView() { +fun VenueView(currentConference: Conference) { Scaffold { paddingValues -> VenueBodyView( modifier = Modifier.padding(paddingValues), + currentConference, ) } } @Composable -fun VenueBodyView(modifier: Modifier = Modifier) { - ZoomImage( - painter = painterResource(droidcon.shared_ui.generated.resources.Res.drawable.venue_map_1), - contentDescription = null, - modifier = modifier.fillMaxSize(), - ) +fun VenueBodyView(modifier: Modifier = Modifier, currentConference: Conference) { + val painter = rememberAsyncImagePainter(currentConference.venueMap) + val state by painter.state.collectAsState() + + Column( + modifier = Modifier.fillMaxSize(), + horizontalAlignment = Alignment.CenterHorizontally, + verticalArrangement = Arrangement.Center, + ) { + when (state) { + is AsyncImagePainter.State.Empty, + is AsyncImagePainter.State.Loading -> { + CircularProgressIndicator() + } + is AsyncImagePainter.State.Error -> { + Text("Error loading venue map.") + } + is AsyncImagePainter.State.Success -> { + ZoomImage( + painter = painter, + contentDescription = null, + modifier = modifier.fillMaxSize(), + ) + } + } + } } diff --git a/shared/build.gradle.kts b/shared/build.gradle.kts index bdaf0388..4dad6cc1 100644 --- a/shared/build.gradle.kts +++ b/shared/build.gradle.kts @@ -108,5 +108,6 @@ kotlin { sqldelight { databases.create("DroidconDatabase") { packageName.set("co.touchlab.droidcon.db") + schemaOutputDirectory.set(file("src/commonMain/sqldelight/databases")) } } diff --git a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/entity/Conference.kt b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/entity/Conference.kt index e15cf9af..4e333b3c 100644 --- a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/entity/Conference.kt +++ b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/entity/Conference.kt @@ -12,8 +12,9 @@ data class Conference( val scheduleId: String, val selected: Boolean = false, val active: Boolean = true, + val venueMap: String?, ) : DomainEntity() { - val showVenueMap: Boolean = false // We'll need to add this to the table + val showVenueMap: Boolean = venueMap != null override val id: Long get() = requireNotNull(_id) { "Conference id cannot be null" } } diff --git a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/repository/impl/SqlDelightConferenceRepository.kt b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/repository/impl/SqlDelightConferenceRepository.kt index c33205c0..de9913bc 100644 --- a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/repository/impl/SqlDelightConferenceRepository.kt +++ b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/repository/impl/SqlDelightConferenceRepository.kt @@ -43,6 +43,7 @@ class SqlDelightConferenceRepository( scheduleId = conference.scheduleId, selected = conference.selected, active = conference.active, + venueMap = conference.venueMap, ) // Return the last inserted ID return conferenceQueries.lastInsertRowId().executeAsOne() @@ -60,6 +61,7 @@ class SqlDelightConferenceRepository( selected = conference.selected, active = conference.active, id = conference.id, + venueMap = conference.venueMap, ) return true } catch (e: Exception) { @@ -83,6 +85,7 @@ class SqlDelightConferenceRepository( scheduleId: String, selected: Boolean, active: Boolean, + venueMap: String?, ): Conference = Conference( _id = id, name = conferenceName, @@ -93,5 +96,6 @@ class SqlDelightConferenceRepository( scheduleId = scheduleId, selected = selected, active = active, + venueMap = venueMap, ) } diff --git a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/DefaultSyncService.kt b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/DefaultSyncService.kt index 94a20564..582ed241 100644 --- a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/DefaultSyncService.kt +++ b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/DefaultSyncService.kt @@ -240,13 +240,15 @@ class DefaultSyncService( val collectionName = conferenceFields.collectionName.stringValue val apiKey = conferenceFields.apiKey.stringValue val scheduleId = conferenceFields.scheduleId.stringValue + val venueMap = conferenceFields.venueMap?.stringValue // Only update if any field has changed val needsUpdate = existingConference.timeZone != timeZone || existingConference.projectId != projectId || existingConference.collectionName != collectionName || existingConference.apiKey != apiKey || - existingConference.scheduleId != scheduleId + existingConference.scheduleId != scheduleId || + existingConference.venueMap != venueMap if (needsUpdate) { val updatedConference = Conference( @@ -259,6 +261,7 @@ class DefaultSyncService( scheduleId = scheduleId, selected = existingConference.selected, active = existingConference.active, + venueMap = venueMap, ) conferenceRepository.update(updatedConference) log.d { "Updated conference: $conferenceName (fields changed)" } @@ -276,6 +279,7 @@ class DefaultSyncService( scheduleId = conferenceFields.scheduleId.stringValue, selected = false, active = true, + venueMap = conferenceFields.venueMap?.stringValue ) conferenceRepository.add(newConference) log.d { "Added new conference: $conferenceName" } @@ -296,6 +300,7 @@ class DefaultSyncService( scheduleId = conference.scheduleId, selected = conference.selected, active = false, + venueMap = conference.venueMap, ) conferenceRepository.update(deactivatedConference) log.d { "Marked conference as inactive: $name" } diff --git a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/dto/ConferencesDto.kt b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/dto/ConferencesDto.kt index f4a86156..5d05f38a 100644 --- a/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/dto/ConferencesDto.kt +++ b/shared/src/commonMain/kotlin/co/touchlab/droidcon/domain/service/impl/dto/ConferencesDto.kt @@ -22,7 +22,7 @@ object ConferencesDto { val collectionName: StringValue, val apiKey: StringValue, val scheduleId: StringValue, - val venueMap: StringValue, + val venueMap: StringValue? = null, ) @Serializable diff --git a/shared/src/commonMain/sqldelight/co/touchlab/droidcon/db/Conference.sq b/shared/src/commonMain/sqldelight/co/touchlab/droidcon/db/Conference.sq index 59f3aacd..422786de 100644 --- a/shared/src/commonMain/sqldelight/co/touchlab/droidcon/db/Conference.sq +++ b/shared/src/commonMain/sqldelight/co/touchlab/droidcon/db/Conference.sq @@ -10,16 +10,17 @@ CREATE TABLE conferenceTable( apiKey TEXT NOT NULL, scheduleId TEXT NOT NULL, selected INTEGER AS Boolean NOT NULL DEFAULT 0, - active INTEGER AS Boolean NOT NULL DEFAULT 1 + active INTEGER AS Boolean NOT NULL DEFAULT 1, + venueMap TEXT ); insert: -INSERT INTO conferenceTable(conferenceName, conferenceTimeZone, projectId, collectionName, apiKey, scheduleId, selected, active) -VALUES (?, ?, ?, ?, ?, ?, ?, ?); +INSERT INTO conferenceTable(conferenceName, conferenceTimeZone, projectId, collectionName, apiKey, scheduleId, selected, active, venueMap) +VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?); updateConference: UPDATE conferenceTable -SET conferenceName = ?, conferenceTimeZone = ?, projectId = ?, collectionName = ?, apiKey = ?, scheduleId = ?, selected = ?, active = ? +SET conferenceName = ?, conferenceTimeZone = ?, projectId = ?, collectionName = ?, apiKey = ?, scheduleId = ?, selected = ?, active = ?, venueMap = ? WHERE id = ?; selectAll: @@ -52,8 +53,8 @@ changeSelectedConference { UPDATE conferenceTable SET selected = 1 WHERE id = :conferenceId; } -INSERT INTO conferenceTable(conferenceName, conferenceTimeZone, projectId, collectionName, apiKey, scheduleId, selected, active) -VALUES ("Droidcon NYC 2025", "America/New_York", "droidcon-148cc", "sponsors-nyc-2025", "AIzaSyCkD5DH2rUJ8aZuJzANpIFj0AVuCNik1l0", "4lffd9w7", 1, 1); +INSERT INTO conferenceTable(conferenceName, conferenceTimeZone, projectId, collectionName, apiKey, scheduleId, selected, active, venueMap) +VALUES ("Droidcon NYC 2025", "America/New_York", "droidcon-148cc", "sponsors-nyc-2025", "AIzaSyCkD5DH2rUJ8aZuJzANpIFj0AVuCNik1l0", "4lffd9w7", 1, 1, "https://www.google.com"); lastInsertRowId: SELECT last_insert_rowid(); \ No newline at end of file diff --git a/shared/src/commonMain/sqldelight/databases/2.db b/shared/src/commonMain/sqldelight/databases/2.db new file mode 100644 index 0000000000000000000000000000000000000000..42d825edc5931cc27e4ffbfbc1f777c56d7adeb1 GIT binary patch literal 77824 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 Cmf1J} literal 0 HcmV?d00001 diff --git a/shared/src/commonMain/sqldelight/migrations/1.sqm b/shared/src/commonMain/sqldelight/migrations/1.sqm new file mode 100644 index 00000000..da7898f4 --- /dev/null +++ b/shared/src/commonMain/sqldelight/migrations/1.sqm @@ -0,0 +1 @@ +ALTER TABLE conferenceTable ADD COLUMN venueMap TEXT; \ No newline at end of file