Move auth to service, UI/UX improvements

- Service handles auth: auto-login via Quest SDK on onCreate, periodic
  token refresh, isAuthenticated/login AIDL methods
- Clients tab shows actual connected game clients from ClientTracker
  instead of plans filtered by status
- Create Plan service picker shows "YouTube - DisplayName" per linked
  account instead of raw service IDs
- createDefaultPlan AIDL method creates plan with one destination per
  linked account (unlisted)
- Session validation on Activity open via getMe() call
- Backend health indicator (green/red dot) on Dashboard nav icon
- ConnectedClientInfo parcelable for client data over AIDL
- SDK client exposes isAuthenticated, login, createDefaultPlan,
  getConnectedClients, authenticated StateFlow
This commit is contained in:
2026-02-27 13:20:48 +01:00
parent ad2c398d78
commit 5b8ede3a19
24 changed files with 623 additions and 183 deletions

View File

@@ -5,6 +5,7 @@ import android.content.Context
import android.content.Intent
import android.content.ServiceConnection
import android.os.IBinder
import com.omixlab.lckcontrol.shared.ConnectedClientInfo
import com.omixlab.lckcontrol.shared.ILckControlCallback
import com.omixlab.lckcontrol.shared.ILckControlService
import com.omixlab.lckcontrol.shared.LinkedAccount
@@ -28,6 +29,9 @@ class LckControlClient(private val context: Context) {
private val _connected = MutableStateFlow(false)
val connected: StateFlow<Boolean> = _connected.asStateFlow()
private val _authenticated = MutableStateFlow(false)
val authenticated: StateFlow<Boolean> = _authenticated.asStateFlow()
private val _streamPlans = MutableStateFlow<List<StreamPlan>>(emptyList())
val streamPlans: StateFlow<List<StreamPlan>> = _streamPlans.asStateFlow()
@@ -44,6 +48,10 @@ class LckControlClient(private val context: Context) {
override fun onClientRegistered(id: String) {}
override fun onClientUnregistered(id: String) {}
override fun onAuthStateChanged(authenticated: Boolean) {
_authenticated.value = authenticated
}
}
private val connection = object : ServiceConnection {
@@ -51,12 +59,14 @@ class LckControlClient(private val context: Context) {
service = ILckControlService.Stub.asInterface(binder)
service?.registerCallback(callback)
_connected.value = true
_authenticated.value = service?.isAuthenticated ?: false
}
override fun onServiceDisconnected(name: ComponentName?) {
service = null
clientId = null
_connected.value = false
_authenticated.value = false
}
}
@@ -80,18 +90,39 @@ class LckControlClient(private val context: Context) {
service = null
clientId = null
_connected.value = false
_authenticated.value = false
}
// ── Auth ────────────────────────────────────────────
fun isAuthenticated(): Boolean {
return service?.isAuthenticated ?: false
}
fun login() {
service?.login()
}
// ── Client registration ─────────────────────────────
fun registerAsClient(clientName: String, packageName: String): String? {
val id = service?.registerClient(clientName, packageName)
clientId = id
return id
}
fun getConnectedClients(): List<ConnectedClientInfo> {
return service?.connectedClients ?: emptyList()
}
// ── Accounts ────────────────────────────────────────
fun getLinkedAccounts(): List<LinkedAccount> {
return service?.linkedAccounts ?: emptyList()
}
// ── Stream plans ────────────────────────────────────
fun getStreamPlans(): List<StreamPlan> {
return service?.streamPlans ?: emptyList()
}
@@ -104,6 +135,10 @@ class LckControlClient(private val context: Context) {
return service?.createStreamPlan(config)
}
fun createDefaultPlan(clientName: String): StreamPlan? {
return service?.createDefaultPlan(clientName)
}
fun prepareStreamPlan(planId: String): StreamPlan? {
return service?.prepareStreamPlan(planId)
}