mirror of
https://github.com/bbara04/Purefin.git
synced 2026-07-24 03:36:51 +00:00
feat: redesign login screen on both app and app-tv
This commit is contained in:
@@ -0,0 +1,21 @@
|
||||
package hu.bbara.purefin.ui.common.image
|
||||
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.graphics.Color
|
||||
import androidx.compose.ui.res.painterResource
|
||||
import hu.bbara.purefin.core.ui.R
|
||||
|
||||
@Composable
|
||||
fun PurefinLogo(
|
||||
modifier: Modifier = Modifier,
|
||||
color: Color = Color(0xFF7C42F0)
|
||||
) {
|
||||
Icon(
|
||||
painter = painterResource(id = R.drawable.purefin_logo_tintable),
|
||||
contentDescription = "Purefin logo",
|
||||
modifier = modifier,
|
||||
tint = color
|
||||
)
|
||||
}
|
||||
@@ -1,201 +0,0 @@
|
||||
package hu.bbara.purefin.ui.screen.login
|
||||
|
||||
import androidx.compose.foundation.background
|
||||
import androidx.compose.foundation.layout.Arrangement
|
||||
import androidx.compose.foundation.layout.Box
|
||||
import androidx.compose.foundation.layout.Column
|
||||
import androidx.compose.foundation.layout.Row
|
||||
import androidx.compose.foundation.layout.Spacer
|
||||
import androidx.compose.foundation.layout.fillMaxSize
|
||||
import androidx.compose.foundation.layout.fillMaxWidth
|
||||
import androidx.compose.foundation.layout.height
|
||||
import androidx.compose.foundation.layout.padding
|
||||
import androidx.compose.foundation.layout.size
|
||||
import androidx.compose.foundation.rememberScrollState
|
||||
import androidx.compose.foundation.shape.RoundedCornerShape
|
||||
import androidx.compose.foundation.verticalScroll
|
||||
import androidx.compose.material.icons.Icons
|
||||
import androidx.compose.material.icons.filled.Lock
|
||||
import androidx.compose.material.icons.filled.Movie
|
||||
import androidx.compose.material.icons.filled.Person
|
||||
import androidx.compose.material.icons.filled.Search
|
||||
import androidx.compose.material.icons.filled.Storage
|
||||
import androidx.compose.material3.Icon
|
||||
import androidx.compose.material3.MaterialTheme
|
||||
import androidx.compose.material3.Text
|
||||
import androidx.compose.material3.TextButton
|
||||
import androidx.compose.runtime.Composable
|
||||
import androidx.compose.runtime.Immutable
|
||||
import androidx.compose.ui.Alignment
|
||||
import androidx.compose.ui.Modifier
|
||||
import androidx.compose.ui.text.font.FontWeight
|
||||
import androidx.compose.ui.unit.dp
|
||||
import androidx.compose.ui.unit.sp
|
||||
import hu.bbara.purefin.ui.common.button.PurefinTextButton
|
||||
import hu.bbara.purefin.ui.common.textfield.PurefinComplexTextField
|
||||
import hu.bbara.purefin.ui.common.textfield.PurefinPasswordField
|
||||
import hu.bbara.purefin.ui.screen.waiting.PurefinWaitingScreen
|
||||
|
||||
@Immutable
|
||||
data class LoginContentState(
|
||||
val serverUrl: String,
|
||||
val username: String,
|
||||
val password: String,
|
||||
val errorMessage: String? = null
|
||||
)
|
||||
|
||||
class LoginContentCallbacks(
|
||||
val onServerUrlChange: (String) -> Unit,
|
||||
val onUsernameChange: (String) -> Unit,
|
||||
val onPasswordChange: (String) -> Unit,
|
||||
val onConnect: () -> Unit,
|
||||
val onDiscoverServers: () -> Unit = {},
|
||||
val onNeedHelp: () -> Unit = {}
|
||||
)
|
||||
|
||||
@Composable
|
||||
fun LoginContent(
|
||||
state: LoginContentState,
|
||||
callbacks: LoginContentCallbacks,
|
||||
isLoggingIn: Boolean,
|
||||
modifier: Modifier = Modifier
|
||||
) {
|
||||
val scheme = MaterialTheme.colorScheme
|
||||
|
||||
if (isLoggingIn) {
|
||||
PurefinWaitingScreen(modifier = modifier)
|
||||
return
|
||||
}
|
||||
|
||||
Column(
|
||||
modifier = modifier
|
||||
.fillMaxSize()
|
||||
.background(scheme.background)
|
||||
.padding(24.dp)
|
||||
.verticalScroll(rememberScrollState()),
|
||||
horizontalAlignment = Alignment.CenterHorizontally
|
||||
) {
|
||||
Spacer(modifier = Modifier.weight(0.5f))
|
||||
|
||||
Box(
|
||||
modifier = Modifier
|
||||
.size(100.dp)
|
||||
.background(scheme.primary, RoundedCornerShape(24.dp)),
|
||||
contentAlignment = Alignment.Center
|
||||
) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Movie,
|
||||
contentDescription = "Logo",
|
||||
tint = scheme.onPrimary,
|
||||
modifier = Modifier.size(60.dp)
|
||||
)
|
||||
}
|
||||
|
||||
Text(
|
||||
text = "Jellyfin",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 32.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.padding(top = 16.dp)
|
||||
)
|
||||
Text(
|
||||
text = "PERSONAL MEDIA SYSTEM",
|
||||
color = scheme.onSurfaceVariant,
|
||||
fontSize = 12.sp,
|
||||
letterSpacing = 2.sp
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(48.dp))
|
||||
|
||||
Text(
|
||||
text = "Connect to Server",
|
||||
color = scheme.onBackground,
|
||||
fontSize = 22.sp,
|
||||
fontWeight = FontWeight.Bold,
|
||||
modifier = Modifier.align(Alignment.Start)
|
||||
)
|
||||
Text(
|
||||
text = "Enter your details to access your library",
|
||||
color = scheme.onSurfaceVariant,
|
||||
fontSize = 14.sp,
|
||||
modifier = Modifier
|
||||
.align(Alignment.Start)
|
||||
.padding(bottom = 24.dp)
|
||||
)
|
||||
|
||||
state.errorMessage?.let { errorMessage ->
|
||||
Text(
|
||||
text = errorMessage,
|
||||
color = scheme.error,
|
||||
fontSize = 14.sp,
|
||||
modifier = Modifier
|
||||
.fillMaxWidth()
|
||||
.background(
|
||||
scheme.errorContainer,
|
||||
RoundedCornerShape(8.dp)
|
||||
)
|
||||
.padding(12.dp)
|
||||
)
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
|
||||
PurefinComplexTextField(
|
||||
label = "Server URL",
|
||||
value = state.serverUrl,
|
||||
onValueChange = callbacks.onServerUrlChange,
|
||||
placeholder = "http://192.168.1.100:8096",
|
||||
leadingIcon = Icons.Default.Storage
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
PurefinComplexTextField(
|
||||
label = "Username",
|
||||
value = state.username,
|
||||
onValueChange = callbacks.onUsernameChange,
|
||||
placeholder = "Enter your username",
|
||||
leadingIcon = Icons.Default.Person
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
|
||||
PurefinPasswordField(
|
||||
label = "Password",
|
||||
value = state.password,
|
||||
onValueChange = callbacks.onPasswordChange,
|
||||
placeholder = "••••••••",
|
||||
leadingIcon = Icons.Default.Lock,
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.height(32.dp))
|
||||
|
||||
PurefinTextButton(
|
||||
content = { Text("Connect") },
|
||||
onClick = callbacks.onConnect
|
||||
)
|
||||
|
||||
Spacer(modifier = Modifier.weight(0.5f))
|
||||
|
||||
Row(
|
||||
modifier = Modifier.fillMaxWidth(),
|
||||
horizontalArrangement = Arrangement.SpaceBetween
|
||||
) {
|
||||
TextButton(onClick = callbacks.onDiscoverServers) {
|
||||
Row(verticalAlignment = Alignment.CenterVertically) {
|
||||
Icon(
|
||||
imageVector = Icons.Default.Search,
|
||||
contentDescription = null,
|
||||
tint = scheme.onSurfaceVariant,
|
||||
modifier = Modifier.size(18.dp)
|
||||
)
|
||||
Text(" Discover Servers", color = scheme.onSurfaceVariant)
|
||||
}
|
||||
}
|
||||
TextButton(onClick = callbacks.onNeedHelp) {
|
||||
Text("Need Help?", color = scheme.onSurfaceVariant)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer(modifier = Modifier.height(16.dp))
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package hu.bbara.purefin.ui.screen.login
|
||||
|
||||
import androidx.compose.runtime.Immutable
|
||||
|
||||
@Immutable
|
||||
data class LoginContentState(
|
||||
val serverUrl: String,
|
||||
val username: String,
|
||||
val password: String,
|
||||
val errorMessage: String? = null
|
||||
)
|
||||
|
||||
class LoginContentCallbacks(
|
||||
val onServerUrlChange: (String) -> Unit,
|
||||
val onUsernameChange: (String) -> Unit,
|
||||
val onPasswordChange: (String) -> Unit,
|
||||
val onConnect: () -> Unit
|
||||
)
|
||||
21
core-ui/src/main/res/drawable/purefin_logo_tintable.xml
Normal file
21
core-ui/src/main/res/drawable/purefin_logo_tintable.xml
Normal file
@@ -0,0 +1,21 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="494dp"
|
||||
android:height="552dp"
|
||||
android:viewportWidth="494"
|
||||
android:viewportHeight="552">
|
||||
|
||||
<group
|
||||
android:scaleX="0.1"
|
||||
android:scaleY="-0.1"
|
||||
android:translateX="-106"
|
||||
android:translateY="552">
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M2068,4685c-72,-14 -140,-56 -183,-112 -67,-88 -65,-56 -65,-986l0,-840 68,5c80,7 95,10 104,23 4,6 8,375 7,822 0,884 -2,851 55,888 35,23 91,29 128,14 18,-7 123,-68 233,-135 110,-67 304,-185 430,-262 127,-77 231,-146 233,-154 2,-11 -9,-17 -40,-22 -67,-10 -236,-65 -298,-96 -150,-75 -322,-227 -376,-331 -25,-47 -29,-65 -29,-139 0,-64 5,-95 19,-123 26,-53 87,-112 146,-142 28,-14 50,-30 50,-35 0,-6 -14,-39 -31,-73 -21,-41 -59,-90 -113,-143 -121,-120 -260,-182 -466,-209 -25,-3 -63,-8 -85,-10 -258,-33 -399,-80 -520,-172 -57,-44 -143,-152 -184,-233 -36,-70 -75,-189 -66,-198 4,-4 10,-2 12,5 10,27 111,152 166,205 64,61 171,123 273,157 53,17 157,34 339,55 277,31 426,83 582,202 84,64 148,140 210,246 61,104 62,105 118,77 73,-37 74,-39 20,-132 -60,-103 -119,-180 -215,-280 -153,-161 -331,-266 -575,-342 -263,-81 -395,-137 -496,-211 -75,-54 -193,-186 -240,-265 -24,-41 -60,-117 -80,-169 -37,-94 -75,-248 -67,-272 3,-7 27,35 55,92 69,144 114,212 202,304 155,160 275,221 698,356 247,78 427,183 592,342 102,99 150,158 237,291 110,168 95,152 132,133 37,-19 102,-74 102,-87 0,-4 -32,-41 -71,-80 -94,-97 -163,-197 -263,-382 -105,-195 -146,-256 -207,-311 -94,-85 -172,-116 -409,-166 -80,-17 -167,-38 -195,-46 -82,-27 -198,-91 -256,-143 -53,-48 -137,-156 -128,-165 3,-3 27,13 54,35 122,98 253,141 495,164 198,19 216,21 305,47 165,48 287,143 390,303 18,28 60,105 93,170 120,236 287,445 355,445 25,0 99,-73 92,-91 -3,-8 -28,-30 -56,-49 -28,-19 -74,-60 -102,-90 -102,-112 -153,-215 -231,-470 -102,-332 -179,-434 -451,-595 -83,-48 -195,-114 -250,-147 -139,-83 -191,-90 -258,-37 -45,37 -57,84 -57,232 0,69 -4,128 -9,131 -11,7 -116,-29 -149,-50 -24,-16 -24,-17 -20,-153 3,-125 6,-141 31,-193 37,-76 119,-151 191,-173 109,-35 198,-10 400,109 50,30 145,85 211,123 189,109 283,189 367,311 42,60 101,191 133,292 75,238 91,281 131,360 24,47 65,108 91,136 51,55 136,114 163,114 9,0 37,-16 62,-35 177,-138 388,-82 487,129 111,235 125,557 37,805 -9,24 -16,47 -16,52 0,18 37,8 85,-24 28,-17 84,-52 125,-76 108,-64 444,-267 517,-313 92,-58 116,-128 72,-203 -16,-27 -51,-53 -143,-107 -66,-39 -175,-102 -241,-141 -66,-39 -145,-85 -175,-102 -30,-18 -100,-59 -155,-92 -55,-33 -143,-84 -195,-115 -52,-30 -183,-107 -290,-170 -107,-63 -249,-145 -316,-181l-120,-66 -18,-56c-14,-45 -51,-132 -84,-197 -9,-18 27,-5 83,28 33,21 114,68 180,107 66,38 183,107 260,152 259,153 679,398 845,493 468,269 493,287 541,387 57,119 32,253 -66,350 -22,22 -117,86 -210,141 -94,56 -343,206 -555,334 -212,128 -428,259 -480,290 -154,93 -587,356 -835,507 -583,354 -665,403 -692,414 -48,20 -118,26 -175,14zM3375,3729c381,-94 641,-440 634,-844 -4,-220 -69,-404 -160,-451 -56,-28 -87,-8 -284,185 -253,248 -359,330 -619,475 -49,27 -136,68 -195,92 -172,71 -214,95 -234,137 -29,58 -11,96 92,197 204,200 487,277 766,209z" />
|
||||
|
||||
<path
|
||||
android:fillColor="@android:color/white"
|
||||
android:pathData="M3754,3278c14,-45 28,-231 22,-298 -3,-42 -18,-116 -32,-164 -27,-94 -25,-118 11,-142 66,-43 121,70 119,251 -1,87 -30,208 -69,285 -26,51 -60,96 -51,68z" />
|
||||
</group>
|
||||
</vector>
|
||||
Reference in New Issue
Block a user