Shared items: Add tab for polls

Resolves: #2029

Signed-off-by: Tim Krüger <t@timkrueger.me>
This commit is contained in:
Tim Krüger 2022-07-26 18:36:17 +02:00
parent 32235632c8
commit 00f06c6ef2
No known key found for this signature in database
GPG Key ID: FECE3A7222C52A4E
16 changed files with 196 additions and 64 deletions

View File

@ -2557,6 +2557,10 @@ class ChatController(args: Bundle) :
intent.putExtra(KEY_CONVERSATION_NAME, currentConversation?.displayName) intent.putExtra(KEY_CONVERSATION_NAME, currentConversation?.displayName)
intent.putExtra(KEY_ROOM_TOKEN, roomToken) intent.putExtra(KEY_ROOM_TOKEN, roomToken)
intent.putExtra(KEY_USER_ENTITY, conversationUser as Parcelable) intent.putExtra(KEY_USER_ENTITY, conversationUser as Parcelable)
intent.putExtra(
SharedItemsActivity.KEY_USER_IS_OWNER_OR_MODERATOR,
currentConversation?.isParticipantOwnerOrModerator
)
activity!!.startActivity(intent) activity!!.startActivity(intent)
} }

View File

@ -192,6 +192,7 @@ class ConversationInfoController(args: Bundle) :
intent.putExtra(BundleKeys.KEY_CONVERSATION_NAME, conversation?.displayName) intent.putExtra(BundleKeys.KEY_CONVERSATION_NAME, conversation?.displayName)
intent.putExtra(BundleKeys.KEY_ROOM_TOKEN, conversationToken) intent.putExtra(BundleKeys.KEY_ROOM_TOKEN, conversationToken)
intent.putExtra(BundleKeys.KEY_USER_ENTITY, conversationUser as Parcelable) intent.putExtra(BundleKeys.KEY_USER_ENTITY, conversationUser as Parcelable)
intent.putExtra(SharedItemsActivity.KEY_USER_IS_OWNER_OR_MODERATOR, conversation?.isParticipantOwnerOrModerator)
activity!!.startActivity(intent) activity!!.startActivity(intent)
} }

View File

@ -63,6 +63,7 @@ class SharedItemsActivity : AppCompatActivity() {
val roomToken = intent.getStringExtra(KEY_ROOM_TOKEN)!! val roomToken = intent.getStringExtra(KEY_ROOM_TOKEN)!!
val conversationName = intent.getStringExtra(KEY_CONVERSATION_NAME) val conversationName = intent.getStringExtra(KEY_CONVERSATION_NAME)
val user = intent.getParcelableExtra<User>(KEY_USER_ENTITY)!! val user = intent.getParcelableExtra<User>(KEY_USER_ENTITY)!!
val isUserConversationOwnerOrModerator = intent.getBooleanExtra(KEY_USER_IS_OWNER_OR_MODERATOR, false)
binding = ActivitySharedItemsBinding.inflate(layoutInflater) binding = ActivitySharedItemsBinding.inflate(layoutInflater)
setSupportActionBar(binding.sharedItemsToolbar) setSupportActionBar(binding.sharedItemsToolbar)
@ -104,7 +105,12 @@ class SharedItemsActivity : AppCompatActivity() {
LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false) LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
} }
val adapter = SharedItemsAdapter(showGrid, user).apply { val adapter = SharedItemsAdapter(
showGrid,
user,
roomToken,
isUserConversationOwnerOrModerator
).apply {
items = sharedMediaItems.items items = sharedMediaItems.items
} }
binding.imageRecycler.adapter = adapter binding.imageRecycler.adapter = adapter
@ -176,6 +182,13 @@ class SharedItemsActivity : AppCompatActivity() {
binding.sharedItemsTabs.addTab(tabVoice) binding.sharedItemsTabs.addTab(tabVoice)
} }
if (sharedItemTypes.contains(SharedItemType.POLL)) {
val tabVoice: TabLayout.Tab = binding.sharedItemsTabs.newTab()
tabVoice.tag = SharedItemType.POLL
tabVoice.setText(R.string.shared_items_poll)
binding.sharedItemsTabs.addTab(tabVoice)
}
// if(sharedItemTypes.contains(SharedItemType.LOCATION)) { // if(sharedItemTypes.contains(SharedItemType.LOCATION)) {
// val tabLocation: TabLayout.Tab = binding.sharedItemsTabs.newTab() // val tabLocation: TabLayout.Tab = binding.sharedItemsTabs.newTab()
// tabLocation.tag = SharedItemType.LOCATION // tabLocation.tag = SharedItemType.LOCATION
@ -220,5 +233,6 @@ class SharedItemsActivity : AppCompatActivity() {
companion object { companion object {
private val TAG = SharedItemsActivity::class.simpleName private val TAG = SharedItemsActivity::class.simpleName
const val SPAN_COUNT: Int = 4 const val SPAN_COUNT: Int = 4
const val KEY_USER_IS_OWNER_OR_MODERATOR = "userIsOwnerOrModerator"
} }
} }

View File

@ -22,17 +22,24 @@
package com.nextcloud.talk.shareditems.adapters package com.nextcloud.talk.shareditems.adapters
import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.ViewGroup import android.view.ViewGroup
import androidx.recyclerview.widget.RecyclerView import androidx.recyclerview.widget.RecyclerView
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.SharedItemGridBinding import com.nextcloud.talk.databinding.SharedItemGridBinding
import com.nextcloud.talk.databinding.SharedItemListBinding import com.nextcloud.talk.databinding.SharedItemListBinding
import com.nextcloud.talk.polls.ui.PollMainDialogFragment
import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
import com.nextcloud.talk.shareditems.model.SharedFileItem
import com.nextcloud.talk.shareditems.model.SharedItem import com.nextcloud.talk.shareditems.model.SharedItem
import com.nextcloud.talk.shareditems.model.SharedPollItem
class SharedItemsAdapter( class SharedItemsAdapter(
private val showGrid: Boolean, private val showGrid: Boolean,
private val user: User private val user: User,
private val roomToken: String,
private val isUserConversationOwnerOrModerator: Boolean
) : RecyclerView.Adapter<SharedItemsViewHolder>() { ) : RecyclerView.Adapter<SharedItemsViewHolder>() {
var items: List<SharedItem> = emptyList() var items: List<SharedItem> = emptyList()
@ -61,10 +68,31 @@ class SharedItemsAdapter(
} }
override fun onBindViewHolder(holder: SharedItemsViewHolder, position: Int) { override fun onBindViewHolder(holder: SharedItemsViewHolder, position: Int) {
holder.onBind(items[position]) when (val item = items[position]) {
is SharedPollItem -> holder.onBind(item, ::showPoll)
is SharedFileItem -> holder.onBind(item)
}
} }
override fun getItemCount(): Int { override fun getItemCount(): Int {
return items.size return items.size
} }
private fun showPoll(item: SharedItem, context: Context) {
val pollVoteDialog = PollMainDialogFragment.newInstance(
user,
roomToken,
isUserConversationOwnerOrModerator,
item.id,
item.name
)
pollVoteDialog.show(
(context as SharedItemsActivity).supportFragmentManager,
TAG
)
}
companion object {
private val TAG = SharedItemsAdapter::class.simpleName
}
} }

View File

@ -22,13 +22,18 @@
package com.nextcloud.talk.shareditems.adapters package com.nextcloud.talk.shareditems.adapters
import android.content.Context
import android.text.format.Formatter import android.text.format.Formatter
import android.view.View import android.view.View
import android.widget.ProgressBar import android.widget.ProgressBar
import androidx.core.content.ContextCompat
import com.facebook.drawee.view.SimpleDraweeView import com.facebook.drawee.view.SimpleDraweeView
import com.nextcloud.talk.R
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.databinding.SharedItemListBinding import com.nextcloud.talk.databinding.SharedItemListBinding
import com.nextcloud.talk.shareditems.model.SharedFileItem
import com.nextcloud.talk.shareditems.model.SharedItem import com.nextcloud.talk.shareditems.model.SharedItem
import com.nextcloud.talk.shareditems.model.SharedPollItem
import com.nextcloud.talk.utils.DateUtils import com.nextcloud.talk.utils.DateUtils
class SharedItemsListViewHolder( class SharedItemsListViewHolder(
@ -43,12 +48,12 @@ class SharedItemsListViewHolder(
override val progressBar: ProgressBar override val progressBar: ProgressBar
get() = binding.progressBar get() = binding.progressBar
override fun onBind(item: SharedItem) { override fun onBind(item: SharedFileItem) {
super.onBind(item) super.onBind(item)
binding.fileName.text = item.name binding.fileName.text = item.name
binding.fileSize.text = item.fileSize?.let { binding.fileSize.text = item.fileSize.let {
Formatter.formatShortFileSize( Formatter.formatShortFileSize(
binding.fileSize.context, binding.fileSize.context,
it it
@ -59,6 +64,21 @@ class SharedItemsListViewHolder(
) )
} }
override fun onBind(item: SharedPollItem, showPoll: (item: SharedItem, context: Context) -> Unit) {
super.onBind(item, showPoll)
binding.fileName.text = item.name
binding.fileMetadata.visibility = View.GONE
image.hierarchy.setPlaceholderImage(R.drawable.ic_baseline_bar_chart_24)
image.setColorFilter(
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
android.graphics.PorterDuff.Mode.SRC_IN
)
clickTarget.setOnClickListener {
showPoll(item, it.context)
}
}
companion object { companion object {
private const val ONE_SECOND_IN_MILLIS = 1000 private const val ONE_SECOND_IN_MILLIS = 1000
} }

View File

@ -22,6 +22,7 @@
package com.nextcloud.talk.shareditems.adapters package com.nextcloud.talk.shareditems.adapters
import android.content.Context
import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable
import android.net.Uri import android.net.Uri
import android.util.Log import android.util.Log
@ -39,14 +40,16 @@ import com.facebook.imagepipeline.common.RotationOptions
import com.facebook.imagepipeline.image.ImageInfo import com.facebook.imagepipeline.image.ImageInfo
import com.facebook.imagepipeline.request.ImageRequestBuilder import com.facebook.imagepipeline.request.ImageRequestBuilder
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.shareditems.model.SharedFileItem
import com.nextcloud.talk.shareditems.model.SharedItem import com.nextcloud.talk.shareditems.model.SharedItem
import com.nextcloud.talk.shareditems.model.SharedPollItem
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.DrawableUtils import com.nextcloud.talk.utils.DrawableUtils
import com.nextcloud.talk.utils.FileViewerUtils import com.nextcloud.talk.utils.FileViewerUtils
abstract class SharedItemsViewHolder( abstract class SharedItemsViewHolder(
open val binding: ViewBinding, open val binding: ViewBinding,
private val user: User internal val user: User
) : RecyclerView.ViewHolder(binding.root) { ) : RecyclerView.ViewHolder(binding.root) {
companion object { companion object {
@ -64,9 +67,9 @@ abstract class SharedItemsViewHolder(
) )
) )
open fun onBind(item: SharedItem) { open fun onBind(item: SharedFileItem) {
image.hierarchy.setPlaceholderImage(staticImage(item.mimeType, image)) image.hierarchy.setPlaceholderImage(staticImage(item.mimeType, image))
if (item.previewAvailable == true) { if (item.previewAvailable) {
image.controller = configurePreview(item) image.controller = configurePreview(item)
} }
@ -100,7 +103,7 @@ abstract class SharedItemsViewHolder(
) )
} }
private fun configurePreview(item: SharedItem): DraweeController { private fun configurePreview(item: SharedFileItem): DraweeController {
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(item.previewLink)) val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(item.previewLink))
.setProgressiveRenderingEnabled(true) .setProgressiveRenderingEnabled(true)
@ -123,6 +126,8 @@ abstract class SharedItemsViewHolder(
.build() .build()
} }
open fun onBind(item: SharedPollItem, showPoll: (item: SharedItem, context: Context) -> Unit) {}
private fun staticImage( private fun staticImage(
mimeType: String?, mimeType: String?,
image: SimpleDraweeView image: SimpleDraweeView

View File

@ -0,0 +1,37 @@
/*
* Nextcloud Talk application
*
* @author Tim Krüger
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.shareditems.model
data class SharedFileItem(
override val id: String,
override val name: String,
override val actorId: String,
override val actorName: String,
val fileSize: Long,
val date: Long,
val path: String,
val link: String,
val mimeType: String,
val previewAvailable: Boolean = false,
val previewLink: String
) : SharedItem

View File

@ -1,35 +1,8 @@
/*
* Nextcloud Talk application
*
* @author Tim Krüger
* @author Álvaro Brey
* Copyright (C) 2022 Álvaro Brey
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.shareditems.model package com.nextcloud.talk.shareditems.model
data class SharedItem( interface SharedItem {
val id: String, val id: String
val name: String, val name: String
val fileSize: Long?, val actorId: String
val date: Long, val actorName: String
val path: String, }
val link: String?,
val mimeType: String?,
val previewAvailable: Boolean?,
val previewLink: String
)

View File

@ -32,7 +32,8 @@ enum class SharedItemType {
VOICE, VOICE,
LOCATION, LOCATION,
DECKCARD, DECKCARD,
OTHER; OTHER,
POLL;
companion object { companion object {
fun typeFor(name: String) = valueOf(name.uppercase(Locale.ROOT)) fun typeFor(name: String) = valueOf(name.uppercase(Locale.ROOT))

View File

@ -22,8 +22,9 @@
package com.nextcloud.talk.shareditems.model package com.nextcloud.talk.shareditems.model
class SharedMediaItems( class SharedItems(
val items: List<SharedItem>, val items: List<SharedItem>,
val type: SharedItemType,
var lastSeenId: Int?, var lastSeenId: Int?,
var moreItemsExisting: Boolean var moreItemsExisting: Boolean
) )

View File

@ -0,0 +1,27 @@
/*
* Nextcloud Talk application
*
* @author Tim Krüger
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package com.nextcloud.talk.shareditems.model
data class SharedPollItem(
override val id: String,
override val name: String,
override val actorId: String,
override val actorName: String,
) : SharedItem

View File

@ -23,7 +23,7 @@
package com.nextcloud.talk.shareditems.repositories package com.nextcloud.talk.shareditems.repositories
import com.nextcloud.talk.shareditems.model.SharedItemType import com.nextcloud.talk.shareditems.model.SharedItemType
import com.nextcloud.talk.shareditems.model.SharedMediaItems import com.nextcloud.talk.shareditems.model.SharedItems
import io.reactivex.Observable import io.reactivex.Observable
interface SharedItemsRepository { interface SharedItemsRepository {
@ -31,13 +31,13 @@ interface SharedItemsRepository {
fun media( fun media(
parameters: Parameters, parameters: Parameters,
type: SharedItemType type: SharedItemType
): Observable<SharedMediaItems>? ): Observable<SharedItems>?
fun media( fun media(
parameters: Parameters, parameters: Parameters,
type: SharedItemType, type: SharedItemType,
lastKnownMessageId: Int? lastKnownMessageId: Int?
): Observable<SharedMediaItems>? ): Observable<SharedItems>?
fun availableTypes(parameters: Parameters): Observable<Set<SharedItemType>> fun availableTypes(parameters: Parameters): Observable<Set<SharedItemType>>

View File

@ -27,9 +27,11 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
import com.nextcloud.talk.models.json.chat.ChatShareOverall import com.nextcloud.talk.models.json.chat.ChatShareOverall
import com.nextcloud.talk.shareditems.model.SharedFileItem
import com.nextcloud.talk.shareditems.model.SharedItem import com.nextcloud.talk.shareditems.model.SharedItem
import com.nextcloud.talk.shareditems.model.SharedItemType import com.nextcloud.talk.shareditems.model.SharedItemType
import com.nextcloud.talk.shareditems.model.SharedMediaItems import com.nextcloud.talk.shareditems.model.SharedItems
import com.nextcloud.talk.shareditems.model.SharedPollItem
import com.nextcloud.talk.utils.ApiUtils import com.nextcloud.talk.utils.ApiUtils
import io.reactivex.Observable import io.reactivex.Observable
import retrofit2.Response import retrofit2.Response
@ -41,7 +43,7 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
override fun media( override fun media(
parameters: SharedItemsRepository.Parameters, parameters: SharedItemsRepository.Parameters,
type: SharedItemType type: SharedItemType
): Observable<SharedMediaItems>? { ): Observable<SharedItems>? {
return media(parameters, type, null) return media(parameters, type, null)
} }
@ -49,7 +51,7 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
parameters: SharedItemsRepository.Parameters, parameters: SharedItemsRepository.Parameters,
type: SharedItemType, type: SharedItemType,
lastKnownMessageId: Int? lastKnownMessageId: Int?
): Observable<SharedMediaItems>? { ): Observable<SharedItems>? {
val credentials = ApiUtils.getCredentials(parameters.userName, parameters.userToken) val credentials = ApiUtils.getCredentials(parameters.userName, parameters.userToken)
return ncApi.getSharedItems( return ncApi.getSharedItems(
@ -58,13 +60,14 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
type.toString().lowercase(Locale.ROOT), type.toString().lowercase(Locale.ROOT),
lastKnownMessageId, lastKnownMessageId,
BATCH_SIZE BATCH_SIZE
).map { map(it, parameters) } ).map { map(it, parameters, type) }
} }
private fun map( private fun map(
response: Response<ChatShareOverall>, response: Response<ChatShareOverall>,
parameters: SharedItemsRepository.Parameters parameters: SharedItemsRepository.Parameters,
): SharedMediaItems { type: SharedItemType
): SharedItems {
var chatLastGiven: Int? = null var chatLastGiven: Int? = null
val items = mutableMapOf<String, SharedItem>() val items = mutableMapOf<String, SharedItem>()
@ -76,15 +79,18 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
val mediaItems = response.body()!!.ocs!!.data val mediaItems = response.body()!!.ocs!!.data
if (mediaItems != null) { if (mediaItems != null) {
for (it in mediaItems) { for (it in mediaItems) {
val actorParameters = it.value.messageParameters!!["actor"]!!
if (it.value.messageParameters?.containsKey("file") == true) { if (it.value.messageParameters?.containsKey("file") == true) {
val fileParameters = it.value.messageParameters!!["file"]!! val fileParameters = it.value.messageParameters!!["file"]!!
val previewAvailable = val previewAvailable =
"yes".equals(fileParameters["preview-available"]!!, ignoreCase = true) "yes".equals(fileParameters["preview-available"]!!, ignoreCase = true)
items[it.value.id] = SharedItem( items[it.value.id] = SharedFileItem(
fileParameters["id"]!!, fileParameters["id"]!!,
fileParameters["name"]!!, fileParameters["name"]!!,
actorParameters["id"]!!,
actorParameters["name"]!!,
fileParameters["size"]!!.toLong(), fileParameters["size"]!!.toLong(),
it.value.timestamp, it.value.timestamp,
fileParameters["path"]!!, fileParameters["path"]!!,
@ -93,6 +99,16 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
previewAvailable, previewAvailable,
previewLink(fileParameters["id"], parameters.baseUrl) previewLink(fileParameters["id"], parameters.baseUrl)
) )
} else if (it.value.messageParameters?.containsKey("object") == true) {
val objectParameters = it.value.messageParameters!!["object"]!!
if ("talk-poll" == objectParameters["type"]) {
items[it.value.id] = SharedPollItem(
objectParameters["id"]!!,
objectParameters["name"]!!,
actorParameters["id"]!!,
actorParameters["name"]!!
)
}
} else { } else {
Log.w(TAG, "location and deckcard are not yet supported") Log.w(TAG, "location and deckcard are not yet supported")
} }
@ -102,8 +118,9 @@ class SharedItemsRepositoryImpl @Inject constructor(private val ncApi: NcApi) :
val sortedMutableItems = items.toSortedMap().values.toList().reversed().toMutableList() val sortedMutableItems = items.toSortedMap().values.toList().reversed().toMutableList()
val moreItemsExisting = items.count() == BATCH_SIZE val moreItemsExisting = items.count() == BATCH_SIZE
return SharedMediaItems( return SharedItems(
sortedMutableItems, sortedMutableItems,
type,
chatLastGiven, chatLastGiven,
moreItemsExisting moreItemsExisting
) )

View File

@ -28,7 +28,7 @@ import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModel
import com.nextcloud.talk.data.user.model.User import com.nextcloud.talk.data.user.model.User
import com.nextcloud.talk.shareditems.model.SharedItemType import com.nextcloud.talk.shareditems.model.SharedItemType
import com.nextcloud.talk.shareditems.model.SharedMediaItems import com.nextcloud.talk.shareditems.model.SharedItems
import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository import com.nextcloud.talk.shareditems.repositories.SharedItemsRepository
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.android.schedulers.AndroidSchedulers import io.reactivex.android.schedulers.AndroidSchedulers
@ -50,7 +50,7 @@ class SharedItemsViewModel @Inject constructor(
class LoadingItemsState(types: Set<SharedItemType>, selectedType: SharedItemType) : class LoadingItemsState(types: Set<SharedItemType>, selectedType: SharedItemType) :
TypesLoadedState(types, selectedType) TypesLoadedState(types, selectedType)
class LoadedState(types: Set<SharedItemType>, selectedType: SharedItemType, val items: SharedMediaItems) : class LoadedState(types: Set<SharedItemType>, selectedType: SharedItemType, val items: SharedItems) :
TypesLoadedState(types, selectedType) TypesLoadedState(types, selectedType)
private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState) private val _viewState: MutableLiveData<ViewState> = MutableLiveData(InitialState)
@ -128,13 +128,13 @@ class SharedItemsViewModel @Inject constructor(
} }
} }
inner class SharedMediaItemsObserver : Observer<SharedMediaItems> { inner class SharedMediaItemsObserver : Observer<SharedItems> {
var newSharedItems: SharedMediaItems? = null var newSharedItems: SharedItems? = null
override fun onSubscribe(d: Disposable) = Unit override fun onSubscribe(d: Disposable) = Unit
override fun onNext(response: SharedMediaItems) { override fun onNext(response: SharedItems) {
newSharedItems = response newSharedItems = response
} }
@ -148,8 +148,9 @@ class SharedItemsViewModel @Inject constructor(
if (state is LoadedState) { if (state is LoadedState) {
val oldItems = state.items.items val oldItems = state.items.items
val newItems = val newItems =
SharedMediaItems( SharedItems(
oldItems + newSharedItems!!.items, oldItems + newSharedItems!!.items,
state.items.type,
newSharedItems!!.lastSeenId, newSharedItems!!.lastSeenId,
newSharedItems!!.moreItemsExisting newSharedItems!!.moreItemsExisting
) )
@ -159,7 +160,7 @@ class SharedItemsViewModel @Inject constructor(
} }
} }
private fun setCurrentState(items: SharedMediaItems) { private fun setCurrentState(items: SharedItems) {
when (val state = this@SharedItemsViewModel._viewState.value) { when (val state = this@SharedItemsViewModel._viewState.value) {
is TypesLoadedState -> { is TypesLoadedState -> {
this@SharedItemsViewModel._viewState.value = LoadedState( this@SharedItemsViewModel._viewState.value = LoadedState(

View File

@ -78,6 +78,7 @@
tools:text="Filename.md" /> tools:text="Filename.md" />
<LinearLayout <LinearLayout
android:id="@+id/file_metadata"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:orientation="horizontal"> android:orientation="horizontal">
@ -91,12 +92,13 @@
tools:text="11 KB" /> tools:text="11 KB" />
<TextView <TextView
android:id="@+id/separator"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/standard_quarter_margin" android:layout_marginStart="@dimen/standard_quarter_margin"
android:text="|"
android:textColor="@color/textColorMaxContrast" android:textColor="@color/textColorMaxContrast"
android:textSize="14sp" android:textSize="14sp"
android:text="|"
tools:ignore="HardcodedText" /> tools:ignore="HardcodedText" />
<TextView <TextView
@ -106,7 +108,7 @@
android:layout_marginStart="@dimen/standard_quarter_margin" android:layout_marginStart="@dimen/standard_quarter_margin"
android:textColor="@color/textColorMaxContrast" android:textColor="@color/textColorMaxContrast"
android:textSize="14sp" android:textSize="14sp"
tools:text="04-05-2022 21:16"/> tools:text="04-05-2022 21:16" />
</LinearLayout> </LinearLayout>
</LinearLayout> </LinearLayout>

View File

@ -523,6 +523,7 @@
<string name="shared_items_audio">Audio</string> <string name="shared_items_audio">Audio</string>
<string name="shared_items_voice">Voice</string> <string name="shared_items_voice">Voice</string>
<string name="shared_items_other">Other</string> <string name="shared_items_other">Other</string>
<string name="shared_items_poll">Poll</string>
<!-- Message search --> <!-- Message search -->
<string name="messages">Messages</string> <string name="messages">Messages</string>