diff --git a/app/src/main/java/com/example/nasa_mars_api_service/core/Mapping.kt b/app/src/main/java/com/example/nasa_mars_api_service/core/Mapping.kt index e3ad5fb..4b03e74 100644 --- a/app/src/main/java/com/example/nasa_mars_api_service/core/Mapping.kt +++ b/app/src/main/java/com/example/nasa_mars_api_service/core/Mapping.kt @@ -223,4 +223,28 @@ fun MarsPhoto.isFavourite(): MarsPhoto { launchDate, status ) +} + +fun PictureOfDayPhoto.isNotFavourite(): PictureOfDayPhoto { + return PictureOfDayPhoto( + id, + author, + title, + description, + date, + false, + imageSrc + ) +} + +fun PictureOfDayPhoto.isFavourite(): PictureOfDayPhoto { + return PictureOfDayPhoto( + id, + author, + title, + description, + date, + true, + imageSrc + ) } \ No newline at end of file diff --git a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayFragment.kt b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayFragment.kt index aac5742..bfe9363 100644 --- a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayFragment.kt +++ b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayFragment.kt @@ -1,6 +1,28 @@ package com.example.nasa_mars_api_service.ui.fragment.image_of_day_description +import android.os.Bundle +import android.view.LayoutInflater +import android.view.View +import android.view.ViewGroup +import android.widget.Toast +import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment +import androidx.lifecycle.Observer +import androidx.lifecycle.ViewModelProvider +import androidx.navigation.fragment.findNavController +import com.bumptech.glide.Glide +import com.bumptech.glide.load.resource.drawable.DrawableTransitionOptions.withCrossFade +import com.example.nasa_mars_api_service.R +import com.example.nasa_mars_api_service.core.enums.PhotoTypes +import com.example.nasa_mars_api_service.core.getBaseRequestOptions +import com.example.nasa_mars_api_service.core.models.PictureOfDayPhoto +import com.example.nasa_mars_api_service.database.db.MainDatabase +import com.example.nasa_mars_api_service.databinding.FragmentImageOfDayDescriptionBinding +import com.example.nasa_mars_api_service.network.api.MarsPhotosApi +import com.example.nasa_mars_api_service.preferences.implementations.AppPreferences +import com.example.nasa_mars_api_service.preferences.interfaces.BaseApplicationPreferences +import com.example.nasa_mars_api_service.repository.implementations.MainRepository +import com.example.nasa_mars_api_service.repository.interfaces.BaseRepository /** * Created by Matvey Popov. @@ -9,5 +31,113 @@ import androidx.fragment.app.Fragment * Project: NASA-Mars-API-Service */ class ImageOfDayFragment: Fragment() { + private lateinit var binding: FragmentImageOfDayDescriptionBinding + private lateinit var viewModel: ImageOfDayViewModel + + + override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View? { + binding = DataBindingUtil.inflate(inflater, R.layout.fragment_image_of_day_description, container, false) + + getViewModel() + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + setAllClickListeners() + setAllObservers() + getImageOfDay() + } + + private fun getViewModel() { + val context = requireContext() + val preferences: BaseApplicationPreferences = AppPreferences.getInstance(context) + val dataBase = MainDatabase.getInstance(context) + val remoteSource = MarsPhotosApi.marsPhotosService + val repository: BaseRepository = MainRepository.getInstance( + dataBase.marsPhotoDao, + dataBase.favoritePhotoDao, + dataBase.pictureOfDayDao, + remoteSource, + preferences + ) + + val factory = ImageOfDayViewModelFactory(repository) + viewModel = ViewModelProvider(this, factory).get(ImageOfDayViewModel::class.java) + } + + private fun setAllClickListeners() { + binding.appBar.setNavigationOnClickListener { + findNavController().popBackStack() + } + + binding.imageView.setOnClickListener { + val args = ImageOfDayFragmentArgs.fromBundle(requireArguments()) + val id = args.id + findNavController().navigate(ImageOfDayFragmentDirections.actionImageOfDayFragmentToPhotoViewFragment(id, PhotoTypes.PICTURE_OF_DAY)) + } + + binding.appBar.setOnMenuItemClickListener { + when(viewModel.imageOfDay.value?.isFavourite) { + true -> { + viewModel.removeImageOfDayFromFavourites() + true + } + false -> { + viewModel.addImageOfDayToFavourites() + true + } + else -> { + false + } + } + } + } + + private fun setAllObservers() { + viewModel.errorMessage.observe(viewLifecycleOwner, Observer { newMessage -> + if (newMessage != null) { + showErrorMessage(newMessage) + } + }) + + viewModel.imageOfDay.observe(viewLifecycleOwner, Observer { image -> + startLoadingImage(image) + setAllFields(image) + }) + } + + private fun startLoadingImage(image: PictureOfDayPhoto) { + val src = image.imageSrc + val options = getBaseRequestOptions() + Glide.with(binding.imageView) + .applyDefaultRequestOptions(options) + .load(src) + .transition(withCrossFade()) + .into(binding.imageView) + } + + private fun setAllFields(image: PictureOfDayPhoto) { + binding.authorTextView.text = image.author + binding.dateTextView.text = image.date + binding.titleTextView.text = image.title + binding.descriptionTextView.text = image.description + when(image.isFavourite) { + true -> binding.appBar.menu.getItem(0).setIcon(R.drawable.ic_star__filled) + false -> binding.appBar.menu.getItem(0).setIcon(R.drawable.ic_star) + } + } + + private fun showErrorMessage(message: String) { + val context = requireContext() + Toast.makeText(context, "Something went wrong: $message", Toast.LENGTH_SHORT).show() + } + + private fun getImageOfDay() { + val args = ImageOfDayFragmentArgs.fromBundle(requireArguments()) + val id = args.id + viewModel.getImageOfDay(id) + } } \ No newline at end of file diff --git a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModel.kt b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModel.kt new file mode 100644 index 0000000..201434e --- /dev/null +++ b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModel.kt @@ -0,0 +1,71 @@ +package com.example.nasa_mars_api_service.ui.fragment.image_of_day_description + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import androidx.lifecycle.ViewModel +import androidx.lifecycle.viewModelScope +import com.example.nasa_mars_api_service.core.isFavourite +import com.example.nasa_mars_api_service.core.isNotFavourite +import com.example.nasa_mars_api_service.core.models.PictureOfDayPhoto +import com.example.nasa_mars_api_service.repository.interfaces.BaseRepository +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import timber.log.Timber + +/** + * Created by Matvey Popov. + * Date: 12.01.2021 + * Time: 14:07 + * Project: NASA-Mars-API-Service + */ +class ImageOfDayViewModel( + private val repository: BaseRepository +): ViewModel() { + private val _imageOfDay: MutableLiveData = MutableLiveData() + val imageOfDay: LiveData + get() = _imageOfDay + + private val _errorMessage: MutableLiveData = MutableLiveData(null) + val errorMessage: LiveData + get() = _errorMessage + + + fun getImageOfDay(id: Int) { + viewModelScope.launch(Dispatchers.IO) { + try { + val result = repository.getPictureOfDayFromCash(id) + _imageOfDay.postValue(result) + } + catch (ex: Exception) { + Timber.e(ex) + _errorMessage.postValue(ex.message) + } + } + } + + fun removeImageOfDayFromFavourites() { + viewModelScope.launch(Dispatchers.IO) { + try { + repository.deleteFavouritePhoto(imageOfDay.value!!) + _imageOfDay.postValue(imageOfDay.value!!.isNotFavourite()) + } + catch (ex: Exception) { + Timber.e(ex) + _errorMessage.postValue(ex.message) + } + } + } + + fun addImageOfDayToFavourites() { + viewModelScope.launch(Dispatchers.IO) { + try { + repository.addPhotoToFavourite(imageOfDay.value!!) + _imageOfDay.postValue(imageOfDay.value!!.isFavourite()) + } + catch (ex: Exception) { + Timber.e(ex) + _errorMessage.postValue(ex.message) + } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModelFactory.kt b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModelFactory.kt new file mode 100644 index 0000000..9e19c68 --- /dev/null +++ b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/image_of_day_description/ImageOfDayViewModelFactory.kt @@ -0,0 +1,26 @@ +package com.example.nasa_mars_api_service.ui.fragment.image_of_day_description + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import com.example.nasa_mars_api_service.repository.interfaces.BaseRepository +import com.example.nasa_mars_api_service.ui.fragment.ViewModelFactory + +/** + * Created by Matvey Popov. + * Date: 12.01.2021 + * Time: 14:07 + * Project: NASA-Mars-API-Service + */ +class ImageOfDayViewModelFactory( + private val repository: BaseRepository +): ViewModelProvider.Factory { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + if (modelClass.isAssignableFrom(ImageOfDayViewModel::class.java)) { + return ImageOfDayViewModel(repository) as T + } + throw IllegalArgumentException("Unexpected View Model to create: $modelClass") + } + +} \ No newline at end of file diff --git a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/main_list/MainListFragment.kt b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/main_list/MainListFragment.kt index 6f4a45f..5918dfe 100644 --- a/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/main_list/MainListFragment.kt +++ b/app/src/main/java/com/example/nasa_mars_api_service/ui/fragment/main_list/MainListFragment.kt @@ -1,19 +1,15 @@ package com.example.nasa_mars_api_service.ui.fragment.main_list import android.os.Bundle -import android.util.Log import android.view.LayoutInflater import android.view.View import android.view.ViewGroup -import android.widget.LinearLayout import android.widget.Toast import androidx.databinding.DataBindingUtil import androidx.fragment.app.Fragment import androidx.lifecycle.Observer import androidx.lifecycle.ViewModelProvider import androidx.navigation.fragment.findNavController -import androidx.recyclerview.widget.LinearLayoutManager -import androidx.recyclerview.widget.RecyclerView import com.example.nasa_mars_api_service.R import com.example.nasa_mars_api_service.core.Variables import com.example.nasa_mars_api_service.core.enums.PhotoTypes diff --git a/app/src/main/res/layout/fragment_image_of_day_description.xml b/app/src/main/res/layout/fragment_image_of_day_description.xml index e4596cd..cb77af8 100644 --- a/app/src/main/res/layout/fragment_image_of_day_description.xml +++ b/app/src/main/res/layout/fragment_image_of_day_description.xml @@ -16,7 +16,7 @@ app:liftOnScroll="true">