feat: basic upcoming events list view

This commit is contained in:
Matthieu Bessat 2024-02-07 17:45:05 +01:00
parent ea3a307f96
commit 2d665ab631
14 changed files with 155 additions and 10 deletions

View file

@ -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")
}

View file

@ -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)
}

View file

@ -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");
}
}
}

View file

@ -0,0 +1,11 @@
package net.mbess.popequer
import java.time.Instant
class EventItem(
val name: String,
val startTime: Instant,
val endTime: Instant?
) {
}

View file

@ -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() {

View file

@ -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<EventItem> {
val events_str = adapter.upcomingEvents()
Log.d("Popequer", "From rust: $events_str")
val events = PopequerDeserializer().deserializeEvents(events_str)
return events;
}
}

View file

@ -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<EventItem> {
val listType: Type = object : TypeToken<ArrayList<EventItem>?>() {}.type
return gsonInstance
.fromJson(inp, listType)
}
}

View file

@ -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
}) {

View file

@ -28,7 +28,7 @@ fun AppNavGraph(
composable(
route = AppDestinations.UPCOMING_EVENTS
) {
UpcomingEventsRoute()
UpcomingEventsRoute(appContext)
}
}
}

View file

@ -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)
}

View file

@ -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)}")
}
}
}
}
}
}

View file

@ -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<Instant?> {
@Throws(JsonParseException::class)
override fun deserialize(
json: JsonElement,
typeOfT: Type?,
context: JsonDeserializationContext?
): Instant?
{
if (json.isJsonNull) {
return null
}
return Instant.parse(json.asString)
}
}

View file

@ -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" }

View file

@ -20,6 +20,7 @@ enum PopequerAdapterErr {
}
#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct EventItem {
name: String,
start_time: String,