Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Combine socket #34

Closed
wants to merge 10 commits into from
Closed
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
8 changes: 7 additions & 1 deletion build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
plugins {
id(libs.plugins.android.library.get().pluginId) apply false
id(libs.plugins.kotlin.multiplatform.get().pluginId) apply false
alias(libs.plugins.ktfmt)
}

Expand All @@ -7,4 +9,8 @@ subprojects {
ktfmt {
kotlinLangStyle()
}
}
}

tasks.wrapper {
gradleVersion = "8.8"
}
1 change: 0 additions & 1 deletion buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
@Suppress("UnstableApiUsage")
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
Expand Down
50 changes: 21 additions & 29 deletions buildSrc/src/main/kotlin/Projects.kt
Original file line number Diff line number Diff line change
@@ -1,51 +1,45 @@
package lighthouse

import com.android.build.api.dsl.CommonExtension
import com.android.build.api.dsl.Lint
import com.android.build.gradle.BaseExtension
import com.android.build.gradle.LibraryExtension
import com.android.build.gradle.TestExtension
import com.android.build.gradle.internal.dsl.BaseAppModuleExtension
import com.vanniktech.maven.publish.MavenPublishBaseExtension
import com.vanniktech.maven.publish.SonatypeHost
import org.gradle.api.JavaVersion
import org.gradle.api.Project
import org.gradle.api.publish.PublishingExtension
import org.gradle.api.publish.maven.MavenPublication
import org.gradle.kotlin.dsl.apply
import org.gradle.kotlin.dsl.configure
import org.gradle.kotlin.dsl.create
import org.gradle.kotlin.dsl.get
import org.gradle.kotlin.dsl.withType
import org.jetbrains.kotlin.gradle.dsl.JvmTarget
import org.jetbrains.kotlin.gradle.tasks.KotlinJvmCompile
/**
*
*/

fun Project.setupLibraryModule(
moduleName: String,
shouldBePublished: Boolean,
action: LibraryExtension.() -> Unit = {},
) = setupBaseModule<LibraryExtension>(moduleName) {
if (shouldBePublished) {
apply(plugin = "com.vanniktech.maven.publish.base")
publishing {
singleVariant("release") {
withJavadocJar()
withSourcesJar()
}
}
afterEvaluate {
extensions.configure<PublishingExtension> {
publications.create<MavenPublication>("release") {
from(components["release"])
// https://github.com/vanniktech/gradle-maven-publish-plugin/issues/326
val id = project.property("POM_ARTIFACT_ID").toString()
artifactId = artifactId.replace(project.name, id)
}
}
}
// publishing {
// singleVariant("release") {
// withJavadocJar()
// withSourcesJar()
// }
// }
// afterEvaluate {
// extensions.configure<PublishingExtension> {
// publications.create<MavenPublication>("release") {
// from(components["release"])
// // https://github.com/vanniktech/gradle-maven-publish-plugin/issues/326
// val id = project.property("POM_ARTIFACT_ID").toString()
// artifactId = artifactId.replace(project.name, id)
// }
// }
// }
extensions.configure<MavenPublishBaseExtension> {
configure(
com.vanniktech.maven.publish.KotlinMultiplatform(javadocJar = com.vanniktech.maven.publish.JavadocJar.Empty())
)
publishToMavenCentral(SonatypeHost.S01, automaticRelease = true)
signAllPublications()

Expand Down Expand Up @@ -97,13 +91,11 @@ fun Project.setupDemoModule(
applicationId = name
versionCode = 1
versionName = project.versionName
targetSdk = project.targetSdk
}
buildFeatures {
compose = true
}
composeOptions {
kotlinCompilerExtensionVersion = "1.4.2"
}

buildTypes {
getByName("release") {
Expand Down
56 changes: 41 additions & 15 deletions demo/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,27 +1,53 @@
import lighthouse.setupDemoModule

plugins {
id("com.android.application")
id("org.jetbrains.kotlin.android")
id(libs.plugins.kotlin.multiplatform.get().pluginId)
id(libs.plugins.android.application.get().pluginId)
alias(libs.plugins.jetbrainsCompose)
alias(libs.plugins.compose.compiler)
}

setupDemoModule(name = "com.ivanempire.lighthouse.demo")

dependencies {
// Core Android libraries
implementation(libs.androidx.core)
implementation(libs.androidx.runtime)
kotlin {
androidTarget()
jvm()

// Compose libraries
implementation(platform("androidx.compose:compose-bom:2023.01.00"))
implementation(libs.material3)
jvmToolchain(17)

// Compose integration with activities
implementation(libs.compose.activity)
sourceSets {
val commonMain by getting {
dependencies {
// Compose libraries
implementation(compose.material3)

// Switch out for local development
implementation(project(":lighthouse"))
implementation(project(":lighthouse"))
}
}

// Always points to latest release
// implementation("com.ivanempire:lighthouse:2.1.1")
val androidMain by getting {
dependencies {
// Core Android libraries
implementation(libs.androidx.core)
implementation(libs.androidx.runtime)

// Compose integration with activities
implementation(libs.compose.activity)
}
}

val jvmMain by getting {
dependencies {
implementation(compose.desktop.currentOs)
}
}
}
}

compose {
desktop {
application {
mainClass = "com.ivanempire.lighthouse.demo.MainKt"
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package com.ivanempire.lighthouse.demo

import android.os.Bundle
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import com.ivanempire.lighthouse.LighthouseClient
import com.ivanempire.lighthouse.LighthouseLogger
import com.ivanempire.lighthouse.lighthouseClient

class MainActivity : ComponentActivity() {

private lateinit var lighthouseClient: LighthouseClient

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

// Example implementation of a custom logging system
val customLogger =
object : LighthouseLogger() {
override fun logStateMessage(tag: String, message: String) {
Log.d(tag, message)
}

override fun logStatusMessage(tag: String, message: String) {
Log.d(tag, message)
}

override fun logPacketMessage(tag: String, message: String) {
Log.d(tag, message)
}

override fun logErrorMessage(tag: String, message: String, ex: Throwable?) {
Log.e(tag, message, ex)
}
}

// Setup the client
lighthouseClient =
lighthouseClient(this) {
logger = customLogger
retryCount = 2
}

// Skips the need for Dagger in a simple demo app
val viewModelFactory = MainActivityViewModelFactory(lighthouseClient)
val viewModel = viewModelFactory.create(MainActivityViewModel::class.java)

setContent {
val discoveredDeviceList by viewModel.discoveredDevices.collectAsState()
DeviceList(
discoveredDeviceList = discoveredDeviceList,
startDiscovery = viewModel::startDiscovery,
stopDiscovery = viewModel::stopDiscovery,
)
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,14 @@ import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.ivanempire.lighthouse.LighthouseClient
import com.ivanempire.lighthouse.models.devices.AbridgedMediaDevice
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
import kotlinx.coroutines.cancelAndJoin
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.flowOn
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import kotlinx.coroutines.runBlocking

class MainActivityViewModel(
private val lighthouseClient: LighthouseClient,
Expand All @@ -21,11 +23,17 @@ class MainActivityViewModel(
val discoveredDevices = backingDiscoveredDevices.asStateFlow()

fun startDiscovery() {
discoveryJob =
viewModelScope.launch {
lighthouseClient.discoverDevices().collect { backingDiscoveredDevices.value = it }
}
viewModelScope.launch {
discoveryJob =
lighthouseClient
.discoverDevices()
.flowOn(Dispatchers.IO)
.onEach { backingDiscoveredDevices.value = it }
.launchIn(viewModelScope)
}
}

fun stopDiscovery() = runBlocking { discoveryJob?.cancelAndJoin() }
fun stopDiscovery() {
discoveryJob?.cancel()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package com.ivanempire.lighthouse.demo

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material3.Button
import androidx.compose.material3.ListItem
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.unit.dp
import com.ivanempire.lighthouse.models.devices.AbridgedMediaDevice
import kotlinx.coroutines.delay

@Composable
fun DeviceList(
discoveredDeviceList: List<AbridgedMediaDevice>,
startDiscovery: () -> Unit,
stopDiscovery: () -> Unit,
) {
Column(modifier = Modifier.padding(16.dp)) {
LazyColumn(
modifier = Modifier.weight(1f).fillMaxWidth(),
) {
items(
items = discoveredDeviceList,
key = { it.uuid },
) {
DeviceListItem(device = it)
}
}

val isDiscoveryRunning = remember { mutableStateOf(false) }

Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.SpaceEvenly) {
Button(
onClick = {
stopDiscovery()
isDiscoveryRunning.value = false
},
enabled = isDiscoveryRunning.value
) {
Text(text = "Stop discovery")
}
Button(
onClick = {
startDiscovery()
isDiscoveryRunning.value = true
},
enabled = !isDiscoveryRunning.value
) {
Text(text = "Start discovery")
}
}
}
}

@Composable
private fun DeviceListItem(device: AbridgedMediaDevice) {
var currentTime by remember { mutableStateOf(System.currentTimeMillis()) }
val ttl = device.cache - (currentTime - device.latestTimestamp) / 1000
ListItem(
headlineContent = { Text(device.location.toString()) },
supportingContent = { Text(device.uuid) },
trailingContent = { Text(ttl.toString()) },
)
LaunchedEffect(Unit) {
while (true) {
currentTime = System.currentTimeMillis()
delay(1000)
}
}
}
Loading
Loading