-
Notifications
You must be signed in to change notification settings - Fork 0
Linking profile to image upload #228
Changes from 18 commits
57cb7a1
ea9b282
45575e1
89f7b22
64c4041
d45e0cf
7aee916
2ec01c3
f9c9282
4d85c3f
d0a08f3
cf04e42
a76487a
231c4fa
ca09d82
bb2e831
83dffc4
d263915
46fd991
a62630e
1d26e0f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,9 @@ package ch.sdp.vibester.activity | |
|
||
import android.content.Context | ||
import android.content.Intent | ||
import android.net.Uri | ||
import android.provider.CalendarContract.CalendarCache.URI | ||
import android.widget.ImageView | ||
import androidx.test.core.app.ActivityScenario | ||
import androidx.test.core.app.ApplicationProvider | ||
import androidx.test.espresso.Espresso.onView | ||
|
@@ -13,9 +16,9 @@ import androidx.test.espresso.intent.matcher.IntentMatchers | |
import androidx.test.espresso.matcher.ViewMatchers.* | ||
import androidx.test.ext.junit.runners.AndroidJUnit4 | ||
import ch.sdp.vibester.R | ||
import ch.sdp.vibester.TestMode | ||
import ch.sdp.vibester.auth.FireBaseAuthenticator | ||
import ch.sdp.vibester.database.DataGetter | ||
import ch.sdp.vibester.database.ImageGetter | ||
import ch.sdp.vibester.user.User | ||
import com.google.firebase.auth.FirebaseUser | ||
import dagger.hilt.android.testing.BindValue | ||
|
@@ -64,15 +67,27 @@ class ProfileActivityTest { | |
@BindValue @JvmField | ||
val mockUsersRepo = mockk<DataGetter>() | ||
|
||
private fun createMockInvocation(mockProfile: User) { | ||
@BindValue @JvmField | ||
val mockImageGetter = mockk<ImageGetter>() | ||
|
||
private fun createMockDataGetter(mockProfile: User) { | ||
every { mockUsersRepo.getUserData(any(), any()) } answers { | ||
secondArg<(User) -> Unit>().invoke(mockProfile) | ||
} | ||
|
||
every {mockUsersRepo.getCurrentUser()} answers { | ||
null | ||
} | ||
every { mockUsersRepo.setFieldValue(any(), any(), any()) } answers {} | ||
every { mockUsersRepo.setFieldValue(any(), any(), any()) } answers {} | ||
} | ||
|
||
val mockImageURI = Uri.parse("https://raw.githubusercontent.com/Ashwinvalento/cartoon-avatar/master/lib/images/male/45.png") | ||
private fun createMockImageGetter() { | ||
every {mockImageGetter.fetchImage(any(), any())} answers { | ||
secondArg<(Uri) -> Unit>().invoke(mockImageURI) | ||
} | ||
} | ||
|
||
@After | ||
fun clean() { | ||
Intents.release() | ||
|
@@ -84,8 +99,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
|
||
|
@@ -101,8 +117,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
|
||
|
@@ -117,8 +134,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
|
||
|
@@ -134,8 +152,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
onView(withId(R.id.showQRCode)).perform(click()) | ||
|
@@ -151,8 +170,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
val newUsername = "Lalisa Bon idomesniu" | ||
|
@@ -171,8 +191,9 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
|
||
|
@@ -187,12 +208,29 @@ class ProfileActivityTest { | |
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockInvocation(inputProfile) | ||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
onView(withId(R.id.showQRCode)).perform(click()) | ||
onView(withId(R.id.qrCode)).check(matches(isDisplayed())) | ||
} | ||
|
||
} | ||
@Test | ||
fun checkIfPictureIsDisplayed() { | ||
val inputProfile = User( "Lalisa Bon","bit.ly/3IUnyAF", "[email protected]", 12, 8, 29, 0, "VvPB47tQCLdjz3YebilS6h5EXdJ3") | ||
val ctx = ApplicationProvider.getApplicationContext() as Context | ||
val intent = Intent(ctx, ProfileActivity::class.java) | ||
|
||
createMockDataGetter(inputProfile) | ||
createMockAuthenticatorInvocation() | ||
createMockImageGetter() | ||
|
||
val scn: ActivityScenario<ProfileActivity> = ActivityScenario.launch(intent) | ||
|
||
Thread.sleep(5000) | ||
onView(withId(R.id.avatar)).check(matches(isDisplayed())) | ||
} | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,7 @@ | ||
package ch.sdp.vibester.activity | ||
|
||
import android.graphics.* | ||
import android.net.Uri | ||
import android.os.Bundle | ||
import android.text.InputType | ||
import android.util.Log | ||
|
@@ -18,6 +19,7 @@ import ch.sdp.vibester.R | |
import ch.sdp.vibester.api.BitmapGetterApi | ||
import ch.sdp.vibester.auth.FireBaseAuthenticator | ||
import ch.sdp.vibester.database.DataGetter | ||
import ch.sdp.vibester.database.ImageGetter | ||
import ch.sdp.vibester.helper.IntentSwitcher | ||
import ch.sdp.vibester.user.User | ||
import com.google.android.material.floatingactionbutton.FloatingActionButton | ||
|
@@ -42,10 +44,13 @@ import javax.inject.Inject | |
class ProfileActivity : AppCompatActivity() { | ||
@Inject | ||
lateinit var dataGetter: DataGetter | ||
|
||
@Inject | ||
lateinit var authenticator: FireBaseAuthenticator | ||
|
||
@Inject | ||
lateinit var imageGetter: ImageGetter | ||
|
||
/** | ||
* Generic onCreate method belonging to ProfileActivity. | ||
*/ | ||
|
@@ -180,6 +185,32 @@ class ProfileActivity : AppCompatActivity() { | |
} | ||
} | ||
|
||
|
||
/** | ||
* A function that downloads an image and sets it. | ||
* @param imageURI URI of the image | ||
*/ | ||
private fun setImage(imageURI: Uri) { | ||
CoroutineScope(Dispatchers.Main).launch { | ||
val task = async(Dispatchers.IO) { | ||
try { | ||
val bit = BitmapGetterApi.download(imageURI.toString()) | ||
bit.get(10, TimeUnit.SECONDS) | ||
} catch (e: Exception){ | ||
|
||
null | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why the handle exception is null? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @MaximeZmt wrote this function I just reused it, so maybe he can answer better :) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. It as was null because it was not a critical feature. I mean that the download of an image can fail for many reasons (user, server, Internet Provider, other users, ...) |
||
} | ||
} | ||
val bm = task.await() | ||
|
||
if(bm != null){ | ||
val avatar = findViewById<ImageView>(R.id.avatar) | ||
avatar.setImageBitmap(Bitmap.createScaledBitmap(bm, 1000,1000, false)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe put 1000 in a meaningful val? |
||
} | ||
} | ||
} | ||
|
||
|
||
/** | ||
* Function that sets the text of a given TextView to the string variant of an integer. | ||
* @param id: The id of the TextView to be changed. | ||
|
@@ -210,36 +241,15 @@ class ProfileActivity : AppCompatActivity() { | |
findViewById<TextView>(R.id.username).text = user.username | ||
setTextOfMultipleViews(user) | ||
} | ||
setupProfilePhoto(user) | ||
|
||
val imageID = dataGetter.getCurrentUser()?.uid | ||
imageGetter.fetchImage("profileImg/${imageID}", this::setImage) | ||
|
||
if (user.uid != "") { | ||
generateQrCode(user.uid) | ||
} | ||
} | ||
|
||
/** | ||
* Helper function to setupProfile to set the profile photo of a user. | ||
* @param user: The user whose profile picture we are setting up. | ||
*/ | ||
private fun setupProfilePhoto(user: User) { | ||
CoroutineScope(Dispatchers.Main).launch { | ||
val task = async(Dispatchers.IO) { | ||
try { | ||
Log.e(getString(R.string.log_tag),user.image) | ||
val bit = BitmapGetterApi.download("https://raw.githubusercontent.com/Ashwinvalento/cartoon-avatar/master/lib/images/male/45.png") | ||
bit.get(10, TimeUnit.SECONDS) | ||
} catch (e: Exception) { | ||
null | ||
} | ||
} | ||
val bm = task.await() | ||
if (bm != null) { | ||
val avatar = findViewById<ImageView>(R.id.avatar) | ||
avatar.setImageBitmap(Bitmap.createScaledBitmap(bm, 1000,1000, false)) | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* generate the qr code bitmap of the given data | ||
* @param data Qr Code data | ||
|
@@ -264,4 +274,3 @@ class ProfileActivity : AppCompatActivity() { | |
findViewById<ImageView>(R.id.qrCode).setImageBitmap(bmp) | ||
} | ||
} | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -5,6 +5,7 @@ import android.util.Log | |
import ch.sdp.vibester.auth.FireBaseAuthenticator | ||
import ch.sdp.vibester.helper.PartyRoom | ||
import ch.sdp.vibester.user.User | ||
import com.google.firebase.auth.FirebaseUser | ||
import com.google.firebase.database.DataSnapshot | ||
import com.google.firebase.database.DatabaseError | ||
import com.google.firebase.database.ValueEventListener | ||
|
@@ -207,6 +208,10 @@ class DataGetter @Inject constructor() { | |
dbRoomRef.child(partyRoom.getRoomID()).child("emailList").setValue(partyRoom.getEmailList()) | ||
} | ||
|
||
fun getCurrentUser(): FirebaseUser? { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Reminder to add documentation for functions that are not private, no matter how obvious they can be. Not too important for this PR as we need a general check over our entire codebase and write docs, but a small reminder |
||
return authenticator.getCurrUser() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. why is it in dataFetter? We need to think of a separation between firebaseUser and Datagetter |
||
} | ||
|
||
/** | ||
* This functions fetches the data of the given user from the database | ||
* @param roomName the name of the room to retrieve data from | ||
|
@@ -223,7 +228,7 @@ class DataGetter @Inject constructor() { | |
for (snapshot in dataSnapshot.children) { | ||
val partyRoom: PartyRoom? = snapshot.getValue(PartyRoom::class.java) | ||
if(partyRoom != null) { | ||
val currUserEmail = authenticator.getCurrUser()?.email!! | ||
val currUserEmail = getCurrentUser()?.email!! | ||
if(!partyRoom.getEmailList().contains(currUserEmail)) { | ||
partyRoom.addUserEmail(currUserEmail) | ||
updateRoomUserList(partyRoom) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package ch.sdp.vibester.database | ||
|
||
import android.net.Uri | ||
import com.google.android.gms.tasks.OnSuccessListener | ||
import javax.inject.Inject | ||
|
||
/** | ||
* The users class which handled all the interactions with the database that are linked to users | ||
*/ | ||
class ImageGetter @Inject constructor() { | ||
private val storageRef = Storage.get().reference | ||
|
||
/** | ||
* This function uploads a provided image to the database | ||
* @param filePath file path of the picture on the phone | ||
* @param fileUri URI of the image on the database | ||
* @param callback function to be called when image is done uploading | ||
*/ | ||
fun uploadFile(filePath: String, fileUri: Uri, callback: () -> Unit) { | ||
val profilePicRef = storageRef.child(filePath) | ||
|
||
val uploadTask = profilePicRef.putFile(fileUri) | ||
|
||
uploadTask.addOnSuccessListener { callback() } | ||
} | ||
|
||
/** | ||
* This function fetches an image | ||
* @param imageID ID of the image in the database | ||
* @param callback function to be called when image fetched | ||
*/ | ||
fun fetchImage(imageID: String, callback: (downloadUR: Uri) -> Unit) { | ||
storageRef.child(imageID).downloadUrl.addOnSuccessListener( | ||
OnSuccessListener(callback)) | ||
} | ||
|
||
} |
This file was deleted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not use Completable Future to detect if images have been downloaded?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea, I'll implement it next week