WIP
This commit is contained in:
parent
c00bd001ea
commit
a2c9091598
28
.idea/assetWizardSettings.xml
generated
28
.idea/assetWizardSettings.xml
generated
@ -79,7 +79,7 @@
|
|||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="color" value="000000" />
|
<entry key="color" value="000000" />
|
||||||
<entry key="imagePath" value="C:\Users\erike\Downloads\path1-3.svg" />
|
<entry key="imagePath" value="C:\Users\erike\isolaatti-icon.png" />
|
||||||
<entry key="scalingPercent" value="74" />
|
<entry key="scalingPercent" value="74" />
|
||||||
<entry key="trimmed" value="true" />
|
<entry key="trimmed" value="true" />
|
||||||
</map>
|
</map>
|
||||||
@ -181,6 +181,19 @@
|
|||||||
</PersistentState>
|
</PersistentState>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="image">
|
||||||
|
<value>
|
||||||
|
<PersistentState>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="color" value="000000" />
|
||||||
|
<entry key="imagePath" value="C:\Users\erike\isolaatti-notification-icon.png" />
|
||||||
|
<entry key="paddingPercent" value="-10" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</PersistentState>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="text">
|
<entry key="text">
|
||||||
<value>
|
<value>
|
||||||
<PersistentState>
|
<PersistentState>
|
||||||
@ -205,6 +218,13 @@
|
|||||||
</entry>
|
</entry>
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
|
<option name="values">
|
||||||
|
<map>
|
||||||
|
<entry key="assetType" value="IMAGE" />
|
||||||
|
<entry key="imageAsset" value="C:\Users\erike\isolaatti-notification-icon.png" />
|
||||||
|
<entry key="outputName" value="ic_notification" />
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
@ -308,7 +328,7 @@
|
|||||||
<PersistentState>
|
<PersistentState>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/play_arrow/baseline_play_arrow_24.xml" />
|
<entry key="url" value="file:/$USER_HOME$/AppData/Local/Android/Sdk/icons/material/materialicons/article/baseline_article_24.xml" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
@ -318,8 +338,8 @@
|
|||||||
</option>
|
</option>
|
||||||
<option name="values">
|
<option name="values">
|
||||||
<map>
|
<map>
|
||||||
<entry key="outputName" value="baseline_play_arrow_24" />
|
<entry key="outputName" value="baseline_article_24" />
|
||||||
<entry key="sourceFile" value="C:\Users\erike\Downloads\face-kiss-wink-heart-solid.svg" />
|
<entry key="sourceFile" value="C:\Users\erike\Downloads\hashtag-solid.svg" />
|
||||||
</map>
|
</map>
|
||||||
</option>
|
</option>
|
||||||
</PersistentState>
|
</PersistentState>
|
||||||
|
|||||||
70
.idea/navEditor.xml
generated
70
.idea/navEditor.xml
generated
@ -25,6 +25,37 @@
|
|||||||
</LayoutPositions>
|
</LayoutPositions>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="comment_thread_navigation.xml">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="commentThreadFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPosition">
|
||||||
|
<Point>
|
||||||
|
<option name="x" value="-258" />
|
||||||
|
<option name="y" value="8" />
|
||||||
|
</Point>
|
||||||
|
</option>
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="action_commentThreadFragment_self">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions />
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="followers_navigation.xml">
|
<entry key="followers_navigation.xml">
|
||||||
<value>
|
<value>
|
||||||
<LayoutPositions>
|
<LayoutPositions>
|
||||||
@ -206,6 +237,18 @@
|
|||||||
</LayoutPositions>
|
</LayoutPositions>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="profileListingFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPosition">
|
||||||
|
<Point>
|
||||||
|
<option name="x" value="-277" />
|
||||||
|
<option name="y" value="154" />
|
||||||
|
</Point>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="searchFragment">
|
<entry key="searchFragment">
|
||||||
<value>
|
<value>
|
||||||
<LayoutPositions>
|
<LayoutPositions>
|
||||||
@ -217,11 +260,6 @@
|
|||||||
</option>
|
</option>
|
||||||
<option name="myPositions">
|
<option name="myPositions">
|
||||||
<map>
|
<map>
|
||||||
<entry key="action_searchFragment_to_browseProfilesFragment">
|
|
||||||
<value>
|
|
||||||
<LayoutPositions />
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
<entry key="action_searchFragment_to_hashtagPostsFragment">
|
<entry key="action_searchFragment_to_hashtagPostsFragment">
|
||||||
<value>
|
<value>
|
||||||
<LayoutPositions />
|
<LayoutPositions />
|
||||||
@ -363,6 +401,28 @@
|
|||||||
</LayoutPositions>
|
</LayoutPositions>
|
||||||
</value>
|
</value>
|
||||||
</entry>
|
</entry>
|
||||||
|
<entry key="profile_listing_navigation.xml">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPositions">
|
||||||
|
<map>
|
||||||
|
<entry key="profileListingFragment">
|
||||||
|
<value>
|
||||||
|
<LayoutPositions>
|
||||||
|
<option name="myPosition">
|
||||||
|
<Point>
|
||||||
|
<option name="x" value="40" />
|
||||||
|
<option name="y" value="40" />
|
||||||
|
</Point>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
|
</map>
|
||||||
|
</option>
|
||||||
|
</LayoutPositions>
|
||||||
|
</value>
|
||||||
|
</entry>
|
||||||
<entry key="profile_navigation.xml">
|
<entry key="profile_navigation.xml">
|
||||||
<value>
|
<value>
|
||||||
<LayoutPositions>
|
<LayoutPositions>
|
||||||
|
|||||||
@ -22,8 +22,8 @@ android {
|
|||||||
applicationId "com.isolaatti"
|
applicationId "com.isolaatti"
|
||||||
minSdk 24
|
minSdk 24
|
||||||
targetSdk 34
|
targetSdk 34
|
||||||
versionCode 6
|
versionCode 7
|
||||||
versionName "0.6-vc6"
|
versionName "0.7-vc7"
|
||||||
|
|
||||||
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,85 +0,0 @@
|
|||||||
package com.isolaatti.audio.audio_selector.presentation
|
|
||||||
|
|
||||||
import android.view.LayoutInflater
|
|
||||||
import android.view.ViewGroup
|
|
||||||
import android.widget.LinearLayout
|
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.core.view.marginStart
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
|
||||||
import com.google.android.material.divider.MaterialDivider
|
|
||||||
import com.isolaatti.audio.common.domain.Audio
|
|
||||||
import com.isolaatti.audio.common.domain.Playable
|
|
||||||
import com.isolaatti.audio.drafts.domain.AudioDraft
|
|
||||||
import com.isolaatti.audio.drafts.presentation.AudioDraftsAdapter
|
|
||||||
import com.isolaatti.databinding.AudioListItemBinding
|
|
||||||
|
|
||||||
class AudioSelectorAdapter : RecyclerView.Adapter<RecyclerView.ViewHolder>() {
|
|
||||||
|
|
||||||
companion object {
|
|
||||||
const val TYPE_TITLE = 1
|
|
||||||
const val TYPE_DIVIDER = 2
|
|
||||||
const val TYPE_AUDIO = 3
|
|
||||||
const val TYPE_AUDIO_DRAFT = 4
|
|
||||||
const val TYPE_UNKNOWN = -1
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// viewholders
|
|
||||||
inner class AudioViewHolder(val audioListItemBinding: AudioListItemBinding) : RecyclerView.ViewHolder(audioListItemBinding.root)
|
|
||||||
inner class TitleViewHolder(val textView: TextView) : RecyclerView.ViewHolder(textView)
|
|
||||||
inner class DividerViewHolder(val divider: MaterialDivider) : RecyclerView.ViewHolder(divider)
|
|
||||||
|
|
||||||
data object Divider
|
|
||||||
data class TitleItem(val text: String)
|
|
||||||
|
|
||||||
private var list: List<Any> = listOf()
|
|
||||||
|
|
||||||
fun setList(item: List<Any>) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemViewType(position: Int): Int {
|
|
||||||
return when(list[position]) {
|
|
||||||
is Divider -> TYPE_DIVIDER
|
|
||||||
is TitleItem -> TYPE_TITLE
|
|
||||||
is Audio -> TYPE_AUDIO
|
|
||||||
is AudioDraft -> TYPE_AUDIO_DRAFT
|
|
||||||
else -> TYPE_UNKNOWN
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): RecyclerView.ViewHolder {
|
|
||||||
return when(viewType) {
|
|
||||||
TYPE_TITLE -> {
|
|
||||||
val textView = TextView(parent.context)
|
|
||||||
TitleViewHolder(textView)
|
|
||||||
}
|
|
||||||
TYPE_DIVIDER -> {
|
|
||||||
DividerViewHolder(MaterialDivider(parent.context))
|
|
||||||
}
|
|
||||||
TYPE_AUDIO, TYPE_AUDIO_DRAFT -> {
|
|
||||||
AudioViewHolder(AudioListItemBinding.inflate(LayoutInflater.from(parent.context), parent, false))
|
|
||||||
}
|
|
||||||
// this should not enter
|
|
||||||
else -> {
|
|
||||||
object: RecyclerView.ViewHolder(LinearLayout(parent.context)){}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun getItemCount(): Int {
|
|
||||||
return list.size
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: RecyclerView.ViewHolder, position: Int) {
|
|
||||||
when(holder) {
|
|
||||||
is TitleViewHolder -> {
|
|
||||||
holder.textView.text = (list[position] as TitleItem).text
|
|
||||||
}
|
|
||||||
|
|
||||||
is AudioViewHolder -> {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -0,0 +1,18 @@
|
|||||||
|
package com.isolaatti.audio.audio_selector.presentation
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
import androidx.fragment.app.FragmentActivity
|
||||||
|
import androidx.viewpager2.adapter.FragmentStateAdapter
|
||||||
|
import com.isolaatti.audio.audio_selector.ui.AudiosListSelectorFragment
|
||||||
|
|
||||||
|
class AudioSelectorFragmentAdapter(fragmentActivity: FragmentActivity) : FragmentStateAdapter(fragmentActivity) {
|
||||||
|
override fun getItemCount(): Int = 2
|
||||||
|
|
||||||
|
override fun createFragment(position: Int): Fragment {
|
||||||
|
return when(position) {
|
||||||
|
0 -> AudiosListSelectorFragment.getInstance()
|
||||||
|
1 -> AudiosListSelectorFragment.getInstanceForDrafts()
|
||||||
|
else -> Fragment()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,43 @@
|
|||||||
|
package com.isolaatti.audio.audio_selector.presentation
|
||||||
|
|
||||||
|
import androidx.lifecycle.MutableLiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
|
import androidx.lifecycle.viewModelScope
|
||||||
|
import com.isolaatti.audio.common.domain.Audio
|
||||||
|
import com.isolaatti.audio.common.domain.AudiosRepository
|
||||||
|
import com.isolaatti.audio.common.domain.Playable
|
||||||
|
import com.isolaatti.audio.drafts.domain.AudioDraft
|
||||||
|
import com.isolaatti.audio.drafts.domain.repository.AudioDraftsRepository
|
||||||
|
import com.isolaatti.common.SortingEnum
|
||||||
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
|
import kotlinx.coroutines.flow.onEach
|
||||||
|
import kotlinx.coroutines.launch
|
||||||
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
@HiltViewModel
|
||||||
|
class AudioSelectorViewModel @Inject constructor(
|
||||||
|
private val audiosRepository: AudiosRepository,
|
||||||
|
private val audioDraftsRepository: AudioDraftsRepository
|
||||||
|
) : ViewModel() {
|
||||||
|
val audios: MutableLiveData<List<Audio>> = MutableLiveData()
|
||||||
|
val drafts: MutableLiveData<List<AudioDraft>> = MutableLiveData()
|
||||||
|
val sorting: MutableLiveData<SortingEnum> = MutableLiveData()
|
||||||
|
|
||||||
|
fun setSorting(sort: SortingEnum) {
|
||||||
|
sorting.value = sort
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAudioDrafts() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
audioDraftsRepository.getAudioDrafts().onEach {
|
||||||
|
drafts.postValue(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getAudios() {
|
||||||
|
viewModelScope.launch {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,7 +1,17 @@
|
|||||||
package com.isolaatti.audio.audio_selector.ui
|
package com.isolaatti.audio.audio_selector.ui
|
||||||
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
|
import androidx.activity.viewModels
|
||||||
|
import androidx.appcompat.widget.PopupMenu
|
||||||
|
import androidx.navigation.findNavController
|
||||||
|
import androidx.viewpager2.widget.ViewPager2
|
||||||
|
import com.google.android.material.tabs.TabLayoutMediator
|
||||||
|
import com.isolaatti.R
|
||||||
|
import com.isolaatti.audio.audio_selector.presentation.AudioSelectorFragmentAdapter
|
||||||
|
import com.isolaatti.audio.audio_selector.presentation.AudioSelectorViewModel
|
||||||
|
import com.isolaatti.audio.recorder.ui.AudioRecorderContract
|
||||||
import com.isolaatti.common.IsolaattiBaseActivity
|
import com.isolaatti.common.IsolaattiBaseActivity
|
||||||
|
import com.isolaatti.common.SortingEnum
|
||||||
import com.isolaatti.databinding.ActivityAudioSelectorBinding
|
import com.isolaatti.databinding.ActivityAudioSelectorBinding
|
||||||
|
|
||||||
class AudioSelectorActivity : IsolaattiBaseActivity() {
|
class AudioSelectorActivity : IsolaattiBaseActivity() {
|
||||||
@ -12,13 +22,69 @@ class AudioSelectorActivity : IsolaattiBaseActivity() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivityAudioSelectorBinding
|
private lateinit var binding: ActivityAudioSelectorBinding
|
||||||
|
private val viewModel: AudioSelectorViewModel by viewModels()
|
||||||
|
|
||||||
|
private val audioRecorderLauncher = registerForActivityResult(AudioRecorderContract()) {
|
||||||
|
|
||||||
|
}
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
binding = ActivityAudioSelectorBinding.inflate(layoutInflater)
|
binding = ActivityAudioSelectorBinding.inflate(layoutInflater)
|
||||||
|
|
||||||
setContentView(binding.root)
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
binding.viewpager.adapter = AudioSelectorFragmentAdapter(this)
|
||||||
|
|
||||||
|
TabLayoutMediator(binding.tabLayout, binding.viewpager) {tab, position ->
|
||||||
|
when(position) {
|
||||||
|
0 -> tab.text = getString(R.string.audios)
|
||||||
|
1 -> tab.text = getString(R.string.drafts)
|
||||||
|
}
|
||||||
|
}.attach()
|
||||||
|
|
||||||
|
binding.sort.setText(R.string.descending_by_name)
|
||||||
|
|
||||||
|
setupListeners()
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setupListeners() {
|
||||||
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
|
binding.newAudio.setOnClickListener {
|
||||||
|
audioRecorderLauncher.launch(null)
|
||||||
|
}
|
||||||
|
|
||||||
|
binding.sort.setOnClickListener {
|
||||||
|
val popupMenu = PopupMenu(this, it)
|
||||||
|
popupMenu.inflate(R.menu.audios_sort_menu)
|
||||||
|
|
||||||
|
popupMenu.setOnMenuItemClickListener { menuItem ->
|
||||||
|
binding.sort.text = menuItem.title
|
||||||
|
when(menuItem.itemId) {
|
||||||
|
R.id.desc_by_name -> {
|
||||||
|
viewModel.setSorting(SortingEnum.DescendingByName)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.asc_by_name -> {
|
||||||
|
viewModel.setSorting(SortingEnum.AscendingByName)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.asc_by_creation_date -> {
|
||||||
|
viewModel.setSorting(SortingEnum.AscendingByCreationDate)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
R.id.desc_by_creation_date -> {
|
||||||
|
viewModel.setSorting(SortingEnum.DescendingByCreationDate)
|
||||||
|
true
|
||||||
|
}
|
||||||
|
else -> false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
popupMenu.show()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -14,6 +14,10 @@ import java.io.Serializable
|
|||||||
*/
|
*/
|
||||||
class AudioSelectorContract : ActivityResultContract<AudioSelectorContract.SelectorConfig, Playable?>() {
|
class AudioSelectorContract : ActivityResultContract<AudioSelectorContract.SelectorConfig, Playable?>() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param forSquad audios source will be a specified squad in the id param
|
||||||
|
* @param id squad id, should be non null if forSquad is true
|
||||||
|
*/
|
||||||
data class SelectorConfig(val forSquad: Boolean, val id: String?): Serializable
|
data class SelectorConfig(val forSquad: Boolean, val id: String?): Serializable
|
||||||
|
|
||||||
override fun createIntent(context: Context, input: SelectorConfig): Intent {
|
override fun createIntent(context: Context, input: SelectorConfig): Intent {
|
||||||
|
|||||||
@ -0,0 +1,103 @@
|
|||||||
|
package com.isolaatti.audio.audio_selector.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 com.isolaatti.audio.audio_selector.presentation.AudioSelectorViewModel
|
||||||
|
import com.isolaatti.audio.audios_list.presentation.AudiosAdapter
|
||||||
|
import com.isolaatti.databinding.FragmentAudiosListSelectorBinding
|
||||||
|
import dagger.hilt.android.AndroidEntryPoint
|
||||||
|
|
||||||
|
@AndroidEntryPoint
|
||||||
|
class AudiosListSelectorFragment : Fragment() {
|
||||||
|
private lateinit var binding: FragmentAudiosListSelectorBinding
|
||||||
|
private val viewModel: AudioSelectorViewModel by activityViewModels()
|
||||||
|
|
||||||
|
private var mode: Int = ARG_VAL_MODE_AUDIOS
|
||||||
|
private var squadId: String? = null
|
||||||
|
|
||||||
|
private lateinit var adapter: AudiosAdapter
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
|
||||||
|
arguments?.getInt(ARG_MODE)?.let { mode = it }
|
||||||
|
arguments?.getString(ARG_SQUAD_ID)?.let { squadId = it }
|
||||||
|
|
||||||
|
|
||||||
|
when(mode) {
|
||||||
|
ARG_VAL_MODE_AUDIOS -> {}
|
||||||
|
ARG_VAL_MODE_DRAFTS -> {
|
||||||
|
viewModel.getAudioDrafts()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onCreateView(
|
||||||
|
inflater: LayoutInflater,
|
||||||
|
container: ViewGroup?,
|
||||||
|
savedInstanceState: Bundle?
|
||||||
|
): View {
|
||||||
|
binding = FragmentAudiosListSelectorBinding.inflate(inflater, container, false)
|
||||||
|
return binding.root
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
|
||||||
|
super.onViewCreated(view, savedInstanceState)
|
||||||
|
adapter = AudiosAdapter(
|
||||||
|
onPlayClick = {
|
||||||
|
|
||||||
|
},
|
||||||
|
onOptionsClick = {audio, button ->
|
||||||
|
false
|
||||||
|
}
|
||||||
|
)
|
||||||
|
binding.recycler.adapter = adapter
|
||||||
|
|
||||||
|
when(mode) {
|
||||||
|
ARG_VAL_MODE_AUDIOS -> {
|
||||||
|
viewModel.audios.observe(viewLifecycleOwner) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ARG_VAL_MODE_DRAFTS -> {
|
||||||
|
viewModel.drafts.observe(viewLifecycleOwner) {
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val ARG_MODE = "mode"
|
||||||
|
private const val ARG_SQUAD_ID = "squadId"
|
||||||
|
private const val ARG_VAL_MODE_DRAFTS = 0
|
||||||
|
private const val ARG_VAL_MODE_AUDIOS = 1
|
||||||
|
fun getInstance(): AudiosListSelectorFragment {
|
||||||
|
return AudiosListSelectorFragment().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putInt(ARG_MODE, ARG_VAL_MODE_AUDIOS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getInstanceForDrafts(): AudiosListSelectorFragment {
|
||||||
|
return AudiosListSelectorFragment().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putInt(ARG_MODE, ARG_VAL_MODE_DRAFTS)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun getInstanceForSquad(squadId: String): AudiosListSelectorFragment {
|
||||||
|
return AudiosListSelectorFragment().apply {
|
||||||
|
arguments = Bundle().apply {
|
||||||
|
putString(ARG_SQUAD_ID, squadId)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -70,6 +70,7 @@ class AudiosRepositoryImpl @Inject constructor(private val audiosApi: AudiosApi,
|
|||||||
val audioDto = response.body()
|
val audioDto = response.body()
|
||||||
if(audioDto != null) {
|
if(audioDto != null) {
|
||||||
Log.d(LOG_TAG, "emit audio dto")
|
Log.d(LOG_TAG, "emit audio dto")
|
||||||
|
audiosDraftsDao.deleteDrafts(arrayOf(audioDraftEntity))
|
||||||
emit(Resource.Success(Audio.fromDto(audioDto)))
|
emit(Resource.Success(Audio.fromDto(audioDto)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -6,8 +6,9 @@ import com.isolaatti.MyApplication
|
|||||||
import com.isolaatti.audio.common.domain.Playable
|
import com.isolaatti.audio.common.domain.Playable
|
||||||
import com.isolaatti.audio.drafts.data.AudioDraftEntity
|
import com.isolaatti.audio.drafts.data.AudioDraftEntity
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
import java.io.Serializable
|
||||||
|
|
||||||
data class AudioDraft(val id: Long, val name: String, val localStorageRelativePath: String, val size: Long) : Playable() {
|
data class AudioDraft(val id: Long, val name: String, val localStorageRelativePath: String, val size: Long) : Playable(), Serializable {
|
||||||
override val thumbnail: String?
|
override val thumbnail: String?
|
||||||
get() = null
|
get() = null
|
||||||
|
|
||||||
|
|||||||
@ -49,7 +49,7 @@ class AudioRecorderActivity : AppCompatActivity() {
|
|||||||
const val LOG_TAG = "AudioRecorderActivity"
|
const val LOG_TAG = "AudioRecorderActivity"
|
||||||
|
|
||||||
const val IN_EXTRA_DRAFT_ID = "in_draft_id"
|
const val IN_EXTRA_DRAFT_ID = "in_draft_id"
|
||||||
const val OUT_EXTRA_DRAFT_ID = "out_draft_id"
|
const val OUT_EXTRA_DRAFT = "out_draft"
|
||||||
}
|
}
|
||||||
|
|
||||||
private lateinit var binding: ActivityAudioRecorderBinding
|
private lateinit var binding: ActivityAudioRecorderBinding
|
||||||
@ -204,6 +204,10 @@ class AudioRecorderActivity : AppCompatActivity() {
|
|||||||
else -> false
|
else -> false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
binding.toolbar.setNavigationOnClickListener {
|
||||||
|
finish()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun setupObservers() {
|
private fun setupObservers() {
|
||||||
@ -214,7 +218,7 @@ class AudioRecorderActivity : AppCompatActivity() {
|
|||||||
// audio draft is saved!
|
// audio draft is saved!
|
||||||
viewModel.audioDraft.observe(this) {
|
viewModel.audioDraft.observe(this) {
|
||||||
val result = Intent().apply {
|
val result = Intent().apply {
|
||||||
putExtra(OUT_EXTRA_DRAFT_ID, it.id)
|
putExtra(OUT_EXTRA_DRAFT, it)
|
||||||
}
|
}
|
||||||
setResult(RESULT_OK, result)
|
setResult(RESULT_OK, result)
|
||||||
finish()
|
finish()
|
||||||
|
|||||||
@ -4,8 +4,9 @@ import android.app.Activity
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import androidx.activity.result.contract.ActivityResultContract
|
import androidx.activity.result.contract.ActivityResultContract
|
||||||
|
import com.isolaatti.audio.drafts.domain.AudioDraft
|
||||||
|
|
||||||
class AudioRecorderContract : ActivityResultContract<Long?, Long?>() {
|
class AudioRecorderContract : ActivityResultContract<Long?, AudioDraft?>() {
|
||||||
|
|
||||||
override fun createIntent(context: Context, input: Long?): Intent {
|
override fun createIntent(context: Context, input: Long?): Intent {
|
||||||
val intent = Intent(context, AudioRecorderActivity::class.java).apply {
|
val intent = Intent(context, AudioRecorderActivity::class.java).apply {
|
||||||
@ -17,10 +18,10 @@ class AudioRecorderContract : ActivityResultContract<Long?, Long?>() {
|
|||||||
return intent
|
return intent
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun parseResult(resultCode: Int, intent: Intent?): Long? {
|
override fun parseResult(resultCode: Int, intent: Intent?): AudioDraft? {
|
||||||
return when(resultCode){
|
return when(resultCode){
|
||||||
Activity.RESULT_OK -> {
|
Activity.RESULT_OK -> {
|
||||||
intent?.getLongExtra(AudioRecorderActivity.OUT_EXTRA_DRAFT_ID, 0)?.takeUnless { it == 0L }
|
intent?.getSerializableExtra(AudioRecorderActivity.OUT_EXTRA_DRAFT) as? AudioDraft
|
||||||
}
|
}
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
|
|||||||
8
app/src/main/java/com/isolaatti/common/SortingEnum.kt
Normal file
8
app/src/main/java/com/isolaatti/common/SortingEnum.kt
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package com.isolaatti.common
|
||||||
|
|
||||||
|
enum class SortingEnum {
|
||||||
|
AscendingByName,
|
||||||
|
DescendingByName,
|
||||||
|
AscendingByCreationDate,
|
||||||
|
DescendingByCreationDate
|
||||||
|
}
|
||||||
@ -23,6 +23,7 @@ data class Options(
|
|||||||
const val OPTION_PROFILE_PHOTO_VIEW_PHOTO = 6
|
const val OPTION_PROFILE_PHOTO_VIEW_PHOTO = 6
|
||||||
const val OPTION_PROFILE_PHOTO_CHANGE_PHOTO = 7
|
const val OPTION_PROFILE_PHOTO_CHANGE_PHOTO = 7
|
||||||
const val OPTION_PROFILE_PHOTO_REMOVE_PHOTO = 8
|
const val OPTION_PROFILE_PHOTO_REMOVE_PHOTO = 8
|
||||||
|
const val OPTION_PROFILE_DESCRIPTION_SET_AUDIO = 9
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,6 +31,7 @@ data class Options(
|
|||||||
const val POST_OPTIONS = 1
|
const val POST_OPTIONS = 1
|
||||||
const val COMMENT_OPTIONS = 2
|
const val COMMENT_OPTIONS = 2
|
||||||
const val PROFILE_PHOTO_OPTIONS = 3
|
const val PROFILE_PHOTO_OPTIONS = 3
|
||||||
|
const val PROFILE_DESCRIPTION_OPTIONS = 4
|
||||||
|
|
||||||
val noOptions = Options(0, 0, listOf())
|
val noOptions = Options(0, 0, listOf())
|
||||||
|
|
||||||
@ -93,5 +95,10 @@ data class Options(
|
|||||||
|
|
||||||
return Options(R.string.profile_photo,PROFILE_PHOTO_OPTIONS, list)
|
return Options(R.string.profile_photo,PROFILE_PHOTO_OPTIONS, list)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun getProfileDescriptionOptions(): Options {
|
||||||
|
val list = listOf(Option(R.string.set_audio_description, R.drawable.baseline_audio_file_24, Option.OPTION_PROFILE_DESCRIPTION_SET_AUDIO))
|
||||||
|
return Options(R.string.description, PROFILE_DESCRIPTION_OPTIONS, list)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -9,6 +9,7 @@ import com.isolaatti.common.options_bottom_sheet.domain.OptionClicked
|
|||||||
import com.isolaatti.common.options_bottom_sheet.domain.Options
|
import com.isolaatti.common.options_bottom_sheet.domain.Options
|
||||||
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.COMMENT_OPTIONS
|
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.COMMENT_OPTIONS
|
||||||
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.POST_OPTIONS
|
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.POST_OPTIONS
|
||||||
|
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.PROFILE_DESCRIPTION_OPTIONS
|
||||||
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.PROFILE_PHOTO_OPTIONS
|
import com.isolaatti.common.options_bottom_sheet.domain.Options.Companion.PROFILE_PHOTO_OPTIONS
|
||||||
import com.isolaatti.settings.domain.UserIdSetting
|
import com.isolaatti.settings.domain.UserIdSetting
|
||||||
import dagger.hilt.android.lifecycle.HiltViewModel
|
import dagger.hilt.android.lifecycle.HiltViewModel
|
||||||
@ -40,6 +41,8 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
|||||||
fun setOptions(options: Int, callerId: Int, payload: Ownable? = null) {
|
fun setOptions(options: Int, callerId: Int, payload: Ownable? = null) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
CoroutineScope(Dispatchers.IO).launch {
|
CoroutineScope(Dispatchers.IO).launch {
|
||||||
|
_payload = payload
|
||||||
|
_callerId = callerId
|
||||||
when(options) {
|
when(options) {
|
||||||
POST_OPTIONS -> {
|
POST_OPTIONS -> {
|
||||||
userIdSetting.getUserId().onEach { userId ->
|
userIdSetting.getUserId().onEach { userId ->
|
||||||
@ -49,8 +52,6 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
|||||||
savable = false,
|
savable = false,
|
||||||
snapshotAble = false)
|
snapshotAble = false)
|
||||||
)
|
)
|
||||||
_callerId = callerId
|
|
||||||
_payload = payload
|
|
||||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||||
}
|
}
|
||||||
COMMENT_OPTIONS -> {
|
COMMENT_OPTIONS -> {
|
||||||
@ -61,17 +62,16 @@ class BottomSheetPostOptionsViewModel @Inject constructor(private val userIdSett
|
|||||||
savable = false,
|
savable = false,
|
||||||
snapshotAble = false)
|
snapshotAble = false)
|
||||||
)
|
)
|
||||||
_callerId = callerId
|
|
||||||
_payload = payload
|
|
||||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||||
}
|
}
|
||||||
PROFILE_PHOTO_OPTIONS -> {
|
PROFILE_PHOTO_OPTIONS -> {
|
||||||
userIdSetting.getUserId().onEach { userId ->
|
userIdSetting.getUserId().onEach { userId ->
|
||||||
_options.postValue(Options.getProfilePhotoOptions(userOwned = userId == payload?.userId,))
|
_options.postValue(Options.getProfilePhotoOptions(userOwned = userId == payload?.userId,))
|
||||||
_callerId = callerId
|
|
||||||
_payload = payload
|
|
||||||
}.flowOn(Dispatchers.IO).launchIn(this)
|
}.flowOn(Dispatchers.IO).launchIn(this)
|
||||||
}
|
}
|
||||||
|
PROFILE_DESCRIPTION_OPTIONS -> {
|
||||||
|
_options.postValue(Options.getProfileDescriptionOptions())
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -12,7 +12,12 @@ import com.isolaatti.common.OnUserInteractedCallback
|
|||||||
import com.isolaatti.utils.UrlGen
|
import com.isolaatti.utils.UrlGen
|
||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
|
|
||||||
class CommentsRecyclerViewAdapter(private var list: List<Comment>, private val markwon: Markwon, private val callback: OnUserInteractedCallback) : RecyclerView.Adapter<CommentsRecyclerViewAdapter.CommentViewHolder>() {
|
class CommentsRecyclerViewAdapter(
|
||||||
|
private var list: List<Comment>,
|
||||||
|
private val markwon: Markwon,
|
||||||
|
private val callback: OnUserInteractedCallback,
|
||||||
|
private val onCommentClick: (Comment) -> Unit
|
||||||
|
) : RecyclerView.Adapter<CommentsRecyclerViewAdapter.CommentViewHolder>() {
|
||||||
|
|
||||||
private var previousSize = 0
|
private var previousSize = 0
|
||||||
var blockInfiniteScroll = false
|
var blockInfiniteScroll = false
|
||||||
|
|||||||
@ -230,7 +230,9 @@ class BottomSheetPostComments() : BottomSheetDialogFragment(), OnUserInteractedC
|
|||||||
.usePlugin(LinkifyPlugin.create())
|
.usePlugin(LinkifyPlugin.create())
|
||||||
.build()
|
.build()
|
||||||
|
|
||||||
adapter = CommentsRecyclerViewAdapter(listOf(), markwon, this)
|
adapter = CommentsRecyclerViewAdapter(listOf(), markwon, this, onCommentClick = {
|
||||||
|
|
||||||
|
})
|
||||||
viewBinding.recyclerComments.adapter = adapter
|
viewBinding.recyclerComments.adapter = adapter
|
||||||
viewBinding.recyclerComments.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
viewBinding.recyclerComments.layoutManager = LinearLayoutManager(requireContext(), LinearLayoutManager.VERTICAL, false)
|
||||||
|
|
||||||
|
|||||||
@ -0,0 +1,44 @@
|
|||||||
|
package com.isolaatti.posting.comments.ui
|
||||||
|
|
||||||
|
import android.content.Context
|
||||||
|
import android.content.Intent
|
||||||
|
import android.os.Bundle
|
||||||
|
import android.widget.Toast
|
||||||
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
|
import androidx.navigation.fragment.NavHostFragment
|
||||||
|
import com.isolaatti.R
|
||||||
|
import com.isolaatti.databinding.ActivityCommentThreadBinding
|
||||||
|
|
||||||
|
class CommentThreadActivity : AppCompatActivity() {
|
||||||
|
private lateinit var binding: ActivityCommentThreadBinding
|
||||||
|
|
||||||
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
|
super.onCreate(savedInstanceState)
|
||||||
|
binding = ActivityCommentThreadBinding.inflate(layoutInflater)
|
||||||
|
setContentView(binding.root)
|
||||||
|
|
||||||
|
val commentId = intent.extras?.getLong(EXTRA_COMMENT_ID)
|
||||||
|
|
||||||
|
if(commentId == null || commentId == 0L) {
|
||||||
|
Toast.makeText(this, R.string.invalid_arg, Toast.LENGTH_SHORT).show()
|
||||||
|
finish()
|
||||||
|
} else {
|
||||||
|
(supportFragmentManager.findFragmentById(R.id.fragment_container) as NavHostFragment)
|
||||||
|
.navController.setGraph(R.navigation.comment_thread_navigation,
|
||||||
|
Bundle().apply {
|
||||||
|
putLong(CommentThreadFragment.ARG_COMMENT_ID, commentId)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private const val EXTRA_COMMENT_ID = "commentId"
|
||||||
|
fun startActivity(context: Context, commentId: Long) {
|
||||||
|
val intent = Intent(context, CommentThreadActivity::class.java).apply {
|
||||||
|
putExtra(EXTRA_COMMENT_ID, commentId)
|
||||||
|
}
|
||||||
|
|
||||||
|
context.startActivity(intent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -0,0 +1,9 @@
|
|||||||
|
package com.isolaatti.posting.comments.ui
|
||||||
|
|
||||||
|
import androidx.fragment.app.Fragment
|
||||||
|
|
||||||
|
class CommentThreadFragment : Fragment() {
|
||||||
|
companion object {
|
||||||
|
const val ARG_COMMENT_ID = "commentId"
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -7,6 +7,7 @@ import androidx.lifecycle.viewModelScope
|
|||||||
import com.isolaatti.audio.common.domain.Audio
|
import com.isolaatti.audio.common.domain.Audio
|
||||||
import com.isolaatti.audio.common.domain.Playable
|
import com.isolaatti.audio.common.domain.Playable
|
||||||
import com.isolaatti.audio.common.domain.UploadAudioUC
|
import com.isolaatti.audio.common.domain.UploadAudioUC
|
||||||
|
import com.isolaatti.audio.drafts.domain.AudioDraft
|
||||||
import com.isolaatti.audio.drafts.domain.repository.AudioDraftsRepository
|
import com.isolaatti.audio.drafts.domain.repository.AudioDraftsRepository
|
||||||
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
import com.isolaatti.posting.posts.data.remote.CreatePostDto
|
||||||
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
import com.isolaatti.posting.posts.data.remote.EditPostDto
|
||||||
@ -161,15 +162,15 @@ class CreatePostViewModel @Inject constructor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
// call this when user has recorded or selected a draft
|
// call this when user has recorded or selected a draft
|
||||||
fun putAudioDraft(draftId: Long) {
|
fun putAudioDraft(draft: AudioDraft) {
|
||||||
viewModelScope.launch {
|
viewModelScope.launch {
|
||||||
audioDraftsRepository.getAudioDraftById(draftId).onEach { draft ->
|
audioDraftsRepository.getAudioDraftById(draft.id).onEach { draft ->
|
||||||
when(draft) {
|
when(draft) {
|
||||||
is Resource.Error -> {}
|
is Resource.Error -> {}
|
||||||
is Resource.Loading -> {}
|
is Resource.Loading -> {}
|
||||||
is Resource.Success -> {
|
is Resource.Success -> {
|
||||||
audioAttachment.postValue(draft.data)
|
audioAttachment.postValue(draft.data)
|
||||||
this@CreatePostViewModel.audioDraft = draftId
|
this@CreatePostViewModel.audioDraft = draft.data!!.id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -40,9 +40,9 @@ class MarkdownEditingFragment : Fragment(){
|
|||||||
|
|
||||||
private var audioPlayerConnector: AudioPlayerConnector? = null
|
private var audioPlayerConnector: AudioPlayerConnector? = null
|
||||||
|
|
||||||
private val audioRecorderLauncher = registerForActivityResult(AudioRecorderContract()) { draftId ->
|
private val audioRecorderLauncher = registerForActivityResult(AudioRecorderContract()) { audioDraft ->
|
||||||
if(draftId != null) {
|
if(audioDraft != null) {
|
||||||
viewModel.putAudioDraft(draftId)
|
viewModel.putAudioDraft(audioDraft)
|
||||||
binding.viewAnimator.displayedChild = 1
|
binding.viewAnimator.displayedChild = 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -22,6 +22,7 @@ import coil.load
|
|||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.isolaatti.BuildConfig
|
import com.isolaatti.BuildConfig
|
||||||
import com.isolaatti.R
|
import com.isolaatti.R
|
||||||
|
import com.isolaatti.audio.audio_selector.ui.AudioSelectorContract
|
||||||
import com.isolaatti.audio.audios_list.ui.AudiosFragment
|
import com.isolaatti.audio.audios_list.ui.AudiosFragment
|
||||||
import com.isolaatti.audio.common.domain.Audio
|
import com.isolaatti.audio.common.domain.Audio
|
||||||
import com.isolaatti.audio.common.domain.Playable
|
import com.isolaatti.audio.common.domain.Playable
|
||||||
@ -111,6 +112,10 @@ class ProfileMainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val audioSelectorLauncher = registerForActivityResult(AudioSelectorContract()) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
private val audioPlayerConnectorListener = object: AudioPlayerConnector.Listener {
|
private val audioPlayerConnectorListener = object: AudioPlayerConnector.Listener {
|
||||||
override fun onPlaying(isPlaying: Boolean, audio: Playable) {
|
override fun onPlaying(isPlaying: Boolean, audio: Playable) {
|
||||||
@ -280,6 +285,10 @@ class ProfileMainFragment : Fragment() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Options.PROFILE_DESCRIPTION_OPTIONS -> {
|
||||||
|
optionsViewModel.handle()
|
||||||
|
audioSelectorLauncher.launch(AudioSelectorContract.SelectorConfig(false, null))
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -458,6 +467,11 @@ class ProfileMainFragment : Fragment() {
|
|||||||
removeItem(R.id.block_profile_menu_item)
|
removeItem(R.id.block_profile_menu_item)
|
||||||
removeItem(R.id.report_profile_menu_item)
|
removeItem(R.id.report_profile_menu_item)
|
||||||
}
|
}
|
||||||
|
viewBinding.descriptionCard.setOnClickListener {
|
||||||
|
optionsViewModel.setOptions(Options.PROFILE_DESCRIPTION_OPTIONS, CALLER_ID, null)
|
||||||
|
val fragment = BottomSheetPostOptionsFragment()
|
||||||
|
fragment.show(parentFragmentManager, BottomSheetPostOptionsFragment.TAG)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
viewBinding.createPostButton.visibility = View.GONE
|
viewBinding.createPostButton.visibility = View.GONE
|
||||||
viewBinding.topAppBar.menu.removeItem(R.id.edit_profile)
|
viewBinding.topAppBar.menu.removeItem(R.id.edit_profile)
|
||||||
|
|||||||
@ -4,65 +4,64 @@
|
|||||||
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">
|
||||||
|
|
||||||
<com.google.android.material.appbar.MaterialToolbar
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/appbar"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
app:title="@string/select_audio"
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
app:navigationIcon="@drawable/baseline_close_24"
|
|
||||||
app:layout_constraintTop_toTopOf="parent"/>
|
|
||||||
<HorizontalScrollView
|
|
||||||
android:id="@+id/filter_container"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/toolbar"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
android:layout_marginHorizontal="8dp">
|
|
||||||
<com.google.android.material.chip.ChipGroup
|
|
||||||
android:id="@+id/filter"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:singleLine="true">
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/chip_drafts"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/drafts"
|
|
||||||
android:checkable="true"
|
|
||||||
app:chipIcon="@drawable/baseline_pending_24"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
<com.google.android.material.appbar.MaterialToolbar
|
||||||
android:id="@+id/chip_audios"
|
android:id="@+id/toolbar"
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/audios"
|
|
||||||
android:checkable="true"
|
|
||||||
app:chipIcon="@drawable/baseline_audio_file_24"/>
|
|
||||||
|
|
||||||
<com.google.android.material.chip.Chip
|
|
||||||
android:id="@+id/sort"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:text="@string/sort"
|
|
||||||
app:chipIcon="@drawable/baseline_sort_24"/>
|
|
||||||
</com.google.android.material.chip.ChipGroup>
|
|
||||||
</HorizontalScrollView>
|
|
||||||
|
|
||||||
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
|
||||||
android:id="@+id/swipe_to_refresh"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="0dp"
|
|
||||||
app:layout_constraintTop_toBottomOf="@id/filter_container"
|
|
||||||
app:layout_constraintBottom_toBottomOf="parent"
|
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
|
||||||
app:layout_constraintEnd_toEndOf="parent">
|
|
||||||
<androidx.recyclerview.widget.RecyclerView
|
|
||||||
android:id="@+id/recycler"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"/>
|
android:layout_height="wrap_content"
|
||||||
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
app:title="@string/select_audio"
|
||||||
|
app:navigationIcon="@drawable/baseline_close_24"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<HorizontalScrollView
|
||||||
|
android:id="@+id/options_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginHorizontal="8dp">
|
||||||
|
<com.google.android.material.chip.ChipGroup
|
||||||
|
android:id="@+id/options"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:singleLine="true">
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/new_audio"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:text="@string/record_new_audio"
|
||||||
|
app:chipIcon="@drawable/baseline_mic_24"/>
|
||||||
|
|
||||||
|
<com.google.android.material.chip.Chip
|
||||||
|
android:id="@+id/sort"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:chipIcon="@drawable/baseline_sort_24"
|
||||||
|
android:enabled="false"/>
|
||||||
|
</com.google.android.material.chip.ChipGroup>
|
||||||
|
</HorizontalScrollView>
|
||||||
|
|
||||||
|
<com.google.android.material.tabs.TabLayout
|
||||||
|
android:id="@+id/tab_layout"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/options_container"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.viewpager2.widget.ViewPager2
|
||||||
|
android:id="@+id/viewpager"
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="0dp"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
app:layout_constraintTop_toBottomOf="@id/appbar"
|
||||||
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
|
app:layout_constraintEnd_toEndOf="parent"/>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
25
app/src/main/res/layout/activity_comment_thread.xml
Normal file
25
app/src/main/res/layout/activity_comment_thread.xml
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
<?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:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
app:navigationIcon="@drawable/baseline_arrow_back_24"
|
||||||
|
/>
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
|
<androidx.fragment.app.FragmentContainerView
|
||||||
|
android:id="@+id/fragment_container"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:name="androidx.navigation.fragment.NavHostFragment"
|
||||||
|
app:defaultNavHost="true"
|
||||||
|
app:layout_behavior="com.google.android.material.appbar.AppBarLayout$ScrollingViewBehavior"/>
|
||||||
|
|
||||||
|
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
||||||
16
app/src/main/res/layout/fragment_audios_list_selector.xml
Normal file
16
app/src/main/res/layout/fragment_audios_list_selector.xml
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_to_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
19
app/src/main/res/layout/fragment_comment_thread.xml
Normal file
19
app/src/main/res/layout/fragment_comment_thread.xml
Normal file
@ -0,0 +1,19 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
|
||||||
|
|
||||||
|
<androidx.swiperefreshlayout.widget.SwipeRefreshLayout
|
||||||
|
android:id="@+id/swipe_to_refresh"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent">
|
||||||
|
<androidx.recyclerview.widget.RecyclerView
|
||||||
|
android:id="@+id/recycler_view"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"/>
|
||||||
|
</androidx.swiperefreshlayout.widget.SwipeRefreshLayout>
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||||
14
app/src/main/res/menu/audios_sort_menu.xml
Normal file
14
app/src/main/res/menu/audios_sort_menu.xml
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
|
||||||
|
<item android:id="@+id/desc_by_name"
|
||||||
|
android:title="@string/descending_by_name"/>
|
||||||
|
<item android:id="@+id/asc_by_name"
|
||||||
|
android:title="@string/ascending_by_name"/>
|
||||||
|
<item android:id="@+id/asc_by_creation_date"
|
||||||
|
android:title="@string/ascending_by_creation_date"/>
|
||||||
|
<item android:id="@+id/desc_by_creation_date"
|
||||||
|
android:title="@string/descending_by_creation_date"/>
|
||||||
|
|
||||||
|
|
||||||
|
</menu>
|
||||||
18
app/src/main/res/navigation/comment_thread_navigation.xml
Normal file
18
app/src/main/res/navigation/comment_thread_navigation.xml
Normal file
@ -0,0 +1,18 @@
|
|||||||
|
<?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/comment_thread_navigation"
|
||||||
|
app:startDestination="@id/commentThreadFragment">
|
||||||
|
|
||||||
|
<fragment
|
||||||
|
android:id="@+id/commentThreadFragment"
|
||||||
|
android:name="com.isolaatti.posting.comments.ui.CommentThreadFragment"
|
||||||
|
android:label="CommentThreadFragment" >
|
||||||
|
<action
|
||||||
|
android:id="@+id/action_commentThreadFragment_self"
|
||||||
|
app:destination="@id/commentThreadFragment" />
|
||||||
|
<argument
|
||||||
|
android:name="commentId"
|
||||||
|
app:argType="long" />
|
||||||
|
</fragment>
|
||||||
|
</navigation>
|
||||||
@ -212,6 +212,12 @@
|
|||||||
<string name="edited_at">Edited at %s</string>
|
<string name="edited_at">Edited at %s</string>
|
||||||
<string name="block_profile_dialog_message">Do you really want to block %s?</string>
|
<string name="block_profile_dialog_message">Do you really want to block %s?</string>
|
||||||
<string name="user_profile_picture">%s\'s profile picture</string>
|
<string name="user_profile_picture">%s\'s profile picture</string>
|
||||||
|
<string name="set_audio_description">Set audio description</string>
|
||||||
|
<string name="ascending_by_name">Z-A</string>
|
||||||
|
<string name="descending_by_name">A-Z</string>
|
||||||
|
<string name="ascending_by_creation_date">older-newer</string>
|
||||||
|
<string name="descending_by_creation_date">newer-older</string>
|
||||||
|
<string name="invalid_arg">Invalid value passed</string>
|
||||||
<string-array name="report_reasons">
|
<string-array name="report_reasons">
|
||||||
<item>Spam</item>
|
<item>Spam</item>
|
||||||
<item>Explicit content</item>
|
<item>Explicit content</item>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user