diff --git a/app/build.gradle b/app/build.gradle index b569a18234..12b174e0b5 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -96,6 +96,7 @@ dependencies { kapt 'com.github.bumptech.glide:compiler:4.8.0' implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1' implementation 'com.google.android.material:material:1.1.0-alpha02' + implementation 'me.gujun.android:span:1.7' // DI implementation "org.koin:koin-android:$koin_version" diff --git a/app/src/main/java/im/vector/riotredesign/core/di/AppModule.kt b/app/src/main/java/im/vector/riotredesign/core/di/AppModule.kt index 13f93eba5f..bbc973152c 100644 --- a/app/src/main/java/im/vector/riotredesign/core/di/AppModule.kt +++ b/app/src/main/java/im/vector/riotredesign/core/di/AppModule.kt @@ -18,6 +18,7 @@ package im.vector.riotredesign.core.di import android.content.Context import android.content.Context.MODE_PRIVATE +import im.vector.riotredesign.core.resources.ColorProvider import im.vector.riotredesign.core.resources.LocaleProvider import im.vector.riotredesign.core.resources.StringProvider import im.vector.riotredesign.features.home.room.list.RoomSelectionRepository @@ -35,6 +36,10 @@ class AppModule(private val context: Context) { StringProvider(context.resources) } + single { + ColorProvider(context) + } + single { context.getSharedPreferences("im.vector.riot", MODE_PRIVATE) } diff --git a/app/src/main/java/im/vector/riotredesign/core/epoxy/EmptyItem.kt b/app/src/main/java/im/vector/riotredesign/core/epoxy/EmptyItem.kt new file mode 100644 index 0000000000..9abf7c7aa1 --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/core/epoxy/EmptyItem.kt @@ -0,0 +1,27 @@ +/* + * + * * Copyright 2019 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.riotredesign.core.epoxy + +import com.airbnb.epoxy.EpoxyModelClass +import im.vector.riotredesign.R + +@EpoxyModelClass(layout = R.layout.item_empty) +abstract class EmptyItem : RiotEpoxyModel() { + class Holder : RiotEpoxyHolder() +} \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/LoadingItem.kt b/app/src/main/java/im/vector/riotredesign/core/epoxy/LoadingItem.kt similarity index 88% rename from app/src/main/java/im/vector/riotredesign/features/home/LoadingItem.kt rename to app/src/main/java/im/vector/riotredesign/core/epoxy/LoadingItem.kt index c803c04782..cade275ba0 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/LoadingItem.kt +++ b/app/src/main/java/im/vector/riotredesign/core/epoxy/LoadingItem.kt @@ -14,7 +14,7 @@ * limitations under the License. */ -package im.vector.riotredesign.features.home +package im.vector.riotredesign.core.epoxy import android.content.Context import android.widget.ProgressBar diff --git a/app/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt b/app/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt new file mode 100644 index 0000000000..4fd37212a9 --- /dev/null +++ b/app/src/main/java/im/vector/riotredesign/core/resources/ColorProvider.kt @@ -0,0 +1,31 @@ +/* + * + * * Copyright 2019 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.riotredesign.core.resources + +import android.content.Context +import androidx.annotation.ColorRes +import androidx.core.content.ContextCompat + +class ColorProvider(private val context: Context) { + + fun getColor(@ColorRes colorRes: Int): Int { + return ContextCompat.getColor(context, colorRes) + } + +} \ No newline at end of file diff --git a/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt b/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt index b63f7142f2..0500181862 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/HomeModule.kt @@ -18,14 +18,7 @@ package im.vector.riotredesign.features.home import im.vector.riotredesign.features.home.group.SelectedGroupStore import im.vector.riotredesign.features.home.room.VisibleRoomStore -import im.vector.riotredesign.features.home.room.detail.timeline.DefaultItemFactory -import im.vector.riotredesign.features.home.room.detail.timeline.MessageItemFactory -import im.vector.riotredesign.features.home.room.detail.timeline.RoomMemberItemFactory -import im.vector.riotredesign.features.home.room.detail.timeline.RoomNameItemFactory -import im.vector.riotredesign.features.home.room.detail.timeline.RoomTopicItemFactory -import im.vector.riotredesign.features.home.room.detail.timeline.TimelineDateFormatter -import im.vector.riotredesign.features.home.room.detail.timeline.TimelineEventController -import im.vector.riotredesign.features.home.room.detail.timeline.TimelineItemFactory +import im.vector.riotredesign.features.home.room.detail.timeline.* import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider import im.vector.riotredesign.features.home.room.list.RoomSummaryComparator import im.vector.riotredesign.features.home.room.list.RoomSummaryController @@ -40,7 +33,7 @@ class HomeModule { } single { - MessageItemFactory(get(), get()) + MessageItemFactory(get(), get(), get()) } single { diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt index fc377798dd..e2f61cf0c8 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/MessageItemFactory.kt @@ -22,17 +22,18 @@ import im.vector.matrix.android.api.permalinks.MatrixLinkify import im.vector.matrix.android.api.permalinks.MatrixPermalinkSpan import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.events.model.toModel -import im.vector.matrix.android.api.session.room.model.message.MessageContent -import im.vector.matrix.android.api.session.room.model.message.MessageEmoteContent -import im.vector.matrix.android.api.session.room.model.message.MessageImageContent -import im.vector.matrix.android.api.session.room.model.message.MessageTextContent +import im.vector.matrix.android.api.session.room.model.message.* import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.riotredesign.R import im.vector.riotredesign.core.epoxy.RiotEpoxyModel import im.vector.riotredesign.core.extensions.localDateTime +import im.vector.riotredesign.core.resources.ColorProvider import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider import im.vector.riotredesign.features.media.MediaContentRenderer +import me.gujun.android.span.span -class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSizeProvider, +class MessageItemFactory(private val colorProvider: ColorProvider, + private val timelineMediaSizeProvider: TimelineMediaSizeProvider, private val timelineDateFormatter: TimelineDateFormatter) { private val messagesDisplayedWithInformation = HashSet() @@ -66,10 +67,11 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz val informationData = MessageInformationData(time, avatarUrl, memberName, showInformation) return when (messageContent) { - is MessageTextContent -> buildTextMessageItem(messageContent, informationData, callback) - is MessageImageContent -> buildImageMessageItem(messageContent, informationData) - is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, callback) - else -> buildNotHandledMessageItem(messageContent) + is MessageTextContent -> buildTextMessageItem(messageContent, informationData, callback) + is MessageImageContent -> buildImageMessageItem(messageContent, informationData) + is MessageEmoteContent -> buildEmoteMessageItem(messageContent, informationData, callback) + is MessageNoticeContent -> buildNoticeMessageItem(messageContent, informationData, callback) + else -> buildNotHandledMessageItem(messageContent) } } @@ -106,6 +108,23 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz .informationData(informationData) } + private fun buildNoticeMessageItem(messageContent: MessageNoticeContent, + informationData: MessageInformationData, + callback: TimelineEventController.Callback?): MessageTextItem? { + + val message = messageContent.body.let { + val formattedBody = span { + text = it + textColor = colorProvider.getColor(R.color.slate_grey) + textStyle = "italic" + } + linkifyBody(formattedBody, callback) + } + return MessageTextItem_() + .message(message) + .informationData(informationData) + } + private fun buildEmoteMessageItem(messageContent: MessageEmoteContent, informationData: MessageInformationData, callback: TimelineEventController.Callback?): MessageTextItem? { @@ -119,7 +138,7 @@ class MessageItemFactory(private val timelineMediaSizeProvider: TimelineMediaSiz .informationData(informationData) } - private fun linkifyBody(body: String, callback: TimelineEventController.Callback?): CharSequence { + private fun linkifyBody(body: CharSequence, callback: TimelineEventController.Callback?): CharSequence { val spannable = SpannableStringBuilder(body) MatrixLinkify.addLinks(spannable, object : MatrixPermalinkSpan.Callback { override fun onUrlClicked(url: String) { diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt index 75b3f26580..373612c1ac 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineEventController.kt @@ -23,9 +23,9 @@ import com.airbnb.epoxy.VisibilityState import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.timeline.TimelineData import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.riotredesign.core.epoxy.LoadingItemModel_ import im.vector.riotredesign.core.epoxy.RiotEpoxyModel import im.vector.riotredesign.core.extensions.localDateTime -import im.vector.riotredesign.features.home.LoadingItemModel_ import im.vector.riotredesign.features.home.room.detail.timeline.helper.TimelineMediaSizeProvider import im.vector.riotredesign.features.home.room.detail.timeline.paging.PagedListEpoxyController diff --git a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt index 8fca5301b0..366ea2d92e 100644 --- a/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt +++ b/app/src/main/java/im/vector/riotredesign/features/home/room/detail/timeline/TimelineItemFactory.kt @@ -18,6 +18,7 @@ package im.vector.riotredesign.features.home.room.detail.timeline import im.vector.matrix.android.api.session.events.model.EventType import im.vector.matrix.android.api.session.room.timeline.TimelineEvent +import im.vector.riotredesign.core.epoxy.EmptyItem_ import im.vector.riotredesign.core.epoxy.RiotEpoxyModel class TimelineItemFactory(private val messageItemFactory: MessageItemFactory, @@ -36,6 +37,9 @@ class TimelineItemFactory(private val messageItemFactory: MessageItemFactory, EventType.STATE_ROOM_NAME -> roomNameItemFactory.create(event) EventType.STATE_ROOM_TOPIC -> roomTopicItemFactory.create(event) EventType.STATE_ROOM_MEMBER -> roomMemberItemFactory.create(event) + EventType.STATE_ROOM_CREATE, + EventType.STATE_ROOM_POWER_LEVELS, + EventType.REDACTION -> EmptyItem_() else -> defaultItemFactory.create(event) } } catch (e: Exception) { diff --git a/app/src/main/res/layout/item_empty.xml b/app/src/main/res/layout/item_empty.xml new file mode 100644 index 0000000000..f7afb77576 --- /dev/null +++ b/app/src/main/res/layout/item_empty.xml @@ -0,0 +1,4 @@ + + \ No newline at end of file