Skip to content

Commit

Permalink
Merge pull request #9 from jyyyeung/logout-button
Browse files Browse the repository at this point in the history
Logout button
  • Loading branch information
jyyyeung authored Apr 25, 2024
2 parents 539a635 + aba430f commit 005dc97
Show file tree
Hide file tree
Showing 12 changed files with 219 additions and 49 deletions.
54 changes: 51 additions & 3 deletions app/src/main/java/com/example/sharedcalendar/MainActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,76 @@ package com.example.sharedcalendar

import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.widget.Button
import android.widget.ImageButton
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.drawerlayout.widget.DrawerLayout
import androidx.lifecycle.ViewModelProvider
import com.example.sharedcalendar.data.SessionManager
import com.example.sharedcalendar.ui.login.AuthActivity
import com.example.sharedcalendar.ui.login.LoginViewModel
import com.example.sharedcalendar.ui.login.LoginViewModelFactory
import com.google.android.material.navigation.NavigationView

class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private val TAG: String = MainActivity::class.java.name

class MainActivity : AppCompatActivity() {
private lateinit var sessionManager: SessionManager
private lateinit var loginViewModel: LoginViewModel

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)

sessionManager = SessionManager(this)
loginViewModel =
ViewModelProvider(this, LoginViewModelFactory())[LoginViewModel::class.java]

// START SIDEBAR NAVIGATION //
//Drawer button
val drawerLayout: DrawerLayout = findViewById(R.id.drawerLayout)
val buttonDrawerToggle: ImageButton = findViewById(R.id.drawerLayoutToggle)
val nvSidebar: NavigationView = findViewById(R.id.nvSidebar)

// If Click on Burger, Open drawer Layout
buttonDrawerToggle.setOnClickListener {
drawerLayout.open()

val tvUsername: TextView = findViewById(R.id.tvSidebarUsername)
val tvEmail: TextView = findViewById(R.id.tvSidebarEmail)
// Update Sidebar username if current values are default
if (tvUsername.text == getString(R.string.default_sidebar_username) ||
tvEmail.text == getString(
R.string.default_sidebar_email
)
) {
val user = sessionManager.getUser()
tvUsername.text = user?.username
tvEmail.text = user?.email
}
}


nvSidebar.setNavigationItemSelectedListener { menuItem ->
// Handle menu item selected
menuItem.isChecked = true
Log.i(TAG, menuItem.toString() + menuItem.itemId)
if (menuItem.toString() == "Settings") {
// TODO: Handle to settings page
} else if (menuItem.toString() == "Logout") {
// Call Logout process
loginViewModel.logout(
sessionManager = sessionManager
)
startActivity(Intent(this, AuthActivity::class.java))
finish()
} else if (menuItem.toString() == "Add Person to Calendar") {
// TODO: Handle add person to calendar
}
// menuItem.itemId
drawerLayout.close()
true
}
// END SIDEBAR NAVIGATION //

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ class LoginRepository(val dataSource: LoginDataSource) {
suspend fun logout(sessionManager: SessionManager) {
user = null
sessionManager.setAuthToken("")
sessionManager.setUser(null)
val apiService = ApiClient(sessionManager).apiService
dataSource.logout(apiService)
}
Expand All @@ -60,7 +61,7 @@ class LoginRepository(val dataSource: LoginDataSource) {
if (result is Result.Success) {
// If Login is successful
sessionManager.setAuthToken(result.data.token)
setLoggedInUser(result.data.user)
setLoggedInUser(sessionManager, result.data.user)
}
return result
}
Expand All @@ -87,7 +88,7 @@ class LoginRepository(val dataSource: LoginDataSource) {
if (result is Result.Success) {
// If Login is successful
sessionManager.setAuthToken(result.data.token)
setLoggedInUser(result.data.user)
setLoggedInUser(sessionManager, result.data.user)
}
return result
}
Expand All @@ -97,9 +98,10 @@ class LoginRepository(val dataSource: LoginDataSource) {
*
* @param loggedInUser
*/
private fun setLoggedInUser(loggedInUser: User) {
private fun setLoggedInUser(sessionManager: SessionManager, loggedInUser: User) {
this.user = loggedInUser
// If user credentials will be cached in local storage, it is recommended it be encrypted
// @see https://developer.android.com/training/articles/keystore
sessionManager.setUser(loggedInUser)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,31 @@ package com.example.sharedcalendar.data

import android.content.Context
import android.content.SharedPreferences
import android.content.SharedPreferences.Editor
import com.example.sharedcalendar.R
import com.example.sharedcalendar.models.User

/**
* Session manager to save and fetch data from SharedPreferences
*/
class SessionManager(context: Context) {
private var prefs: SharedPreferences =
context.getSharedPreferences(context.getString(R.string.app_name), Context.MODE_PRIVATE)
private var editor: Editor = prefs.edit()

companion object {
const val USER_TOKEN = ""
const val API_BASE_URL = "http://10.0.2.2:8000/api/"
const val USER_TOKEN = "userToken"
const val API_BASE_URL = "apiBaseUrl"
const val USER_USERNAME = "userUsername"
const val USER_NAME = "userName"
const val USER_EMAIL = "userEmail"
const val USER_ID = "userId"
}

/**
* Save the logged in user token
*/
fun setAuthToken(token: String) {
val editor = prefs.edit()
editor.putString(USER_TOKEN, token)
editor.apply()
}
Expand All @@ -30,12 +36,39 @@ class SessionManager(context: Context) {
}

fun setAPIBaseURL(apiBaseUrl: String) {
val editor = prefs.edit()
editor.putString(API_BASE_URL, apiBaseUrl)
editor.apply()
}

fun getAPIBaseURL(): String? {
return prefs.getString(API_BASE_URL, null)
}

fun setUser(user: User? = null) {
if (user == null) {
editor.remove(USER_USERNAME)
editor.remove(USER_EMAIL)
editor.remove(USER_ID)
editor.remove(USER_USERNAME)

} else {
editor.putString(USER_USERNAME, user.username)
editor.putString(USER_EMAIL, user.email)
editor.putInt(USER_ID, user.id)
editor.putString(USER_NAME, user.name)
}
editor.apply()
}

fun getUser(): User? {
if (getAuthToken() == null)
return null

return User(
id = prefs.getInt(USER_ID, -1),
username = prefs.getString(USER_USERNAME, "")!!,
name = prefs.getString(USER_NAME, "")!!,
email = prefs.getString(USER_EMAIL, "")!!
)
}
}
13 changes: 13 additions & 0 deletions app/src/main/java/com/example/sharedcalendar/ui/#/AuthActivity.kt
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.example.sharedcalendar.ui.login

import android.content.Intent
import android.os.Bundle
import androidx.activity.enableEdgeToEdge
import androidx.appcompat.app.AppCompatActivity
Expand All @@ -8,7 +9,9 @@ import androidx.fragment.app.FragmentManager
import androidx.lifecycle.Lifecycle
import androidx.viewpager2.adapter.FragmentStateAdapter
import androidx.viewpager2.widget.ViewPager2
import com.example.sharedcalendar.MainActivity
import com.example.sharedcalendar.R
import com.example.sharedcalendar.data.SessionManager

class AuthenticationPagerAdapter(
fragmentManager: FragmentManager,
Expand All @@ -30,10 +33,20 @@ class AuthenticationPagerAdapter(
}
}

private lateinit var sessionManager: SessionManager

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

sessionManager = SessionManager(this)
// Skip Authentication Page if user has already logged in
if (sessionManager.getAuthToken() != "") {
// If auth token exist
startActivity(Intent(this, MainActivity::class.java))
}

setContentView(R.layout.activity_auth)

val viewPager = findViewById<ViewPager2>(R.id.viewPager)
Expand Down
15 changes: 15 additions & 0 deletions app/src/main/java/com/example/sharedcalendar/ui/#/#ViewModel.kt
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.example.sharedcalendar.ui.login

import android.text.Editable
import android.util.Log
import android.util.Patterns
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
Expand All @@ -12,6 +13,8 @@ import com.example.sharedcalendar.data.Result
import com.example.sharedcalendar.data.SessionManager
import kotlinx.coroutines.launch

private val TAG: String = LoginViewModel::class.java.name

/**
* ViewModel for the login screen.
* @property loginRepository The login repository to be used.
Expand Down Expand Up @@ -80,6 +83,18 @@ class LoginViewModel(
}
}

fun logout(sessionManager: SessionManager) {
viewModelScope.launch {

try {
loginRepository.logout(sessionManager = sessionManager)
} catch (ex: Exception) {
Log.d(TAG, "Logout Failed: $ex")
}
}
}


private fun valueIsNotEmpty(value: Editable): Boolean {
return value.isNotBlank()
}
Expand Down
11 changes: 11 additions & 0 deletions app/src/main/res/drawable/baseline_logout_24.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:autoMirrored="true"
android:tint="#000000"
android:viewportWidth="24"
android:viewportHeight="24">
<path
android:fillColor="@android:color/white"
android:pathData="M17,7l-1.41,1.41L18.17,11H8v2h10.17l-2.58,2.58L17,17l5,-5zM4,5h8V3H4c-1.1,0 -2,0.9 -2,2v14c0,1.1 0.9,2 2,2h8v-2H4V5z" />
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_person_add_24px.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#FF000000"
android:pathData="M720,560v-120L600,440v-80h120v-120h80v120h120v80L800,440v120h-80ZM360,480q-66,0 -113,-47t-47,-113q0,-66 47,-113t113,-47q66,0 113,47t47,113q0,66 -47,113t-113,47ZM40,800v-112q0,-34 17.5,-62.5T104,582q62,-31 126,-46.5T360,520q66,0 130,15.5T616,582q29,15 46.5,43.5T680,688v112L40,800ZM120,720h480v-32q0,-11 -5.5,-20T580,654q-54,-27 -109,-40.5T360,600q-56,0 -111,13.5T140,654q-9,5 -14.5,14t-5.5,20v32ZM360,400q33,0 56.5,-23.5T440,320q0,-33 -23.5,-56.5T360,240q-33,0 -56.5,23.5T280,320q0,33 23.5,56.5T360,400ZM360,320ZM360,720Z" />
</vector>
9 changes: 9 additions & 0 deletions app/src/main/res/drawable/ic_settings_24px.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="24dp"
android:height="24dp"
android:viewportWidth="960"
android:viewportHeight="960">
<path
android:fillColor="#FF000000"
android:pathData="m370,880 l-16,-128q-13,-5 -24.5,-12T307,725l-119,50L78,585l103,-78q-1,-7 -1,-13.5v-27q0,-6.5 1,-13.5L78,375l110,-190 119,50q11,-8 23,-15t24,-12l16,-128h220l16,128q13,5 24.5,12t22.5,15l119,-50 110,190 -103,78q1,7 1,13.5v27q0,6.5 -2,13.5l103,78 -110,190 -118,-50q-11,8 -23,15t-24,12L590,880L370,880ZM440,800h79l14,-106q31,-8 57.5,-23.5T639,633l99,41 39,-68 -86,-65q5,-14 7,-29.5t2,-31.5q0,-16 -2,-31.5t-7,-29.5l86,-65 -39,-68 -99,42q-22,-23 -48.5,-38.5T533,266l-13,-106h-79l-14,106q-31,8 -57.5,23.5T321,327l-99,-41 -39,68 86,64q-5,15 -7,30t-2,32q0,16 2,31t7,30l-86,65 39,68 99,-42q22,23 48.5,38.5T427,694l13,106ZM482,620q58,0 99,-41t41,-99q0,-58 -41,-99t-99,-41q-59,0 -99.5,41T342,480q0,58 40.5,99t99.5,41ZM480,480Z" />
</vector>
19 changes: 10 additions & 9 deletions app/src/main/res/layout/activity_main.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,23 @@
<androidx.drawerlayout.widget.DrawerLayout 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:orientation="vertical"
android:id="@+id/drawerLayout"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:openDrawer="start"
android:id="@+id/drawerLayout"
tools:context=".MainActivity">
<include
layout="@layout/activity_main_content"/>
android:orientation="vertical"
tools:context=".MainActivity"
tools:openDrawer="start">

<include layout="@layout/activity_main_content" />

<com.google.android.material.navigation.NavigationView
android:id="@+id/nvSidebar"
android:layout_width="wrap_content"
android:layout_height="match_parent"
app:menu="@menu/drawer_items"
app:headerLayout="@layout/drawer_header"
android:layout_gravity="start"
app:drawerLayoutCornerSize="15dp"
android:layout_gravity="start"/>
app:headerLayout="@layout/drawer_header"
app:menu="@menu/drawer_items" />


</androidx.drawerlayout.widget.DrawerLayout>
Loading

0 comments on commit 005dc97

Please # to comment.