* seleccionador de imagenes.

* se puede insertar imagenes en posts
This commit is contained in:
erik-everardo 2024-01-04 00:35:39 -06:00
parent 53e41d2034
commit 8373adcb63
26 changed files with 593 additions and 76 deletions

View File

@ -301,10 +301,24 @@
<entry key="vectorAssetStep"> <entry key="vectorAssetStep">
<value> <value>
<PersistentState> <PersistentState>
<option name="children">
<map>
<entry key="clipartAsset">
<value>
<PersistentState>
<option name="values">
<map>
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/file_upload/baseline_file_upload_24.xml" />
</map>
</option>
</PersistentState>
</value>
</entry>
</map>
</option>
<option name="values"> <option name="values">
<map> <map>
<entry key="assetSourceType" value="FILE" /> <entry key="outputName" value="baseline_file_upload_24" />
<entry key="outputName" value="face_kiss_wink_heart_solid" />
<entry key="sourceFile" value="C:\Users\erike\Downloads\face-kiss-wink-heart-solid.svg" /> <entry key="sourceFile" value="C:\Users\erike\Downloads\face-kiss-wink-heart-solid.svg" />
</map> </map>
</option> </option>

43
.idea/navEditor.xml generated
View File

@ -159,6 +159,49 @@
</LayoutPositions> </LayoutPositions>
</value> </value>
</entry> </entry>
<entry key="image_chooser_navigation.xml">
<value>
<LayoutPositions>
<option name="myPositions">
<map>
<entry key="imageChooserMainFragment">
<value>
<LayoutPositions>
<option name="myPosition">
<Point>
<option name="x" value="-268" />
<option name="y" value="-16" />
</Point>
</option>
<option name="myPositions">
<map>
<entry key="action_imageChooserMainFragment_to_imageChooserPreview">
<value>
<LayoutPositions />
</value>
</entry>
</map>
</option>
</LayoutPositions>
</value>
</entry>
<entry key="imageChooserPreview">
<value>
<LayoutPositions>
<option name="myPosition">
<Point>
<option name="x" value="9" />
<option name="y" value="-18" />
</Point>
</option>
</LayoutPositions>
</value>
</entry>
</map>
</option>
</LayoutPositions>
</value>
</entry>
<entry key="picture_viewer_navigation.xml"> <entry key="picture_viewer_navigation.xml">
<value> <value>
<LayoutPositions> <LayoutPositions>

View File

@ -2,6 +2,7 @@ package com.isolaatti.images.common.domain.entity
import com.isolaatti.common.Deletable import com.isolaatti.common.Deletable
import com.isolaatti.images.common.data.remote.ImageDto import com.isolaatti.images.common.data.remote.ImageDto
import com.isolaatti.markdown.Generators
import com.isolaatti.utils.UrlGen import com.isolaatti.utils.UrlGen
import java.io.Serializable import java.io.Serializable
@ -15,7 +16,7 @@ data class Image(
val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL) val smallImageUrl : String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_SMALL)
val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED) val reducedImageUrl: String get() = UrlGen.imageUrl(id, UrlGen.IMAGE_MODE_REDUCED)
val markdown: String get() = Generators.generateImage(imageUrl)
companion object { companion object {
fun fromDto(imageDto: ImageDto) = Image(imageDto.id, imageDto.userId, imageDto.name, imageDto.username) fun fromDto(imageDto: ImageDto) = Image(imageDto.id, imageDto.userId, imageDto.name, imageDto.username)

View File

@ -1,6 +1,34 @@
package com.isolaatti.images.image_chooser.presentation package com.isolaatti.images.image_chooser.presentation
import androidx.lifecycle.LiveData
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.isolaatti.auth.domain.AuthRepository
import com.isolaatti.images.common.domain.entity.Image
import com.isolaatti.images.common.domain.repository.ImagesRepository
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
@HiltViewModel
class ImageChooserViewModel @Inject constructor(private val authRepository: AuthRepository) : ViewModel() {
val userId: MutableLiveData<Int> = MutableLiveData()
var selectedImage: Image? = null
val choose: MutableLiveData<Boolean> = MutableLiveData()
fun getUserId() {
viewModelScope.launch {
authRepository.getUserId().onEach {
userId.postValue(it)
}.flowOn(Dispatchers.IO).launchIn(this)
}
}
class ImageChooserViewModel : ViewModel() {
} }

View File

@ -1,18 +1,39 @@
package com.isolaatti.images.image_chooser.ui package com.isolaatti.images.image_chooser.ui
import android.content.Intent
import android.os.Bundle import android.os.Bundle
import android.os.PersistableBundle import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity import com.isolaatti.common.IsolaattiBaseActivity
import com.isolaatti.databinding.ActivityImageChooserBinding import com.isolaatti.databinding.ActivityImageChooserBinding
import com.isolaatti.images.image_chooser.presentation.ImageChooserViewModel
import dagger.hilt.android.AndroidEntryPoint
class ImageChooserActivity : AppCompatActivity() { @AndroidEntryPoint
class ImageChooserActivity : IsolaattiBaseActivity() {
private lateinit var binding: ActivityImageChooserBinding private lateinit var binding: ActivityImageChooserBinding
override fun onCreate(savedInstanceState: Bundle?, persistentState: PersistableBundle?) { private val viewModel: ImageChooserViewModel by viewModels()
super.onCreate(savedInstanceState, persistentState)
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityImageChooserBinding.inflate(layoutInflater) binding = ActivityImageChooserBinding.inflate(layoutInflater)
setContentView(binding.root) setContentView(binding.root)
setupObservers()
}
private fun setupObservers() {
viewModel.choose.observe(this) {
if(it == true && viewModel.selectedImage != null) {
viewModel.choose.value = false
val resultIntent = Intent().apply {
putExtra(OUTPUT_EXTRA_IMAGE, viewModel.selectedImage)
}
setResult(RESULT_OK, resultIntent)
finish()
return@observe
}
}
} }
companion object { companion object {

View File

@ -0,0 +1,133 @@
package com.isolaatti.images.image_chooser.ui
import android.app.Activity
import android.content.res.Resources
import android.net.Uri
import android.os.Bundle
import android.util.Log
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
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.recyclerview.widget.GridLayoutManager
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.isolaatti.MyApplication
import com.isolaatti.R
import com.isolaatti.databinding.FragmentImageChooserMainBinding
import com.isolaatti.images.common.domain.entity.Image
import com.isolaatti.images.image_chooser.presentation.ImageChooserViewModel
import com.isolaatti.images.image_list.presentation.ImageListViewModel
import com.isolaatti.images.image_list.presentation.ImagesAdapter
import com.isolaatti.images.image_maker.ui.ImageMakerContract
import dagger.hilt.android.AndroidEntryPoint
import java.io.File
import java.util.Calendar
@AndroidEntryPoint
class ImageChooserMainFragment : Fragment() {
private lateinit var binding: FragmentImageChooserMainBinding
private val viewModel: ImageChooserViewModel by activityViewModels()
private val imagesListViewModel: ImageListViewModel by viewModels()
private lateinit var adapter: ImagesAdapter
private var cameraPhotoUri: Uri? = null
private val imageOnClick: (images: List<Image>, position: Int) -> Unit = { images, position ->
viewModel.selectedImage = images[position]
findNavController().navigate(ImageChooserMainFragmentDirections.actionImageChooserMainFragmentToImageChooserPreview())
}
private fun makePhotoUri(): Uri {
val cacheFile = File(requireContext().filesDir, "temp_picture_${Calendar.getInstance().timeInMillis}")
return FileProvider.getUriForFile(requireContext(), "${MyApplication.myApp.packageName}.provider", cacheFile)
}
private val imageMakerLauncher = registerForActivityResult(ImageMakerContract()) { image ->
image?.also {
viewModel.selectedImage = it
viewModel.choose.value = true
}
}
private val choosePictureLauncher = registerForActivityResult(ActivityResultContracts.PickVisualMedia()) {
if(it != null) {
imageMakerLauncher.launch(it)
}
}
private val takePhotoLauncher = registerForActivityResult(ActivityResultContracts.TakePicture()) {
if(it && cameraPhotoUri != null) {
imageMakerLauncher.launch(cameraPhotoUri)
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
viewModel.getUserId()
}
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentImageChooserMainBinding.inflate(inflater)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
adapter = ImagesAdapter(
imageOnClick = imageOnClick,
itemWidth = Resources.getSystem().displayMetrics.widthPixels/3
)
binding.recycler.layoutManager =
GridLayoutManager(requireContext(), 3, GridLayoutManager.VERTICAL, false)
binding.recycler.adapter = adapter
setupObservers()
setupListeners()
}
private fun setupListeners() {
binding.toolbar.setNavigationOnClickListener {
requireActivity().run {
setResult(Activity.RESULT_CANCELED)
finish()
}
}
binding.takePhoto.setOnClickListener {
cameraPhotoUri = makePhotoUri()
takePhotoLauncher.launch(cameraPhotoUri)
}
binding.uploadPhoto.setOnClickListener {
choosePictureLauncher.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
}
}
private fun setupObservers() {
viewModel.userId.observe(viewLifecycleOwner) {
imagesListViewModel.userId = it
imagesListViewModel.loadNext()
Log.d("*****", "Se obtiene userId $it")
}
imagesListViewModel.liveList.observe(viewLifecycleOwner) { imageList ->
Log.d("*****", "Se obtiene lista $imageList")
adapter.submitList(imageList)
}
}
}

View File

@ -0,0 +1,48 @@
package com.isolaatti.images.image_chooser.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels
import androidx.navigation.fragment.findNavController
import coil.load
import com.isolaatti.databinding.FragmentImageChooserPreviewBinding
import com.isolaatti.images.image_chooser.presentation.ImageChooserViewModel
class ImageChooserPreview : Fragment() {
private lateinit var binding: FragmentImageChooserPreviewBinding
private val viewModel: ImageChooserViewModel by activityViewModels()
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentImageChooserPreviewBinding.inflate(inflater)
return binding.root
}
private fun showLoading(show: Boolean) {
binding.chooseImageButton.visibility = if(show) View.INVISIBLE else View.VISIBLE
binding.progressBarLoading.visibility = if(show) View.VISIBLE else View.INVISIBLE
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.toolbar.setNavigationOnClickListener {
findNavController().popBackStack()
}
binding.image.load(viewModel.selectedImage?.imageUrl)
binding.imageDescription.text = viewModel.selectedImage?.name
binding.chooseImageButton.setOnClickListener {
showLoading(true)
viewModel.choose.value = true
}
}
}

View File

@ -0,0 +1,29 @@
package com.isolaatti.images.image_list.presentation
import com.isolaatti.images.common.domain.entity.Image
interface ImageAdapterItem {
val image: Image?
val addImage: Boolean
companion object {
val AddImagePlaceholder: ImageAdapterItem = object: ImageAdapterItem {
override val image: Image?
get() = null
override val addImage: Boolean
get() = true
}
fun fromImage(image: Image): ImageAdapterItem {
return object: ImageAdapterItem {
override val addImage: Boolean
get() = false
override val image: Image?
get() = image
}
}
}
}

View File

@ -27,6 +27,7 @@ import com.isolaatti.R
import com.isolaatti.common.ErrorMessageViewModel import com.isolaatti.common.ErrorMessageViewModel
import com.isolaatti.databinding.FragmentImagesBinding import com.isolaatti.databinding.FragmentImagesBinding
import com.isolaatti.images.common.domain.entity.Image import com.isolaatti.images.common.domain.entity.Image
import com.isolaatti.images.image_list.presentation.ImageAdapterItem
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

View File

@ -27,7 +27,9 @@ class CreatePostViewModel @Inject constructor(private val makePost: MakePost, pr
val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData() val error: MutableLiveData<Resource.Error.ErrorType?> = MutableLiveData()
val loading: MutableLiveData<Boolean> = MutableLiveData(false) val loading: MutableLiveData<Boolean> = MutableLiveData(false)
val postToEdit: MutableLiveData<EditPostDto> = MutableLiveData() val postToEdit: MutableLiveData<EditPostDto> = MutableLiveData()
val liveContent: MutableLiveData<String> = MutableLiveData()
var content: String = "" var content: String = ""
set(value) {field = value; liveContent.value = value} // TODO remove this and use only liveContent
fun postDiscussion() { fun postDiscussion() {
viewModelScope.launch { viewModelScope.launch {

View File

@ -11,6 +11,7 @@ import androidx.lifecycle.lifecycleScope
import androidx.lifecycle.repeatOnLifecycle import androidx.lifecycle.repeatOnLifecycle
import androidx.navigation.findNavController import androidx.navigation.findNavController
import com.google.android.material.tabs.TabLayout import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import com.isolaatti.R import com.isolaatti.R
import com.isolaatti.common.IsolaattiBaseActivity import com.isolaatti.common.IsolaattiBaseActivity
import com.isolaatti.databinding.ActivityCreatePostBinding import com.isolaatti.databinding.ActivityCreatePostBinding
@ -84,6 +85,16 @@ class CreatePostActivity : IsolaattiBaseActivity() {
private fun setupUI() { private fun setupUI() {
binding.toolbar.setTitle(if(mode == EXTRA_MODE_EDIT && postId != 0L) R.string.edit else R.string.new_post) binding.toolbar.setTitle(if(mode == EXTRA_MODE_EDIT && postId != 0L) R.string.edit else R.string.new_post)
binding.pager.adapter = CreatePostFragmentStateAdapter(this)
TabLayoutMediator(binding.tabs, binding.pager) { tab, position ->
when(position) {
0 -> tab.setText(R.string.markdown)
1 -> tab.setText(R.string.preview)
}
}.attach()
} }
private fun setListeners() { private fun setListeners() {
@ -100,28 +111,6 @@ class CreatePostActivity : IsolaattiBaseActivity() {
} }
} }
binding.tabs.addOnTabSelectedListener(object : TabLayout.OnTabSelectedListener {
override fun onTabSelected(tab: TabLayout.Tab?) {
when(tab?.position) {
0 -> /*editing*/ {
findNavController(binding.fragmentContainerView.id).navigate(R.id.markdownEditingFragment)
}
1 -> /*preview*/ {
findNavController(binding.fragmentContainerView.id).navigate(R.id.markdownPreviewFragment)
}
}
}
override fun onTabReselected(tab: TabLayout.Tab?) {
// Handle tab reselect
}
override fun onTabUnselected(tab: TabLayout.Tab?) {
// Handle tab unselect
}
})
} }
private fun setObservers() { private fun setObservers() {

View File

@ -0,0 +1,20 @@
package com.isolaatti.posting.posts.ui
import androidx.fragment.app.Fragment
import androidx.fragment.app.FragmentActivity
import androidx.fragment.app.FragmentManager
import androidx.viewpager2.adapter.FragmentStateAdapter
class CreatePostFragmentStateAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
override fun getItemCount(): Int {
return 2
}
override fun createFragment(position: Int): Fragment {
return if(position == 0) {
MarkdownEditingFragment()
} else {
MarkdownPreviewFragment()
}
}
}

View File

@ -2,29 +2,29 @@ package com.isolaatti.posting.posts.ui
import android.os.Bundle import android.os.Bundle
import android.util.Log import android.util.Log
import android.view.ActionMode
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.core.widget.doOnTextChanged import androidx.core.widget.doOnTextChanged
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.fragment.app.activityViewModels import androidx.fragment.app.activityViewModels
import com.isolaatti.R
import com.isolaatti.databinding.FragmentMarkdownEditingBinding import com.isolaatti.databinding.FragmentMarkdownEditingBinding
import com.isolaatti.images.image_chooser.ui.ImageChooserActivity
import com.isolaatti.images.image_chooser.ui.ImageChooserContract import com.isolaatti.images.image_chooser.ui.ImageChooserContract
import com.isolaatti.posting.posts.presentation.CreatePostViewModel import com.isolaatti.posting.posts.presentation.CreatePostViewModel
import dagger.hilt.EntryPoint
class MarkdownEditingFragment : Fragment(){ class MarkdownEditingFragment : Fragment(){
private lateinit var binding: FragmentMarkdownEditingBinding private lateinit var binding: FragmentMarkdownEditingBinding
private val viewModel: CreatePostViewModel by activityViewModels() private val viewModel: CreatePostViewModel by activityViewModels()
private val imageChooserLauncher = registerForActivityResult(ImageChooserContract()) { image -> private val imageChooserLauncher = registerForActivityResult(ImageChooserContract()) { image ->
Log.d("MarkdownEditingFragment", "$image") Log.d("MarkdownEditingFragment", "${image?.markdown}")
if(image != null) {
viewModel.content += "\n\n ${image.markdown}"
binding.filledTextField.editText?.setText(viewModel.content)
}
} }
override fun onCreateView( override fun onCreateView(
@ -41,6 +41,11 @@ class MarkdownEditingFragment : Fragment(){
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState) super.onViewCreated(view, savedInstanceState)
setupListeners()
setupObservers()
}
private fun setupListeners() {
binding.filledTextField.editText?.setText(viewModel.content) binding.filledTextField.editText?.setText(viewModel.content)
binding.filledTextField.requestFocus() binding.filledTextField.requestFocus()
binding.filledTextField.editText?.doOnTextChanged { text, _, _, _ -> binding.filledTextField.editText?.doOnTextChanged { text, _, _, _ ->
@ -48,7 +53,12 @@ class MarkdownEditingFragment : Fragment(){
viewModel.validation.postValue(!text.isNullOrEmpty()) viewModel.validation.postValue(!text.isNullOrEmpty())
viewModel.content = text.toString() viewModel.content = text.toString()
} }
binding.addImageButton.setOnClickListener {
insertImage()
}
}
private fun setupObservers(){
viewModel.postToEdit.observe(viewLifecycleOwner) { viewModel.postToEdit.observe(viewLifecycleOwner) {
binding.filledTextField.editText?.setText(it.content) binding.filledTextField.editText?.setText(it.content)
} }

View File

@ -56,6 +56,9 @@ class MarkdownPreviewFragment : Fragment() {
} }
override fun onViewCreated(view: View, savedInstanceState: Bundle?) { override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
markwon?.setMarkdown(binding.textView, viewModel.content) viewModel.liveContent.observe(viewLifecycleOwner) {
markwon?.setMarkdown(binding.textView, it)
}
} }
} }

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M8,11h8v2L8,13zM20.1,12L22,12c0,-2.76 -2.24,-5 -5,-5h-4v1.9h4c1.71,0 3.1,1.39 3.1,3.1zM3.9,12c0,-1.71 1.39,-3.1 3.1,-3.1h4L11,7L7,7c-2.76,0 -5,2.24 -5,5s2.24,5 5,5h4v-1.9L7,15.1c-1.71,0 -3.1,-1.39 -3.1,-3.1zM19,12h-2v3h-3v2h3v3h2v-3h3v-2h-3z"/>
</vector>

View File

@ -0,0 +1,6 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M12,12m-3.2,0a3.2,3.2 0,1 1,6.4 0a3.2,3.2 0,1 1,-6.4 0"/>
<path android:fillColor="@android:color/white" android:pathData="M9,2L7.17,4L4,4c-1.1,0 -2,0.9 -2,2v12c0,1.1 0.9,2 2,2h16c1.1,0 2,-0.9 2,-2L22,6c0,-1.1 -0.9,-2 -2,-2h-3.17L15,2L9,2zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5z"/>
</vector>

View File

@ -0,0 +1,5 @@
<vector android:height="24dp" android:tint="#000000"
android:viewportHeight="24" android:viewportWidth="24"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@android:color/white" android:pathData="M9,16h6v-6h4l-7,-7 -7,7h4zM5,18h14v2L5,20z"/>
</vector>

View File

@ -36,19 +36,10 @@
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/appBarLayout"> app:layout_constraintTop_toBottomOf="@+id/appBarLayout">
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/markdown" />
<com.google.android.material.tabs.TabItem
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/preview" />
</com.google.android.material.tabs.TabLayout> </com.google.android.material.tabs.TabLayout>
<androidx.fragment.app.FragmentContainerView <androidx.viewpager2.widget.ViewPager2
android:id="@+id/fragmentContainerView" android:id="@+id/pager"
android:name="androidx.navigation.fragment.NavHostFragment" android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
@ -56,8 +47,7 @@
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/tabs" app:layout_constraintTop_toBottomOf="@+id/tabs" />
app:navGraph="@navigation/post_creator_navigation" />
<ProgressBar <ProgressBar
android:id="@+id/progress_bar_loading" android:id="@+id/progress_bar_loading"

View File

@ -1,7 +1,14 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" <androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent">
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:navGraph="@navigation/image_chooser_navigation"
android:name="androidx.navigation.fragment.NavHostFragment"
app:defaultNavHost="true"/>
</androidx.coordinatorlayout.widget.CoordinatorLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -1,15 +1,10 @@
<?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.fragment.app.FragmentContainerView xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/profile_fragment_view"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent"> android:layout_height="match_parent"
app:defaultNavHost="true"
<androidx.fragment.app.FragmentContainerView app:navGraph="@navigation/profile_navigation" />
android:id="@+id/profile_fragment_view"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:defaultNavHost="true"
app:navGraph="@navigation/profile_navigation" />
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:title="@string/choose_image"
app:navigationIcon="@drawable/baseline_close_24"/>
</com.google.android.material.appbar.AppBarLayout>
<androidx.core.widget.NestedScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<com.google.android.material.card.MaterialCardView
android:id="@+id/image_chooser_actions"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_margin="24dp">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="horizontal"
android:layout_margin="16dp"
android:gravity="center">
<com.google.android.material.button.MaterialButton
android:id="@+id/take_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="4dp"
app:icon="@drawable/baseline_camera_alt_24"
android:text="@string/take_a_photo"/>
<com.google.android.material.button.MaterialButton
android:id="@+id/upload_photo"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="4dp"
android:text="@string/upload_photo"
app:icon="@drawable/baseline_file_upload_24"/>
</LinearLayout>
</com.google.android.material.card.MaterialCardView>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_anchor="@id/image_chooser_actions" />
</LinearLayout>
</androidx.core.widget.NestedScrollView>
</androidx.coordinatorlayout.widget.CoordinatorLayout>

View File

@ -0,0 +1,63 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:background="@color/black">
<com.google.android.material.appbar.MaterialToolbar
android:id="@+id/toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:navigationIcon="@drawable/baseline_arrow_back_24"
app:navigationIconTint="#FFF"
android:translationZ="5dp"
android:background="@color/translucent_black"/>
<com.ortiz.touchview.TouchImageView
android:id="@+id/image"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/image_description"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:background="@color/translucent_black"
android:padding="16dp"
android:textColor="@android:color/white"
android:textSize="16sp"
app:layout_constraintBottom_toTopOf="@+id/choose_image_button"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
tools:text="Image description" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton
android:id="@+id/choose_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginEnd="16dp"
android:layout_marginBottom="16dp"
android:text="@string/choose_image"
app:icon="@drawable/baseline_check_24"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ProgressBar
android:id="@+id/progress_bar_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="@+id/choose_image_button"
app:layout_constraintEnd_toEndOf="@+id/choose_image_button"
app:layout_constraintStart_toStartOf="@+id/choose_image_button"
app:layout_constraintTop_toTopOf="@+id/choose_image_button"
android:visibility="invisible"/>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -6,17 +6,39 @@
android:paddingBottom="100dp" android:paddingBottom="100dp"
android:layout_marginTop="?attr/actionBarSize" android:layout_marginTop="?attr/actionBarSize"
android:clipToPadding="false"> android:clipToPadding="false">
<com.google.android.material.textfield.TextInputLayout <LinearLayout
style="?attr/textInputFilledStyle"
android:id="@+id/filledTextField"
android:layout_width="match_parent" android:layout_width="match_parent"
app:boxBackgroundMode="none"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:hintEnabled="false"> android:orientation="vertical">
<com.google.android.material.textfield.TextInputEditText <com.google.android.material.textfield.TextInputLayout
style="?attr/textInputFilledStyle"
android:id="@+id/filledTextField"
android:layout_width="match_parent" android:layout_width="match_parent"
app:boxBackgroundMode="none"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:hint="@string/what_do_you_want_to_talk_about_markdown_is_compatible_you_can_record_an_audio_if_you_want"/> app:hintEnabled="false">
<com.google.android.material.textfield.TextInputEditText
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/what_do_you_want_to_talk_about_markdown_is_compatible_you_can_record_an_audio_if_you_want"/>
</com.google.android.material.textfield.TextInputLayout> </com.google.android.material.textfield.TextInputLayout>
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<com.google.android.material.button.MaterialButton
android:id="@+id/add_image_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
style="@style/Widget.Material3.Button.IconButton"
app:icon="@drawable/baseline_image_24" />
<!-- <com.google.android.material.button.MaterialButton-->
<!-- android:id="@+id/add_link_button"-->
<!-- android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- style="@style/Widget.Material3.Button.IconButton"-->
<!-- app:icon="@drawable/baseline_add_link_24" />-->
</LinearLayout>
</LinearLayout>
</androidx.core.widget.NestedScrollView> </androidx.core.widget.NestedScrollView>

View File

@ -8,7 +8,6 @@
android:id="@+id/textView" android:id="@+id/textView"
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="0dp" android:layout_height="0dp"
android:text="TextView"
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"

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<navigation xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/image_chooser_navigation"
app:startDestination="@id/imageChooserMainFragment">
<fragment
android:id="@+id/imageChooserMainFragment"
android:name="com.isolaatti.images.image_chooser.ui.ImageChooserMainFragment"
android:label="ImageChooserMainFragment" >
<action
android:id="@+id/action_imageChooserMainFragment_to_imageChooserPreview"
app:destination="@id/imageChooserPreview" />
</fragment>
<fragment
android:id="@+id/imageChooserPreview"
android:name="com.isolaatti.images.image_chooser.ui.ImageChooserPreview"
android:label="ImageChooserPreview" />
</navigation>

View File

@ -128,4 +128,5 @@
<string name="markdown">Markdown</string> <string name="markdown">Markdown</string>
<string name="preview">Preview</string> <string name="preview">Preview</string>
<string name="add_image_here">Add image here</string> <string name="add_image_here">Add image here</string>
<string name="choose_image">Choose image</string>
</resources> </resources>