Skip to content
This repository has been archived by the owner on May 11, 2024. It is now read-only.

Commit

Permalink
Merge pull request #4 from wed0n/master
Browse files Browse the repository at this point in the history
修复登录功能
  • Loading branch information
thriic committed Mar 14, 2024
2 parents c83fcdc + df98873 commit 9382bc4
Show file tree
Hide file tree
Showing 15 changed files with 2,020 additions and 162 deletions.
7 changes: 1 addition & 6 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,12 +1,7 @@
*.iml
.gradle
/local.properties
/.idea/caches
/.idea/libraries
/.idea/modules.xml
/.idea/workspace.xml
/.idea/navEditor.xml
/.idea/assetWizardSettings.xml
.idea/
.DS_Store
/build
/captures
Expand Down
3 changes: 2 additions & 1 deletion app/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
/build
/build
/release
8 changes: 4 additions & 4 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ android {
applicationId = "com.thryan.secondclass"
minSdk = 26
targetSdk = 34
versionCode = 1
versionName = "1.3.3"
versionCode = 2
versionName = "1.3.4"

testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
vectorDrawables {
Expand All @@ -24,7 +24,8 @@ android {

buildTypes {
release {
isMinifyEnabled = false
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android-optimize.txt"),
"proguard-rules.pro"
Expand Down Expand Up @@ -57,7 +58,6 @@ dependencies {
implementation("androidx.core:core-ktx:1.12.0")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.8.0"))
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.6.2")
implementation("org.jetbrains.kotlinx:kotlinx-coroutines-android:1.7.3")

implementation("androidx.activity:activity-compose:1.7.2")
Expand Down
2 changes: 1 addition & 1 deletion app/proguard-rules.pro
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,4 @@

# If you keep the line number information, uncomment this to
# hide the original source file name.
#-renamesourcefileattribute SourceFile
#-renamesourcefileattribute SourceFile
Binary file added app/src/main/assets/model.onnx
Binary file not shown.
Binary file added app/src/main/assets/ort-wasm-simd.wasm
Binary file not shown.
1,822 changes: 1,822 additions & 0 deletions app/src/main/assets/script.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion app/src/main/java/com/thryan/secondclass/SCRepository.kt
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ import kotlinx.coroutines.flow.MutableStateFlow
class SCRepository {

val activities: MutableStateFlow<List<SCActivity>> = MutableStateFlow(emptyList())
private var secondClass: SecondClass? = null
var secondClass: SecondClass? = null
private var account: String? = null
private var password: String? = null

Expand Down
170 changes: 25 additions & 145 deletions app/src/main/java/com/thryan/secondclass/ui/login/Login.kt
Original file line number Diff line number Diff line change
@@ -1,165 +1,45 @@
package com.thryan.secondclass.ui.login

import android.annotation.SuppressLint
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.RowScope
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import com.thryan.secondclass.R
import kotlinx.coroutines.delay


@SuppressLint("FlowOperatorInvokedInComposition")
@Composable
fun Login(modifier: Modifier = Modifier, viewModel: LoginViewModel) {
val uiState by viewModel.uiState.collectAsState()

Column(
modifier = modifier
.verticalScroll(rememberScrollState())
.padding(16.dp)
.statusBarsPadding(),
verticalArrangement = Arrangement.spacedBy(16.dp)
) {
LoginContent(uiState = uiState, viewModel = viewModel)
}
if (uiState.showDialog) Dialog(message = uiState.message, viewModel = viewModel)
}

@Composable
fun LoginContent(uiState: LoginState, viewModel: LoginViewModel) {
var err by rememberSaveable {
mutableStateOf(false)
}


Text(
"第二课堂",
style = MaterialTheme.typography.displaySmall,
modifier = Modifier.padding(bottom = 16.dp)
)

OutlinedTextField(
value = uiState.account,
singleLine = true,
modifier = Modifier
.fillMaxWidth(),
onValueChange = {
viewModel.send(LoginIntent.UpdateAccount(it))
err = !it.all { char -> char.isDigit() }
},
label = { Text("学号") },
isError = err,
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { }
),
supportingText = {
if (err) {
Text(
modifier = Modifier.fillMaxWidth(),
text = "仅数字",
color = MaterialTheme.colorScheme.error
)
}
}
)
OutlinedTextField(
value = uiState.password,
singleLine = true,
modifier = Modifier.fillMaxWidth(),
onValueChange = { viewModel.send(LoginIntent.UpdatePassword(it)) },
label = { Text("密码") },
placeholder = { Text("EasyConnect/教务处密码") },
isError = false,
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { }
),
trailingIcon = {
IconButton(onClick = { viewModel.send(LoginIntent.UpdatePasswordVisible(!uiState.showPassword)) }) {
Icon(
if (uiState.showPassword) painterResource(R.drawable.visibility)
else painterResource(R.drawable.visibility_off),
"visible",
modifier = Modifier.padding(8.dp)
)
}
},
visualTransformation = if (uiState.showPassword) VisualTransformation.None else PasswordVisualTransformation()
)

OutlinedTextField(
value = uiState.scPassword,
singleLine = true,
modifier = Modifier
.fillMaxWidth()
.padding(top = 8.dp),
onValueChange = { viewModel.send(LoginIntent.UpdateSCAccount(it)) },
label = { Text("二课密码") },
placeholder = { Text("默认为123456,可不填") },
keyboardOptions = KeyboardOptions.Default.copy(
imeAction = ImeAction.Done
),
keyboardActions = KeyboardActions(
onDone = { }
)
)
Text(
stringResource(R.string.login_tips),
style = MaterialTheme.typography.labelSmall
val url = "http://ekt-cuit-edu-cn.webvpn.cuit.edu.cn:8118/api/mSsoLogin"
WebView(
Modifier.fillMaxSize().statusBarsPadding(), viewModel, url
)
Row(
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.End,
modifier = Modifier.fillMaxWidth()
) {
DebouncedButton(
modifier = Modifier.padding(start = 8.dp),
enabled = !uiState.pending,
onClick = {
viewModel.send(LoginIntent.Login)
}
if (uiState.pending) {
val interactionSource = remember { MutableInteractionSource() }
Box(
contentAlignment = Alignment.Center,
modifier = Modifier
.fillMaxSize()
.background(with(MaterialTheme.colorScheme.background) {
Color(red, green, blue, 0.5f)
})
// 拦截对WebView的点击
.clickable(onClick = {}, interactionSource = interactionSource, indication = null)
) {
Text(if (uiState.pending) "Login..." else "Login")
CircularProgressIndicator(
modifier = Modifier.size(64.dp)
)
}
}
if (uiState.showDialog) Dialog(message = uiState.message, viewModel = viewModel)
}

@Composable
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,6 @@ sealed class LoginIntent {
data class UpdatePassword(val password: String) : LoginIntent()
data class UpdateSCAccount(val scAccount: String) : LoginIntent()
data class UpdatePasswordVisible(val visible: Boolean) : LoginIntent()
data class UpdatePending(val isPending: Boolean) : LoginIntent()
data class WebLogin(val twfid: String, val token: String) : LoginIntent()
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@ package com.thryan.secondclass.ui.login
import android.util.Log
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import cn.thriic.common.SecondClass
import cn.thriic.common.WebVpn
import cn.thriic.common.data.VpnInfo
import com.thryan.secondclass.AppDataStore
import com.thryan.secondclass.Navigator
import com.thryan.secondclass.SCRepository
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.Job
Expand All @@ -20,7 +22,8 @@ import javax.inject.Inject
@HiltViewModel
class LoginViewModel @Inject constructor(
private val appDataStore: AppDataStore,
private val navigator: Navigator
private val navigator: Navigator,
private val scRepository: SCRepository
) : ViewModel() {

private val _uiState = MutableStateFlow(LoginState("", "", "", false, "", false, false))
Expand Down Expand Up @@ -138,6 +141,23 @@ class LoginViewModel @Inject constructor(
update(uiState.value.copy(showPassword = intent.visible))
}

is LoginIntent.UpdatePending -> {
update(uiState.value.copy(pending = intent.isPending))
}

is LoginIntent.WebLogin -> {
scRepository.secondClass = SecondClass(intent.twfid, intent.token)
appDataStore.putLastTime(
System.currentTimeMillis().toString()
)
withContext(Dispatchers.Main) {
navigator.navigate("page?twfid=\"\"&account=\"\"&password=\"\"") {
popUpTo("login") { inclusive = true }
launchSingleTop = true
}
}
}

is LoginIntent.Init -> {
update(
uiState.value.copy(
Expand Down
Loading

0 comments on commit 9382bc4

Please sign in to comment.