Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
806 changes: 806 additions & 0 deletions app/schemas/com.nextcloud.talk.data.source.local.TalkDatabase/24.json

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions app/src/main/java/com/nextcloud/talk/api/NcApiCoroutines.kt
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ import com.nextcloud.talk.models.json.status.StatusOverall
import com.nextcloud.talk.models.json.testNotification.TestNotificationOverall
import com.nextcloud.talk.models.json.threads.ThreadOverall
import com.nextcloud.talk.models.json.threads.ThreadsOverall
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEventsOverall
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceOverall
import okhttp3.MultipartBody
import okhttp3.RequestBody
Expand Down Expand Up @@ -270,6 +271,12 @@ interface NcApiCoroutines {
@Url url: String
): UserAbsenceOverall

@GET
suspend fun getUpcomingEvents(
@Header("Authorization") authorization: String,
@Url url: String
): UpcomingEventsOverall

@POST
suspend fun testPushNotifications(
@Header("Authorization") authorization: String,
Expand Down
73 changes: 57 additions & 16 deletions app/src/main/java/com/nextcloud/talk/chat/ChatActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -250,7 +250,6 @@ import java.text.SimpleDateFormat
import java.time.Instant
import java.time.ZoneId
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
import java.util.Date
import java.util.Locale
import java.util.concurrent.ExecutionException
Expand Down Expand Up @@ -790,6 +789,15 @@ class ChatActivity :
}
}

conversationUser?.let { user ->
val credentials = ApiUtils.getCredentials(user.username, user.token)
chatViewModel.fetchUpcomingEvent(
credentials!!,
user.baseUrl!!,
roomToken
)
}

if (currentConversation?.objectType == ConversationEnums.ObjectType.EVENT &&
hasSpreedFeatureCapability(
conversationUser?.capabilities!!.spreedCapability!!,
Expand Down Expand Up @@ -1384,6 +1392,47 @@ class ChatActivity :
}
}

chatViewModel.upcomingEventViewState.observe(this) { uiState ->
when (uiState) {
is ChatViewModel.UpcomingEventUIState.Success -> {
val hiddenEventKey = "${uiState.event.uri}${uiState.event.start}${uiState.event.summary}"
if (hiddenEventKey == chatViewModel.hiddenUpcomingEvent) {
binding.upcomingEventCard.visibility = View.GONE
} else {
binding.upcomingEventCard.visibility = View.VISIBLE
viewThemeUtils.material.themeCardView(binding.upcomingEventCard)

binding.upcomingEventContainer.upcomingEventSummary.text = uiState.event.summary

uiState.event.start?.let { start ->
val startDateTime = Instant.ofEpochSecond(start).atZone(ZoneId.systemDefault())
val currentTime = ZonedDateTime.now(ZoneId.systemDefault())
binding.upcomingEventContainer.upcomingEventTime.text =
DateUtils(context).getStringForMeetingStartDateTime(startDateTime, currentTime)
}

binding.upcomingEventContainer.upcomingEventDismiss.setOnClickListener {
binding.upcomingEventCard.visibility = View.GONE
chatViewModel.saveHiddenUpcomingEvent(hiddenEventKey)
Snackbar.make(
binding.root,
R.string.nc_upcoming_event_dismissed,
Snackbar.LENGTH_LONG
).show()
}
}
}

is ChatViewModel.UpcomingEventUIState.Error -> {
Log.e(TAG, "Error fetching upcoming events", uiState.exception)
}

ChatViewModel.UpcomingEventUIState.None -> {
binding.upcomingEventCard.visibility = View.GONE
}
}
}

this.lifecycleScope.launch {
chatViewModel.threadRetrieveState.collect { uiState ->
when (uiState) {
Expand Down Expand Up @@ -2778,6 +2827,12 @@ class ChatActivity :
bundle.putString(KEY_ROOM_TOKEN, roomToken)
bundle.putBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, isOneToOneConversation())

val upcomingEvent =
(chatViewModel.upcomingEventViewState.value as? ChatViewModel.UpcomingEventUIState.Success)?.event
if (upcomingEvent != null) {
bundle.putParcelable(BundleKeys.KEY_UPCOMING_EVENT, upcomingEvent)
}

val intent = Intent(this, ConversationInfoActivity::class.java)
intent.putExtras(bundle)
startActivity(intent)
Expand Down Expand Up @@ -3815,21 +3870,7 @@ class ChatActivity :

return when {
currentTime.isBefore(startDateTime) -> {
val isToday = startDateTime.toLocalDate().isEqual(currentTime.toLocalDate())
val isTomorrow = startDateTime.toLocalDate().isEqual(currentTime.toLocalDate().plusDays(1))
when {
isToday -> String.format(
context.resources.getString(R.string.nc_today_meeting),
startDateTime.format(DateTimeFormatter.ofPattern("HH:mm"))
)

isTomorrow -> String.format(
context.resources.getString(R.string.nc_tomorrow_meeting),
startDateTime.format(DateTimeFormatter.ofPattern("HH:mm"))
)

else -> startDateTime.format(DateTimeFormatter.ofPattern("MMM d, yyyy, HH:mm"))
}
DateUtils(context).getStringForMeetingStartDateTime(startDateTime, currentTime)
}

currentTime.isAfter(endDateTime) -> context.resources.getString(R.string.nc_meeting_ended)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.opengraph.Reference
import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEventsOverall
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceOverall
import io.reactivex.Observable
import retrofit2.Response
Expand Down Expand Up @@ -70,6 +71,7 @@ interface ChatNetworkDataSource {
fun setChatReadMarker(credentials: String, url: String, previousMessageId: Int): Observable<GenericOverall>
suspend fun editChatMessage(credentials: String, url: String, text: String): ChatOverallSingleMessage
suspend fun getOutOfOfficeStatusForUser(credentials: String, baseUrl: String, userId: String): UserAbsenceOverall
suspend fun getUpcomingEvents(credentials: String, baseUrl: String, roomToken: String): UpcomingEventsOverall
suspend fun getContextForChatMessage(
credentials: String,
baseUrl: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.opengraph.Reference
import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEventsOverall
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceOverall
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.message.SendMessageUtils
Expand Down Expand Up @@ -194,6 +195,16 @@ class RetrofitChatNetwork(private val ncApi: NcApi, private val ncApiCoroutines:
ApiUtils.getUrlForOutOfOffice(baseUrl, userId)
)

override suspend fun getUpcomingEvents(
credentials: String,
baseUrl: String,
roomToken: String
): UpcomingEventsOverall =
ncApiCoroutines.getUpcomingEvents(
credentials,
ApiUtils.getUrlForUpcomingEvents(baseUrl, roomToken)
)

override suspend fun getContextForChatMessage(
credentials: String,
baseUrl: String,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.opengraph.Reference
import com.nextcloud.talk.models.json.reminder.Reminder
import com.nextcloud.talk.models.json.threads.ThreadInfo
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEvent
import com.nextcloud.talk.models.json.userAbsence.UserAbsenceData
import com.nextcloud.talk.repositories.reactions.ReactionsRepository
import com.nextcloud.talk.threadsoverview.data.ThreadsRepository
Expand Down Expand Up @@ -101,6 +102,7 @@ class ChatViewModel @Inject constructor(
val mediaPlayerPosition = mediaPlayerManager.mediaPlayerPosition
var chatRoomToken: String = ""
var messageDraft: MessageDraft = MessageDraft()
var hiddenUpcomingEvent: String? = null
lateinit var participantPermissions: ParticipantPermissions

fun getChatRepository(): ChatMessageRepository = chatRepository
Expand Down Expand Up @@ -164,6 +166,10 @@ class ChatViewModel @Inject constructor(
val outOfOfficeViewState: LiveData<OutOfOfficeUIState>
get() = _outOfOfficeViewState

private val _upcomingEventViewState = MutableLiveData<UpcomingEventUIState>(UpcomingEventUIState.None)
val upcomingEventViewState: LiveData<UpcomingEventUIState>
get() = _upcomingEventViewState

private val _unbindRoomResult = MutableLiveData<UnbindRoomUiState>(UnbindRoomUiState.None)
val unbindRoomResult: LiveData<UnbindRoomUiState>
get() = _unbindRoomResult
Expand Down Expand Up @@ -990,6 +996,24 @@ class ChatViewModel @Inject constructor(
}
}

@Suppress("Detekt.TooGenericExceptionCaught")
fun fetchUpcomingEvent(credentials: String, baseUrl: String, roomToken: String) {
viewModelScope.launch {
updateHiddenUpcomingEvent()
try {
val response = chatNetworkDataSource.getUpcomingEvents(credentials, baseUrl, roomToken)
val firstEvent = response.ocs?.data?.events?.firstOrNull()
if (firstEvent != null) {
_upcomingEventViewState.value = UpcomingEventUIState.Success(firstEvent)
} else {
_upcomingEventViewState.value = UpcomingEventUIState.None
}
} catch (exception: Exception) {
_upcomingEventViewState.value = UpcomingEventUIState.Error(exception)
}
}
}

fun deleteTempMessage(chatMessage: ChatMessage) {
viewModelScope.launch {
chatRepository.deleteTempMessage(chatMessage)
Expand Down Expand Up @@ -1057,6 +1081,30 @@ class ChatViewModel @Inject constructor(
}
}

suspend fun updateHiddenUpcomingEvent() {
val model = conversationRepository.getLocallyStoredConversation(
currentUser,
chatRoomToken
)
model?.hiddenUpcomingEvent?.let {
hiddenUpcomingEvent = it
}
}

fun saveHiddenUpcomingEvent(value: String) {
hiddenUpcomingEvent = value
viewModelScope.launch {
val model = conversationRepository.getLocallyStoredConversation(
currentUser,
chatRoomToken
)
model?.let {
it.hiddenUpcomingEvent = value
conversationRepository.updateConversation(it)
}
}
}

fun pinMessage(credentials: String, url: String, pinUntil: Int = 0) {
viewModelScope.launch {
chatRepository.pinMessage(credentials, url, pinUntil).collect {
Expand Down Expand Up @@ -1118,4 +1166,10 @@ class ChatViewModel @Inject constructor(
data class Success(val thread: ThreadInfo?) : ThreadRetrieveUiState()
data class Error(val exception: Exception) : ThreadRetrieveUiState()
}

sealed class UpcomingEventUIState {
data object None : UpcomingEventUIState()
data class Success(val event: UpcomingEvent) : UpcomingEventUIState()
data class Error(val exception: Exception) : UpcomingEventUIState()
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,7 @@ import com.nextcloud.talk.databinding.ActivityConversationInfoBinding
import com.nextcloud.talk.databinding.DialogBanParticipantBinding
import com.nextcloud.talk.events.EventStatus
import com.nextcloud.talk.extensions.getParcelableArrayListExtraProvider
import com.nextcloud.talk.extensions.getParcelableExtraProvider
import com.nextcloud.talk.extensions.loadConversationAvatar
import com.nextcloud.talk.extensions.loadNoteToSelfAvatar
import com.nextcloud.talk.extensions.loadSystemAvatar
Expand All @@ -73,6 +74,7 @@ import com.nextcloud.talk.models.domain.converters.DomainEnumNotificationLevelCo
import com.nextcloud.talk.models.json.autocomplete.AutocompleteUser
import com.nextcloud.talk.models.json.capabilities.SpreedCapability
import com.nextcloud.talk.models.json.conversations.ConversationEnums
import com.nextcloud.talk.models.json.upcomingEvents.UpcomingEvent
import com.nextcloud.talk.models.json.converters.EnumActorTypeConverter
import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.participants.Participant
Expand Down Expand Up @@ -105,6 +107,7 @@ import kotlinx.coroutines.launch
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.time.Instant
import java.time.ZoneId
import java.time.ZoneOffset
import java.time.ZonedDateTime
import java.time.format.DateTimeFormatter
Expand Down Expand Up @@ -200,6 +203,19 @@ class ConversationInfoActivity :

hasAvatarSpacing = intent.getBooleanExtra(BundleKeys.KEY_ROOM_ONE_TO_ONE, false)

val upcomingEvent = intent.getParcelableExtraProvider<UpcomingEvent>(BundleKeys.KEY_UPCOMING_EVENT)
if (upcomingEvent != null && (upcomingEvent.summary != null || upcomingEvent.start != null)) {
binding.upcomingEventCard.visibility = VISIBLE
viewThemeUtils.material.themeCardView(binding.upcomingEventCard)
binding.upcomingEventContainer.upcomingEventSummary.text = upcomingEvent.summary
upcomingEvent.start?.let { start ->
val startDateTime = Instant.ofEpochSecond(start).atZone(ZoneId.systemDefault())
val currentTime = ZonedDateTime.now(ZoneId.systemDefault())
binding.upcomingEventContainer.upcomingEventTime.text =
DateUtils(this).getStringForMeetingStartDateTime(startDateTime, currentTime)
}
}

viewModel = ViewModelProvider(this, viewModelFactory)[ConversationInfoViewModel::class.java]

lifecycleScope.launch {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class OfflineFirstConversationsRepository @Inject constructor(

override fun onNext(model: ConversationModel) {
runBlocking {
val existingEntity = dao.getConversationForUser(user.id!!, model.token).first()
model.hiddenUpcomingEvent = existingEntity?.hiddenUpcomingEvent
_conversationFlow.emit(model)
val entityList = listOf(model.asEntity())
dao.upsertConversations(user.id!!, entityList)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ interface ConversationsDao {
if (existingItem != null) {
val mergedItem = serverItem.copy()
mergedItem.messageDraft = existingItem.messageDraft
mergedItem.hiddenUpcomingEvent = existingItem.hiddenUpcomingEvent
updateConversation(mergedItem)
} else {
insertConversation(serverItem)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,8 @@ fun ConversationModel.asEntity() =
hasImportant = hasImportant,
messageDraft = messageDraft,
hiddenPinnedId = hiddenPinnedId,
lastPinnedId = lastPinnedId
lastPinnedId = lastPinnedId,
hiddenUpcomingEvent = hiddenUpcomingEvent
)

fun ConversationEntity.asModel() =
Expand Down Expand Up @@ -123,7 +124,8 @@ fun ConversationEntity.asModel() =
hasImportant = hasImportant,
messageDraft = messageDraft,
hiddenPinnedId = hiddenPinnedId,
lastPinnedId = lastPinnedId
lastPinnedId = lastPinnedId,
hiddenUpcomingEvent = hiddenUpcomingEvent
)

fun Conversation.asEntity(accountId: Long) =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,8 @@ data class ConversationEntity(
@ColumnInfo(name = "hasImportant") var hasImportant: Boolean = false,
@ColumnInfo(name = "hiddenPinnedId") var hiddenPinnedId: Long? = null,
@ColumnInfo(name = "lastPinnedId") var lastPinnedId: Long? = null,
@ColumnInfo(name = "messageDraft") var messageDraft: MessageDraft? = MessageDraft()
@ColumnInfo(name = "messageDraft") var messageDraft: MessageDraft? = MessageDraft(),
@ColumnInfo(name = "hiddenUpcomingEvent") var hiddenUpcomingEvent: String? = null
// missing/not needed: attendeeId
// missing/not needed: attendeePin
// missing/not needed: attendeePermissions
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,14 +48,15 @@ import java.util.Locale
ChatMessageEntity::class,
ChatBlockEntity::class
],
version = 23,
version = 24,
autoMigrations = [
AutoMigration(from = 9, to = 10),
AutoMigration(from = 16, to = 17, spec = AutoMigration16To17::class),
AutoMigration(from = 19, to = 20),
AutoMigration(from = 20, to = 21),
AutoMigration(from = 21, to = 22),
AutoMigration(from = 22, to = 23)
AutoMigration(from = 22, to = 23),
AutoMigration(from = 23, to = 24)
],
exportSchema = true
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,8 @@ data class ConversationModel(

// attributes that don't come from API. This should be changed?!
var password: String? = null,
var messageDraft: MessageDraft? = MessageDraft()
var messageDraft: MessageDraft? = MessageDraft(),
var hiddenUpcomingEvent: String? = null
) {

companion object {
Expand Down
Loading
Loading