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

Laurislopata/upload image #184

Merged
merged 12 commits into from
Apr 19, 2022
Merged
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,7 @@ dependencies {
implementation 'com.squareup.retrofit2:retrofit:2.0.0'
implementation 'com.squareup.retrofit2:converter-gson:2.0.0'
implementation 'com.google.firebase:firebase-database-ktx'
implementation 'com.google.firebase:firebase-storage-ktx'
implementation 'junit:junit:4.13.2'
testImplementation 'junit:junit:4.13.2'
testImplementation 'org.json:json:20180813'
Expand Down
18 changes: 18 additions & 0 deletions app/src/androidTest/java/ch/sdp/vibester/UtilTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
package ch.sdp.vibester

import ch.sdp.vibester.util.Util
import org.junit.Test

import org.junit.Assert.*

/**
* Example local unit test, which will execute on the development machine (host).
*
* See [testing documentation](http://d.android.com/tools/testing).
*/
class UtilTest {
@Test
fun newIdIsCorrectLength() {
assertEquals(Util.createNewId().length, 10)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import androidx.test.espresso.intent.matcher.IntentMatchers
import androidx.test.espresso.matcher.ViewMatchers.* //change this import
import androidx.test.ext.junit.runners.AndroidJUnit4
import ch.sdp.vibester.R
import ch.sdp.vibester.database.ImageRepo
import ch.sdp.vibester.database.UsersRepo
import ch.sdp.vibester.profile.UserProfile
import dagger.hilt.android.testing.BindValue
Expand Down Expand Up @@ -81,5 +82,4 @@ class CreateProfileActivityTest {
Intents.intended(IntentMatchers.hasExtra("email", mockEmail))
}


}
Original file line number Diff line number Diff line change
@@ -1,13 +1,25 @@
package ch.sdp.vibester.activity

import android.app.Activity
import android.content.Intent
import android.graphics.drawable.BitmapDrawable
import android.net.Uri
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.widget.Button
import android.widget.EditText
import android.widget.ImageView
import android.widget.TextView
import ch.sdp.vibester.R
import ch.sdp.vibester.database.ImageRepo
import ch.sdp.vibester.database.UsersRepo
import ch.sdp.vibester.util.Util
import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.StorageReference
import com.google.firebase.storage.ktx.storage
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import javax.inject.Inject

@AndroidEntryPoint
Expand All @@ -16,6 +28,11 @@ class CreateProfileActivity : AppCompatActivity() {
@Inject
lateinit var usersRepo: UsersRepo

@Inject
lateinit var imageRepo: ImageRepo

private val REQUEST_CODE = 500

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_create_profile)
Expand All @@ -25,6 +42,7 @@ class CreateProfileActivity : AppCompatActivity() {
var handle = findViewById<EditText>(R.id.accountHandle)

val btCreateAcc = findViewById<Button>(R.id.createButton)
val btnUploadImg = findViewById<Button>(R.id.uploadImg)

btCreateAcc.setOnClickListener {
usersRepo.createUser(
Expand All @@ -33,6 +51,10 @@ class CreateProfileActivity : AppCompatActivity() {
handle.text.toString(),
this::startNewActivity)
}

btnUploadImg.setOnClickListener {
uploadImage()
}
}

private fun startNewActivity(email: String) {
Expand All @@ -41,4 +63,23 @@ class CreateProfileActivity : AppCompatActivity() {

startActivity(newIntent)
}

private fun uploadImage() {
val intent = Intent(Intent.ACTION_PICK)
intent.type = "image/*"
startActivityForResult(intent, REQUEST_CODE)
}


private fun updateUI() {
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Similar blocks of code found in 2 locations. Consider refactoring.

findViewById<TextView>(R.id.uploadStatus).text = getString(R.string.uploadImageStatus)
}


override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
super.onActivityResult(requestCode, resultCode, data)
if (resultCode == Activity.RESULT_OK && requestCode == REQUEST_CODE){
imageRepo.uploadFile("profileImg/${Util.createNewId()}", data?.data!!) { updateUI() }
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,6 @@ class ProfileActivity : AppCompatActivity() {

private fun queryDatabase(email: String) {
usersRepo.getUserData(email, this::setupProfile)

}


Expand Down
30 changes: 30 additions & 0 deletions app/src/main/java/ch/sdp/vibester/database/ImageRepo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
package ch.sdp.vibester.database

import android.content.ContentValues
import android.net.Uri
import android.util.Log
import ch.sdp.vibester.profile.UserProfile
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.ValueEventListener
import com.google.firebase.database.ktx.getValue
import javax.inject.Inject

/**
* The users class which handled all the interactions with the database that are linked to users
*/

class ImageRepo @Inject constructor() {
private val storageRef = Storage.get().reference

fun uploadFile(filePath: String, fileUri: Uri, callback: () -> Unit): Unit {
val profilePicRef = storageRef.child(filePath)

var uploadTask = profilePicRef.putFile(fileUri)

// taskSnapshot.metadata contains file metadata such as size, content-type, etc.
uploadTask.addOnSuccessListener { taskSnapshot ->
callback()
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you will add the task later but you can put everything in one line here since the callback() is short, it will not affect the readability.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. Also, since testing these calls is hard, maybe consider concatenating some operations or lines.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also agreed, it's an easy way to make the coverage of external calls better.

}
}
}
15 changes: 15 additions & 0 deletions app/src/main/java/ch/sdp/vibester/database/Storage.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package ch.sdp.vibester.database

import com.google.firebase.ktx.Firebase
import com.google.firebase.storage.FirebaseStorage
import com.google.firebase.storage.ktx.storage

/**
* The Database objects that returns our storage instance
*/

object Storage {
fun get(): FirebaseStorage {
return Firebase.storage("gs://vibester-sdp.appspot.com")
}
}
7 changes: 2 additions & 5 deletions app/src/main/java/ch/sdp/vibester/database/UsersRepo.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package ch.sdp.vibester.database
import android.content.ContentValues
import android.util.Log
import ch.sdp.vibester.profile.UserProfile
import ch.sdp.vibester.util.Util
import com.google.firebase.database.DataSnapshot
import com.google.firebase.database.DatabaseError
import com.google.firebase.database.ValueEventListener
Expand Down Expand Up @@ -53,11 +54,7 @@ class UsersRepo @Inject constructor() {
var newUser = UserProfile(handle, username, "", email, 0, 0, 0, 0
)

val charPool : List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val newId = (1..10)
.map { i -> kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("");
val newId = Util.createNewId()

dbRef.child(newId).setValue(newUser)
.addOnSuccessListener {
Expand Down
19 changes: 19 additions & 0 deletions app/src/main/java/ch/sdp/vibester/util/Util.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
package ch.sdp.vibester.util

class Util {
companion object {
/**
* A function that generates a random ID for database storage
*/
fun createNewId(): String {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

consider adding documentation for this (explaining the form of the id, etc)

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed.

val charPool : List<Char> = ('a'..'z') + ('A'..'Z') + ('0'..'9')
val newId = (1..10)
.map { i -> kotlin.random.Random.nextInt(0, charPool.size) }
.map(charPool::get)
.joinToString("");

return newId
}
}

}
27 changes: 27 additions & 0 deletions app/src/main/res/layout/activity_create_profile.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,19 @@
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<TextView
android:id="@+id/uploadStatus"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="129dp"
android:layout_marginBottom="79dp"
android:text="Upload Status"
android:textSize="25sp"
app:layout_constraintBottom_toTopOf="@+id/accountUsername"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />

<Button
android:id="@+id/createButton"
android:layout_width="wrap_content"
Expand All @@ -63,4 +76,18 @@
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/accountHandle" />

<Button
android:id="@+id/uploadImg"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="116dp"
android:layout_marginBottom="148dp"
android:backgroundTint="@color/cg_blue"
android:text="Upload Image"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/accountHandle" />

</androidx.constraintlayout.widget.ConstraintLayout>
1 change: 1 addition & 0 deletions app/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@
<string name="notAnEmail">Not an email</string>
<string name="shortPassword">Password has to be at least 6 symbols</string>
<string name="AccCreation">Account creation form</string>
<string name="uploadImageStatus">Upload OK</string>

<string name="game_end__player_name">Player Name Here</string>
<string name="game_end__show_stats">Here are your stats!</string>
Expand Down