Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Contribute to GitLab
Sign in
Toggle navigation
M
MiYaFastCashier
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
1
Merge Requests
1
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
jiangjiantao
MiYaFastCashier
Commits
7dc5d690
Commit
7dc5d690
authored
Jan 12, 2022
by
jiangjiantao
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
dev
parent
d6fd8355
Show whitespace changes
Inline
Side-by-side
Showing
10 changed files
with
307 additions
and
1 deletion
+307
-1
build.gradle
app/build.gradle
+4
-0
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+4
-1
LoginRepository.kt
...n/java/com/miya/fastcashier/repository/LoginRepository.kt
+5
-0
LoggedInUserView.kt
...in/java/com/miya/fastcashier/ui/login/LoggedInUserView.kt
+9
-0
LoginActivity.kt
.../main/java/com/miya/fastcashier/ui/login/LoginActivity.kt
+130
-0
LoginResult.kt
...rc/main/java/com/miya/fastcashier/ui/login/LoginResult.kt
+9
-0
LoginViewModel.kt
...ain/java/com/miya/fastcashier/viewmodel/LoginViewModel.kt
+56
-0
activity_login.xml
app/src/main/res/layout/activity_login.xml
+76
-0
dimens.xml
app/src/main/res/values/dimens.xml
+5
-0
strings.xml
app/src/main/res/values/strings.xml
+9
-0
No files found.
app/build.gradle
View file @
7dc5d690
...
...
@@ -30,6 +30,9 @@ android {
kotlinOptions
{
jvmTarget
=
'1.8'
}
buildFeatures
{
viewBinding
true
}
}
dependencies
{
...
...
@@ -41,6 +44,7 @@ dependencies {
implementation
'androidx.constraintlayout:constraintlayout:2.0.1'
implementation
'androidx.lifecycle:lifecycle-livedata-ktx:2.2.0'
implementation
'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0'
implementation
'androidx.annotation:annotation:1.1.0'
testImplementation
'junit:junit:4.+'
androidTestImplementation
'androidx.test.ext:junit:1.1.2'
androidTestImplementation
'androidx.test.espresso:espresso-core:3.3.0'
...
...
app/src/main/AndroidManifest.xml
View file @
7dc5d690
...
...
@@ -9,13 +9,16 @@
android:roundIcon=
"@mipmap/ic_launcher_round"
android:supportsRtl=
"true"
android:theme=
"@style/Theme.MiYaFastCashier"
>
<activity
android:name=
".MainActivity"
>
<activity
android:name=
".ui.login.ui.login.LoginActivity"
android:label=
"@string/title_activity_login"
>
<intent-filter>
<action
android:name=
"android.intent.action.MAIN"
/>
<category
android:name=
"android.intent.category.LAUNCHER"
/>
</intent-filter>
</activity>
<activity
android:name=
".MainActivity"
></activity>
</application>
</manifest>
\ No newline at end of file
app/src/main/java/com/miya/fastcashier/repository/LoginRepository.kt
0 → 100644
View file @
7dc5d690
package
com.miya.fastcashier.repository
class
LoginRepository
{
}
\ No newline at end of file
app/src/main/java/com/miya/fastcashier/ui/login/LoggedInUserView.kt
0 → 100644
View file @
7dc5d690
package
com.miya.fastcashier.ui.login.ui.login
/**
* User details post authentication that is exposed to the UI
*/
data class
LoggedInUserView
(
val
displayName
:
String
//... other data fields that may be accessible to the UI
)
\ No newline at end of file
app/src/main/java/com/miya/fastcashier/ui/login/LoginActivity.kt
0 → 100644
View file @
7dc5d690
package
com.miya.fastcashier.ui.login.ui.login
import
android.app.Activity
import
androidx.lifecycle.Observer
import
androidx.lifecycle.ViewModelProvider
import
android.os.Bundle
import
androidx.annotation.StringRes
import
androidx.appcompat.app.AppCompatActivity
import
android.text.Editable
import
android.text.TextWatcher
import
android.view.View
import
android.view.inputmethod.EditorInfo
import
android.widget.EditText
import
android.widget.Toast
import
com.miya.fastcashier.R
import
com.miya.fastcashier.databinding.ActivityLoginBinding
import
com.miya.fastcashier.viewmodel.LoginViewModel
class
LoginActivity
:
AppCompatActivity
()
{
private
lateinit
var
loginViewModel
:
LoginViewModel
private
lateinit
var
binding
:
ActivityLoginBinding
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
binding
=
ActivityLoginBinding
.
inflate
(
layoutInflater
)
setContentView
(
binding
.
root
)
val
username
=
binding
.
username
val
password
=
binding
.
password
val
login
=
binding
.
login
val
loading
=
binding
.
loading
// loginViewModel = ViewModelProvider(this, LoginViewModelFactory())
// .get(LoginViewModel::class.java)
//
// loginViewModel.loginFormState.observe(this@LoginActivity, Observer {
// val loginState = it ?: return@Observer
//
// // disable login button unless both username / password is valid
// login.isEnabled = loginState.isDataValid
//
// if (loginState.usernameError != null) {
// username.error = getString(loginState.usernameError)
// }
// if (loginState.passwordError != null) {
// password.error = getString(loginState.passwordError)
// }
// })
loginViewModel
.
loginResult
.
observe
(
this
@LoginActivity
,
Observer
{
val
loginResult
=
it
?:
return
@Observer
loading
.
visibility
=
View
.
GONE
if
(
loginResult
.
error
!=
null
)
{
showLoginFailed
(
loginResult
.
error
)
}
if
(
loginResult
.
success
!=
null
)
{
updateUiWithUser
(
loginResult
.
success
)
}
setResult
(
Activity
.
RESULT_OK
)
//Complete and destroy login activity once successful
finish
()
})
username
.
afterTextChanged
{
loginViewModel
.
loginDataChanged
(
username
.
text
.
toString
(),
password
.
text
.
toString
()
)
}
password
.
apply
{
afterTextChanged
{
loginViewModel
.
loginDataChanged
(
username
.
text
.
toString
(),
password
.
text
.
toString
()
)
}
setOnEditorActionListener
{
_
,
actionId
,
_
->
when
(
actionId
)
{
EditorInfo
.
IME_ACTION_DONE
->
loginViewModel
.
login
(
username
.
text
.
toString
(),
password
.
text
.
toString
()
)
}
false
}
login
.
setOnClickListener
{
loading
.
visibility
=
View
.
VISIBLE
loginViewModel
.
login
(
username
.
text
.
toString
(),
password
.
text
.
toString
())
}
}
}
private
fun
updateUiWithUser
(
model
:
LoggedInUserView
)
{
val
welcome
=
getString
(
R
.
string
.
welcome
)
val
displayName
=
model
.
displayName
// TODO : initiate successful logged in experience
Toast
.
makeText
(
applicationContext
,
"$welcome $displayName"
,
Toast
.
LENGTH_LONG
).
show
()
}
private
fun
showLoginFailed
(
@StringRes
errorString
:
Int
)
{
Toast
.
makeText
(
applicationContext
,
errorString
,
Toast
.
LENGTH_SHORT
).
show
()
}
}
/**
* Extension function to simplify setting an afterTextChanged action to EditText components.
*/
fun
EditText
.
afterTextChanged
(
afterTextChanged
:
(
String
)
->
Unit
)
{
this
.
addTextChangedListener
(
object
:
TextWatcher
{
override
fun
afterTextChanged
(
editable
:
Editable
?)
{
afterTextChanged
.
invoke
(
editable
.
toString
())
}
override
fun
beforeTextChanged
(
s
:
CharSequence
,
start
:
Int
,
count
:
Int
,
after
:
Int
)
{}
override
fun
onTextChanged
(
s
:
CharSequence
,
start
:
Int
,
before
:
Int
,
count
:
Int
)
{}
})
}
\ No newline at end of file
app/src/main/java/com/miya/fastcashier/ui/login/LoginResult.kt
0 → 100644
View file @
7dc5d690
package
com.miya.fastcashier.ui.login.ui.login
/**
* Authentication result : success (user details) or error message.
*/
data class
LoginResult
(
val
success
:
LoggedInUserView
?
=
null
,
val
error
:
Int
?
=
null
)
\ No newline at end of file
app/src/main/java/com/miya/fastcashier/viewmodel/LoginViewModel.kt
0 → 100644
View file @
7dc5d690
package
com.miya.fastcashier.viewmodel
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.MutableLiveData
import
androidx.lifecycle.ViewModel
import
android.util.Patterns
import
com.miya.fastcashier.R
import
com.miya.fastcashier.repository.LoginRepository
import
com.miya.fastcashier.ui.login.ui.login.LoggedInUserView
import
com.miya.fastcashier.ui.login.ui.login.LoginResult
class
LoginViewModel
(
private
val
loginRepository
:
LoginRepository
)
:
ViewModel
()
{
//
// private val _loginForm = MutableLiveData<LoginFormState>()
// val loginFormState: LiveData<LoginFormState> = _loginForm
//
// private val _loginResult = MutableLiveData<LoginResult>()
// val loginResult: LiveData<LoginResult> = _loginResult
//
// fun login(username: String, password: String) {
// // can be launched in a separate asynchronous job
//// val result = loginRepository.login(username, password)
////
//// if (result is Result.Success) {
//// _loginResult.value =
//// LoginResult(success = LoggedInUserView(displayName = result.data.displayName))
//// } else {
//// _loginResult.value = LoginResult(error = R.string.login_failed)
//// }
// }
//
// fun loginDataChanged(username: String, password: String) {
// if (!isUserNameValid(username)) {
// _loginForm.value = LoginFormState(usernameError = R.string.invalid_username)
// } else if (!isPasswordValid(password)) {
// _loginForm.value = LoginFormState(passwordError = R.string.invalid_password)
// } else {
// _loginForm.value = LoginFormState(isDataValid = true)
// }
// }
//
// // A placeholder username validation check
// private fun isUserNameValid(username: String): Boolean {
// return if (username.contains('@')) {
// Patterns.EMAIL_ADDRESS.matcher(username).matches()
// } else {
// username.isNotBlank()
// }
// }
//
// // A placeholder password validation check
// private fun isPasswordValid(password: String): Boolean {
// return password.length > 5
// }
}
\ No newline at end of file
app/src/main/res/layout/activity_login.xml
0 → 100644
View file @
7dc5d690
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android=
"http://schemas.android.com/apk/res/android"
xmlns:app=
"http://schemas.android.com/apk/res-auto"
xmlns:tools=
"http://schemas.android.com/tools"
android:id=
"@+id/container"
android:layout_width=
"match_parent"
android:layout_height=
"match_parent"
android:paddingLeft=
"@dimen/activity_horizontal_margin"
android:paddingTop=
"@dimen/activity_vertical_margin"
android:paddingRight=
"@dimen/activity_horizontal_margin"
android:paddingBottom=
"@dimen/activity_vertical_margin"
tools:context=
".ui.login.ui.login.LoginActivity"
>
<EditText
android:id=
"@+id/username"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"96dp"
android:layout_marginEnd=
"24dp"
android:hint=
"@string/prompt_email"
android:inputType=
"textEmailAddress"
android:selectAllOnFocus=
"true"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
/>
<EditText
android:id=
"@+id/password"
android:layout_width=
"0dp"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"8dp"
android:layout_marginEnd=
"24dp"
android:hint=
"@string/prompt_password"
android:imeActionLabel=
"@string/action_sign_in_short"
android:imeOptions=
"actionDone"
android:inputType=
"textPassword"
android:selectAllOnFocus=
"true"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/username"
/>
<Button
android:id=
"@+id/login"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"start"
android:layout_marginStart=
"48dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"48dp"
android:layout_marginBottom=
"64dp"
android:enabled=
"false"
android:text=
"@string/action_sign_in"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toBottomOf=
"@+id/password"
app:layout_constraintVertical_bias=
"0.2"
/>
<ProgressBar
android:id=
"@+id/loading"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_gravity=
"center"
android:layout_marginStart=
"32dp"
android:layout_marginTop=
"64dp"
android:layout_marginEnd=
"32dp"
android:layout_marginBottom=
"64dp"
android:visibility=
"gone"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@+id/password"
app:layout_constraintStart_toStartOf=
"@+id/password"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintVertical_bias=
"0.3"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
app/src/main/res/values/dimens.xml
0 → 100644
View file @
7dc5d690
<resources>
<!-- Default screen margins, per the Android Design guidelines. -->
<dimen
name=
"activity_horizontal_margin"
>
16dp
</dimen>
<dimen
name=
"activity_vertical_margin"
>
16dp
</dimen>
</resources>
\ No newline at end of file
app/src/main/res/values/strings.xml
View file @
7dc5d690
<resources>
<string
name=
"app_name"
>
MiYaFastCashier
</string>
<string
name=
"title_activity_login"
>
LoginActivity
</string>
<string
name=
"prompt_email"
>
Email
</string>
<string
name=
"prompt_password"
>
Password
</string>
<string
name=
"action_sign_in"
>
Sign in or register
</string>
<string
name=
"action_sign_in_short"
>
Sign in
</string>
<string
name=
"welcome"
>
"Welcome !"
</string>
<string
name=
"invalid_username"
>
Not a valid username
</string>
<string
name=
"invalid_password"
>
Password must be >5 characters
</string>
<string
name=
"login_failed"
>
"Login failed"
</string>
</resources>
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment