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

Commit

Permalink
Merge pull request #181 from MaximeZmt/kamila/refactor_sharedPreferences
Browse files Browse the repository at this point in the history
Kamila/add_user_search
  • Loading branch information
MaximeZmt authored Apr 17, 2022
2 parents 5da7824 + 354458c commit 4707b9f
Show file tree
Hide file tree
Showing 11 changed files with 331 additions and 10 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
package ch.sdp.vibester.activity

import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ApplicationProvider
import androidx.test.espresso.Espresso
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions
import androidx.test.espresso.assertion.ViewAssertions
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.intent.Intents
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.ext.junit.rules.ActivityScenarioRule
import androidx.test.ext.junit.runners.AndroidJUnit4
import ch.sdp.vibester.R
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith

@RunWith(AndroidJUnit4::class)
class SearchUserActivityTest {

@Rule
@JvmField
val activityRule = ActivityScenarioRule(SearchUserActivity::class.java)

@Before
fun setUp() {
Intents.init()
}

@After
fun clean() {
Intents.release()
}

@Test
fun recycleViewToViewTest() {
onView(ViewMatchers.withId(R.id.searchList))
.check(ViewAssertions.matches(ViewMatchers.isDisplayed()))
}

@Test
fun recycleViewClickTest() {
onView((ViewMatchers.withId(R.id.searchList)))
.perform(
RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(
2,
ViewActions.click()
)
)
}

@Test
fun recycleViewScrollDownTest() {
val recyclerView = RecyclerView(ApplicationProvider.getApplicationContext())
val itemCount = recyclerView.adapter?.itemCount
if (itemCount != null) {
onView(ViewMatchers.withId(R.id.searchList)).perform(
RecyclerViewActions.scrollToPosition<RecyclerView.ViewHolder>(
itemCount.minus(1)
)
)
}
}
@Test
fun recycleViewCheckEmpty() {
val inputTxt= "TESTESTESTEST"
onView(ViewMatchers.withId(R.id.searchUserET)).perform(ViewActions.typeText(inputTxt),
ViewActions.closeSoftKeyboard())
val recyclerView = RecyclerView(ApplicationProvider.getApplicationContext())
val itemCount = recyclerView.adapter?.itemCount
assertEquals(itemCount, null)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -68,4 +68,10 @@ class WelcomeActivityTest {
onView(withId(R.id.welcome_download)).perform(click())
intended(hasComponent(DownloadActivity::class.java.name))
}

@Test
fun checkIntentOnSearch() {
onView(withId(R.id.welcome_search)).perform(click())
intended(hasComponent(SearchUserActivity::class.java.name))
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package ch.sdp.vibester.profile

import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import androidx.test.core.app.ApplicationProvider
import org.hamcrest.CoreMatchers
import org.hamcrest.MatcherAssert
import org.junit.Test

class UserProfileAdapterTest {

@Test
fun recyclerViewShowsCorrectCount() {
val user1 = UserProfile("test1", "Brownie", "https://images.app.goo.gl/yiPpy7JDRFaZRiAg9", "[email protected]")
val user2 = UserProfile("test2", "Cookie", "https://images.app.goo.gl/yiPpy7JDRFaZRiAg9", "[email protected]")
val users: MutableList<UserProfile> = arrayListOf()
users.addAll(listOf(user1, user2))
val userProfileViewHolder: RecyclerView.Adapter<UserProfileAdapter.UserProfileViewHolder> = UserProfileAdapter(users)
MatcherAssert.assertThat(userProfileViewHolder.itemCount, CoreMatchers.equalTo(2))
}

@Test
fun itemTypeIsCorrect() {
val user1 = UserProfile("test1", "Brownie", "https://images.app.goo.gl/yiPpy7JDRFaZRiAg9", "[email protected]")
val user2 = UserProfile("test2", "Cookie", "https://images.app.goo.gl/yiPpy7JDRFaZRiAg9", "[email protected]")
val users: MutableList<UserProfile> = arrayListOf()
users.addAll(listOf(user1, user2))
val userProfileViewHolder: RecyclerView.Adapter<UserProfileAdapter.UserProfileViewHolder> = UserProfileAdapter(users)
val defaultType = 0
MatcherAssert.assertThat(
userProfileViewHolder.getItemViewType(0),
CoreMatchers.equalTo(defaultType)
)
}
}
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
android:usesCleartextTraffic="true">
<activity
android:name=".activity.SearchUserActivity"
android:exported="false" />
<activity
android:name=".activity.DownloadActivity"
android:exported="false" />
Expand Down
89 changes: 89 additions & 0 deletions app/src/main/java/ch/sdp/vibester/activity/SearchUserActivity.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
package ch.sdp.vibester.activity

import android.content.ContentValues
import android.os.Bundle
import android.text.Editable
import android.text.TextWatcher
import android.util.Log
import android.view.Window
import android.widget.EditText
import androidx.appcompat.app.AppCompatActivity
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import ch.sdp.vibester.R
import ch.sdp.vibester.database.Database
import ch.sdp.vibester.profile.UserProfile
import ch.sdp.vibester.profile.UserProfileAdapter
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.DatabaseReference
import com.google.firebase.database.ValueEventListener

/**
* Search for users based on their usernames.
*/
class SearchUserActivity : AppCompatActivity() {
private var userProfileAdapter: UserProfileAdapter? = null
private var users: MutableList<UserProfile>? = null
private var recyclerView: RecyclerView? = null
private var searchEditText: EditText? = null
private val dbRef: DatabaseReference = Database.get().getReference("users")

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
requestWindowFeature(Window.FEATURE_NO_TITLE)
supportActionBar?.hide()
setContentView(R.layout.activity_search_user)

recyclerView = findViewById(R.id.searchList)
recyclerView!!.setHasFixedSize(true)
recyclerView!!.layoutManager = LinearLayoutManager(this)

users = ArrayList()

searchEditText = findViewById(R.id.searchUserET)
searchForUsers("")

searchEditText!!.addTextChangedListener(object:TextWatcher{
override fun beforeTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
}
override fun onTextChanged(p0: CharSequence?, p1: Int, p2: Int, p3: Int) {
searchForUsers(p0.toString())
}
override fun afterTextChanged(p0: Editable?) {
}
})
}

/**
* Search for users by usernames in Firebase Realtime Database
* @param inputUsername search text inputed by user
* Comment about \uf8ff:
* The \uf8ff character used in the query above is a very high code point in the Unicode range.
* Because it is after most regular characters in Unicode, the query matches all values that start with a inputUsername.
*/
private fun searchForUsers(inputUsername:String){
val queryUsers = dbRef
.orderByChild("username")
.startAt(inputUsername)
.endAt(inputUsername+"\uf8ff")

queryUsers.addValueEventListener(object : ValueEventListener {
override fun onDataChange(dataSnapshot: DataSnapshot) {
(users as ArrayList<UserProfile>).clear()
for (snapshot in dataSnapshot.children) {
val userProfile:UserProfile? = snapshot.getValue(UserProfile::class.java)
if (userProfile != null) {
(users as ArrayList<UserProfile>).add(userProfile)
}
}
userProfileAdapter = UserProfileAdapter(users!!)
recyclerView!!.adapter = userProfileAdapter
}
override fun onCancelled(error: DatabaseError) {
Log.w(ContentValues.TAG, "searchForUsers:onCancelled", error.toException())
}
})
}
}

13 changes: 3 additions & 10 deletions app/src/main/java/ch/sdp/vibester/activity/WelcomeActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@ package ch.sdp.vibester.activity
//import ch.sdp.vibester.profile.ProfileDataProvider
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.View
import android.view.Window.FEATURE_NO_TITLE
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import ch.sdp.vibester.R
import ch.sdp.vibester.model.Song
import ch.sdp.vibester.model.UserSharedPref

class WelcomeActivity : AppCompatActivity() {
Expand Down Expand Up @@ -57,12 +55,7 @@ class WelcomeActivity : AppCompatActivity() {
sendDirectIntent(DownloadActivity::class.java)
}

/*
* Belongs to a previously implemented button, taken out for UI purposes.
* Might bring it back, thus leaving the code for now.
*/

/*fun switchToLogin(view: View) { //FILLER INTENT
sendDirectIntent(GameSetupScreen::class.java)
}*/
fun switchToSearch(view: View) {
sendDirectIntent(SearchUserActivity::class.java)
}
}
51 changes: 51 additions & 0 deletions app/src/main/java/ch/sdp/vibester/profile/UserProfileAdapter.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package ch.sdp.vibester.profile

import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import ch.sdp.vibester.R

/**
* UserAdapter to set userProfile views with username and image in RecycleView. It is used to search for users.
*/
class UserProfileAdapter(val users: MutableList<UserProfile>):
RecyclerView.Adapter<UserProfileAdapter.UserProfileViewHolder>() {

/**
* Create a RecycleView layout with the userProfile view as an item
*/
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): UserProfileViewHolder {
val view: View = LayoutInflater.from(parent.context)
.inflate(R.layout.user_search_item_layout, parent, false)
return UserProfileViewHolder(view)
}

override fun onBindViewHolder(holder: UserProfileViewHolder, position: Int) {
holder.bind(users[position])
}

/**
* Get amount of users displayed
*/
override fun getItemCount(): Int {
return users.size
}

/**
* Customer ViewHolder class for UserProfile. Each item contains username and image.
*/
inner class UserProfileViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
/**
* @param userProfile with all the parameters
*/
fun bind(user: UserProfile) {
itemView.findViewById<TextView>(R.id.search_user_username).text = user.username
// TODO fix the image upload
// itemView.findViewById<ImageView>(R.id.iv_photo).loadImg(player.photo)
}
}


}
26 changes: 26 additions & 0 deletions app/src/main/res/layout/activity_search_user.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
xmlns:tools="http://schemas.android.com/tools"
android:background="@color/floral_white"
tools:context=".activity.SearchUserActivity">

<EditText
android:id="@+id/searchUserET"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="6dp"
android:autofillHints="Enter username to search">
</EditText>

<androidx.recyclerview.widget.RecyclerView
android:id="@+id/searchList"
android:layout_below="@+id/searchUserET"
android:layout_width="match_parent"
android:layout_height="match_parent">

</androidx.recyclerview.widget.RecyclerView>

</RelativeLayout>
13 changes: 13 additions & 0 deletions app/src/main/res/layout/activity_welcome_screen.xml
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,19 @@
android:translationZ="10dp"
app:icon="@android:drawable/stat_sys_download" />

<Button
android:id="@+id/welcome_search"
android:layout_width="200dp"
android:layout_height="48dp"
android:layout_marginTop="10dp"
android:backgroundTint="@color/cg_blue"
android:elevation="10dp"
android:onClick="switchToSearch"
android:stateListAnimator="@null"
android:text="@string/search_users"
android:translationZ="10dp"/>


<Space
android:layout_width="match_parent"
android:layout_height="42dp" />
Expand Down
26 changes: 26 additions & 0 deletions app/src/main/res/layout/user_search_item_layout.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="@color/floral_white"
android:layout_width="match_parent"
android:layout_height="wrap_content">

<ImageView
android:id="@+id/profile_image"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@drawable/logo">
</ImageView>

<TextView
android:id="@+id/search_user_username"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toEndOf="@+id/profile_image"
android:layout_centerInParent="true"
android:layout_marginStart="12dp"
android:text="@string/profile_username"
android:textSize="19sp">
</TextView>

</RelativeLayout>
2 changes: 2 additions & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -101,4 +101,6 @@
<string name="result_will_show_here">result will show here</string>
<string name="welcome_not_logged_in">"User: Not Logged In"</string>
<string name="game_lyrics">Local Lyrics</string>
<string name="profile_username">Profile Username</string>
<string name="search_users">SEARCH USERS</string>
</resources>

0 comments on commit 4707b9f

Please sign in to comment.