Skip to content

Commit

Permalink
Fixed bugs
Browse files Browse the repository at this point in the history
  • Loading branch information
lhwdev committed Dec 19, 2020
1 parent f5b8ca9 commit fb9a5a1
Show file tree
Hide file tree
Showing 8 changed files with 256 additions and 140 deletions.
12 changes: 6 additions & 6 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,8 @@ android {
applicationId "com.lhwdev.selfTestMacro"
minSdkVersion 19
targetSdkVersion 30
versionCode 1006
versionName "2.6"
versionCode 1007
versionName "2.7"

multiDexEnabled true

Expand Down Expand Up @@ -50,13 +50,13 @@ dependencies {

implementation fileTree(dir: "libs", include: ["*.jar"])
implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9"
implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:1.4.1"
implementation "androidx.appcompat:appcompat:1.2.0"
implementation "androidx.core:core-ktx:1.3.2"
implementation "com.google.android.material:material:1.2.1"
implementation "androidx.constraintlayout:constraintlayout:2.0.2"
implementation "androidx.navigation:navigation-fragment-ktx:2.3.1"
implementation "androidx.navigation:navigation-ui-ktx:2.3.1"
implementation "androidx.constraintlayout:constraintlayout:2.0.4"
implementation "androidx.navigation:navigation-fragment-ktx:2.3.2"
implementation "androidx.navigation:navigation-ui-ktx:2.3.2"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-core:1.0.0"
implementation "org.jetbrains.kotlinx:kotlinx-serialization-json:1.0.0"
testImplementation "junit:junit:4.13"
Expand Down
150 changes: 84 additions & 66 deletions app/src/main/java/com/lhwdev/selfTestMacro/FirstActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,14 @@ package com.lhwdev.selfTestMacro
import android.content.DialogInterface
import android.content.Intent
import android.os.Bundle
import android.text.InputFilter
import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager
import android.widget.ArrayAdapter
import android.widget.Filter
import androidx.appcompat.app.AlertDialog
import androidx.appcompat.app.AppCompatActivity
import androidx.core.content.getSystemService
import androidx.core.content.res.ResourcesCompat
import androidx.core.widget.doAfterTextChanged
import androidx.lifecycle.lifecycleScope
Expand All @@ -17,108 +20,104 @@ import kotlinx.android.synthetic.main.activity_first.*
import kotlinx.coroutines.launch


// TODO list:
// * use view binding
// * use preference fragment etc.
// * use better model, like MVVM. This page is small so whole code is not complicated, but
// on larger project, this imperative style lacks.


class FirstActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

setContentView(R.layout.activity_first)
window.setLayout(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT)
val pref = preferenceState
val first = intent.hasExtra("first")

setSupportActionBar(toolbar)

var schoolInfo: SchoolInfo? = null
var institute: InstituteInfo? = null

fun adapter(list: List<String>) = object : ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list) {
override fun getFilter(): Filter {
return DisabledFilter()
}

private inner class DisabledFilter : Filter() {
override fun performFiltering(text: CharSequence): FilterResults {
val result = FilterResults()
result.values = list
result.count = list.size
return result
fun adapter(list: List<String>) =
object : ArrayAdapter<String>(this, android.R.layout.simple_list_item_1, list) {
override fun getFilter(): Filter {
return DisabledFilter()
}
override fun publishResults(text: CharSequence, results: FilterResults) {
notifyDataSetChanged()

private inner class DisabledFilter : Filter() {
override fun performFiltering(text: CharSequence): FilterResults {
val result = FilterResults()
result.values = list
result.count = list.size
return result
}

override fun publishResults(text: CharSequence, results: FilterResults) {
notifyDataSetChanged()
}
}
}
}
// ArrayAdapter(this, android.R.layout.simple_list_item_1, list)

input_loginType.setAdapter(adapter(listOf("학교")))

input_region.setAdapter(adapter(sRegions.keys.toList()))
input_level.setAdapter(adapter(sSchoolLevels.keys.toList()))

input_schoolName.setOnEditorActionListener { _, _, _ ->
button_checkSchoolInfo.performClick()
}

button_checkSchoolInfo.setOnClickListener {
// if(input_region.) {
// showToast("시/도 정보를 입력해주세요")
// return@setOnClickListener
// }
//
// if(spinner_level.selectedItemPosition == -1) {
// showToast("시/도 정보를 입력해주세요")
// return@setOnClickListener
// }

val schoolName = input_schoolName.text
if(schoolName == null || schoolName.isEmpty()) {
showToast("학교 이름을 입력해주세요")
return@setOnClickListener
}

currentFocus?.windowToken?.let {
getSystemService<InputMethodManager>()!!.hideSoftInputFromWindow(it, 0)
}

val nameString = schoolName.toString()

val regionCode = sRegions.getValue(input_region.text.toString())
val levelCode = sSchoolLevels.getValue(input_level.text.toString())

lifecycleScope.launch {
val snackbar =
val snackBar =
Snackbar.make(button_checkSchoolInfo, "잠시만 기다려주세요", Snackbar.LENGTH_INDEFINITE)
snackbar.show()
snackBar.show()

fun selectSchool(school: SchoolInfo) {
schoolInfo = school
fun selectInstitute(instituteInfo: InstituteInfo) {
institute = instituteInfo

// ui interaction
schoolName.clear()
schoolName.append(school.name)
schoolName.append(instituteInfo.name)
button_checkSchoolInfo.icon = ResourcesCompat.getDrawable(
resources,
R.drawable.ic_baseline_check_24,
theme
)

scrollView.smoothScrollTo(0, scrollView.height)
}

val data = getSchoolData(
regionCode = regionCode,
schoolLevelCode = levelCode.toString(),
name = nameString,
loginType = LoginType.school /* TODO */
name = nameString
)
snackbar.dismiss()
if(data.schoolList.isEmpty()) {
snackBar.dismiss()
if(data.instituteList.isEmpty()) {
showToast("학교를 찾을 수 없습니다. 이름을 바르게 입력했는지 확인해주세요.")
return@launch
}

if(data.schoolList.size == 1)
selectSchool(data.schoolList[0])
if(data.instituteList.size == 1)
selectInstitute(data.instituteList[0])
else AlertDialog.Builder(this@FirstActivity).apply {
setTitle("학교를 선택해주세요")
setItems(
data.schoolList.map { "${it.name}(${it.address})" }.toTypedArray(),
data.instituteList.map { "${it.name}(${it.address})" }.toTypedArray(),
DialogInterface.OnClickListener { _, which ->
selectSchool(data.schoolList[which])
selectInstitute(data.instituteList[which])
})
}.show()
}
Expand All @@ -132,10 +131,14 @@ class FirstActivity : AppCompatActivity() {
input_studentBirth.error = null
}

input_studentBirth.setOnEditorActionListener { _, _, _ ->
button_done.callOnClick()
}

button_done.setOnClickListener onClick@{
val school = schoolInfo ?: run {
val instituteInfo = institute ?: run {
button_checkSchoolInfo.callOnClick()
schoolInfo ?: return@onClick
institute ?: return@onClick
}

if(input_studentName.isEmpty()) {
Expand All @@ -152,44 +155,55 @@ class FirstActivity : AppCompatActivity() {

val name = input_studentName.text!!.toString()
val birth = input_studentBirth.text!!.toString()

// require(input_loginType.selectedItemPosition == 0)

if(birth.length != 6) {
input_studentBirth.requestFocus()
input_studentBirth.error = "생년월일을 6자리로 입력해주세요. (주민등록번호 앞 6자리, YYMMDD 형식)"
return@onClick
}

lifecycleScope.launch {
lifecycleScope.launch main@{
// TODO: show progress
try {
val token = findUser(
school,
val userIdentifier = findUser(
instituteInfo,
GetUserTokenRequestBody(
schoolInfo = school,
institute = instituteInfo,
name = name,
birthday = birth,
loginType = LoginType.school /* TODO */
)
)
val groups = getUserGroup(school, token)
if(groups.isEmpty()) {
showToastSuspendAsync("해당 정보의 학생을 찾지 못했습니다.")
return@launch
}
if(groups.size != 1) {
showToastSuspendAsync("여러명의 자가진단은 아직 지원하지 않습니다.")

val password = promptInput { edit, _ ->
setTitle("비밀번호를 입력해주세요.")
edit.filters = arrayOf(InputFilter { source, start, end, dest, destStart, destEnd ->
val result = dest.replaceRange(destStart, destEnd, source.substring(start, end))
if(result.length > 4 || result.any { !it.isDigit() }) null
else source
})
} ?: return@main

val token = catchErrorThanToast {
validatePassword(instituteInfo, userIdentifier, password)
} ?: return@main

if(token is PasswordWrong) {
showToastSuspendAsync("잘못된 비밀번호입니다. 다시 시도해주세요. (${token.data.failedCount}회 틀림)")
return@main
}
val userInfo = groups.single()
require(token is UsersToken)

val groups = getUserGroup(instituteInfo, token)
singleOfUserGroup(groups) ?: return@main // TODO: many users

pref.school = school
pref.user = userInfo
pref.institute = instituteInfo
pref.user = UserLoginInfo(userIdentifier, token)
pref.setting = UserSetting(
loginType = LoginType.school, // TODO
region = sRegions.getValue(input_region.text.toString()),
level = sSchoolLevels.getValue(input_level.text.toString()),
schoolName = school.name,
schoolName = instituteInfo.name,
studentName = name,
studentBirth = birth
)
Expand All @@ -202,6 +216,7 @@ class FirstActivity : AppCompatActivity() {
pref.firstState = 1
}
} catch(e: Throwable) {
e.printStackTrace()
showToastSuspendAsync("잘못된 학생 정보입니다.")
}

Expand All @@ -210,8 +225,11 @@ class FirstActivity : AppCompatActivity() {

pref.setting?.let { setting ->
input_loginType.setText("학교", false) // TODO
input_region.setText(sRegions.entries.first { it.value == setting.region}.key, false)
input_level.setText(sSchoolLevels.entries.first { it.value == setting.level }.key, false)
input_region.setText(sRegions.entries.first { it.value == setting.region }.key, false)
input_level.setText(
sSchoolLevels.entries.first { it.value == setting.level }.key,
false
)
input_schoolName.setText(setting.schoolName)
input_studentName.setText(setting.studentName)
input_studentBirth.setText(setting.studentBirth)
Expand Down
Loading

0 comments on commit fb9a5a1

Please sign in to comment.