From 2d665ab6310cea35cfdd678a13b58616fe088ad2 Mon Sep 17 00:00:00 2001 From: Matthieu Bessat Date: Wed, 7 Feb 2024 17:45:05 +0100 Subject: [PATCH] feat: basic upcoming events list view --- app/build.gradle.kts | 2 + .../java/net/mbess/popequer/AppContext.kt | 3 +- .../net/mbess/popequer/BackgroundActions.kt | 18 ++++++++ .../main/java/net/mbess/popequer/EventItem.kt | 11 +++++ .../java/net/mbess/popequer/GitActions.kt | 8 +++- .../main/java/net/mbess/popequer/Popequer.kt | 18 ++++++++ .../mbess/popequer/PopequerDeserializer.kt | 22 ++++++++++ .../main/java/net/mbess/popequer/ui/App.kt | 8 ++++ .../java/net/mbess/popequer/ui/AppNavGraph.kt | 2 +- .../net/mbess/popequer/ui/MainActivity.kt | 5 +-- .../mbess/popequer/ui/UpcomingEventsRoute.kt | 41 ++++++++++++++++++- app/src/main/java/net/mbess/popequer/utils.kt | 24 +++++++++++ gradle/libs.versions.toml | 2 + rust-adapter/src/lib.rs | 1 + 14 files changed, 155 insertions(+), 10 deletions(-) create mode 100644 app/src/main/java/net/mbess/popequer/BackgroundActions.kt create mode 100644 app/src/main/java/net/mbess/popequer/EventItem.kt create mode 100644 app/src/main/java/net/mbess/popequer/Popequer.kt create mode 100644 app/src/main/java/net/mbess/popequer/PopequerDeserializer.kt create mode 100644 app/src/main/java/net/mbess/popequer/utils.kt diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 104b27e..690369f 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -53,6 +53,7 @@ dependencies { implementation(libs.androidx.material.icons.extended) implementation(libs.androidx.material3) implementation(libs.androidx.ui.tooling.preview) + implementation(libs.protolite.well.known.types) runtimeOnly(libs.androidx.ui.tooling) implementation(libs.org.eclipse.jgit) @@ -64,5 +65,6 @@ dependencies { debugImplementation("androidx.compose.ui:ui-tooling") implementation("androidx.compose.ui:ui-tooling-preview") implementation("androidx.annotation:annotation") + implementation("com.google.code.gson:gson:2.10.1") } diff --git a/app/src/main/java/net/mbess/popequer/AppContext.kt b/app/src/main/java/net/mbess/popequer/AppContext.kt index 975638a..d8e4139 100644 --- a/app/src/main/java/net/mbess/popequer/AppContext.kt +++ b/app/src/main/java/net/mbess/popequer/AppContext.kt @@ -6,5 +6,6 @@ class AppContext( val androidContext: Context, ) { val gitActions = GitActions(androidContext) - val popequer = PopequerAdapter(gitActions.cloneFolder.absolutePath) + val popequer = Popequer(PopequerAdapter(gitActions.cloneFolder.absolutePath)) + val backgroundActions = BackgroundActions(this) } \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/BackgroundActions.kt b/app/src/main/java/net/mbess/popequer/BackgroundActions.kt new file mode 100644 index 0000000..69ed442 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/BackgroundActions.kt @@ -0,0 +1,18 @@ +package net.mbess.popequer + +import android.util.Log +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch + +class BackgroundActions(val context: AppContext) { + fun refresh() { + runCatching { + context.gitActions.sync() + context.popequer.index() + }.onFailure { + Log.e("BackgroundActions", "Failed to refresh the Notebook"); + }.onSuccess { + Log.i("BackgroundActions", "Notebook refresh successfully"); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/EventItem.kt b/app/src/main/java/net/mbess/popequer/EventItem.kt new file mode 100644 index 0000000..7effad0 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/EventItem.kt @@ -0,0 +1,11 @@ +package net.mbess.popequer + +import java.time.Instant + +class EventItem( + val name: String, + val startTime: Instant, + val endTime: Instant? +) { + +} \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/GitActions.kt b/app/src/main/java/net/mbess/popequer/GitActions.kt index 9be9bf9..f1c289e 100644 --- a/app/src/main/java/net/mbess/popequer/GitActions.kt +++ b/app/src/main/java/net/mbess/popequer/GitActions.kt @@ -42,9 +42,13 @@ class GitActions( fun sync() { git.fetch().setCredentialsProvider(credentials).call() - git.rebase().setUpstream("origin/master").call().also { result -> - Log.i("GitActions", "Rebase status: ${result.status} ${result.conflicts}") + git.reset().setMode(ResetCommand.ResetType.HARD).setRef("origin/master").call().also { + result -> + Log.i("GitActions", "reset!"); } + //git.rebase().setUpstream("origin/master").call().also { result -> + // Log.i("GitActions", "Rebase status: ${result.status} ${result.conflicts}") + //} Log.i("GitActions", "Successfully sync repo") } fun trigger() { diff --git a/app/src/main/java/net/mbess/popequer/Popequer.kt b/app/src/main/java/net/mbess/popequer/Popequer.kt new file mode 100644 index 0000000..36080a7 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/Popequer.kt @@ -0,0 +1,18 @@ +package net.mbess.popequer + +import android.util.Log + +class Popequer( + val adapter: PopequerAdapter +) { + + fun index(): String { + return adapter.index() + } + fun upcomingEvents(): List { + val events_str = adapter.upcomingEvents() + Log.d("Popequer", "From rust: $events_str") + val events = PopequerDeserializer().deserializeEvents(events_str) + return events; + } +} \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/PopequerDeserializer.kt b/app/src/main/java/net/mbess/popequer/PopequerDeserializer.kt new file mode 100644 index 0000000..6accde8 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/PopequerDeserializer.kt @@ -0,0 +1,22 @@ +package net.mbess.popequer + +import com.google.gson.Gson +import com.google.gson.GsonBuilder +import java.util.ArrayList + +import com.google.gson.reflect.TypeToken +import java.lang.reflect.Type +import java.time.Instant + + +class PopequerDeserializer() { + private var gsonInstance: Gson = + GsonBuilder().registerTypeAdapter(Instant::class.java, InstantDeserializer()).create() + + fun deserializeEvents(inp: String): List { + val listType: Type = object : TypeToken?>() {}.type + return gsonInstance + .fromJson(inp, listType) + } + +} \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/ui/App.kt b/app/src/main/java/net/mbess/popequer/ui/App.kt index bfcecff..c4ea8b7 100644 --- a/app/src/main/java/net/mbess/popequer/ui/App.kt +++ b/app/src/main/java/net/mbess/popequer/ui/App.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.padding import androidx.compose.material.icons.Icons import androidx.compose.material.icons.filled.Add import androidx.compose.material.icons.filled.Menu +import androidx.compose.material.icons.filled.Refresh import androidx.compose.material.icons.filled.Settings import androidx.compose.material3.* import androidx.compose.runtime.Composable @@ -84,6 +85,13 @@ fun AppContainer( } }, actions = { + IconButton(onClick = { + scope.launch(Dispatchers.IO) { + context.backgroundActions.refresh() + } + }) { + Icon(Icons.Filled.Refresh, contentDescription = "Refresh icon") + } IconButton(onClick = { // TODO: switch to settings view }) { diff --git a/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt b/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt index d22ae56..ac931a6 100644 --- a/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt +++ b/app/src/main/java/net/mbess/popequer/ui/AppNavGraph.kt @@ -28,7 +28,7 @@ fun AppNavGraph( composable( route = AppDestinations.UPCOMING_EVENTS ) { - UpcomingEventsRoute() + UpcomingEventsRoute(appContext) } } } \ No newline at end of file diff --git a/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt b/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt index e8f4a73..1b2e329 100644 --- a/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt +++ b/app/src/main/java/net/mbess/popequer/ui/MainActivity.kt @@ -40,10 +40,7 @@ class MainActivity : ComponentActivity() { Toast.makeText(appContext.androidContext, "A repo was just cloned", Toast.LENGTH_LONG) .show() } - appContext.gitActions.sync() - Log.d("Ppq", "${appContext.popequer}"); - Log.d("Ppq", "Index: ${appContext.popequer.index()}"); - Log.d("Ppq", "Upcoming: ${appContext.popequer.upcomingEvents()}"); + appContext.backgroundActions.refresh() }.onFailure { Log.e("MainActivity", "Failed to prepare git repo", it) } diff --git a/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt b/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt index 0ccc7bc..394d76c 100644 --- a/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt +++ b/app/src/main/java/net/mbess/popequer/ui/UpcomingEventsRoute.kt @@ -1,9 +1,46 @@ package net.mbess.popequer.ui +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.layout.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.MaterialTheme +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import androidx.compose.ui.unit.dp +import net.mbess.popequer.AppContext +import java.time.LocalDateTime +import java.time.ZoneOffset.UTC +import java.time.format.DateTimeFormatter @Composable -fun UpcomingEventsRoute() { - Text(text = "This is the upcoming events route") +fun UpcomingEventsRoute( + appContext: AppContext +) { + Surface(modifier = Modifier.padding(10.dp)) { + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + + LazyColumn { + itemsIndexed(appContext.popequer.upcomingEvents()) { index, item -> + Card( + elevation = CardDefaults.cardElevation( + defaultElevation = 6.dp + ), + shape = MaterialTheme.shapes.medium, + modifier = Modifier.fillMaxWidth().padding(bottom = 10.dp) + ) { + Column(modifier = Modifier.padding(15.dp)) { + Text(item.name, style = MaterialTheme.typography.headlineSmall) + Text("Start: ${LocalDateTime.ofInstant(item.startTime, UTC).format(formatter)}") + } + } + } + } + } } diff --git a/app/src/main/java/net/mbess/popequer/utils.kt b/app/src/main/java/net/mbess/popequer/utils.kt new file mode 100644 index 0000000..1b0e120 --- /dev/null +++ b/app/src/main/java/net/mbess/popequer/utils.kt @@ -0,0 +1,24 @@ +package net.mbess.popequer + +import com.google.gson.JsonDeserializationContext +import com.google.gson.JsonDeserializer +import com.google.gson.JsonElement +import com.google.gson.JsonParseException +import java.lang.reflect.Type +import java.time.Instant + +class InstantDeserializer : JsonDeserializer { + @Throws(JsonParseException::class) + override fun deserialize( + json: JsonElement, + typeOfT: Type?, + context: JsonDeserializationContext? + ): Instant? + { + if (json.isJsonNull) { + return null + } + return Instant.parse(json.asString) + } +} + diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index 7924575..63e237c 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -13,6 +13,7 @@ compose-bom = "2023.10.01" material3 = "1.1.2" org-eclipse-jgit = "6.8.0.202311291450-r" twain = "0.2.2" +protolite-well-known-types = "18.0.0" [libraries] androidx-compose-bom = { group = "androidx.compose", name = "compose-bom", version.ref = "compose-bom" } @@ -27,6 +28,7 @@ compose-markdown = { module = "com.github.jeziellago:compose-markdown", version. kotlinx-coroutines-android = { group = "org.jetbrains.kotlinx", name = "kotlinx-coroutines-android", version.ref = "kotlinx-coroutines-android" } org-eclipse-jgit = { module = "org.eclipse.jgit:org.eclipse.jgit", version.ref = "org-eclipse-jgit" } twain = { module = "com.meetup:twain", version.ref = "twain" } +protolite-well-known-types = { group = "com.google.firebase", name = "protolite-well-known-types", version.ref = "protolite-well-known-types" } [plugins] androidApplication = { id = "com.android.application", version.ref = "agp" } diff --git a/rust-adapter/src/lib.rs b/rust-adapter/src/lib.rs index e9461ea..44b71cd 100644 --- a/rust-adapter/src/lib.rs +++ b/rust-adapter/src/lib.rs @@ -20,6 +20,7 @@ enum PopequerAdapterErr { } #[derive(Serialize)] +#[serde(rename_all = "camelCase")] struct EventItem { name: String, start_time: String,