diff --git a/.idea/misc.xml b/.idea/misc.xml index 773fe0f..8978d23 100644 --- a/.idea/misc.xml +++ b/.idea/misc.xml @@ -1,6 +1,6 @@ - + diff --git a/app/build.gradle b/app/build.gradle index 76d4681..f68e60b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -47,6 +47,7 @@ dependencies { implementation 'androidx.appcompat:appcompat:1.6.1' implementation 'androidx.constraintlayout:constraintlayout:2.1.4' implementation 'com.google.firebase:firebase-auth:21.1.0' + implementation 'com.google.firebase:firebase-storage:20.1.0' testImplementation 'junit:junit:4.13.2' androidTestImplementation 'androidx.test.ext:junit:1.1.5' diff --git a/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java b/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java index 10f1b7d..7354aa5 100644 --- a/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java +++ b/app/src/main/java/com/capstone/foodify/Activity/AccountAndProfileActivity.java @@ -1,9 +1,13 @@ package com.capstone.foodify.Activity; +import android.app.Activity; import android.app.DatePickerDialog; +import android.content.ContentResolver; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.view.View; +import android.webkit.MimeTypeMap; import android.widget.Button; import android.widget.DatePicker; import android.widget.EditText; @@ -11,14 +15,29 @@ import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.Toast; +import androidx.activity.result.ActivityResult; +import androidx.activity.result.ActivityResultCallback; +import androidx.activity.result.ActivityResultLauncher; +import androidx.activity.result.contract.ActivityResultContracts; +import androidx.annotation.NonNull; import androidx.appcompat.app.AppCompatActivity; +import androidx.constraintlayout.widget.ConstraintLayout; import com.capstone.foodify.API.FoodApiToken; import com.capstone.foodify.Common; import com.capstone.foodify.Model.User; import com.capstone.foodify.R; -import com.google.android.material.button.MaterialButton; +import com.google.android.gms.tasks.OnCompleteListener; +import com.google.android.gms.tasks.OnFailureListener; +import com.google.android.gms.tasks.OnSuccessListener; +import com.google.android.gms.tasks.Task; import com.google.android.material.textfield.TextInputLayout; +import com.google.firebase.storage.FirebaseStorage; +import com.google.firebase.storage.OnProgressListener; +import com.google.firebase.storage.StorageReference; +import com.google.firebase.storage.UploadTask; +import com.makeramen.roundedimageview.RoundedImageView; +import com.squareup.picasso.Picasso; import java.text.SimpleDateFormat; import java.util.Calendar; @@ -30,13 +49,17 @@ import retrofit2.Response; public class AccountAndProfileActivity extends AppCompatActivity { + private static final String FOLDER_DIRECTORY = "UserImages/"; TextInputLayout textInput_email, textInput_phone, textInput_fullName, textInput_birthDay; - EditText edt_birthday, edt_email, edt_phone, edt_fullName; final Calendar myCalendar= Calendar.getInstance(); LinearLayout change_password; - Button update_button; + Button update_button, update_image_button; ImageView back_image; + RoundedImageView profile_avatar; + private Uri imageUri; + final private StorageReference storageReference = FirebaseStorage.getInstance().getReference(); + ConstraintLayout progressLayout; @Override protected void onCreate(Bundle savedInstanceState) { @@ -68,10 +91,100 @@ public class AccountAndProfileActivity extends AppCompatActivity { update_button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - updateUser(); + progressLayout.setVisibility(View.VISIBLE); + if(imageUri != null) + uploadToFirebase(imageUri); + else + updateUser(null); } }); + //Activity choose image + ActivityResultLauncher activityResultLauncher = registerForActivityResult(new ActivityResultContracts.StartActivityForResult(), + new ActivityResultCallback() { + @Override + public void onActivityResult(ActivityResult result) { + if(result.getResultCode() == Activity.RESULT_OK){ + Intent data = result.getData(); + imageUri = data.getData(); + profile_avatar.setImageURI(imageUri); + + Toast.makeText(AccountAndProfileActivity.this, "Hãy bấm nút cập nhật phía dưới để thay đổi có hiệu lực!", Toast.LENGTH_SHORT).show(); + } else { + Toast.makeText(AccountAndProfileActivity.this, "Không ảnh nào được chọn!", Toast.LENGTH_SHORT).show(); + } + } + }); + + //Set event on button upload image avatar + update_image_button.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + Intent photoPicker = new Intent(); + photoPicker.setAction(Intent.ACTION_GET_CONTENT); + photoPicker.setType("image/*"); + activityResultLauncher.launch(photoPicker); + } + }); + + } + + private void uploadToFirebase(Uri uri){ + + //Name of image user + String imageName = Common.CURRENT_USER.getFullName().replace(" " , "_") + "_" + Common.CURRENT_USER.getDateOfBirth().replace("-", "_") + + "_" + System.currentTimeMillis(); + + final StorageReference imageReference = storageReference.child(FOLDER_DIRECTORY + imageName + "." + getFileExtension(uri)); + imageReference.putFile(uri).addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(UploadTask.TaskSnapshot taskSnapshot) { + imageReference.getDownloadUrl().addOnSuccessListener(new OnSuccessListener() { + @Override + public void onSuccess(Uri uri) { + if(!Common.CURRENT_USER.getImageUrl().isEmpty()) + deleteOldImage(); + + updateUser(uri.toString()); + + Toast.makeText(AccountAndProfileActivity.this, "Upload ảnh thành công!", Toast.LENGTH_SHORT).show(); + } + }); + } + }).addOnProgressListener(new OnProgressListener() { + @Override + public void onProgress(@NonNull UploadTask.TaskSnapshot snapshot) { + + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + + Toast.makeText(AccountAndProfileActivity.this, "Failed", Toast.LENGTH_SHORT).show(); + } + }); + } + + private void deleteOldImage() { + StorageReference storageReference = FirebaseStorage.getInstance().getReferenceFromUrl(Common.CURRENT_USER.getImageUrl()); + + storageReference.delete().addOnCompleteListener(new OnCompleteListener() { + @Override + public void onComplete(@NonNull Task task) { + Toast.makeText(AccountAndProfileActivity.this, "Delete old image successfully!", Toast.LENGTH_SHORT).show(); + } + }).addOnFailureListener(new OnFailureListener() { + @Override + public void onFailure(@NonNull Exception e) { + Toast.makeText(AccountAndProfileActivity.this, "Can't delete old image!", Toast.LENGTH_SHORT).show(); + } + }); + } + + private String getFileExtension(Uri fileUri){ + ContentResolver contentResolver = getContentResolver(); + MimeTypeMap mime = MimeTypeMap.getSingleton(); + return mime.getExtensionFromMimeType(contentResolver.getType(fileUri)); } private void initData() { @@ -79,11 +192,17 @@ public class AccountAndProfileActivity extends AppCompatActivity { edt_phone.setText(Common.CURRENT_USER.getPhoneNumber()); edt_fullName.setText(Common.CURRENT_USER.getFullName()); edt_birthday.setText(Common.CURRENT_USER.getDateOfBirth()); + + //Set image for user + if(Common.CURRENT_USER.getImageUrl().isEmpty()){ + profile_avatar.setImageResource(R.drawable.profile_avatar); + } else { + Picasso.get().load(Common.CURRENT_USER.getImageUrl()).into(profile_avatar); + } } private void initComponent() { //Init Component - textInput_email= findViewById(R.id.textInput_email); textInput_phone = findViewById(R.id.textInput_phone); textInput_fullName = findViewById(R.id.textInput_fullName); @@ -91,6 +210,7 @@ public class AccountAndProfileActivity extends AppCompatActivity { change_password = findViewById(R.id.change_password); update_button = findViewById(R.id.updated_button); + update_image_button = findViewById(R.id.change_image_button); back_image = findViewById(R.id.back_image); @@ -98,6 +218,10 @@ public class AccountAndProfileActivity extends AppCompatActivity { edt_email = findViewById(R.id.edt_email); edt_phone = findViewById(R.id.edt_phone); edt_fullName = findViewById(R.id.edt_fullName); + + profile_avatar = findViewById(R.id.profile_avatar); + + progressLayout = findViewById(R.id.progress_layout); } private void setFontUI() { @@ -139,7 +263,7 @@ public class AccountAndProfileActivity extends AppCompatActivity { edt_birthday.setText(dateFormat.format(myCalendar.getTime())); } - private void updateUser() { + private void updateUser(String imageUrl) { //Get data from form String fullName = edt_fullName.getText().toString(); String dateOfBirth = edt_birthday.getText().toString(); @@ -147,16 +271,20 @@ public class AccountAndProfileActivity extends AppCompatActivity { //Create object User Common.CURRENT_USER.setFullName(fullName); Common.CURRENT_USER.setDateOfBirth(dateOfBirth); + if(imageUrl != null) + Common.CURRENT_USER.setImageUrl(imageUrl); FoodApiToken.apiService.updateUser(Common.CURRENT_USER.getId(), Common.CURRENT_USER).enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { Toast.makeText(AccountAndProfileActivity.this, "Cập nhật thành công!", Toast.LENGTH_SHORT).show(); + progressLayout.setVisibility(View.GONE); } @Override public void onFailure(Call call, Throwable t) { Common.showErrorServerNotification(AccountAndProfileActivity.this); + progressLayout.setVisibility(View.GONE); } }); } diff --git a/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java b/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java index b9d4599..638ff14 100644 --- a/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java +++ b/app/src/main/java/com/capstone/foodify/Fragment/ProfileFragment.java @@ -2,6 +2,7 @@ package com.capstone.foodify.Fragment; import android.app.Dialog; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.view.LayoutInflater; import android.view.View; @@ -23,9 +24,11 @@ import com.capstone.foodify.Activity.SignUpActivity; import com.capstone.foodify.Common; import com.capstone.foodify.R; import com.google.firebase.auth.FirebaseAuth; +import com.makeramen.roundedimageview.RoundedImageView; import com.saadahmedsoft.popupdialog.PopupDialog; import com.saadahmedsoft.popupdialog.Styles; import com.saadahmedsoft.popupdialog.listener.OnDialogButtonClickListener; +import com.squareup.picasso.Picasso; import io.paperdb.Paper; @@ -33,6 +36,7 @@ public class ProfileFragment extends Fragment { LinearLayout account_and_profile, manage_address, favorite_food, order_history, log_out; PopupDialog popupDialog; TextView user_name; + RoundedImageView profile_avatar; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { @@ -46,12 +50,20 @@ public class ProfileFragment extends Fragment { order_history = rootView.findViewById(R.id.order_history); log_out = rootView.findViewById(R.id.log_out); user_name = rootView.findViewById(R.id.user_name); + profile_avatar = rootView.findViewById(R.id.profile_avatar); popupDialog = PopupDialog.getInstance(getContext()); //Set user name on textview user_name.setText(Common.CURRENT_USER.getFullName()); + //Set image for user + if(Common.CURRENT_USER.getImageUrl().isEmpty()){ + profile_avatar.setImageResource(R.drawable.profile_avatar); + } else { + Picasso.get().load(Common.CURRENT_USER.getImageUrl()).into(profile_avatar); + } + account_and_profile.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View view) { diff --git a/app/src/main/res/layout/activity_account_and_profile.xml b/app/src/main/res/layout/activity_account_and_profile.xml index eada0c1..08fcd23 100644 --- a/app/src/main/res/layout/activity_account_and_profile.xml +++ b/app/src/main/res/layout/activity_account_and_profile.xml @@ -6,185 +6,241 @@ android:layout_height="match_parent" tools:context=".Activity.AccountAndProfileActivity"> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + android:layout_marginStart="10dp" + android:layout_marginTop="25dp" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> - + - + +