Skip to content

Commit 75b35a2

Browse files
committed
feat: add log in and add device via QR
1 parent 3e460e3 commit 75b35a2

56 files changed

Lines changed: 3711 additions & 1680 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package org.monogram.core.models
2+
3+
data class DeviceSession(
4+
val hash: Long,
5+
val current: Boolean,
6+
val passwordPending: Boolean,
7+
val deviceModel: String,
8+
val platform: String,
9+
val systemVersion: String,
10+
val appName: String,
11+
val appVersion: String,
12+
val dateActive: Int,
13+
val ip: String,
14+
val country: String,
15+
val region: String,
16+
)
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package org.monogram.core.models
2+
3+
sealed interface QrLogin {
4+
class Code(val link: String, val expires: Int) : QrLogin
5+
6+
data class Authorized(val session: AuthSession) : QrLogin
7+
8+
data object AwaitingPassword : QrLogin
9+
}
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
package org.monogram.core.ui.components
2+
3+
import androidx.compose.foundation.layout.Arrangement
4+
import androidx.compose.foundation.layout.Box
5+
import androidx.compose.foundation.layout.BoxWithConstraints
6+
import androidx.compose.foundation.layout.Column
7+
import androidx.compose.foundation.layout.ColumnScope
8+
import androidx.compose.foundation.layout.Spacer
9+
import androidx.compose.foundation.layout.WindowInsets
10+
import androidx.compose.foundation.layout.fillMaxSize
11+
import androidx.compose.foundation.layout.fillMaxWidth
12+
import androidx.compose.foundation.layout.height
13+
import androidx.compose.foundation.layout.padding
14+
import androidx.compose.foundation.layout.safeDrawing
15+
import androidx.compose.foundation.layout.size
16+
import androidx.compose.foundation.layout.widthIn
17+
import androidx.compose.foundation.layout.windowInsetsPadding
18+
import androidx.compose.foundation.rememberScrollState
19+
import androidx.compose.foundation.shape.CircleShape
20+
import androidx.compose.foundation.verticalScroll
21+
import androidx.compose.material.icons.Icons
22+
import androidx.compose.material.icons.automirrored.outlined.ArrowBack
23+
import androidx.compose.material3.FilledTonalIconButton
24+
import androidx.compose.material3.Icon
25+
import androidx.compose.material3.IconButtonDefaults
26+
import androidx.compose.material3.MaterialTheme
27+
import androidx.compose.material3.Surface
28+
import androidx.compose.material3.Text
29+
import androidx.compose.runtime.Composable
30+
import androidx.compose.ui.Alignment
31+
import androidx.compose.ui.Modifier
32+
import androidx.compose.ui.graphics.vector.ImageVector
33+
import androidx.compose.ui.text.style.TextAlign
34+
import androidx.compose.ui.unit.dp
35+
36+
@Composable
37+
fun QrCodeScreen(
38+
title: String,
39+
description: String,
40+
icon: ImageVector,
41+
backDescription: String,
42+
onBack: () -> Unit,
43+
modifier: Modifier = Modifier,
44+
descriptionAlignment: TextAlign = TextAlign.Start,
45+
content: @Composable ColumnScope.() -> Unit,
46+
) {
47+
Surface(modifier.fillMaxSize(), color = MaterialTheme.colorScheme.surfaceContainer) {
48+
BoxWithConstraints(Modifier.fillMaxSize().windowInsetsPadding(WindowInsets.safeDrawing)) {
49+
val contentGap = (maxHeight * 0.13f).coerceIn(32.dp, 112.dp)
50+
Column(
51+
modifier =
52+
Modifier.align(Alignment.TopCenter)
53+
.widthIn(max = 600.dp)
54+
.fillMaxWidth()
55+
.verticalScroll(rememberScrollState())
56+
.padding(horizontal = 24.dp, vertical = 16.dp),
57+
horizontalAlignment = Alignment.CenterHorizontally,
58+
) {
59+
Box(Modifier.fillMaxWidth().height(72.dp)) {
60+
FilledTonalIconButton(
61+
onClick = onBack,
62+
modifier = Modifier.align(Alignment.CenterStart).size(44.dp),
63+
shape = CircleShape,
64+
colors =
65+
IconButtonDefaults.filledTonalIconButtonColors(
66+
containerColor = MaterialTheme.colorScheme.surfaceContainerHigh,
67+
contentColor = MaterialTheme.colorScheme.onSurface,
68+
),
69+
) {
70+
Icon(
71+
Icons.AutoMirrored.Outlined.ArrowBack,
72+
contentDescription = backDescription,
73+
)
74+
}
75+
Icon(
76+
icon,
77+
contentDescription = null,
78+
tint = MaterialTheme.colorScheme.primary,
79+
modifier = Modifier.align(Alignment.Center).size(48.dp),
80+
)
81+
}
82+
Spacer(Modifier.height(24.dp))
83+
Text(
84+
title,
85+
modifier = Modifier.fillMaxWidth(),
86+
style = MaterialTheme.typography.displaySmall,
87+
)
88+
Spacer(Modifier.height(24.dp))
89+
Text(
90+
description,
91+
modifier = Modifier.fillMaxWidth(),
92+
style = MaterialTheme.typography.bodyLarge,
93+
color = MaterialTheme.colorScheme.onSurfaceVariant,
94+
textAlign = descriptionAlignment,
95+
)
96+
Spacer(Modifier.height(contentGap))
97+
Column(
98+
modifier =
99+
Modifier.padding(horizontal = 24.dp).widthIn(max = 360.dp).fillMaxWidth(),
100+
horizontalAlignment = Alignment.CenterHorizontally,
101+
verticalArrangement = Arrangement.spacedBy(24.dp),
102+
content = content,
103+
)
104+
Spacer(Modifier.height(32.dp))
105+
}
106+
}
107+
}
108+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package org.monogram.core.ui.qr
2+
3+
import android.graphics.Bitmap
4+
import uniffi.monogram_mtproto.decodeQrCode
5+
import uniffi.monogram_mtproto.generateQrCode
6+
7+
object QrCode {
8+
fun render(text: String, size: Int, foreground: Int, background: Int): Bitmap {
9+
require(size in 1..2048)
10+
val matrix = generateQrCode(text, size.toUInt())
11+
val pixels =
12+
IntArray(matrix.luma.size) { index ->
13+
if (matrix.luma[index] == 0.toByte()) foreground else background
14+
}
15+
val side = matrix.size.toInt()
16+
return Bitmap.createBitmap(pixels, side, side, Bitmap.Config.ARGB_8888)
17+
}
18+
19+
fun decode(luma: ByteArray, width: Int, height: Int): String? {
20+
require(width in 1..2048 && height in 1..2048 && luma.size == width * height)
21+
return decodeQrCode(luma, width.toUInt(), height.toUInt())
22+
}
23+
}

‎feature/auth/build.gradle.kts‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,8 @@ android {
2424
}
2525

2626
dependencies {
27+
implementation(libs.androidx.activity.compose)
28+
implementation(libs.androidx.lifecycle.runtime.compose)
2729
implementation(project(":core:common"))
2830
implementation(project(":core:models"))
2931
implementation(libs.mvikotlin)

0 commit comments

Comments
 (0)