Feat no op (#81)

* feat: [ANDROID] no op lib

* feat: [ANDROID] no op lib

* renamed modules

* renamed modules

* renamed modules

* renamed modules

* updated publish yml

---------

Co-authored-by: Florent Champigny <florent@bere.al>
This commit is contained in:
Florent CHAMPIGNY 2025-08-10 14:05:18 +02:00 committed by GitHub
parent 92fc478b12
commit ed07d7e674
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
106 changed files with 558 additions and 218 deletions

View file

@ -0,0 +1,41 @@
package io.github.openflocon.flocon
import android.content.Context
import io.github.openflocon.flocon.core.FloconMessageSender
import io.github.openflocon.flocon.plugins.analytics.FloconAnalyticsPlugin
import io.github.openflocon.flocon.plugins.dashboard.FloconDashboardPlugin
import io.github.openflocon.flocon.plugins.deeplinks.FloconDeeplinksPlugin
import io.github.openflocon.flocon.plugins.network.FloconNetworkPlugin
import io.github.openflocon.flocon.plugins.tables.FloconTablePlugin
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
abstract class FloconApp {
companion object {
var instance: FloconApp? = null
private set
}
interface Client : FloconMessageSender {
@Throws(Throwable::class)
suspend fun connect(onClosed: () -> Unit)
fun disconnect()
val dashboardPlugin: FloconDashboardPlugin
val tablePlugin: FloconTablePlugin
val deeplinksPlugin: FloconDeeplinksPlugin
val analyticsPlugin: FloconAnalyticsPlugin
val networkPlugin: FloconNetworkPlugin
}
open val client: FloconApp.Client? = null
abstract val isInitialized : StateFlow<Boolean>
open fun initialize(context: Context) {
instance = this
}
}

View file

@ -0,0 +1,18 @@
package io.github.openflocon.flocon
import android.util.Log
object FloconLogger {
var enabled = false
private const val TAG = "Flocon"
fun logError(text: String, throwable: Throwable?) {
if(enabled) {
Log.e(TAG, text, throwable)
}
}
fun log(text: String) {
if(enabled) {
Log.d(TAG, text)
}
}
}

View file

@ -0,0 +1,9 @@
package io.github.openflocon.flocon.core
interface FloconMessageSender {
fun send(
plugin: String,
method: String,
body: String,
)
}

View file

@ -0,0 +1,14 @@
package io.github.openflocon.flocon.core
import io.github.openflocon.flocon.model.FloconMessageFromServer
interface FloconPlugin {
fun onMessageReceived(
messageFromServer: FloconMessageFromServer,
sender: FloconMessageSender,
)
fun onConnectedToServer(
sender: FloconMessageSender,
)
}

View file

@ -0,0 +1,7 @@
package io.github.openflocon.flocon.model
data class FloconMessageFromServer(
val plugin: String,
val method: String,
val body: String,
)

View file

@ -0,0 +1,17 @@
package io.github.openflocon.flocon.plugins.analytics
import io.github.openflocon.flocon.FloconApp
import io.github.openflocon.flocon.core.FloconPlugin
import io.github.openflocon.flocon.plugins.analytics.builder.AnalyticsBuilder
import io.github.openflocon.flocon.plugins.analytics.model.AnalyticsItem
fun FloconApp.analytics(analyticsName: String): AnalyticsBuilder {
return AnalyticsBuilder(
analyticsTableId = analyticsName,
analyticsPlugin = this.client?.analyticsPlugin,
)
}
interface FloconAnalyticsPlugin : FloconPlugin {
fun registerAnalytics(analyticsItems: List<AnalyticsItem>)
}

View file

@ -0,0 +1,28 @@
package io.github.openflocon.flocon.plugins.analytics.builder
import io.github.openflocon.flocon.plugins.analytics.FloconAnalyticsPlugin
import io.github.openflocon.flocon.plugins.analytics.model.AnalyticsEvent
import io.github.openflocon.flocon.plugins.analytics.model.AnalyticsItem
import java.util.UUID
class AnalyticsBuilder(
val analyticsTableId: String,
private val analyticsPlugin: FloconAnalyticsPlugin?,
) {
fun logEvents(vararg events: AnalyticsEvent) {
this.logEvents(events.toList())
}
fun logEvents(events: List<AnalyticsEvent>) {
val analyticsItems = events.map {
AnalyticsItem(
id = UUID.randomUUID().toString(),
analyticsTableId = analyticsTableId,
eventName = it.eventName,
createdAt = System.currentTimeMillis(),
properties = it.properties,
)
}
analyticsPlugin?.registerAnalytics(analyticsItems)
}
}

View file

@ -0,0 +1,11 @@
package io.github.openflocon.flocon.plugins.analytics.model
data class AnalyticsEvent(
val eventName: String,
val properties: List<AnalyticsPropertiesConfig>,
) {
constructor(
eventName: String,
vararg properties: AnalyticsPropertiesConfig,
) : this(eventName, properties.toList())
}

View file

@ -0,0 +1,11 @@
package io.github.openflocon.flocon.plugins.analytics.model
data class AnalyticsPropertiesConfig(
val name: String,
val value: String,
)
infix fun String.analyticsProperty(value: String) = AnalyticsPropertiesConfig(
name = this,
value = value,
)

View file

@ -0,0 +1,9 @@
package io.github.openflocon.flocon.plugins.analytics.model
data class AnalyticsItem(
val id: String,
val analyticsTableId: String,
val eventName: String,
val createdAt: Long,
val properties: List<AnalyticsPropertiesConfig>,
)

View file

@ -0,0 +1,20 @@
package io.github.openflocon.flocon.plugins.dashboard
import io.github.openflocon.flocon.FloconApp
import io.github.openflocon.flocon.core.FloconPlugin
import io.github.openflocon.flocon.plugins.dashboard.dsl.DashboardBuilder
import io.github.openflocon.flocon.plugins.dashboard.dsl.dashboardConfig
import io.github.openflocon.flocon.plugins.dashboard.model.DashboardConfig
fun FloconApp.dashboard(id: String, block: DashboardBuilder.() -> Unit) {
this.client?.dashboardPlugin?.let {
// on no op, this callback is never called
val dashboardConfig = dashboardConfig(id = id, block)
it.registerDashboard(dashboardConfig)
}
}
interface FloconDashboardPlugin : FloconPlugin {
fun registerDashboard(dashboardConfig: DashboardConfig)
}

View file

@ -0,0 +1,19 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.ButtonConfig
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
@DashboardDsl
fun SectionBuilder.button(
text: String,
id : String,
onClick: () -> Unit,
) {
add(
ButtonConfig(
text = text,
id = id,
onClick = onClick,
)
)
}

View file

@ -0,0 +1,21 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.CheckBoxConfig
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
@DashboardDsl
fun SectionBuilder.checkBox(
id: String,
label: String,
value: Boolean,
onUpdated: (Boolean) -> Unit,
) {
add(
CheckBoxConfig(
id = id,
label = label,
value = value,
onUpdated = onUpdated,
)
)
}

View file

@ -0,0 +1,21 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.DashboardConfig
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionConfig
@DashboardDsl
class DashboardBuilder(private val id: String) {
private val sections = mutableListOf<SectionConfig>()
fun add(section: SectionConfig) {
sections.add(section)
}
fun build(): DashboardConfig {
return DashboardConfig(
id = id,
sections = sections
)
}
}

View file

@ -0,0 +1,14 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.DashboardConfig
@DslMarker
annotation class DashboardDsl
fun dashboardConfig(id: String, block: DashboardBuilder.() -> Unit): DashboardConfig {
val builder = DashboardBuilder(id = id)
.apply {
block()
}
return builder.build()
}

View file

@ -0,0 +1,24 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.PlainTextConfig
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
@DashboardDsl
fun SectionBuilder.plainText(label: String, value: String) {
add(
PlainTextConfig(
label = label,
value = value,
type = "text",
)
)
}
@DashboardDsl
fun SectionBuilder.json(label: String, value: String) {
add(PlainTextConfig(
label = label,
value = value,
type = "json",
))
}

View file

@ -0,0 +1,11 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
@DashboardDsl
fun DashboardBuilder.section(name: String, block: SectionBuilder.() -> Unit) {
val builder = SectionBuilder(name).apply {
block()
}
add(builder.build())
}

View file

@ -0,0 +1,9 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
import io.github.openflocon.flocon.plugins.dashboard.model.config.TextConfig
@DashboardDsl
fun SectionBuilder.text(label: String, value: String, color: Int? = null) {
add(TextConfig(label = label, value = value, color = color))
}

View file

@ -0,0 +1,23 @@
package io.github.openflocon.flocon.plugins.dashboard.dsl
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionBuilder
import io.github.openflocon.flocon.plugins.dashboard.model.config.TextFieldConfig
@DashboardDsl
fun SectionBuilder.textField(
id: String,
label: String,
placeHolder: String?,
value: String,
onSubmitted: (String) -> Unit,
) {
add(
TextFieldConfig(
id = id,
label = label,
placeHolder = placeHolder,
value = value,
onSubmitted = onSubmitted,
)
)
}

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.dashboard.model
import io.github.openflocon.flocon.plugins.dashboard.model.config.SectionConfig
data class DashboardConfig(
val id: String,
val sections: List<SectionConfig>
)

View file

@ -0,0 +1,7 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class ButtonConfig(
val text: String,
val id: String,
val onClick: () -> Unit,
) : ElementConfig

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class CheckBoxConfig(
val id: String,
val label: String,
val value: Boolean,
val onUpdated: (Boolean) -> Unit,
) : ElementConfig

View file

@ -0,0 +1,3 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
sealed interface ElementConfig

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class PlainTextConfig(
val label: String,
val value: String,
val type: String, // text, json
) : ElementConfig

View file

@ -0,0 +1,13 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
class SectionBuilder(val name: String) {
private val elements = mutableListOf<ElementConfig>()
fun add(element: ElementConfig) {
elements.add(element)
}
fun build(): SectionConfig {
return SectionConfig(name, elements)
}
}

View file

@ -0,0 +1,6 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class SectionConfig(
val name: String,
val elements: List<ElementConfig>
)

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class TextConfig(
val label: String,
val value: String,
val color: Int?,
) : ElementConfig

View file

@ -0,0 +1,9 @@
package io.github.openflocon.flocon.plugins.dashboard.model.config
data class TextFieldConfig(
val id: String,
val label: String,
val placeHolder: String?,
val value: String,
val onSubmitted: (String) -> Unit,
) : ElementConfig

View file

@ -0,0 +1,6 @@
package io.github.openflocon.flocon.plugins.database
import io.github.openflocon.flocon.core.FloconPlugin
interface FloconDatabasePlugin : FloconPlugin

View file

@ -0,0 +1,13 @@
package io.github.openflocon.flocon.plugins.deeplinks
import io.github.openflocon.flocon.FloconApp
import io.github.openflocon.flocon.core.FloconPlugin
import io.github.openflocon.flocon.plugins.deeplinks.model.Deeplink
fun FloconApp.deeplinks(deeplinks: List<Deeplink>) {
this.client?.deeplinksPlugin?.registerDeeplinks(deeplinks)
}
interface FloconDeeplinksPlugin : FloconPlugin {
fun registerDeeplinks(deeplinks: List<Deeplink>)
}

View file

@ -0,0 +1,7 @@
package io.github.openflocon.flocon.plugins.deeplinks.model
data class Deeplink(
val link: String,
val label: String? = null,
val description: String? = null,
)

View file

@ -0,0 +1,5 @@
package io.github.openflocon.flocon.plugins.files
import io.github.openflocon.flocon.core.FloconPlugin
interface FloconFilesPlugin : FloconPlugin

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.network
import io.github.openflocon.flocon.core.FloconPlugin
import io.github.openflocon.flocon.plugins.network.model.FloconNetworkRequest
interface FloconNetworkPlugin : FloconPlugin {
fun log(call: FloconNetworkRequest)
}

View file

@ -0,0 +1,26 @@
package io.github.openflocon.flocon.plugins.network.model
data class FloconNetworkRequest(
val request: Request,
val response: Response,
val durationMs: Double,
val floconNetworkType: String,
) {
data class Request(
val url: String,
val method: String,
val startTime: Long,
val headers: Map<String, String>,
val body: String?,
val size: Long?,
)
data class Response(
val httpCode: Int?,
val grpcStatus: String?,
val contentType: String?,
val body: String?,
val size: Long?,
val headers: Map<String, String>,
)
}

View file

@ -0,0 +1,5 @@
package io.github.openflocon.flocon.plugins.SharedPreferences
import io.github.openflocon.flocon.core.FloconPlugin
interface FloconSharedPreferencesPlugin : FloconPlugin

View file

@ -0,0 +1,17 @@
package io.github.openflocon.flocon.plugins.tables
import io.github.openflocon.flocon.FloconApp
import io.github.openflocon.flocon.core.FloconPlugin
import io.github.openflocon.flocon.plugins.tables.builder.TableBuilder
import io.github.openflocon.flocon.plugins.tables.model.TableItem
fun FloconApp.table(tableName: String): TableBuilder {
return TableBuilder(
tableName = tableName,
tablePlugin = this.client?.tablePlugin,
)
}
interface FloconTablePlugin : FloconPlugin {
fun registerTable(tableItem: TableItem)
}

View file

@ -0,0 +1,21 @@
package io.github.openflocon.flocon.plugins.tables.builder
import io.github.openflocon.flocon.plugins.tables.FloconTablePlugin
import io.github.openflocon.flocon.plugins.tables.model.TableColumnConfig
import io.github.openflocon.flocon.plugins.tables.model.TableItem
import java.util.UUID
class TableBuilder(
val tableName: String,
private val tablePlugin: FloconTablePlugin?,
) {
fun log(vararg columns: TableColumnConfig) {
val dashboardConfig = TableItem(
id = UUID.randomUUID().toString(),
name = tableName,
columns = columns.toList(),
createdAt = System.currentTimeMillis(),
)
tablePlugin?.registerTable(dashboardConfig)
}
}

View file

@ -0,0 +1,11 @@
package io.github.openflocon.flocon.plugins.tables.model
data class TableColumnConfig(
val columnName: String,
val value: String,
)
infix fun String.toParam(value: String) = TableColumnConfig(
columnName = this,
value = value,
)

View file

@ -0,0 +1,8 @@
package io.github.openflocon.flocon.plugins.tables.model
data class TableItem(
val id: String,
val name: String,
val createdAt: Long,
val columns: List<TableColumnConfig>,
)