From 41c85ddf168d3d2f69db77b79fef4cac232ac4fc Mon Sep 17 00:00:00 2001 From: Aayush Gupta Date: Sun, 27 Oct 2024 00:08:46 +0530 Subject: [PATCH] shared: Add support for announcements Signed-off-by: Aayush Gupta --- .../ccip/database/OPassDatabaseHelper.kt | 33 +++++++++++++++++++ .../ccip/extensions/AnnouncementTable.kt | 20 +++++++++++ .../app/opass/ccip/helpers/PortalHelper.kt | 26 +++++++++++++++ .../app/opass/ccip/network/PortalClient.kt | 8 +++++ .../network/models/fastpass/Announcement.kt | 29 ++++++++++++++++ .../app/opass/ccip/database/OPassDatabase.sq | 27 +++++++++++++++ 6 files changed, 143 insertions(+) create mode 100644 shared/src/commonMain/kotlin/app/opass/ccip/extensions/AnnouncementTable.kt create mode 100644 shared/src/commonMain/kotlin/app/opass/ccip/network/models/fastpass/Announcement.kt diff --git a/shared/src/commonMain/kotlin/app/opass/ccip/database/OPassDatabaseHelper.kt b/shared/src/commonMain/kotlin/app/opass/ccip/database/OPassDatabaseHelper.kt index 20bbbd7..e272e33 100644 --- a/shared/src/commonMain/kotlin/app/opass/ccip/database/OPassDatabaseHelper.kt +++ b/shared/src/commonMain/kotlin/app/opass/ccip/database/OPassDatabaseHelper.kt @@ -5,6 +5,7 @@ package app.opass.ccip.database +import app.opass.ccip.extensions.toAnnouncement import app.opass.ccip.extensions.toAttendee import app.opass.ccip.extensions.toEvent import app.opass.ccip.extensions.toEventConfig @@ -14,6 +15,7 @@ import app.opass.ccip.extensions.toSpeaker import app.opass.ccip.network.models.common.LocalizedObject import app.opass.ccip.network.models.event.Event import app.opass.ccip.network.models.eventconfig.EventConfig +import app.opass.ccip.network.models.fastpass.Announcement import app.opass.ccip.network.models.fastpass.Attendee import app.opass.ccip.network.models.schedule.Schedule import app.opass.ccip.network.models.schedule.Session @@ -284,4 +286,35 @@ internal class OPassDatabaseHelper { } } } + + suspend fun getAllAnnouncements(eventId: String, token: String? = null): List { + return withContext(Dispatchers.IO) { + dbQuery.selectAllAnnouncements(eventId, token) + .executeAsList() + .map { it.toAnnouncement() } + } + } + + suspend fun addAnnouncements( + eventId: String, + announcements: List, + token: String? = null + ) { + withContext(Dispatchers.IO) { + dbQuery.transaction { + dbQuery.deleteAllAnnouncements(eventId, token) + announcements.forEach { + dbQuery.insertAnnouncement( + datetime = it.datetime, + url = it.url, + msg_en = it._msg_en, + msg_zh = it._msg_zh, + role = Json.encodeToString(it.role), + token = token, + eventId = eventId + ) + } + } + } + } } diff --git a/shared/src/commonMain/kotlin/app/opass/ccip/extensions/AnnouncementTable.kt b/shared/src/commonMain/kotlin/app/opass/ccip/extensions/AnnouncementTable.kt new file mode 100644 index 0000000..e18eae9 --- /dev/null +++ b/shared/src/commonMain/kotlin/app/opass/ccip/extensions/AnnouncementTable.kt @@ -0,0 +1,20 @@ +/* + * SPDX-FileCopyrightText: 2024 OPass + * SPDX-License-Identifier: GPL-3.0-only + */ + +package app.opass.ccip.extensions + +import app.opass.ccip.database.AnnouncementTable +import app.opass.ccip.network.models.fastpass.Announcement +import kotlinx.serialization.json.Json + +internal fun AnnouncementTable.toAnnouncement(): Announcement { + return Announcement( + datetime = this.datetime, + _msg_en = this.msg_en, + _msg_zh = this.msg_zh, + role = Json.decodeFromString>(this.role), + url = this.url + ) +} diff --git a/shared/src/commonMain/kotlin/app/opass/ccip/helpers/PortalHelper.kt b/shared/src/commonMain/kotlin/app/opass/ccip/helpers/PortalHelper.kt index a2fff73..09ffbd6 100644 --- a/shared/src/commonMain/kotlin/app/opass/ccip/helpers/PortalHelper.kt +++ b/shared/src/commonMain/kotlin/app/opass/ccip/helpers/PortalHelper.kt @@ -11,6 +11,7 @@ import app.opass.ccip.network.models.common.LocalizedObject import app.opass.ccip.network.models.event.Event import app.opass.ccip.network.models.eventconfig.EventConfig import app.opass.ccip.network.models.eventconfig.FeatureType +import app.opass.ccip.network.models.fastpass.Announcement import app.opass.ccip.network.models.fastpass.Attendee import app.opass.ccip.network.models.schedule.Schedule import app.opass.ccip.network.models.schedule.Session @@ -79,6 +80,31 @@ class PortalHelper { } } + /** + * Fetches [Announcement] for specified event using given token from event's FastPass feature + * @param eventId ID of the event + * @param token Token to identify attendee + * @param forceReload Whether to ignore cache, false by default + * @return empty list if announcements haven't been cached yet or token is invalid; Announcements otherwise + */ + suspend fun getAnnouncements( + eventId: String, + token: String? = null, + forceReload: Boolean = false + ): List { + val eventConfig = dbHelper.getEventConfig(eventId) ?: return emptyList() + val feat = eventConfig.features.find { f -> f.type == FeatureType.FAST_PASS } ?: return emptyList() + + val cachedAnnouncements = dbHelper.getAllAnnouncements(eventId, token) + return if (cachedAnnouncements.isNotEmpty() && !forceReload) { + cachedAnnouncements + } else { + client.getAnnouncements(feat.url!!, token).also { + dbHelper.addAnnouncements(eventId, it, token) + } + } + } + /** * Fetches [Attendee] for specified event using given token from event's FastPass feature * @param eventId ID of the event diff --git a/shared/src/commonMain/kotlin/app/opass/ccip/network/PortalClient.kt b/shared/src/commonMain/kotlin/app/opass/ccip/network/PortalClient.kt index 737f26d..dcb1a83 100644 --- a/shared/src/commonMain/kotlin/app/opass/ccip/network/PortalClient.kt +++ b/shared/src/commonMain/kotlin/app/opass/ccip/network/PortalClient.kt @@ -7,6 +7,7 @@ package app.opass.ccip.network import app.opass.ccip.network.models.event.Event import app.opass.ccip.network.models.eventconfig.EventConfig +import app.opass.ccip.network.models.fastpass.Announcement import app.opass.ccip.network.models.fastpass.Attendee import app.opass.ccip.network.models.schedule.Schedule import io.ktor.client.HttpClient @@ -54,4 +55,11 @@ internal class PortalClient { parameter("token", token) }.body() } + + suspend fun getAnnouncements(url: String, token: String? = null): List { + return universalClient.get { + url(url) + if (token != null) parameter("token", token) + }.body() + } } diff --git a/shared/src/commonMain/kotlin/app/opass/ccip/network/models/fastpass/Announcement.kt b/shared/src/commonMain/kotlin/app/opass/ccip/network/models/fastpass/Announcement.kt new file mode 100644 index 0000000..38b60ef --- /dev/null +++ b/shared/src/commonMain/kotlin/app/opass/ccip/network/models/fastpass/Announcement.kt @@ -0,0 +1,29 @@ +/* + * SPDX-FileCopyrightText: 2024 OPass + * SPDX-License-Identifier: GPL-3.0-only + */ + +package app.opass.ccip.network.models.fastpass + +import app.opass.ccip.extensions.localized +import kotlinx.serialization.SerialName +import kotlinx.serialization.Serializable + +@Serializable +data class Announcement( + val datetime: Long, + + @SerialName("msg_en") + val _msg_en: String, + + @SerialName("msg_zh") + val _msg_zh: String, + + val role: List, + + @SerialName("uri") + val url: String +) { + val message: String + get() = localized(_msg_en, _msg_zh) +} diff --git a/shared/src/commonMain/sqldelight/app/opass/ccip/database/OPassDatabase.sq b/shared/src/commonMain/sqldelight/app/opass/ccip/database/OPassDatabase.sq index 34083c1..85b2663 100644 --- a/shared/src/commonMain/sqldelight/app/opass/ccip/database/OPassDatabase.sq +++ b/shared/src/commonMain/sqldelight/app/opass/ccip/database/OPassDatabase.sq @@ -123,6 +123,20 @@ CREATE TABLE AttendeeTable( FOREIGN KEY (eventId) REFERENCES EventConfigTable(id) ON DELETE CASCADE ); +-- Create Announcement table + +CREATE TABLE AnnouncementTable( + primaryId INTEGER PRIMARY KEY AUTOINCREMENT, + datetime INTEGER NOT NULL, + role TEXT NOT NULL, + msg_en TEXT NOT NULL, + msg_zh TEXT NOT NULL, + token TEXT, + url TEXT NOT NULL, + eventId TEXT NOT NULL, + FOREIGN KEY (eventId) REFERENCES EventConfigTable(id) ON DELETE CASCADE +); + -- Named queries for event table selectAllEvents: @@ -228,3 +242,16 @@ DELETE FROM AttendeeTable WHERE eventId = :eventId AND token = :token; insertAttendee: INSERT INTO AttendeeTable (userId, attr, firstUse, role, scenarios, token, eventId) VALUES (:userId, :attr, :firstUse, :role, :scenarios, :token, :eventId); + +-- Named queries for announcement table + +selectAllAnnouncements: +SELECT * FROM AnnouncementTable WHERE eventId = :eventId AND token = :token; + +deleteAllAnnouncements: +DELETE FROM AnnouncementTable WHERE eventId = :eventId AND token = :token; + +insertAnnouncement: +INSERT INTO AnnouncementTable (datetime, role, msg_en, msg_zh, token, url, eventId) +VALUES (:datetime, :role, :msg_en, :msg_zh, :token, :url, :eventId); +