WIP subir foto
This commit is contained in:
parent
1cca08df0b
commit
5992f2a07a
@ -1,12 +1,17 @@
|
|||||||
package com.isolaatti.images
|
package com.isolaatti.images
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.content.Context
|
||||||
|
import com.isolaatti.MyApplication
|
||||||
import com.isolaatti.connectivity.RetrofitClient
|
import com.isolaatti.connectivity.RetrofitClient
|
||||||
import com.isolaatti.images.image_list.data.remote.ImagesApi
|
import com.isolaatti.images.common.data.remote.ImagesApi
|
||||||
import com.isolaatti.images.image_list.data.repository.ImagesRepositoryImpl
|
import com.isolaatti.images.common.data.repository.ImagesRepositoryImpl
|
||||||
import com.isolaatti.images.image_list.domain.repository.ImagesRepository
|
import com.isolaatti.images.common.domain.repository.ImagesRepository
|
||||||
import dagger.Module
|
import dagger.Module
|
||||||
import dagger.Provides
|
import dagger.Provides
|
||||||
import dagger.hilt.InstallIn
|
import dagger.hilt.InstallIn
|
||||||
|
import dagger.hilt.android.qualifiers.ApplicationContext
|
||||||
import dagger.hilt.components.SingletonComponent
|
import dagger.hilt.components.SingletonComponent
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
@ -18,7 +23,12 @@ class Module {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
fun provideImagesRepository(imagesApi: ImagesApi): ImagesRepository {
|
fun provideContentResolver(@ApplicationContext application: Context): ContentResolver {
|
||||||
return ImagesRepositoryImpl(imagesApi)
|
return application.contentResolver
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
fun provideImagesRepository(imagesApi: ImagesApi, contentResolver: ContentResolver): ImagesRepository {
|
||||||
|
return ImagesRepositoryImpl(imagesApi, contentResolver)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.isolaatti.images.image_list.data.remote
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
data class DeleteImagesDto(
|
data class DeleteImagesDto(
|
||||||
val imageIds: List<String>
|
val imageIds: List<String>
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.isolaatti.images.image_list.data.remote
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
data class DeleteImagesResultDto(
|
data class DeleteImagesResultDto(
|
||||||
val success: Boolean,
|
val success: Boolean,
|
||||||
@ -1,4 +1,4 @@
|
|||||||
package com.isolaatti.images.image_list.data.remote
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
data class ImageDto(
|
data class ImageDto(
|
||||||
val id: String,
|
val id: String,
|
||||||
@ -1,6 +1,7 @@
|
|||||||
package com.isolaatti.images.image_list.data.remote
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
import com.isolaatti.utils.SimpleData
|
import com.isolaatti.utils.SimpleData
|
||||||
|
import okhttp3.MultipartBody
|
||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import retrofit2.Call
|
import retrofit2.Call
|
||||||
import retrofit2.http.Body
|
import retrofit2.http.Body
|
||||||
@ -19,7 +20,7 @@ interface ImagesApi {
|
|||||||
|
|
||||||
@POST("images/create")
|
@POST("images/create")
|
||||||
@Multipart
|
@Multipart
|
||||||
fun postImage(@Part("file") file: RequestBody,
|
fun postImage(@Part file: MultipartBody.Part,
|
||||||
@Part("name") name: String,
|
@Part("name") name: String,
|
||||||
@Part("setAsProfile") setAsProfile: Boolean? = null,
|
@Part("setAsProfile") setAsProfile: Boolean? = null,
|
||||||
@Part("squadId") squadId: String? = null): Call<ImageDto>
|
@Part("squadId") squadId: String? = null): Call<ImageDto>
|
||||||
@ -0,0 +1,5 @@
|
|||||||
|
package com.isolaatti.images.common.data.remote
|
||||||
|
|
||||||
|
data class ImagesDto(
|
||||||
|
val data: List<ImageDto>
|
||||||
|
)
|
||||||
@ -0,0 +1,76 @@
|
|||||||
|
package com.isolaatti.images.common.data.repository
|
||||||
|
|
||||||
|
import android.content.ContentResolver
|
||||||
|
import android.net.Uri
|
||||||
|
import android.util.Log
|
||||||
|
import com.isolaatti.images.common.data.remote.ImagesApi
|
||||||
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
|
import com.isolaatti.images.common.domain.repository.ImagesRepository
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
import kotlinx.coroutines.flow.flow
|
||||||
|
import okhttp3.MultipartBody
|
||||||
|
import okhttp3.RequestBody
|
||||||
|
import okhttp3.RequestBody.Companion.toRequestBody
|
||||||
|
import retrofit2.awaitResponse
|
||||||
|
import java.io.InputStream
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
class ImagesRepositoryImpl @Inject constructor(private val imagesApi: ImagesApi, private val contentResolver: ContentResolver) :
|
||||||
|
ImagesRepository {
|
||||||
|
override fun getImagesOfUser(userId: Int, lastId: String?): Flow<Resource<List<Image>>> = flow {
|
||||||
|
emit(Resource.Loading())
|
||||||
|
try {
|
||||||
|
val response = imagesApi.getImagesOfUser(userId, lastId).awaitResponse()
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
val imagesDto = response.body()
|
||||||
|
val images = imagesDto?.data?.map { Image.fromDto(it) }
|
||||||
|
|
||||||
|
emit(Resource.Success(images))
|
||||||
|
|
||||||
|
} else {
|
||||||
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
|
}
|
||||||
|
} catch(_: Exception) {
|
||||||
|
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun deleteImages(images: List<Image>): Flow<Resource<Boolean>> = flow {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun uploadImage(name: String, imageUri: Uri, squadId: String?): Flow<Resource<Image>> = flow {
|
||||||
|
var imageInputStream: InputStream? = null
|
||||||
|
try {
|
||||||
|
imageInputStream = contentResolver.openInputStream(imageUri)
|
||||||
|
val imageBytes = imageInputStream?.readBytes()
|
||||||
|
|
||||||
|
if(imageBytes == null) {
|
||||||
|
emit(Resource.Error(Resource.Error.ErrorType.InputError))
|
||||||
|
return@flow
|
||||||
|
}
|
||||||
|
|
||||||
|
Log.d("ImagesRepository", "${imageBytes.size} bytes")
|
||||||
|
|
||||||
|
val response = imagesApi.postImage(MultipartBody.Part.createFormData("file", name,imageBytes.toRequestBody()), name).awaitResponse()
|
||||||
|
if(response.isSuccessful) {
|
||||||
|
val imageDto = response.body()
|
||||||
|
if(imageDto == null) {
|
||||||
|
emit(Resource.Error(Resource.Error.ErrorType.ServerError))
|
||||||
|
return@flow
|
||||||
|
}
|
||||||
|
val image = Image.fromDto(imageDto)
|
||||||
|
emit(Resource.Success(image))
|
||||||
|
} else {
|
||||||
|
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
||||||
|
}
|
||||||
|
|
||||||
|
} catch(e: Exception) {
|
||||||
|
Log.e("ImagesRepository", e.toString())
|
||||||
|
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
||||||
|
} finally {
|
||||||
|
imageInputStream?.close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,6 +1,6 @@
|
|||||||
package com.isolaatti.images.image_list.domain.entity
|
package com.isolaatti.images.common.domain.entity
|
||||||
|
|
||||||
import com.isolaatti.images.image_list.data.remote.ImageDto
|
import com.isolaatti.images.common.data.remote.ImageDto
|
||||||
import com.isolaatti.utils.UrlGen
|
import com.isolaatti.utils.UrlGen
|
||||||
import java.io.Serializable
|
import java.io.Serializable
|
||||||
|
|
||||||
@ -1,10 +1,12 @@
|
|||||||
package com.isolaatti.images.image_list.domain.repository
|
package com.isolaatti.images.common.domain.repository
|
||||||
|
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import android.net.Uri
|
||||||
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.utils.Resource
|
import com.isolaatti.utils.Resource
|
||||||
import kotlinx.coroutines.flow.Flow
|
import kotlinx.coroutines.flow.Flow
|
||||||
|
|
||||||
interface ImagesRepository {
|
interface ImagesRepository {
|
||||||
fun getImagesOfUser(userId: Int, lastId: String? = null): Flow<Resource<List<Image>>>
|
fun getImagesOfUser(userId: Int, lastId: String? = null): Flow<Resource<List<Image>>>
|
||||||
fun deleteImages(images: List<Image>): Flow<Resource<Boolean>>
|
fun deleteImages(images: List<Image>): Flow<Resource<Boolean>>
|
||||||
|
fun uploadImage(name: String, imageUri: Uri, squadId: String?): Flow<Resource<Image>>
|
||||||
}
|
}
|
||||||
@ -1,5 +0,0 @@
|
|||||||
package com.isolaatti.images.image_list.data.remote
|
|
||||||
|
|
||||||
data class ImagesDto(
|
|
||||||
val data: List<ImageDto>
|
|
||||||
)
|
|
||||||
@ -1,33 +0,0 @@
|
|||||||
package com.isolaatti.images.image_list.data.repository
|
|
||||||
|
|
||||||
import com.isolaatti.images.image_list.data.remote.ImagesApi
|
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
|
||||||
import com.isolaatti.images.image_list.domain.repository.ImagesRepository
|
|
||||||
import com.isolaatti.utils.Resource
|
|
||||||
import kotlinx.coroutines.flow.Flow
|
|
||||||
import kotlinx.coroutines.flow.flow
|
|
||||||
import retrofit2.awaitResponse
|
|
||||||
import javax.inject.Inject
|
|
||||||
|
|
||||||
class ImagesRepositoryImpl @Inject constructor(private val imagesApi: ImagesApi) : ImagesRepository {
|
|
||||||
override fun getImagesOfUser(userId: Int, lastId: String?): Flow<Resource<List<Image>>> = flow {
|
|
||||||
try {
|
|
||||||
val response = imagesApi.getImagesOfUser(userId, lastId).awaitResponse()
|
|
||||||
if(response.isSuccessful) {
|
|
||||||
val imagesDto = response.body()
|
|
||||||
val images = imagesDto?.data?.map { Image.fromDto(it) }
|
|
||||||
|
|
||||||
emit(Resource.Success(images))
|
|
||||||
|
|
||||||
} else {
|
|
||||||
emit(Resource.Error(Resource.Error.mapErrorCode(response.code())))
|
|
||||||
}
|
|
||||||
} catch(_: Exception) {
|
|
||||||
emit(Resource.Error(Resource.Error.ErrorType.NetworkError))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun deleteImages(images: List<Image>): Flow<Resource<Boolean>> = flow {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -3,8 +3,8 @@ package com.isolaatti.images.image_list.presentation
|
|||||||
import androidx.lifecycle.MutableLiveData
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
import androidx.lifecycle.viewModelScope
|
import androidx.lifecycle.viewModelScope
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.images.image_list.domain.repository.ImagesRepository
|
import com.isolaatti.images.common.domain.repository.ImagesRepository
|
||||||
import com.isolaatti.utils.Resource
|
import com.isolaatti.utils.Resource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
import kotlinx.coroutines.Dispatchers
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
|||||||
@ -9,7 +9,7 @@ import androidx.recyclerview.widget.RecyclerView.Adapter
|
|||||||
import coil.load
|
import coil.load
|
||||||
import com.isolaatti.common.CoilImageLoader.imageLoader
|
import com.isolaatti.common.CoilImageLoader.imageLoader
|
||||||
import com.isolaatti.databinding.ImageItemBinding
|
import com.isolaatti.databinding.ImageItemBinding
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
|
|
||||||
class ImagesAdapter(
|
class ImagesAdapter(
|
||||||
private val imageOnClick: ((images: List<Image>, position: Int) -> Unit),
|
private val imageOnClick: ((images: List<Image>, position: Int) -> Unit),
|
||||||
|
|||||||
@ -9,6 +9,7 @@ import android.view.Menu
|
|||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
|
import android.widget.Toast
|
||||||
import androidx.activity.result.PickVisualMediaRequest
|
import androidx.activity.result.PickVisualMediaRequest
|
||||||
import androidx.activity.result.contract.ActivityResultContracts
|
import androidx.activity.result.contract.ActivityResultContracts
|
||||||
import androidx.appcompat.widget.PopupMenu
|
import androidx.appcompat.widget.PopupMenu
|
||||||
@ -22,7 +23,7 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
|||||||
import com.isolaatti.MyApplication
|
import com.isolaatti.MyApplication
|
||||||
import com.isolaatti.R
|
import com.isolaatti.R
|
||||||
import com.isolaatti.databinding.FragmentImagesBinding
|
import com.isolaatti.databinding.FragmentImagesBinding
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.images.image_list.presentation.ImageListViewModel
|
import com.isolaatti.images.image_list.presentation.ImageListViewModel
|
||||||
import com.isolaatti.images.image_list.presentation.ImagesAdapter
|
import com.isolaatti.images.image_list.presentation.ImagesAdapter
|
||||||
import com.isolaatti.images.image_maker.ui.ImageMakerContract
|
import com.isolaatti.images.image_maker.ui.ImageMakerContract
|
||||||
@ -46,7 +47,7 @@ class ImagesFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private val imageMakerLauncher = registerForActivityResult(ImageMakerContract()) {
|
private val imageMakerLauncher = registerForActivityResult(ImageMakerContract()) {
|
||||||
|
Toast.makeText(requireContext(), "se subio la imagen ${it?.id}", Toast.LENGTH_SHORT).show()
|
||||||
}
|
}
|
||||||
|
|
||||||
private val choosePictureLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) {
|
private val choosePictureLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) {
|
||||||
@ -191,9 +192,12 @@ class ImagesFragment : Fragment() {
|
|||||||
viewModel.list.observe(viewLifecycleOwner) { resource ->
|
viewModel.list.observe(viewLifecycleOwner) { resource ->
|
||||||
when(resource) {
|
when(resource) {
|
||||||
is Resource.Error -> {}
|
is Resource.Error -> {}
|
||||||
is Resource.Loading -> {}
|
is Resource.Loading -> {
|
||||||
|
viewBinding.progressBarLoading.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
resource.data?.let {
|
resource.data?.let {
|
||||||
|
viewBinding.progressBarLoading.visibility = View.GONE
|
||||||
adapter.setData(it)
|
adapter.setData(it)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,33 @@
|
|||||||
package com.isolaatti.images.image_maker.presentation
|
package com.isolaatti.images.image_maker.presentation
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
import androidx.lifecycle.ViewModel
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
|
import com.isolaatti.images.common.domain.repository.ImagesRepository
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.Dispatchers
|
||||||
|
import kotlinx.coroutines.flow.flowOn
|
||||||
|
import kotlinx.coroutines.flow.launchIn
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@HiltViewModel
|
@HiltViewModel
|
||||||
class ImageMakerViewModel @Inject constructor() : ViewModel() {
|
class ImageMakerViewModel @Inject constructor(private val imagesRepository: ImagesRepository) : ViewModel() {
|
||||||
|
var imageUri: Uri? = null
|
||||||
|
var name: String? = null
|
||||||
|
val image: MutableLiveData<Resource<Image>> = MutableLiveData()
|
||||||
|
fun uploadPicture() {
|
||||||
|
if(imageUri == null || name == null) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
viewModelScope.launch {
|
||||||
|
imagesRepository.uploadImage(name!!, imageUri!!, null).onEach {
|
||||||
|
image.postValue(it)
|
||||||
|
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -1,21 +1,73 @@
|
|||||||
package com.isolaatti.images.image_maker.ui
|
package com.isolaatti.images.image_maker.ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
|
import android.content.ContentProvider
|
||||||
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import android.view.View
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.core.content.ContentProviderCompat
|
||||||
|
import androidx.core.widget.doOnTextChanged
|
||||||
import coil.load
|
import coil.load
|
||||||
|
import com.isolaatti.R
|
||||||
import com.isolaatti.common.IsolaattiBaseActivity
|
import com.isolaatti.common.IsolaattiBaseActivity
|
||||||
import com.isolaatti.databinding.ActivityImageMakerBinding
|
import com.isolaatti.databinding.ActivityImageMakerBinding
|
||||||
|
import com.isolaatti.images.image_maker.presentation.ImageMakerViewModel
|
||||||
|
import com.isolaatti.utils.Resource
|
||||||
import dagger.hilt.android.AndroidEntryPoint
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
@AndroidEntryPoint
|
@AndroidEntryPoint
|
||||||
class ImageMakerActivity : IsolaattiBaseActivity() {
|
class ImageMakerActivity : IsolaattiBaseActivity() {
|
||||||
private lateinit var binding: ActivityImageMakerBinding
|
private lateinit var binding: ActivityImageMakerBinding
|
||||||
|
private val viewModel: ImageMakerViewModel by viewModels()
|
||||||
|
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
binding = ActivityImageMakerBinding.inflate(layoutInflater)
|
binding = ActivityImageMakerBinding.inflate(layoutInflater)
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
viewModel.imageUri = intent.data
|
||||||
|
|
||||||
binding.imagePreview.load(intent.data)
|
binding.imagePreview.load(intent.data)
|
||||||
|
|
||||||
|
setupListeners()
|
||||||
|
setupObservers()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListeners() {
|
||||||
|
binding.materialToolbar.setOnMenuItemClickListener {
|
||||||
|
when(it.itemId) {
|
||||||
|
R.id.upload_picture_item -> {
|
||||||
|
viewModel.uploadPicture()
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
binding.textImageName.editText?.doOnTextChanged { text, _, _, _ ->
|
||||||
|
viewModel.name = text.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupObservers() {
|
||||||
|
viewModel.image.observe(this) {
|
||||||
|
when(it) {
|
||||||
|
is Resource.Error -> {
|
||||||
|
errorViewModel.error.value = it.errorType
|
||||||
|
}
|
||||||
|
is Resource.Loading -> {
|
||||||
|
binding.progressBarLoading.visibility = View.VISIBLE
|
||||||
|
}
|
||||||
|
is Resource.Success -> {
|
||||||
|
binding.progressBarLoading.visibility = View.GONE
|
||||||
|
setResult(Activity.RESULT_OK)
|
||||||
|
intent = Intent().putExtra(EXTRA_IMAGE, it.data)
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val EXTRA_IMAGE = "image"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1,10 +1,12 @@
|
|||||||
package com.isolaatti.images.image_maker.ui
|
package com.isolaatti.images.image_maker.ui
|
||||||
|
|
||||||
|
import android.app.Activity
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
|
|
||||||
class ImageMakerContract : ActivityResultContract<Uri, Image?>() {
|
class ImageMakerContract : ActivityResultContract<Uri, Image?>() {
|
||||||
override fun createIntent(context: Context, input: Uri): Intent {
|
override fun createIntent(context: Context, input: Uri): Intent {
|
||||||
@ -15,6 +17,13 @@ class ImageMakerContract : ActivityResultContract<Uri, Image?>() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun parseResult(resultCode: Int, intent: Intent?): Image? {
|
override fun parseResult(resultCode: Int, intent: Intent?): Image? {
|
||||||
|
if(resultCode == Activity.RESULT_OK) {
|
||||||
|
return if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
||||||
|
intent?.getSerializableExtra(ImageMakerActivity.EXTRA_IMAGE) as Image?
|
||||||
|
} else {
|
||||||
|
intent?.getSerializableExtra(ImageMakerActivity.EXTRA_IMAGE, Image::class.java)
|
||||||
|
}
|
||||||
|
}
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2,7 +2,7 @@ package com.isolaatti.images.picture_viewer.presentation
|
|||||||
|
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.viewpager2.adapter.FragmentStateAdapter
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.images.picture_viewer.ui.PictureViewerImageWrapperFragment
|
import com.isolaatti.images.picture_viewer.ui.PictureViewerImageWrapperFragment
|
||||||
|
|
||||||
class PictureViewerViewPagerAdapter(fragment: Fragment, private val images: Array<Image>) : FragmentStateAdapter(fragment) {
|
class PictureViewerViewPagerAdapter(fragment: Fragment, private val images: Array<Image>) : FragmentStateAdapter(fragment) {
|
||||||
|
|||||||
@ -5,7 +5,7 @@ import android.content.Intent
|
|||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import com.isolaatti.databinding.ActivityPictureViewerBinding
|
import com.isolaatti.databinding.ActivityPictureViewerBinding
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.images.picture_viewer.presentation.PictureViewerViewPagerAdapter
|
import com.isolaatti.images.picture_viewer.presentation.PictureViewerViewPagerAdapter
|
||||||
|
|
||||||
class PictureViewerActivity : AppCompatActivity() {
|
class PictureViewerActivity : AppCompatActivity() {
|
||||||
|
|||||||
@ -8,7 +8,7 @@ import androidx.fragment.app.Fragment
|
|||||||
import coil.load
|
import coil.load
|
||||||
import com.isolaatti.common.CoilImageLoader.imageLoader
|
import com.isolaatti.common.CoilImageLoader.imageLoader
|
||||||
import com.isolaatti.databinding.FragmentTouchImageViewWrapperBinding
|
import com.isolaatti.databinding.FragmentTouchImageViewWrapperBinding
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.ortiz.touchview.OnTouchImageViewListener
|
import com.ortiz.touchview.OnTouchImageViewListener
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -7,7 +7,7 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
import androidx.viewpager2.widget.ViewPager2
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
import com.isolaatti.databinding.FragmentMainPictureViewerBinding
|
import com.isolaatti.databinding.FragmentMainPictureViewerBinding
|
||||||
import com.isolaatti.images.image_list.domain.entity.Image
|
import com.isolaatti.images.common.domain.entity.Image
|
||||||
import com.isolaatti.images.picture_viewer.presentation.PictureViewerViewPagerAdapter
|
import com.isolaatti.images.picture_viewer.presentation.PictureViewerViewPagerAdapter
|
||||||
|
|
||||||
class PictureViewerMainFragment : Fragment() {
|
class PictureViewerMainFragment : Fragment() {
|
||||||
|
|||||||
@ -60,6 +60,7 @@ class LogInActivity: AppCompatActivity() {
|
|||||||
Resource.Error.ErrorType.ServerError -> showServerErrorMessage()
|
Resource.Error.ErrorType.ServerError -> showServerErrorMessage()
|
||||||
Resource.Error.ErrorType.OtherError -> showUnknownErrorMessage()
|
Resource.Error.ErrorType.OtherError -> showUnknownErrorMessage()
|
||||||
null -> {}
|
null -> {}
|
||||||
|
Resource.Error.ErrorType.InputError -> {}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,7 +5,7 @@ sealed class Resource<T> {
|
|||||||
class Loading<T>: Resource<T>()
|
class Loading<T>: Resource<T>()
|
||||||
class Error<T>(val errorType: ErrorType? = null, val message: String? = null): Resource<T>() {
|
class Error<T>(val errorType: ErrorType? = null, val message: String? = null): Resource<T>() {
|
||||||
enum class ErrorType {
|
enum class ErrorType {
|
||||||
NetworkError, AuthError, NotFoundError, ServerError, OtherError
|
NetworkError, AuthError, NotFoundError, ServerError, InputError, OtherError
|
||||||
}
|
}
|
||||||
companion object {
|
companion object {
|
||||||
fun mapErrorCode(errorCode: Int): ErrorType {
|
fun mapErrorCode(errorCode: Int): ErrorType {
|
||||||
|
|||||||
@ -13,7 +13,8 @@
|
|||||||
app:title="@string/upload_a_picture"
|
app:title="@string/upload_a_picture"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent" />
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
|
app:menu="@menu/image_maker_menu"/>
|
||||||
|
|
||||||
<com.google.android.material.textfield.TextInputLayout
|
<com.google.android.material.textfield.TextInputLayout
|
||||||
android:id="@+id/textImageName"
|
android:id="@+id/textImageName"
|
||||||
@ -24,6 +25,7 @@
|
|||||||
android:layout_marginStart="16dp"
|
android:layout_marginStart="16dp"
|
||||||
android:layout_marginTop="8dp"
|
android:layout_marginTop="8dp"
|
||||||
android:layout_marginEnd="16dp"
|
android:layout_marginEnd="16dp"
|
||||||
|
android:hint="@string/picture_name"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/materialToolbar">
|
app:layout_constraintTop_toBottomOf="@+id/materialToolbar">
|
||||||
@ -39,20 +41,21 @@
|
|||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="0dp"
|
android:layout_height="0dp"
|
||||||
android:layout_margin="32dp"
|
android:layout_margin="32dp"
|
||||||
app:layout_constraintBottom_toTopOf="@+id/postButton"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toBottomOf="@+id/textImageName" />
|
app:layout_constraintTop_toBottomOf="@+id/textImageName" />
|
||||||
|
|
||||||
<com.google.android.material.button.MaterialButton
|
<ProgressBar
|
||||||
android:id="@+id/postButton"
|
android:id="@+id/progress_bar_loading"
|
||||||
android:layout_width="0dp"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="@string/upload_photo"
|
android:visibility="gone"
|
||||||
android:layout_marginStart="16dp"
|
|
||||||
android:layout_marginEnd="16dp"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
app:layout_constraintEnd_toEndOf="parent"
|
||||||
app:layout_constraintStart_toStartOf="parent" />
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@+id/materialToolbar"
|
||||||
|
tools:visibility="visible" />
|
||||||
|
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
@ -1,5 +1,6 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto">
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
@ -22,6 +23,13 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior" />
|
||||||
|
<ProgressBar
|
||||||
|
android:id="@+id/progress_bar_loading"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_gravity="center"
|
||||||
|
android:visibility="gone"
|
||||||
|
tools:visibility="visible"/>
|
||||||
|
|
||||||
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
<com.google.android.material.floatingactionbutton.FloatingActionButton
|
||||||
android:id="@+id/new_picture_button"
|
android:id="@+id/new_picture_button"
|
||||||
|
|||||||
12
app/src/main/res/menu/image_maker_menu.xml
Normal file
12
app/src/main/res/menu/image_maker_menu.xml
Normal file
@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/upload_picture_item"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:icon="@drawable/baseline_check_24"
|
||||||
|
android:title="@string/upload_photo"
|
||||||
|
app:showAsAction="always"/>
|
||||||
|
</menu>
|
||||||
@ -120,4 +120,5 @@
|
|||||||
<string name="upload_photo">Upload picture</string>
|
<string name="upload_photo">Upload picture</string>
|
||||||
<string name="delete_images_dialog_message">Remove %d images?</string>
|
<string name="delete_images_dialog_message">Remove %d images?</string>
|
||||||
<string name="selected_images_count">Images selected: %d</string>
|
<string name="selected_images_count">Images selected: %d</string>
|
||||||
|
<string name="picture_name">Picture name</string>
|
||||||
</resources>
|
</resources>
|
||||||
Loading…
x
Reference in New Issue
Block a user