mirror of
https://github.com/SchildiChat/SchildiChat-android.git
synced 2024-11-24 18:36:21 +03:00
Adding go to timeline event button
This commit is contained in:
parent
eaa9cc740e
commit
384e7f674d
9 changed files with 203 additions and 10 deletions
|
@ -3207,6 +3207,7 @@
|
|||
<string name="room_polls_wait_for_display">Displaying polls</string>
|
||||
<string name="room_polls_load_more">Load more polls</string>
|
||||
<string name="room_polls_loading_error">Error fetching polls.</string>
|
||||
<string name="room_poll_details_go_to_timeline">View poll in timeline</string>
|
||||
|
||||
<!-- Location -->
|
||||
<string name="location_activity_title_static_sharing">Share location</string>
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.polls.detail.domain
|
||||
|
||||
import im.vector.app.core.di.ActiveSessionHolder
|
||||
import org.matrix.android.sdk.api.session.events.model.RelationType
|
||||
import org.matrix.android.sdk.api.session.events.model.isPollEnd
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO add unit tests
|
||||
class GetEndedPollEventIdUseCase @Inject constructor(
|
||||
private val activeSessionHolder: ActiveSessionHolder,
|
||||
) {
|
||||
|
||||
fun execute(roomId: String, startPollEventId: String): String? {
|
||||
return activeSessionHolder.getActiveSession()
|
||||
.roomService()
|
||||
.getRoom(roomId)
|
||||
?.timelineService()
|
||||
?.getTimelineEventsRelatedTo(RelationType.REFERENCE, startPollEventId)
|
||||
?.find { it.root.isPollEnd() }
|
||||
?.eventId
|
||||
}
|
||||
}
|
|
@ -20,5 +20,6 @@ import im.vector.app.features.poll.PollItemViewState
|
|||
|
||||
data class RoomPollDetail(
|
||||
val isEnded: Boolean,
|
||||
val endedPollEventId: String?,
|
||||
val pollItemViewState: PollItemViewState,
|
||||
)
|
||||
|
|
|
@ -17,12 +17,14 @@
|
|||
package im.vector.app.features.roomprofile.polls.detail.ui
|
||||
|
||||
import com.airbnb.epoxy.TypedEpoxyController
|
||||
import java.util.UUID
|
||||
import javax.inject.Inject
|
||||
|
||||
class RoomPollDetailController @Inject constructor() : TypedEpoxyController<RoomPollDetailViewState>() {
|
||||
|
||||
interface Callback {
|
||||
fun vote(pollEventId: String, optionId: String)
|
||||
fun goToTimelineEvent(eventId: String)
|
||||
}
|
||||
|
||||
var callback: Callback? = null
|
||||
|
@ -41,5 +43,17 @@ class RoomPollDetailController @Inject constructor() : TypedEpoxyController<Room
|
|||
optionViewStates(pollItemViewState.optionViewStates.orEmpty())
|
||||
callback(host.callback)
|
||||
}
|
||||
|
||||
buildGoToTimelineItem(targetEventId = pollDetail.endedPollEventId ?: viewState.pollId)
|
||||
}
|
||||
|
||||
private fun buildGoToTimelineItem(targetEventId: String) {
|
||||
val host = this
|
||||
roomPollGoToTimelineItem {
|
||||
id(UUID.randomUUID().toString())
|
||||
clickListener {
|
||||
host.callback?.goToTimelineEvent(targetEventId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -31,6 +31,7 @@ import im.vector.app.core.extensions.configureWith
|
|||
import im.vector.app.core.platform.VectorBaseFragment
|
||||
import im.vector.app.databinding.FragmentRoomPollDetailBinding
|
||||
import kotlinx.parcelize.Parcelize
|
||||
import timber.log.Timber
|
||||
import javax.inject.Inject
|
||||
|
||||
@Parcelize
|
||||
|
@ -45,6 +46,7 @@ class RoomPollDetailFragment :
|
|||
VectorBaseFragment<FragmentRoomPollDetailBinding>(),
|
||||
RoomPollDetailController.Callback {
|
||||
|
||||
@Inject lateinit var viewNavigator: RoomPollDetailNavigator
|
||||
@Inject lateinit var roomPollDetailController: RoomPollDetailController
|
||||
|
||||
private val viewModel: RoomPollDetailViewModel by fragmentViewModel()
|
||||
|
@ -58,7 +60,6 @@ class RoomPollDetailFragment :
|
|||
super.onViewCreated(view, savedInstanceState)
|
||||
setupToolbar(isEnded = roomPollDetailArgs.isEnded)
|
||||
setupDetailView()
|
||||
// TODO add link to go to timeline message + create a ViewNavigator
|
||||
}
|
||||
|
||||
override fun onDestroyView() {
|
||||
|
@ -93,4 +94,12 @@ class RoomPollDetailFragment :
|
|||
override fun vote(pollEventId: String, optionId: String) {
|
||||
viewModel.handle(RoomPollDetailAction.Vote(pollEventId = pollEventId, optionId = optionId))
|
||||
}
|
||||
|
||||
override fun goToTimelineEvent(eventId: String) = withState(viewModel) { state ->
|
||||
viewNavigator.goToTimelineEvent(
|
||||
context = requireContext(),
|
||||
roomId = state.roomId,
|
||||
eventId = eventId,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,6 +19,9 @@ package im.vector.app.features.roomprofile.polls.detail.ui
|
|||
import im.vector.app.core.extensions.getVectorLastMessageContent
|
||||
import im.vector.app.features.home.room.detail.timeline.factory.PollItemViewStateFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.helper.PollResponseDataFactory
|
||||
import im.vector.app.features.home.room.detail.timeline.item.PollResponseData
|
||||
import im.vector.app.features.roomprofile.polls.detail.domain.GetEndedPollEventIdUseCase
|
||||
import org.matrix.android.sdk.api.extensions.orFalse
|
||||
import org.matrix.android.sdk.api.session.room.model.message.MessagePollContent
|
||||
import org.matrix.android.sdk.api.session.room.timeline.TimelineEvent
|
||||
import timber.log.Timber
|
||||
|
@ -28,6 +31,7 @@ import javax.inject.Inject
|
|||
class RoomPollDetailMapper @Inject constructor(
|
||||
private val pollResponseDataFactory: PollResponseDataFactory,
|
||||
private val pollItemViewStateFactory: PollItemViewStateFactory,
|
||||
private val getEndedPollEventIdUseCase: GetEndedPollEventIdUseCase,
|
||||
) {
|
||||
|
||||
fun map(timelineEvent: TimelineEvent): RoomPollDetail? {
|
||||
|
@ -36,16 +40,13 @@ class RoomPollDetailMapper @Inject constructor(
|
|||
val content = timelineEvent.getVectorLastMessageContent()
|
||||
val pollResponseData = pollResponseDataFactory.create(timelineEvent)
|
||||
return if (eventId.isNotEmpty() && content is MessagePollContent) {
|
||||
// we assume poll message has been sent here
|
||||
val pollItemViewState = pollItemViewStateFactory.create(
|
||||
pollContent = content,
|
||||
pollResponseData = pollResponseData,
|
||||
isSent = true,
|
||||
)
|
||||
RoomPollDetail(
|
||||
isEnded = pollResponseData?.isClosed == true,
|
||||
pollItemViewState = pollItemViewState,
|
||||
val isPollEnded = pollResponseData?.isClosed.orFalse()
|
||||
val endedPollEventId = getEndedPollEventId(
|
||||
isPollEnded,
|
||||
startPollEventId = eventId,
|
||||
roomId = timelineEvent.roomId,
|
||||
)
|
||||
convertToRoomPollDetail(content, pollResponseData, isPollEnded, endedPollEventId)
|
||||
} else {
|
||||
Timber.w("missing mandatory info about poll event with id=$eventId")
|
||||
null
|
||||
|
@ -57,4 +58,35 @@ class RoomPollDetailMapper @Inject constructor(
|
|||
}
|
||||
return result.getOrNull()
|
||||
}
|
||||
|
||||
private fun convertToRoomPollDetail(
|
||||
content: MessagePollContent,
|
||||
pollResponseData: PollResponseData?,
|
||||
isPollEnded: Boolean,
|
||||
endedPollEventId: String?,
|
||||
): RoomPollDetail {
|
||||
// we assume the poll has been sent
|
||||
val pollItemViewState = pollItemViewStateFactory.create(
|
||||
pollContent = content,
|
||||
pollResponseData = pollResponseData,
|
||||
isSent = true,
|
||||
)
|
||||
return RoomPollDetail(
|
||||
isEnded = isPollEnded,
|
||||
pollItemViewState = pollItemViewState,
|
||||
endedPollEventId = endedPollEventId,
|
||||
)
|
||||
}
|
||||
|
||||
private fun getEndedPollEventId(
|
||||
isPollEnded: Boolean,
|
||||
startPollEventId: String,
|
||||
roomId: String,
|
||||
): String? {
|
||||
return if (isPollEnded) {
|
||||
getEndedPollEventIdUseCase.execute(startPollEventId = startPollEventId, roomId = roomId)
|
||||
} else {
|
||||
null
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.polls.detail.ui
|
||||
|
||||
import android.content.Context
|
||||
import im.vector.app.features.navigation.Navigator
|
||||
import javax.inject.Inject
|
||||
|
||||
// TODO add unit tests
|
||||
class RoomPollDetailNavigator @Inject constructor(
|
||||
private val navigator: Navigator,
|
||||
) {
|
||||
|
||||
fun goToTimelineEvent(context: Context, roomId: String, eventId: String) {
|
||||
navigator.openRoom(
|
||||
context = context,
|
||||
roomId = roomId,
|
||||
eventId = eventId,
|
||||
buildTask = true,
|
||||
)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (c) 2023 New Vector Ltd
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package im.vector.app.features.roomprofile.polls.detail.ui
|
||||
|
||||
import android.widget.Button
|
||||
import com.airbnb.epoxy.EpoxyAttribute
|
||||
import com.airbnb.epoxy.EpoxyModelClass
|
||||
import im.vector.app.R
|
||||
import im.vector.app.core.epoxy.ClickListener
|
||||
import im.vector.app.core.epoxy.VectorEpoxyHolder
|
||||
import im.vector.app.core.epoxy.VectorEpoxyModel
|
||||
import im.vector.app.core.epoxy.onClick
|
||||
|
||||
@EpoxyModelClass
|
||||
abstract class RoomPollGoToTimelineItem : VectorEpoxyModel<RoomPollGoToTimelineItem.Holder>(R.layout.item_poll_go_to_timeline) {
|
||||
|
||||
@EpoxyAttribute(EpoxyAttribute.Option.DoNotHash)
|
||||
var clickListener: ClickListener? = null
|
||||
|
||||
override fun bind(holder: Holder) {
|
||||
super.bind(holder)
|
||||
holder.goToTimelineButton.onClick(clickListener)
|
||||
}
|
||||
|
||||
class Holder : VectorEpoxyHolder() {
|
||||
val goToTimelineButton by bind<Button>(R.id.roomPollGoToTimeline)
|
||||
}
|
||||
}
|
20
vector/src/main/res/layout/item_poll_go_to_timeline.xml
Normal file
20
vector/src/main/res/layout/item_poll_go_to_timeline.xml
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout 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_height="wrap_content">
|
||||
|
||||
<Button
|
||||
android:id="@+id/roomPollGoToTimeline"
|
||||
style="@style/Widget.Vector.Button.Text"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="33dp"
|
||||
android:layout_marginBottom="46dp"
|
||||
android:padding="0dp"
|
||||
android:text="@string/room_poll_details_go_to_timeline"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
Loading…
Reference in a new issue