diff --git a/.idea/assetWizardSettings.xml b/.idea/assetWizardSettings.xml
index c841460..1941e44 100644
--- a/.idea/assetWizardSettings.xml
+++ b/.idea/assetWizardSettings.xml
@@ -308,7 +308,7 @@
@@ -318,8 +318,8 @@
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
index ae388c2..0897082 100644
--- a/.idea/gradle.xml
+++ b/.idea/gradle.xml
@@ -4,16 +4,15 @@
diff --git a/app/build.gradle b/app/build.gradle
index 4a67d14..cc0b240 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -55,6 +55,7 @@ dependencies {
implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.6.1'
implementation 'com.google.code.gson:gson:2.10.1'
implementation 'com.squareup.retrofit2:converter-gson:2.3.0'
+ implementation "androidx.preference:preference-ktx:1.2.1"
testImplementation 'junit:junit:4.13.2'
androidTestImplementation 'androidx.test.ext:junit:1.1.5'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.5.1'
@@ -106,15 +107,19 @@ dependencies {
exclude group: 'org.json', module: 'json'
}
+ // Room Database
def room_version = "2.5.2"
-
implementation "androidx.room:room-runtime:$room_version"
annotationProcessor "androidx.room:room-compiler:$room_version"
kapt("androidx.room:room-compiler:$room_version")
implementation "androidx.room:room-ktx:2.5.2"
- implementation "androidx.preference:preference-ktx:1.2.1"
-
+ // Image viewer
implementation 'com.github.MikeOrtiz:TouchImageView:3.5'
+ // Media 3
+ implementation 'androidx.media3:media3-session:1.2.0'
+ implementation 'androidx.media3:media3-exoplayer:1.2.0'
+ implementation "androidx.media3:media3-ui:1.2.0"
+
}
\ No newline at end of file
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 81c8d25..ed37e81 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,6 +3,7 @@
xmlns:tools="http://schemas.android.com/tools">
+
{
+ initializePlayer()
+ }
+ Lifecycle.Event.ON_RESUME -> {
+ if(player == null) {
+ initializePlayer()
+ }
+ }
+ Lifecycle.Event.ON_STOP, Lifecycle.Event.ON_DESTROY -> {
+ releasePlayer()
+ }
+ else -> {}
+ }
+ }
+
+ fun playAudio(audio: Audio) {
+ mediaItem = MediaItem.fromUri(Uri.parse(audio.downloadUrl))
+
+ player?.setMediaItem(mediaItem!!)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/audio/player/PlayerFactory.kt b/app/src/main/java/com/isolaatti/audio/player/PlayerFactory.kt
new file mode 100644
index 0000000..c6f1462
--- /dev/null
+++ b/app/src/main/java/com/isolaatti/audio/player/PlayerFactory.kt
@@ -0,0 +1,7 @@
+package com.isolaatti.audio.player
+
+import androidx.media3.common.Player
+
+abstract class PlayerFactory {
+ abstract fun MakePlayer(): Player
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/audio/recorder/ui/AudioRecorderMainFragment.kt b/app/src/main/java/com/isolaatti/audio/recorder/ui/AudioRecorderMainFragment.kt
index c46b94a..77e97bb 100644
--- a/app/src/main/java/com/isolaatti/audio/recorder/ui/AudioRecorderMainFragment.kt
+++ b/app/src/main/java/com/isolaatti/audio/recorder/ui/AudioRecorderMainFragment.kt
@@ -1,6 +1,8 @@
package com.isolaatti.audio.recorder.ui
+import android.media.MediaRecorder
import androidx.fragment.app.Fragment
class AudioRecorderMainFragment : Fragment() {
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt b/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt
index 404ba06..4bcb842 100644
--- a/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt
+++ b/app/src/main/java/com/isolaatti/images/common/domain/entity/Image.kt
@@ -14,7 +14,31 @@ data class Image(
val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL)
val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED)
+
+
companion object {
fun fromDto(imageDto: ImageDto) = Image(imageDto.id, imageDto.userId, imageDto.name, imageDto.username)
}
+
+ override fun equals(other: Any?): Boolean {
+ if (this === other) return true
+ if (javaClass != other?.javaClass) return false
+
+ other as Image
+
+ if (id != other.id) return false
+ if (userId != other.userId) return false
+ if (name != other.name) return false
+ if (username != other.username) return false
+
+ return true
+ }
+
+ override fun hashCode(): Int {
+ var result = id.hashCode()
+ result = 31 * result + userId
+ result = 31 * result + name.hashCode()
+ result = 31 * result + username.hashCode()
+ return result
+ }
}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt
index ecef985..f761c35 100644
--- a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt
+++ b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImageListViewModel.kt
@@ -13,20 +13,59 @@ import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import javax.inject.Inject
+import kotlin.properties.Delegates
@HiltViewModel
class ImageListViewModel @Inject constructor(private val imagesRepository: ImagesRepository) : ViewModel() {
- val list: MutableLiveData>> = MutableLiveData()
- fun loadNext(userId: Int) {
+ val liveList: MutableLiveData> = MutableLiveData()
+ val error: MutableLiveData = MutableLiveData()
+ val loading: MutableLiveData = MutableLiveData()
+ var noMoreContent = false
+ private var loadedFirstTime = false
+ var userId by Delegates.notNull()
+
+ private val list: List get() {
+ return liveList.value ?: listOf()
+ }
+
+ private val lastId: String? get() {
+ return list.lastOrNull()?.id
+ }
+
+ fun loadNext() {
viewModelScope.launch {
- imagesRepository.getImagesOfUser(userId, null).onEach {
- list.postValue(it)
+ imagesRepository.getImagesOfUser(userId, lastId).onEach { resource ->
+ when(resource) {
+ is Resource.Error -> {
+ error.postValue(resource.errorType)
+ }
+ is Resource.Loading -> {
+ if(!loadedFirstTime) {
+ loading.postValue(true)
+ }
+ }
+ is Resource.Success -> {
+ loading.postValue(false)
+ noMoreContent = resource.data?.isEmpty() == true
+ loadedFirstTime = true
+ if(noMoreContent) {
+ return@onEach
+ }
+
+ liveList.postValue(list + (resource.data ?: listOf()))
+ }
+ }
}.flowOn(Dispatchers.IO).launchIn(this)
}
}
+ fun refresh() {
+ liveList.value = listOf()
+ loadNext()
+ }
+
fun removeImages(images: List) {
}
diff --git a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt
index 89de517..1e24295 100644
--- a/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt
+++ b/app/src/main/java/com/isolaatti/images/image_list/presentation/ImagesAdapter.kt
@@ -1,9 +1,12 @@
package com.isolaatti.images.image_list.presentation
+import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import android.widget.LinearLayout
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import androidx.recyclerview.widget.RecyclerView.Adapter
import coil.load
@@ -15,9 +18,22 @@ class ImagesAdapter(
private val imageOnClick: ((images: List, position: Int) -> Unit),
private val itemWidth: Int,
private val onImageSelectedCountUpdate: ((count: Int) -> Unit)? = null,
- private val onDeleteMode: ((enabled: Boolean) -> Unit)? = null) : Adapter(){
+ private val onDeleteMode: ((enabled: Boolean) -> Unit)? = null,
+ private val onContentRequested: (() -> Unit)? = null) : ListAdapter(diffCallback){
+
+ companion object {
+ val diffCallback = object: DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Image, newItem: Image): Boolean {
+ return oldItem.id == newItem.id
+ }
+
+ override fun areContentsTheSame(oldItem: Image, newItem: Image): Boolean {
+ return oldItem == newItem
+ }
+
+ }
+ }
- private var data: List = listOf()
private var selectionState: Array = arrayOf()
var deleteMode: Boolean = false
@@ -31,14 +47,17 @@ class ImagesAdapter(
inner class ImageViewHolder(val imageItemBinding: ImageItemBinding) : RecyclerView.ViewHolder(imageItemBinding.root)
- fun setData(data: List) {
- this.data = data
- selectionState = Array(data.size) { false }
- notifyDataSetChanged()
+ fun getSelectedImages(): List {
+ return currentList.filterIndexed { index, _ -> selectionState[index] }
}
- fun getSelectedImages(): List {
- return data.filterIndexed { index, _ -> selectionState[index] }
+ override fun onCurrentListChanged(
+ previousList: MutableList,
+ currentList: MutableList
+ ) {
+ super.onCurrentListChanged(previousList, currentList)
+ noMoreContent = (currentList.size - previousList.size) == 0
+ selectionState = Array(currentList.size) { false }
}
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ImageViewHolder {
@@ -49,12 +68,18 @@ class ImagesAdapter(
return ImageViewHolder(binding)
}
- override fun getItemCount(): Int {
- return data.size
+ private var requestedNewContent = false
+ private var noMoreContent = false
+
+ /**
+ * Call this method when new content has been added on onLoadMore() callback
+ */
+ fun newContentRequestFinished() {
+ requestedNewContent = false
}
override fun onBindViewHolder(holder: ImageViewHolder, position: Int) {
- val image = data[position]
+ val image = getItem(position)
holder.imageItemBinding.image.load(image.reducedImageUrl, imageLoader)
@@ -76,7 +101,7 @@ class ImagesAdapter(
holder.imageItemBinding.imageCheckbox.isChecked = false
holder.imageItemBinding.imageOverlay.visibility = View.GONE
holder.imageItemBinding.root.setOnClickListener {
- imageOnClick(data, position)
+ imageOnClick(currentList, position)
}
holder.imageItemBinding.imageCheckbox.setOnCheckedChangeListener(null)
holder.imageItemBinding.root.setOnLongClickListener {
@@ -86,5 +111,16 @@ class ImagesAdapter(
true
}
}
+ val totalItems = currentList.size
+ if(totalItems > 0 && !requestedNewContent && !noMoreContent) {
+ Log.d("ImagesAdapter", "Total items: $totalItems")
+ if(position == totalItems - 1) {
+ requestedNewContent = true
+ onContentRequested?.invoke()
+ }
+ }
+
}
+
+
}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt b/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt
index ce8385f..2ca4de7 100644
--- a/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt
+++ b/app/src/main/java/com/isolaatti/images/image_list/ui/ImagesFragment.kt
@@ -15,6 +15,7 @@ import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.FileProvider
import androidx.fragment.app.Fragment
+import androidx.fragment.app.activityViewModels
import androidx.fragment.app.viewModels
import androidx.navigation.fragment.findNavController
import androidx.navigation.fragment.navArgs
@@ -22,6 +23,7 @@ import androidx.recyclerview.widget.GridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.isolaatti.MyApplication
import com.isolaatti.R
+import com.isolaatti.common.ErrorMessageViewModel
import com.isolaatti.databinding.FragmentImagesBinding
import com.isolaatti.images.common.domain.entity.Image
import com.isolaatti.images.image_list.presentation.ImageListViewModel
@@ -38,6 +40,7 @@ class ImagesFragment : Fragment() {
lateinit var viewBinding: FragmentImagesBinding
lateinit var adapter: ImagesAdapter
private val viewModel: ImageListViewModel by viewModels()
+ private val errorViewModel: ErrorMessageViewModel by activityViewModels()
private val arguments: ImagesFragmentArgs by navArgs()
private var cameraPhotoUri: Uri? = null
@@ -84,7 +87,8 @@ class ImagesFragment : Fragment() {
when(arguments.source) {
SOURCE_SQUAD -> {}
SOURCE_PROFILE -> {
- viewModel.loadNext(arguments.sourceId.toInt())
+ viewModel.userId = arguments.sourceId.toInt()
+ viewModel.loadNext()
}
}
@@ -141,11 +145,7 @@ class ImagesFragment : Fragment() {
}
viewBinding.topAppBar.setOnMenuItemClickListener {
when(it.itemId) {
- R.id.delete_mode_item -> {
- adapter.deleteMode = true
- actionMode = requireActivity().startActionMode(contextBarCallback)
- true
- }
+
else -> false
}
}
@@ -170,6 +170,9 @@ class ImagesFragment : Fragment() {
popup.show()
}
+ viewBinding.swipeToRefresh.setOnRefreshListener {
+ viewModel.refresh()
+ }
}
private fun setupAdapter() {
@@ -183,6 +186,10 @@ class ImagesFragment : Fragment() {
onDeleteMode = {
adapter.deleteMode = it
actionMode = requireActivity().startActionMode(contextBarCallback)
+ },
+ onContentRequested = {
+ adapter.newContentRequestFinished()
+ viewModel.loadNext()
})
viewBinding.recyclerView.layoutManager =
GridLayoutManager(requireContext(), 3, GridLayoutManager.VERTICAL, false)
@@ -191,19 +198,23 @@ class ImagesFragment : Fragment() {
private fun setupObservers() {
- viewModel.list.observe(viewLifecycleOwner) { resource ->
- when(resource) {
- is Resource.Error -> {}
- is Resource.Loading -> {
- viewBinding.progressBarLoading.visibility = View.VISIBLE
- }
- is Resource.Success -> {
- resource.data?.let {
- viewBinding.progressBarLoading.visibility = View.GONE
- adapter.setData(it)
- }
- }
+ viewModel.liveList.observe(viewLifecycleOwner) { list ->
+ adapter.submitList(list)
+ }
+
+ viewModel.loading.observe(viewLifecycleOwner) {
+ viewBinding.progressBarLoading.visibility = if(it) {
+ View.VISIBLE
+ } else {
+ View.GONE
}
+ if(!it) {
+ viewBinding.swipeToRefresh.isRefreshing = false
+ }
+ }
+
+ viewModel.error.observe(viewLifecycleOwner) {
+ errorViewModel.error.value = it
}
}
diff --git a/app/src/main/java/com/isolaatti/profile/data/remote/ProfileApi.kt b/app/src/main/java/com/isolaatti/profile/data/remote/ProfileApi.kt
index 7ff4901..0aca5f5 100644
--- a/app/src/main/java/com/isolaatti/profile/data/remote/ProfileApi.kt
+++ b/app/src/main/java/com/isolaatti/profile/data/remote/ProfileApi.kt
@@ -1,12 +1,13 @@
package com.isolaatti.profile.data.remote
import retrofit2.Call
+import retrofit2.http.GET
import retrofit2.http.POST
import retrofit2.http.Path
interface ProfileApi {
- @POST("Fetch/UserProfile/{userId}")
+ @GET("Fetch/UserProfile/{userId}")
fun userProfile(@Path("userId") userId: Int): Call
}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/profile/data/remote/UserProfileDto.kt b/app/src/main/java/com/isolaatti/profile/data/remote/UserProfileDto.kt
index 62b74a0..63d967c 100644
--- a/app/src/main/java/com/isolaatti/profile/data/remote/UserProfileDto.kt
+++ b/app/src/main/java/com/isolaatti/profile/data/remote/UserProfileDto.kt
@@ -1,5 +1,7 @@
package com.isolaatti.profile.data.remote
+import com.isolaatti.audio.common.data.AudioDto
+
data class UserProfileDto(
val id: Int,
val name: String,
@@ -13,5 +15,6 @@ data class UserProfileDto(
val thisUserIsFollowingMe: Boolean,
val profileImageId: String?,
val descriptionText: String?,
- val descriptionAudioId: String?
+ val descriptionAudioId: String?,
+ val audio: AudioDto?
)
diff --git a/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt b/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt
index 07c90a8..6e97894 100644
--- a/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt
+++ b/app/src/main/java/com/isolaatti/profile/domain/entity/UserProfile.kt
@@ -1,5 +1,6 @@
package com.isolaatti.profile.domain.entity
+import com.isolaatti.audio.common.domain.Audio
import com.isolaatti.common.Ownable
import com.isolaatti.profile.data.remote.UserProfileDto
import com.isolaatti.utils.UrlGen
@@ -17,7 +18,8 @@ data class UserProfile(
val thisUserIsFollowingMe: Boolean,
val profileImageId: String?,
val descriptionText: String?,
- val descriptionAudioId: String?
+ val descriptionAudioId: String?,
+ val descriptionAudio: Audio?
) : Ownable {
val profileAvatarPictureUrl: String get() = UrlGen.userProfileImage(userId)
@@ -37,7 +39,8 @@ data class UserProfile(
thisUserIsFollowingMe = userProfileDto.thisUserIsFollowingMe,
profileImageId = userProfileDto.profileImageId,
descriptionText = userProfileDto.descriptionText,
- descriptionAudioId = userProfileDto.descriptionAudioId
+ descriptionAudioId = userProfileDto.descriptionAudioId,
+ descriptionAudio = userProfileDto.audio?.let { Audio.fromDto(it) }
)
}
}
diff --git a/app/src/main/java/com/isolaatti/profile/presentation/EditProfileContract.kt b/app/src/main/java/com/isolaatti/profile/presentation/EditProfileContract.kt
new file mode 100644
index 0000000..3bd5027
--- /dev/null
+++ b/app/src/main/java/com/isolaatti/profile/presentation/EditProfileContract.kt
@@ -0,0 +1,4 @@
+package com.isolaatti.profile.presentation
+
+class EditProfileContract {
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/profile/presentation/EditProfileViewModel.kt b/app/src/main/java/com/isolaatti/profile/presentation/EditProfileViewModel.kt
new file mode 100644
index 0000000..75320ae
--- /dev/null
+++ b/app/src/main/java/com/isolaatti/profile/presentation/EditProfileViewModel.kt
@@ -0,0 +1,9 @@
+package com.isolaatti.profile.presentation
+
+import androidx.lifecycle.ViewModel
+import dagger.hilt.android.lifecycle.HiltViewModel
+import javax.inject.Inject
+
+@HiltViewModel
+class EditProfileViewModel @Inject constructor(): ViewModel() {
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/profile/ui/EditProfileActivity.kt b/app/src/main/java/com/isolaatti/profile/ui/EditProfileActivity.kt
new file mode 100644
index 0000000..c1ef67c
--- /dev/null
+++ b/app/src/main/java/com/isolaatti/profile/ui/EditProfileActivity.kt
@@ -0,0 +1,19 @@
+package com.isolaatti.profile.ui
+
+import android.os.Bundle
+import com.isolaatti.common.IsolaattiBaseActivity
+import com.isolaatti.databinding.ActivityEditProfileBinding
+import dagger.hilt.android.AndroidEntryPoint
+
+@AndroidEntryPoint
+class EditProfileActivity : IsolaattiBaseActivity() {
+ private lateinit var binding: ActivityEditProfileBinding
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ binding = ActivityEditProfileBinding.inflate(layoutInflater)
+
+ setContentView(binding.root)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt
index ec605c2..54ea195 100644
--- a/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt
+++ b/app/src/main/java/com/isolaatti/profile/ui/ProfileMainFragment.kt
@@ -20,6 +20,8 @@ import coil.load
import com.isolaatti.BuildConfig
import com.isolaatti.R
import com.isolaatti.audio.audios_list.ui.AudiosFragment
+import com.isolaatti.audio.common.domain.Audio
+import com.isolaatti.audio.player.AudioPlayerConnector
import com.isolaatti.common.CoilImageLoader.imageLoader
import com.isolaatti.common.Dialogs
import com.isolaatti.common.ErrorMessageViewModel
@@ -61,6 +63,10 @@ class ProfileMainFragment : Fragment() {
lateinit var postsAdapter: PostsRecyclerViewAdapter
+ private var audioDescriptionAudio: Audio? = null
+
+ private lateinit var audioPlayerConnector: AudioPlayerConnector
+
// collapsing bar
private var title = ""
private var scrollRange = -1
@@ -103,6 +109,9 @@ class ProfileMainFragment : Fragment() {
fragment.show(parentFragmentManager, BottomSheetPostOptionsFragment.TAG)
}
+ audioDescriptionAudio = profile.descriptionAudio
+ viewBinding.playButton.visibility = if(profile.descriptionAudio != null) View.VISIBLE else View.GONE
+
setupUiForUserType(profile.isUserItself)
}
@@ -247,6 +256,11 @@ class ProfileMainFragment : Fragment() {
viewBinding.swipeToRefresh.setOnRefreshListener {
viewModel.getFeed(true)
}
+ viewBinding.playButton.setOnClickListener {
+ audioDescriptionAudio?.let { audio ->
+ audioPlayerConnector.playAudio(audio)
+ }
+ }
}
private fun setObservers() {
@@ -309,6 +323,7 @@ class ProfileMainFragment : Fragment() {
override fun onAttach(context: Context) {
super.onAttach(context)
+
postListingRecyclerViewAdapterWiring = object: PostListingRecyclerViewAdapterWiring(viewModel) {
override fun onComment(postId: Long) {
val modalBottomSheet = BottomSheetPostComments.getInstance(postId)
@@ -353,6 +368,9 @@ class ProfileMainFragment : Fragment() {
setObservers()
setupCollapsingBar()
+ audioPlayerConnector = AudioPlayerConnector(requireContext())
+
+ viewLifecycleOwner.lifecycle.addObserver(audioPlayerConnector)
viewLifecycleOwner.lifecycleScope.launch {
diff --git a/app/src/main/res/layout/activity_edit_profile.xml b/app/src/main/res/layout/activity_edit_profile.xml
new file mode 100644
index 0000000..7fd71ed
--- /dev/null
+++ b/app/src/main/res/layout/activity_edit_profile.xml
@@ -0,0 +1,6 @@
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/activity_profile.xml b/app/src/main/res/layout/activity_profile.xml
index 99ab099..f04ec22 100644
--- a/app/src/main/res/layout/activity_profile.xml
+++ b/app/src/main/res/layout/activity_profile.xml
@@ -12,5 +12,4 @@
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/profile_navigation" />
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_discussions.xml b/app/src/main/res/layout/fragment_discussions.xml
index 93f5d2f..7fc0b7a 100644
--- a/app/src/main/res/layout/fragment_discussions.xml
+++ b/app/src/main/res/layout/fragment_discussions.xml
@@ -67,16 +67,38 @@
app:layout_constraintTop_toBottomOf="@id/text_view_username"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent">
-
+
+
+
+
+
-
-
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_images.xml b/app/src/main/res/layout/fragment_images.xml
index e44cb8c..9f39046 100644
--- a/app/src/main/res/layout/fragment_images.xml
+++ b/app/src/main/res/layout/fragment_images.xml
@@ -17,12 +17,16 @@
app:navigationIconTint="@color/on_surface"
app:titleCentered="true"/>
-
-
+ app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
+
+
\ No newline at end of file
+ xmlns:app="http://schemas.android.com/apk/res-auto"/>
\ No newline at end of file