From bddf6f3fb8469fd19acfb84b2ca3797cd5943f3d Mon Sep 17 00:00:00 2001 From: Dolev Date: Wed, 12 Jun 2024 02:25:08 +0300 Subject: [PATCH 1/8] Adding profile xml file --- app/src/main/AndroidManifest.xml | 2 +- .../java/com/example/trainhub/MainActivity.kt | 58 ++++++------ app/src/main/res/layout/fragment_profile.xml | 90 ++++++++++++++++--- 3 files changed, 110 insertions(+), 40 deletions(-) diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 2d9b199..3f8aa04 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -20,7 +20,7 @@ tools:targetApi="34"> + android:value="${GOOGLE_API_KEY}" /> - when (item.itemId) { - - R.id.icHome -> { - - navController?.navigate(R.id.homeFragment) - true - } - R.id.icDiscover -> { - - navController?.navigate(R.id.discoverFragment) - true - } - R.id.icAddPost -> { - navController?.navigate(R.id.addPostFragment) - true - } - R.id.icLocation -> { - navController?.navigate(R.id.locationFragment) - true - } - R.id.icProfile -> { - navController?.navigate(R.id.profileFragment) - true - } - else -> false - - } - } +// bottomNavigationView?.setOnItemSelectedListener { item -> +// when (item.itemId) { +// +// R.id.icHome -> { +// +// navController?.navigate(R.id.homeFragment) +// true +// } +// R.id.icDiscover -> { +// +// navController?.navigate(R.id.discoverFragment) +// true +// } +// R.id.icAddPost -> { +// navController?.navigate(R.id.addPostFragment) +// true +// } +// R.id.icLocation -> { +// navController?.navigate(R.id.locationFragment) +// true +// } +// R.id.icProfile -> { +// navController?.navigate(R.id.profileFragment) +// true +// } +// else -> false +// +// } +// } } fun moveToHome(){ diff --git a/app/src/main/res/layout/fragment_profile.xml b/app/src/main/res/layout/fragment_profile.xml index bf4f116..d0cbe09 100644 --- a/app/src/main/res/layout/fragment_profile.xml +++ b/app/src/main/res/layout/fragment_profile.xml @@ -1,19 +1,89 @@ - - + + + + + + + + + + + android:layout_height="wrap_content" + android:layout_marginTop="60dp" + android:text="My Posts" + android:textSize="20sp" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.0" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@+id/tvAddress" /> - \ No newline at end of file + + \ No newline at end of file From 26a24e390e217c0da08ccfe0405d9b98519edb81 Mon Sep 17 00:00:00 2001 From: Dolev Date: Tue, 18 Jun 2024 17:37:34 +0300 Subject: [PATCH 2/8] adding clickable item to user post --- .../example/trainhub/PostFireBaseModelTest.kt | 106 --------------- .../example/trainhub/UserFirebaseModelTest.kt | 124 ------------------ .../trainhub/adapters/PostRecyclerAdapter.kt | 14 +- .../trainhub/fragments/HomeFragment.kt | 2 +- app/src/main/res/values/ids.xml | 4 + 5 files changed, 18 insertions(+), 232 deletions(-) delete mode 100644 app/src/androidTest/java/com/example/trainhub/PostFireBaseModelTest.kt delete mode 100644 app/src/androidTest/java/com/example/trainhub/UserFirebaseModelTest.kt create mode 100644 app/src/main/res/values/ids.xml diff --git a/app/src/androidTest/java/com/example/trainhub/PostFireBaseModelTest.kt b/app/src/androidTest/java/com/example/trainhub/PostFireBaseModelTest.kt deleted file mode 100644 index a4d2777..0000000 --- a/app/src/androidTest/java/com/example/trainhub/PostFireBaseModelTest.kt +++ /dev/null @@ -1,106 +0,0 @@ -package com.example.trainhub - - -import com.example.trainhub.models.entities.Post -import com.example.trainhub.models.fireBaseModels.PostFireBaseModel -import org.junit.Test -import org.junit.Assert.* -import java.util.concurrent.CountDownLatch -import java.util.concurrent.TimeUnit - -class PostFirebaseModelTask{ - - private val PostFireBaseModel = PostFireBaseModel() - private val id = "Another Test" - private val title = "asdfasd Test 2" - private val description = " asdfdasf updated 2" - private val imageUrl = " asdfasdf Test " - private val userId = "Test User Id" - private val workoutCategory = "Test Workout Category ddd 2" - private val location = "Test Location ddasd 2" - private val lastUpdated: Long? = null - - @Test - fun addPost(){ - val post = Post(id,title, description, imageUrl, userId, workoutCategory, location) - var result: Boolean? = null - val latch = CountDownLatch(1) - - PostFireBaseModel.addPostDocument(post){ isAddedToFireStore-> - result = isAddedToFireStore - latch.countDown() - } - - latch.await(5, TimeUnit.SECONDS) - assertEquals(true, result) - } - - @Test - fun updatePost(){ - val post = Post("test id",title, description, imageUrl, userId, workoutCategory, location) - var result: Boolean? = null - val latch = CountDownLatch(1) - - PostFireBaseModel.updatePostDocument(post){ isUpdatedInFireStore-> - result = isUpdatedInFireStore - latch.countDown() - } - - latch.await(5, TimeUnit.SECONDS) - assertEquals(true, result) - } - - @Test - fun deletePost(){ - val post = Post("test id",title, description, imageUrl, userId, workoutCategory, location) - var result: Boolean? = null - val latch = CountDownLatch(1) - - PostFireBaseModel.deletePostDocument(post){ isDeletedFromFireStore-> - result = isDeletedFromFireStore - latch.countDown() - } - - latch.await(5, TimeUnit.SECONDS) - assertEquals(true, result) - } - - @Test - fun getAllPosts(){ - var result: List? = null - val latch = CountDownLatch(1) - - PostFireBaseModel.getAllPostsDocument{ posts-> - result = posts - latch.countDown() - } - - latch.await(5, TimeUnit.SECONDS) - println("TEST GET ALL POSTS") - println("-------------------") - println(result) - println("-------------------") - assertNotNull(result) - } - - @Test - fun getPostsByUid(){ - var result: List? = null - val latch = CountDownLatch(1) - - PostFireBaseModel.getPostsByUid(userId){ posts-> - result = posts - latch.countDown() - } - - latch.await(5, TimeUnit.SECONDS) - println("TEST GET ALL POSTS OF USER ID") - println("-------------------") - println(result) - println(result?.size) - println("-------------------") - assertNotNull(result) - } - - -} \ No newline at end of file diff --git a/app/src/androidTest/java/com/example/trainhub/UserFirebaseModelTest.kt b/app/src/androidTest/java/com/example/trainhub/UserFirebaseModelTest.kt deleted file mode 100644 index 45aef92..0000000 --- a/app/src/androidTest/java/com/example/trainhub/UserFirebaseModelTest.kt +++ /dev/null @@ -1,124 +0,0 @@ -//import android.content.ContentValues.TAG -//import android.nfc.Tag -//import android.util.Log -//import com.example.trainhub.models.entities.User -//import kotlinx.coroutines.runBlocking -//import org.junit.Test -//import org.junit.Assert.* -//import com.example.trainhub.models.fireBaseModels.UserFireBaseModel -//import com.google.firebase.auth.FirebaseAuth -//import com.google.firebase.auth.FirebaseUser -//import com.google.protobuf.Internal.BooleanList -//import java.util.Date -//import java.util.concurrent.CountDownLatch -//import java.util.concurrent.TimeUnit -// -//class UserFirebaseModelTask { -// -// -// private val userFbModel: UserFireBaseModel = UserFireBaseModel() -// private val email: String = "test@test.com" -// private val password: String = "123456" -// private val latch = CountDownLatch(1) -// private val uid: String? = null -// private val user: User? = null -// private var userAuth: FirebaseUser?= null -// -// @Test -// fun addition_isCorrect() { -// assertEquals(4, 2 + 2) -// } -// -// @Test -// fun testRegisterSuccess() { -// val latch = CountDownLatch(1) -// var result: String? = null -// var uid: String? = null -// -// userFbModel.register(email, password) { uidResult -> -// println("======= Success UID: $uidResult") -//// userAuth = result -// uid = uidResult -// latch.countDown() -// } -// -// latch.await(5, TimeUnit.SECONDS) // wait for the callback -// assertNotNull(uid) -// } -// -// @Test -// fun testSignInSuccess(){ -// var result: Boolean = false -// userFbModel.signIn(email,password){ signedIn -> -// if(signedIn) -// result = true -// latch.countDown() -// } -// val success = latch.await(5, TimeUnit.SECONDS) -// -// assertEquals(true, success) -// assertEquals(true, result != null) -// -// Log.i(TAG,"Test signInSuccess UID: $result") -// } -// -// @Test -// fun testAddUserSuccess() { -// val newUser = User( -// id = "testUid", -// email = email, -//// password = password, -// profileImageUrl = "test_profile_image_url", -// lastUpdated = System.currentTimeMillis() -// ) -// -// val latch = CountDownLatch(1) -// var result: Boolean? = null -// -// userFbModel.addUserDocument(newUser) { success -> -// result = success -// latch.countDown() -// } -// -// latch.await(5, TimeUnit.SECONDS) // wait for the callback -// -// assertEquals(true, result) -// } -// -// @Test -// fun testRegisterFailure() { -// val userFbModel = UserFireBaseModel() -// val email = "invalidemail" -// val password = "123" -// val latch = CountDownLatch(1) -// var result: String? = null -// -// userFbModel.register(email, password) { -//// result = it -// latch.countDown() -// } -// -// latch.await(5, TimeUnit.SECONDS) // wait for the callback -// -// assertNull(result) -// } -// -// @Test -// fun testDeleteUserAuth(){ -// var result: Boolean = false -// val latch = CountDownLatch(1) -// userFbModel.deleteUserAuth() { -// result = true -// latch.countDown() -// } -// latch.await(5, TimeUnit.SECONDS) -// assertEquals(true, result) -// } -// -// @Test -// fun f(){ -// testRegisterSuccess() -// testDeleteUserAuth() -// } -// -//} diff --git a/app/src/main/java/com/example/trainhub/adapters/PostRecyclerAdapter.kt b/app/src/main/java/com/example/trainhub/adapters/PostRecyclerAdapter.kt index a2c51b8..0defab5 100644 --- a/app/src/main/java/com/example/trainhub/adapters/PostRecyclerAdapter.kt +++ b/app/src/main/java/com/example/trainhub/adapters/PostRecyclerAdapter.kt @@ -15,14 +15,17 @@ import com.example.trainhub.viewModel.PostWithUser import com.google.firebase.ktx.Firebase import com.google.firebase.storage.ktx.storage -class PostRecyclerAdapter(var posts: List) : +class PostRecyclerAdapter(var posts: List, private var isClickable:Boolean) : + RecyclerView.Adapter() { val storage = Firebase.storage inner class PostViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) { + val profileImg: ImageFilterView = itemView.findViewById(R.id.ifPostProfileImg) val titleTextView: TextView = itemView.findViewById(R.id.tvCardTitle) val descriptionTextView: TextView = itemView.findViewById(R.id.tvDescription) val postImg: ImageView = itemView.findViewById(R.id.ifPostImg) + } override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): PostViewHolder { @@ -45,6 +48,15 @@ class PostRecyclerAdapter(var posts: List) : .load(currentItem.user?.profileImageUrl) .into(holder.profileImg) Log.d(TAG,"PROFILE IMAGE: profile_images/${currentItem.user?.profileImageUrl}") + + + if (isClickable) { + holder.itemView.setOnClickListener { + Log.d("post", "Item clicked: ${currentItem.post.title}") + } + + } + } override fun getItemCount(): Int { diff --git a/app/src/main/java/com/example/trainhub/fragments/HomeFragment.kt b/app/src/main/java/com/example/trainhub/fragments/HomeFragment.kt index 4cf7327..170c86e 100644 --- a/app/src/main/java/com/example/trainhub/fragments/HomeFragment.kt +++ b/app/src/main/java/com/example/trainhub/fragments/HomeFragment.kt @@ -42,7 +42,7 @@ class HomeFragment : Fragment() , SwipeRefreshLayout.OnRefreshListener{ } postsRecyclerView?.layoutManager = LinearLayoutManager(context) - postAdapter = PostRecyclerAdapter(listOf()) + postAdapter = PostRecyclerAdapter(listOf(), false) postsRecyclerView?.adapter = postAdapter return view diff --git a/app/src/main/res/values/ids.xml b/app/src/main/res/values/ids.xml new file mode 100644 index 0000000..e82015d --- /dev/null +++ b/app/src/main/res/values/ids.xml @@ -0,0 +1,4 @@ + + + + \ No newline at end of file From 28ff6e8fd487712462eb2f5455c07c0bf53d8ecb Mon Sep 17 00:00:00 2001 From: Dolev Date: Wed, 19 Jun 2024 15:43:57 +0300 Subject: [PATCH 3/8] adding edit profile fragment --- .../java/com/example/trainhub/MainActivity.kt | 7 ++ .../trainhub/fragments/EditProfileFragment.kt | 20 ++++ .../trainhub/fragments/ProfileFragment.kt | 43 ++++++- .../trainhub/viewModel/ProfileViewModel.kt | 31 +++++ .../res/layout/dialog_update_password.xml | 109 ++++++++++++++++++ .../main/res/layout/fragment_edit_profile.xml | 85 ++++++++++++++ app/src/main/res/layout/fragment_profile.xml | 65 +++++------ app/src/main/res/navigation/nav_graph.xml | 8 ++ 8 files changed, 333 insertions(+), 35 deletions(-) create mode 100644 app/src/main/java/com/example/trainhub/fragments/EditProfileFragment.kt create mode 100644 app/src/main/java/com/example/trainhub/viewModel/ProfileViewModel.kt create mode 100644 app/src/main/res/layout/dialog_update_password.xml create mode 100644 app/src/main/res/layout/fragment_edit_profile.xml diff --git a/app/src/main/java/com/example/trainhub/MainActivity.kt b/app/src/main/java/com/example/trainhub/MainActivity.kt index 49476ab..025d581 100644 --- a/app/src/main/java/com/example/trainhub/MainActivity.kt +++ b/app/src/main/java/com/example/trainhub/MainActivity.kt @@ -10,6 +10,7 @@ import androidx.navigation.Navigation import androidx.navigation.fragment.NavHostFragment import com.example.trainhub.fragments.AddPostFragment import com.example.trainhub.fragments.DiscoverFragment +import com.example.trainhub.fragments.EditProfileFragment import com.example.trainhub.fragments.HomeFragment import com.example.trainhub.fragments.LocationFragment import com.example.trainhub.fragments.ProfileFragment @@ -23,6 +24,7 @@ class MainActivity : AppCompatActivity() { private val locationFragment = LocationFragment() private val profileFragment = ProfileFragment() private val addPostFragment = AddPostFragment() + private val editProfileFragment = EditProfileFragment() private var bottomNavigationView:BottomNavigationView? = null override fun onCreate(savedInstanceState: Bundle?) { @@ -88,6 +90,11 @@ class MainActivity : AppCompatActivity() { // } } + fun moveToEditProfile(){ + val activity = this + activity.replaceFragment(editProfileFragment) + } + fun moveToHome(){ bottomNavigationView?.selectedItemId = R.id.icHome replaceFragment(homeFragment) diff --git a/app/src/main/java/com/example/trainhub/fragments/EditProfileFragment.kt b/app/src/main/java/com/example/trainhub/fragments/EditProfileFragment.kt new file mode 100644 index 0000000..2ba3e7c --- /dev/null +++ b/app/src/main/java/com/example/trainhub/fragments/EditProfileFragment.kt @@ -0,0 +1,20 @@ +package com.example.trainhub.fragments +import android.os.Bundle +import androidx.fragment.app.Fragment +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import com.example.trainhub.R + + +class EditProfileFragment : Fragment() { + + override fun onCreateView( + inflater: LayoutInflater, container: ViewGroup?, + savedInstanceState: Bundle? + ): View? { + return inflater.inflate(R.layout.fragment_edit_profile, container, false) + } + + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/trainhub/fragments/ProfileFragment.kt b/app/src/main/java/com/example/trainhub/fragments/ProfileFragment.kt index c4a69c6..dae45ce 100644 --- a/app/src/main/java/com/example/trainhub/fragments/ProfileFragment.kt +++ b/app/src/main/java/com/example/trainhub/fragments/ProfileFragment.kt @@ -1,22 +1,61 @@ package com.example.trainhub.fragments import android.os.Bundle +import android.util.Log import androidx.fragment.app.Fragment import android.view.LayoutInflater import android.view.View import android.view.ViewGroup +import android.widget.TextView +import androidx.navigation.NavDirections +import androidx.navigation.fragment.findNavController +import androidx.recyclerview.widget.LinearLayoutManager +import androidx.recyclerview.widget.RecyclerView +import com.example.trainhub.MainActivity import com.example.trainhub.R +import com.example.trainhub.TrainHubApplication +import com.example.trainhub.adapters.PostRecyclerAdapter +import com.example.trainhub.viewModel.PostWithUser +import com.example.trainhub.viewModel.ProfileViewModel class ProfileFragment : Fragment() { + private lateinit var recyclerViewPosts: RecyclerView + private lateinit var postsAdapter: PostRecyclerAdapter + private var editProfile: TextView? = null + private var postsList: List = listOf() + private val profileViewModel: ProfileViewModel = ProfileViewModel() + override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - // Inflate the layout for this fragment - return inflater.inflate(R.layout.fragment_profile, container, false) + val view = inflater.inflate(R.layout.fragment_profile, container, false) + recyclerViewPosts = view.findViewById(R.id.rvMyPosts) + recyclerViewPosts.layoutManager = LinearLayoutManager(context) + postsAdapter = PostRecyclerAdapter(postsList,true) + recyclerViewPosts.adapter = postsAdapter + + profileViewModel.fetchPosts() + profileViewModel.posts.observe(viewLifecycleOwner) {posts-> + val userPosts = posts.filter { it.post.userId == TrainHubApplication.Globals.currentUser?.id } + + postsAdapter.posts = userPosts + postsAdapter.notifyDataSetChanged() + } + + editProfile = view.findViewById(R.id.edit_profile) + editProfile?.setOnClickListener { + val activity = context as MainActivity + activity.moveToEditProfile() + + } + + return view + } + } \ No newline at end of file diff --git a/app/src/main/java/com/example/trainhub/viewModel/ProfileViewModel.kt b/app/src/main/java/com/example/trainhub/viewModel/ProfileViewModel.kt new file mode 100644 index 0000000..f64f06b --- /dev/null +++ b/app/src/main/java/com/example/trainhub/viewModel/ProfileViewModel.kt @@ -0,0 +1,31 @@ +package com.example.trainhub.viewModel + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import com.example.trainhub.models.PostModel +import com.example.trainhub.models.UserModel + +class ProfileViewModel: ViewModel() { + private val um: UserModel = UserModel.instance + private val pm: PostModel = PostModel.instance + + private val _posts = MutableLiveData>() + val posts: LiveData> get() = _posts + + fun fetchPosts() { + pm.getAllPosts { posts-> + val postWithUserList = mutableListOf() + posts?.forEach { post-> + um.getUserById(post.userId) { user-> + postWithUserList.add(PostWithUser(post, user)) + _posts.value = postWithUserList + } + } + } + + } + + + +} \ No newline at end of file diff --git a/app/src/main/res/layout/dialog_update_password.xml b/app/src/main/res/layout/dialog_update_password.xml new file mode 100644 index 0000000..5b55a5b --- /dev/null +++ b/app/src/main/res/layout/dialog_update_password.xml @@ -0,0 +1,109 @@ + + + + + + + + + + + + + + + + + + + +