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
2 changes: 1 addition & 1 deletion DroidconIosDocumentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ The framework provides integration with Compose Multiplatform for UI rendering:
func getRootController(viewModel: DroidconKitWaitForLoadedContextModel) -> UIViewController

// Creates a specific view controller for the venue screen
func venueBodyViewController() -> UIViewController
func venueBodyViewController(venueMapUrl:String?) -> UIViewController
```

### Session Management
Expand Down
4 changes: 2 additions & 2 deletions android/mock-google-services.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
"client_info": {
"mobilesdk_app_id": "1:606665771229:android:c1f0f09aa42abc12",
"android_client_info": {
"package_name": "co.touchlab.droidcon.london"
"package_name": "com.droidcon.app"
}
},
"oauth_client": [
{
"client_id": "123455771229-sc9bpuefbjceq7i1qabk7gssstefrdlv.apps.googleusercontent.com",
"client_type": 1,
"android_info": {
"package_name": "co.touchlab.droidcon.london",
"package_name": "com.droidcon.app",
"certificate_hash": "7f254b538565cfe6c28a88744985f015b1534980"
}
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ import androidx.core.content.ContextCompat
import androidx.core.splashscreen.SplashScreen.Companion.installSplashScreen
import androidx.core.view.WindowCompat
import androidx.lifecycle.lifecycleScope
import com.droidcon.app.R
import co.touchlab.droidcon.application.service.NotificationSchedulingService
import co.touchlab.droidcon.domain.service.AnalyticsService
import co.touchlab.droidcon.service.AndroidNotificationService
import co.touchlab.droidcon.ui.theme.Colors
import co.touchlab.droidcon.ui.util.MainView
import co.touchlab.droidcon.util.NavigationController
import co.touchlab.droidcon.viewmodel.WaitForLoadedContextModel
import com.droidcon.app.R
import kotlinx.coroutines.awaitCancellation
import kotlinx.coroutines.delay
import kotlinx.coroutines.launch
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
package co.touchlab.droidcon.android.util

import android.content.Context
import com.droidcon.app.R
import co.touchlab.droidcon.application.service.NotificationSchedulingService
import com.droidcon.app.R

class NotificationLocalizedStringFactory(private val context: Context) : NotificationSchedulingService.LocalizedStringFactory {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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.",
)

Expand All @@ -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.venueMap)
ApplicationViewModel.Tab.Sponsors -> SponsorsView(viewModel.sponsors)
ApplicationViewModel.Tab.Settings -> SettingsView(viewModel.settings)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,6 @@ private fun MainAppBody(waitForLoadedContextModel: WaitForLoadedContextModel, se
if (conferences.size == 1) {
onConferenceSelected(conferences.get(0))
} else if (conferences.size > 1) {

FirstRunConferenceSelector(
conferences = conferences,
selectedConference = selectedConference,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,28 +1,55 @@
package co.touchlab.droidcon.ui.venue

import androidx.compose.foundation.layout.Box
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 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(venueMapUrl: String?) {
Scaffold { paddingValues ->
VenueBodyView(
modifier = Modifier.padding(paddingValues),
venueMapUrl,
)
}
}

@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, venueMapUrl: String?) {
val painter = rememberAsyncImagePainter(venueMapUrl)
val state by painter.state.collectAsState()

Box(
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.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(),
)
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,6 @@ fun getRootController(viewModel: WaitForLoadedContextModel) = ComposeUIViewContr
}

@Suppress("unused")
fun venueBodyViewController() = ComposeUIViewController {
VenueBodyView()
fun venueBodyViewController(venueMapUrl: String?) = ComposeUIViewController {
VenueBodyView(venueMapUrl = venueMapUrl)
}
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,9 @@ data class Conference(
val scheduleId: String,
val selected: Boolean = false,
val active: Boolean = true,
val venueMap: String?,
) : DomainEntity<Long>() {
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" }
}
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand All @@ -60,6 +61,7 @@ class SqlDelightConferenceRepository(
selected = conference.selected,
active = conference.active,
id = conference.id,
venueMap = conference.venueMap,
)
return true
} catch (e: Exception) {
Expand All @@ -83,6 +85,7 @@ class SqlDelightConferenceRepository(
scheduleId: String,
selected: Boolean,
active: Boolean,
venueMap: String?,
): Conference = Conference(
_id = id,
name = conferenceName,
Expand All @@ -93,5 +96,6 @@ class SqlDelightConferenceRepository(
scheduleId = scheduleId,
selected = selected,
active = active,
venueMap = venueMap,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand All @@ -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)" }
Expand All @@ -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" }
Expand All @@ -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" }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ object ConferencesDto {
val collectionName: StringValue,
val apiKey: StringValue,
val scheduleId: StringValue,
val venueMap: StringValue,
val venueMap: StringValue? = null,
)

@Serializable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down Expand Up @@ -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, NULL);

lastInsertRowId:
SELECT last_insert_rowid();