Skip to content

Commit

Permalink
Colors, QR Codes, Custom Themes, and More!
Browse files Browse the repository at this point in the history
  • Loading branch information
aenriii committed May 25, 2024
1 parent 976e8c5 commit f60ac5f
Show file tree
Hide file tree
Showing 45 changed files with 1,038 additions and 1,749 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ build
xcuserdata
/smali
/appDesktop/.genesis.json
/.idea/artifacts/
8 changes: 7 additions & 1 deletion genesis/app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,14 @@ kotlin {

implementation(libs.napier)

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
implementation(libs.qr)

implementation(libs.coil)
implementation(libs.coil.svg)
implementation(libs.coil.compose)
implementation(libs.coil.network.ktor)

implementation("org.jetbrains.kotlinx:kotlinx-coroutines-core:1.7.3")
// implementation(libs.kamel)


Expand Down
15 changes: 8 additions & 7 deletions genesis/app/src/commonMain/kotlin/uninit/genesis/app/App.kt
Original file line number Diff line number Diff line change
@@ -1,19 +1,18 @@
package uninit.genesis.app

import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.CompositionLocalProvider
import androidx.compose.runtime.compositionLocalOf
import cafe.adriel.voyager.navigator.Navigator
import io.github.aakira.napier.Antilog
import io.github.aakira.napier.Napier
import org.koin.compose.getKoin
import org.koin.core.context.startKoin
import org.koin.dsl.koinApplication
import uninit.common.compose.preferences.PreferencesManager
import uninit.common.compose.theme.LocalApplicationTheme
import uninit.common.compose.theme.ThemeRegistry
import uninit.genesis.app.ui.screens.LaunchScreen
import uninit.genesis.app.ui.theme.Theme
import uninit.genesis.app.ui.theme.catppuccin.mocha.CTPMochaPink

val LocalCompositionTheme = compositionLocalOf<Theme> { CTPMochaPink }

@Composable
fun App() {
Napier.base(getAntiLog())
Expand All @@ -22,7 +21,9 @@ fun App() {
startKoin {
modules(nativeModule)
}
CompositionLocalProvider( LocalCompositionTheme provides CTPMochaPink ) {
val themeId by getKoin().get<PreferencesManager>().preference("currentThemeId", "Catppuccin/Mocha/Pink")

CompositionLocalProvider( LocalApplicationTheme provides ThemeRegistry.getOrDefault(themeId) ) {
Navigator(LaunchScreen())
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,40 +1,51 @@
package uninit.genesis.app.ui.screens.onboarding

import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.geometry.Offset
import androidx.compose.ui.geometry.Size
import androidx.compose.ui.draw.clip
import androidx.compose.ui.layout.onSizeChanged
import androidx.compose.ui.unit.IntSize
import androidx.compose.ui.unit.dp
import cafe.adriel.voyager.core.screen.Screen
import coil3.compose.AsyncImage
import coil3.compose.AsyncImagePainter
import coil3.compose.rememberAsyncImagePainter
import io.github.aakira.napier.Napier
import io.ktor.client.engine.*
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.IO
import kotlinx.coroutines.launch
import org.jetbrains.skia.Bitmap
import org.jetbrains.skia.Image
import org.koin.compose.getKoin
import uninit.common.QrMatrix
import uninit.genesis.app.LocalCompositionTheme
import qrcode.QRCode
import qrcode.color.Colors
import uninit.common.compose.theme.LocalApplicationTheme
import uninit.genesis.discord.client.GenesisClient
import uninit.genesis.discord.client.gateway.GatewayQRLoginClient
import uninit.genesis.discord.client.gateway.auth.GatewayQRAuthAwaitingApprovalEvent

class OnboardingScreen : Screen {
@Composable
override fun Content() {
val theme = LocalCompositionTheme.current
val theme = LocalApplicationTheme.current
// val windowSize = currentWindowAdaptiveInfo().windowSizeClass
Box(
modifier = Modifier
.fillMaxSize()
.background(theme.base)
.background(theme.backgroundPane),
contentAlignment = Alignment.Center

) {
OnboardingQRLoginPage()
}
Expand Down Expand Up @@ -89,7 +100,7 @@ class OnboardingScreen : Screen {
}
QRLoginState.AwaitingApproval,
QRLoginState.ExchangingTicket -> {
partialUser?.let { UserPartialInfo(it) }
partialUser?.let { UserPartialInfo(it, state == QRLoginState.AwaitingApproval) }
if (state == QRLoginState.ExchangingTicket) LoadingScreen("Exchanging ticket...")
}
QRLoginState.TokenReceived -> {
Expand All @@ -106,47 +117,88 @@ class OnboardingScreen : Screen {
modifier = Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
Text(text, color = LocalCompositionTheme.current.text)
Text(text, color = LocalApplicationTheme.current.body)
}

}
@Composable
fun QRCode(link: String) {
Napier.v("QRCode: $link")
val qrMatrix by remember { mutableStateOf(QrMatrix(link)) }
val primary = LocalCompositionTheme.current.primary
var qr by remember<MutableState<ByteArray?>> { mutableStateOf(null) }
var size by remember { mutableStateOf(IntSize.Zero) }
Box(
modifier = Modifier.aspectRatio(1f).fillMaxWidth(0.5f).padding(16.dp),
modifier = Modifier
.aspectRatio(1f)
.fillMaxWidth(0.5f)
.padding(16.dp)
.onSizeChanged {
size = it
},
contentAlignment = Alignment.Center
) {
Canvas(modifier = Modifier.fillMaxSize()) {
val cellSize = size.width / qrMatrix.width
qrMatrix.matrix.forEachIndexed { x, row ->
row.forEachIndexed { y, value ->
if (value) {
drawRect(
color = primary,
topLeft = Offset(x * cellSize, y * cellSize),
size = Size(cellSize, cellSize)
)
}
}
val color = LocalApplicationTheme.current.body
LaunchedEffect(link) {
color.let {
qr = QRCode
.ofRoundedSquares()
.withColor(Colors.rgba(
(it.red * 255F).toInt(),
(it.green * 255F).toInt(),
(it.blue * 255F).toInt(),
(it.alpha * 255F).toInt()
))
.withBackgroundColor(Colors.TRANSPARENT)
.withRadius(10)
.withSize(10)
.build(link)
.renderToBytes()
}
}
qr?.let {
AsyncImage(it, "QR Code")
}
}

}


@Composable
fun UserPartialInfo(partialUser: GatewayQRAuthAwaitingApprovalEvent) {
fun UserPartialInfo(
partialUser: GatewayQRAuthAwaitingApprovalEvent,
sayApprove: Boolean
) {
Napier.v("UserPartialInfo: $partialUser")
val painter = rememberAsyncImagePainter(partialUser.userAvatarUri)
Column(
modifier = Modifier.fillMaxWidth().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center,
) {
Text("User: ${partialUser.userName}")
Text("ID: ${partialUser.userId}")
Text("AvatarUri: ${partialUser.userAvatarUri}")
ThemedText("Welcome Back, ${partialUser.userName}!")
when (painter.state) {
is AsyncImagePainter.State.Loading -> {
CircularProgressIndicator(
modifier = Modifier.size(100.dp),
color = LocalApplicationTheme.current.accent
)
}
is AsyncImagePainter.State.Error -> {
ThemedText("Error loading avatar")
}
is AsyncImagePainter.State.Success -> {
Image(
painter = painter,
contentDescription = "User Avatar",
modifier = Modifier
.size(100.dp)
.clip(
RoundedCornerShape(50.dp)
)
)
}

AsyncImagePainter.State.Empty -> TODO()
}
if (sayApprove) ThemedText("Please approve the login request on your device.")
}
}

Expand All @@ -158,9 +210,9 @@ class OnboardingScreen : Screen {
modifier = Modifier.fillMaxSize().padding(16.dp),
horizontalAlignment = Alignment.CenterHorizontally
) {
Text("Token Received, testing...")
ThemedText("Token Received, testing...")
messages.forEach {
Text(it)
ThemedText(it)
}
}
CoroutineScope(Dispatchers.IO).launch {
Expand All @@ -174,11 +226,26 @@ class OnboardingScreen : Screen {
}
}

@Composable
fun ThemedText(text: String) {
Text(text, color = LocalApplicationTheme.current.body)
}


}

private fun Bitmap.Companion.decodeByteArray(it: ByteArray): Bitmap {
val bitmap = Bitmap()
val image = Image.makeFromEncoded(it)
bitmap.setImageInfo(image.imageInfo)
image.readPixels(dst = bitmap)
return bitmap
}

enum class QRLoginState {
AwaitingQRCode,
AwaitingScan,
AwaitingApproval,
ExchangingTicket,
TokenReceived
}
}

This file was deleted.

This file was deleted.

This file was deleted.

Loading

0 comments on commit f60ac5f

Please sign in to comment.