Commit 3fca452b authored by Janne Koschinski's avatar Janne Koschinski

Implement attachments

parent 2eca6ee2
Pipeline #411 canceled with stages
......@@ -137,6 +137,7 @@ dependencies {
implementation("commons-codec", "commons-codec", "1.11")
implementation("com.squareup.retrofit2", "retrofit", "2.5.0")
implementation("com.squareup.retrofit2", "converter-gson", "2.5.0")
implementation("com.squareup.retrofit2", "adapter-rxjava2", "2.5.0")
withVersion("10.0.0") {
implementation("com.jakewharton", "butterknife", version)
kapt("com.jakewharton", "butterknife-compiler", version)
......
......@@ -39,7 +39,8 @@
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/Theme.SplashTheme">
android:theme="@style/Theme.SplashTheme"
android:usesCleartextTraffic="true">
<meta-data
android:name="WindowManagerPreference:FreeformWindowSize"
......@@ -112,6 +113,18 @@
android:exported="false"
android:label="@string/label_info_certificate"
android:windowSoftInputMode="adjustResize" />
<activity
android:name="de.kuschku.quasseldroid.ui.info.message.MessageInfoActivity"
android:exported="true"
android:label="@string/label_info_message"
android:windowSoftInputMode="adjustResize">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- Core Settings -->
<activity
......
......@@ -77,6 +77,8 @@ import de.kuschku.quasseldroid.ui.info.channellist.ChannelListActivity
import de.kuschku.quasseldroid.ui.info.channellist.ChannelListFragmentProvider
import de.kuschku.quasseldroid.ui.info.core.CoreInfoActivity
import de.kuschku.quasseldroid.ui.info.core.CoreInfoFragmentProvider
import de.kuschku.quasseldroid.ui.info.message.MessageInfoActivity
import de.kuschku.quasseldroid.ui.info.message.MessageInfoFragmentProvider
import de.kuschku.quasseldroid.ui.info.topic.TopicActivity
import de.kuschku.quasseldroid.ui.info.user.UserInfoActivity
import de.kuschku.quasseldroid.ui.info.user.UserInfoFragmentProvider
......@@ -123,6 +125,10 @@ abstract class ActivityModule {
@ContributesAndroidInjector(modules = [CertificateInfoFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class])
abstract fun bindCertificateInfoActivity(): CertificateInfoActivity
@ActivityScope
@ContributesAndroidInjector(modules = [MessageInfoFragmentProvider::class, SettingsModule::class, DatabaseModule::class, ActivityBaseModule::class])
abstract fun bindMessageInfoActivity(): MessageInfoActivity
// Client Settings
@ActivityScope
......
......@@ -31,9 +31,11 @@ import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import com.bumptech.glide.load.engine.DiskCacheStrategy
import de.kuschku.libquassel.protocol.Message_Flag
import de.kuschku.libquassel.protocol.Message_Type
import de.kuschku.libquassel.util.flag.hasFlag
import de.kuschku.quasseldroid.GlideApp
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.persistence.models.MessageData
import de.kuschku.quasseldroid.settings.MessageSettings
......@@ -42,6 +44,7 @@ import de.kuschku.quasseldroid.util.helper.loadAvatars
import de.kuschku.quasseldroid.util.helper.visibleIf
import de.kuschku.quasseldroid.util.ui.BetterLinkMovementMethod
import de.kuschku.quasseldroid.util.ui.DoubleClickHelper
import de.kuschku.quasseldroid.util.ui.view.MessageAttachmentView
import de.kuschku.quasseldroid.viewmodel.data.FormattedMessage
import javax.inject.Inject
......@@ -225,6 +228,10 @@ class MessageAdapter @Inject constructor(
@JvmField
var combined: TextView? = null
@BindView(R.id.attachment)
@JvmField
var attachment: MessageAttachmentView? = null
private var message: FormattedMessage? = null
private var original: MessageData? = null
......@@ -278,6 +285,46 @@ class MessageAdapter @Inject constructor(
content?.text = message.content
combined?.text = message.combined
attachment?.visibleIf(message.attachment != null)
attachment?.post {
attachment?.apply {
val attachment = message.attachment
reinitViews()
if (attachment != null) {
setLink(attachment.fromUrl)
setColor(attachment.color)
GlideApp.with(itemView)
.load(attachment.authorIcon)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(authorIconTarget)
setAuthor(attachment.authorName)
setTitle(attachment.title)
setDescription(attachment.text)
if (false) {
GlideApp.with(itemView)
.clear(thumbnailTarget)
GlideApp.with(itemView)
.load(attachment.imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(previewTarget)
} else {
GlideApp.with(itemView)
.clear(previewTarget)
GlideApp.with(itemView)
.load(attachment.imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(thumbnailTarget)
}
GlideApp.with(itemView)
.load(attachment.serviceIcon)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(serviceIconTarget)
setService(attachment.serviceName)
}
}
}
this.messageContainer?.isSelected = message.isSelected
if (hasDayChange) daychange?.text = message.dayChange
......
......@@ -65,6 +65,7 @@ import de.kuschku.quasseldroid.settings.AutoCompleteSettings
import de.kuschku.quasseldroid.settings.BacklogSettings
import de.kuschku.quasseldroid.settings.MessageSettings
import de.kuschku.quasseldroid.ui.chat.ChatActivity
import de.kuschku.quasseldroid.ui.info.message.MessageInfoActivity
import de.kuschku.quasseldroid.ui.info.user.UserInfoActivity
import de.kuschku.quasseldroid.util.Patterns
import de.kuschku.quasseldroid.util.avatars.AvatarHelper
......@@ -122,7 +123,16 @@ class MessageListFragment : ServiceBoundFragment() {
private val actionModeCallback = object : ActionMode.Callback {
override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?) = when (item?.itemId) {
R.id.action_user_info -> {
R.id.action_message_info -> {
viewModel.selectedMessages.value.values.firstOrNull()?.let { msg ->
MessageInfoActivity.launch(
requireContext(),
messageId = msg.original.messageId
)
true
} ?: false
}
R.id.action_user_info -> {
viewModel.selectedMessages.value.values.firstOrNull()?.let { msg ->
viewModel.session.value?.orNull()?.bufferSyncer?.let { bufferSyncer ->
viewModel.bufferData.value?.info?.let(BufferInfo::networkId)?.let { networkId ->
......@@ -143,7 +153,7 @@ class MessageListFragment : ServiceBoundFragment() {
true
} ?: false
}
R.id.action_copy -> {
R.id.action_copy -> {
val builder = SpannableStringBuilder()
viewModel.selectedMessages.value.values.asSequence().sortedBy {
it.original.messageId
......@@ -172,7 +182,7 @@ class MessageListFragment : ServiceBoundFragment() {
actionMode?.finish()
true
}
R.id.action_share -> {
R.id.action_share -> {
val builder = SpannableStringBuilder()
viewModel.selectedMessages.value.values.asSequence().sortedBy {
it.original.messageId
......@@ -207,7 +217,7 @@ class MessageListFragment : ServiceBoundFragment() {
actionMode?.finish()
true
}
else -> false
else -> false
}
override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
......@@ -250,8 +260,14 @@ class MessageListFragment : ServiceBoundFragment() {
if (actionMode != null) {
when (viewModel.selectedMessagesToggle(msg.original.messageId, msg)) {
0 -> actionMode?.finish()
1 -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
1 -> {
actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
//actionMode?.menu?.findItem(R.id.action_message_info)?.isVisible = true
}
else -> {
actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
//actionMode?.menu?.findItem(R.id.action_message_info)?.isVisible = false
}
}
} else if (msg.hasSpoilers) {
val value = viewModel.expandedMessages.value
......@@ -267,8 +283,14 @@ class MessageListFragment : ServiceBoundFragment() {
}
when (viewModel.selectedMessagesToggle(msg.original.messageId, msg)) {
0 -> actionMode?.finish()
1 -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
else -> actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
1 -> {
actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = true
actionMode?.menu?.findItem(R.id.action_message_info)?.isVisible = true
}
else -> {
actionMode?.menu?.findItem(R.id.action_user_info)?.isVisible = false
actionMode?.menu?.findItem(R.id.action_message_info)?.isVisible = false
}
}
}
if (autoCompleteSettings.senderDoubleClick)
......
......@@ -30,6 +30,8 @@ import android.view.Gravity
import android.view.View
import android.widget.FrameLayout
import android.widget.LinearLayout
import com.google.gson.GsonBuilder
import com.google.gson.JsonSyntaxException
import de.kuschku.libquassel.protocol.Message.MessageType.*
import de.kuschku.libquassel.protocol.Message_Flag
import de.kuschku.libquassel.protocol.Message_Type
......@@ -40,7 +42,9 @@ import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.persistence.models.MessageData
import de.kuschku.quasseldroid.settings.MessageSettings
import de.kuschku.quasseldroid.util.ColorContext
import de.kuschku.quasseldroid.util.attachment.AttachmentData
import de.kuschku.quasseldroid.util.avatars.AvatarHelper
import de.kuschku.quasseldroid.util.helper.fromJson
import de.kuschku.quasseldroid.util.helper.styledAttributes
import de.kuschku.quasseldroid.util.helper.visibleIf
import de.kuschku.quasseldroid.util.irc.format.ContentFormatter
......@@ -103,6 +107,8 @@ class QuasselMessageRenderer @Inject constructor(
private val zoneId = ZoneId.systemDefault()
private val gson = GsonBuilder().setLenient().create()
override fun layout(type: Message_Type?,
hasHighlight: Boolean,
isFollowUp: Boolean,
......@@ -244,6 +250,13 @@ class QuasselMessageRenderer @Inject constructor(
val self = message.content.flag.hasFlag(Message_Flag.Self)
val highlight = message.content.flag.hasFlag(Message_Flag.Highlight)
val monochromeForeground = highlight && monochromeHighlights
val parsedAttachment: AttachmentData? = try {
gson.fromJson<AttachmentData>(message.content.attachments)
} catch (ignored: JsonSyntaxException) {
null
}
return when (message.content.type.enabledValues().firstOrNull()) {
Message_Type.Plain -> {
val realName = ircFormatDeserializer.formatString(message.content.realName,
......@@ -292,7 +305,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Action -> {
......@@ -330,7 +344,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Notice -> {
......@@ -352,7 +367,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Nick -> {
......@@ -395,7 +411,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
}
Message_Type.Mode -> FormattedMessage(
......@@ -412,7 +429,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
Message_Type.Join -> FormattedMessage(
original = message.content,
......@@ -433,7 +451,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
Message_Type.Part -> {
val (content, hasSpoilers) = if (message.content.content.isBlank()) {
......@@ -480,7 +499,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Quit -> {
......@@ -528,7 +548,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Kick -> {
......@@ -575,7 +596,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Kill -> {
......@@ -622,7 +644,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.NetsplitJoin -> {
......@@ -649,7 +672,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
}
Message_Type.NetsplitQuit -> {
......@@ -676,7 +700,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
}
Message_Type.Server,
......@@ -695,7 +720,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.Topic -> {
......@@ -712,7 +738,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
Message_Type.DayChange -> FormattedMessage(
......@@ -724,7 +751,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = false,
isExpanded = false,
isSelected = false,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
Message_Type.Invite -> {
val (content, hasSpoilers) = contentFormatter.formatContent(message.content.content,
......@@ -740,7 +768,8 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = hasSpoilers
hasSpoilers = hasSpoilers,
attachment = parsedAttachment
)
}
else -> FormattedMessage(
......@@ -763,13 +792,15 @@ class QuasselMessageRenderer @Inject constructor(
isMarkerLine = message.isMarkerLine,
isExpanded = message.isExpanded,
isSelected = message.isSelected,
hasSpoilers = false
hasSpoilers = false,
attachment = parsedAttachment
)
}
}
private fun formatDayChange(
message: DisplayMessage) =
if (message.hasDayChange) dateFormatter.format(message.content.time.atZone(zoneId).truncatedTo(
ChronoUnit.DAYS)) else null
private fun formatDayChange(message: DisplayMessage) =
if (message.hasDayChange)
dateFormatter.format(message.content.time.atZone(zoneId).truncatedTo(ChronoUnit.DAYS))
else
null
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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 de.kuschku.quasseldroid.ui.info.message
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.DiffUtil
import androidx.recyclerview.widget.ListAdapter
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import com.bumptech.glide.load.engine.DiskCacheStrategy
import de.kuschku.quasseldroid.GlideApp
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.util.attachment.AttachmentData
import de.kuschku.quasseldroid.util.ui.view.MessageAttachmentView
class MessageAttachmentAdapter(private val showLarge: Boolean) :
ListAdapter<AttachmentData, MessageAttachmentAdapter.MessageAttachmentViewHolder>(
object : DiffUtil.ItemCallback<AttachmentData>() {
override fun areItemsTheSame(oldItem: AttachmentData, newItem: AttachmentData) =
oldItem.fromUrl == newItem.fromUrl
override fun areContentsTheSame(oldItem: AttachmentData, newItem: AttachmentData) =
oldItem == newItem
}
) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageAttachmentViewHolder {
return MessageAttachmentViewHolder(
LayoutInflater.from(parent.context)
.inflate(R.layout.widget_message_attachment_item, parent, false),
showLarge
)
}
override fun onBindViewHolder(holder: MessageAttachmentViewHolder, position: Int) {
holder.bind(getItem(position))
}
class MessageAttachmentViewHolder(itemView: View, private val showLarge: Boolean) :
RecyclerView.ViewHolder(itemView) {
@BindView(R.id.view)
lateinit var attachmentView: MessageAttachmentView
init {
ButterKnife.bind(this, itemView)
}
fun bind(attachment: AttachmentData) {
attachmentView.reinitViews()
attachmentView.setLink(attachment.fromUrl)
attachmentView.setColor(attachment.color)
GlideApp.with(itemView)
.load(attachment.authorIcon)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(attachmentView.authorIconTarget)
attachmentView.setAuthor(attachment.authorName)
//attachmentView.setAuthorLink(attachment.author_link)
attachmentView.setTitle(attachment.title)
attachmentView.setDescription(attachment.text)
if (showLarge) {
GlideApp.with(itemView)
.clear(attachmentView.thumbnailTarget)
GlideApp.with(itemView)
.load(attachment.imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(attachmentView.previewTarget)
} else {
GlideApp.with(itemView)
.clear(attachmentView.previewTarget)
GlideApp.with(itemView)
.load(attachment.imageUrl)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(attachmentView.thumbnailTarget)
}
GlideApp.with(itemView)
.load(attachment.serviceIcon)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.into(attachmentView.serviceIconTarget)
attachmentView.setService(attachment.serviceName)
}
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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 de.kuschku.quasseldroid.ui.info.message
import android.content.Context
import android.content.Intent
import de.kuschku.libquassel.protocol.MsgId
import de.kuschku.quasseldroid.util.ui.settings.ServiceBoundSettingsActivity
class MessageInfoActivity : ServiceBoundSettingsActivity(MessageInfoFragment()) {
companion object {
fun launch(
context: Context,
messageId: MsgId
) = context.startActivity(intent(context, messageId))
fun intent(
context: Context,
messageId: MsgId
) = Intent(context, MessageInfoActivity::class.java).apply {
putExtra("messageId", messageId.id)
}
}
}
/*
* Quasseldroid - Quassel client for Android
*
* Copyright (c) 2019 Janne Koschinski
* Copyright (c) 2019 The Quassel Project
*
* This program is free software: you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 3 as published
* by the Free Software Foundation.
*
* 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 de.kuschku.quasseldroid.ui.info.message
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.lifecycle.Observer
import androidx.recyclerview.widget.DefaultItemAnimator
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import butterknife.BindView
import butterknife.ButterKnife
import com.google.gson.Gson
import de.kuschku.libquassel.protocol.MsgId
import de.kuschku.libquassel.util.Optional
import de.kuschku.quasseldroid.R
import de.kuschku.quasseldroid.persistence.dao.find
import de.kuschku.quasseldroid.persistence.db.QuasselDatabase
import de.kuschku.quasseldroid.util.attachment.AttachmentData
import de.kuschku.quasseldroid.util.attachments.AttachmentApi
import de.kuschku.quasseldroid.util.helper.combineLatest
import de.kuschku.quasseldroid.util.helper.toLiveData
import de.kuschku.quasseldroid.util.service.ServiceBoundFragment
import de.kuschku.quasseldroid.util.ui.BetterLinkMovementMethod
import de.kuschku.quasseldroid.util.ui.LinkLongClickMenuHelper
import retrofit2.Retrofit
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
import retrofit2.converter.gson.GsonConverterFactory
import javax.inject.Inject
class MessageInfoFragment : ServiceBoundFragment() {
@BindView(R.id.list)
lateinit var list: RecyclerView
@Inject
lateinit var database: QuasselDatabase
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?): View? {
val view = inflater.inflate(R.layout.info_message, container, false)
ButterKnife.bind(this, view)
val adapter = MessageAttachmentAdapter(true)
list.adapter = adapter
list.layoutManager = LinearLayoutManager(list.context)
list.itemAnimator = DefaultItemAnimator()
viewModel.session.toLiveData().observe(this, Observer {
runInBackground {
val movementMethod = BetterLinkMovementMethod.newInstance()
movementMethod.setOnLinkLongClickListener(LinkLongClickMenuHelper())
val messageId = MsgId(arguments?.getLong("messageId") ?: -1)
val message = database.message().find(messageId)
val retrofit = Retrofit.Builder()
.baseUrl("http://192.168.178.29:8080/")
.addConverterFactory(GsonConverterFactory.create())
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
.build()
val api = retrofit.create(AttachmentApi::class.java)
val gson = Gson()
val ircCloudEmbeds = listOf(
"{\"ts\":1448400805,\"title_link\":\"https://medium.com/slack-developer-blog/everything-you-ever-wanted-to-know-about-unfurling-but-were-afraid-to-ask-or-how-to-make-your-e64b4bb9254\",\"title\":\"Everything you ever wanted to know about unfurling but were afraid to ask /or/ How to make your…\",\"text\":\"Let’s start with the most obvious question first. This is what an “unfurl” is:\",\"service_name\":\"Medium\",\"service_icon\":\"https://cdn-images-1.medium.com/fit/c/304/304/1*a1O3xhOq8KWSibZF6Ze5xQ.png\",\"image_width\":170,\"image_url\":\"https://cdn-images-1.medium.com/max/1200/1*QOMaDLcO8rExD0ctBV3BWg.png\",\"image_height\":250,\"image_bytes\":695475,\"from_url\":\"https://medium.com/slack-developer-blog/everything-you-ever-wanted-to-know-about-unfurling-but-were-afraid-to-ask-or-how-to-make-your-e64b4bb9254\",\"fields\":[{\"value\":\"10 min read\",\"title\":\"Reading time\",\"short\":true}]}",
"{\"title_link\":\"https://www.youtube.com/watch?v=_Cd9FYO9Rh4\",\"title\":\"Scorpions Berlin Philharmonic Orchestra Rock You Like a Hurricane\",\"service_url\":\"https://www.youtube.com/\",\"service_name\":\"YouTube\",\"service_icon\":\"https://a.slack-edge.com/2089/img/unfurl_icons/youtube.png\",\"from_url\":\"https://www.youtube.com/watch?v=_Cd9FYO9Rh4\",\"author_name\":\"Nathan Allen\",\"author_link\":\"https://www.youtube.com/user/27caboose\"}",
"{\"title_link\":\"http://www.kn-online.de/Nachrichten/Panorama/Lehrerin-fuehrt-Netflix-Experiment-durch-das-Ergebnis-erschreckt\",\"title\":\"Lehrerin führt Netflix-Experiment durch – das Ergebnis erschreckt\",\"text\":\"Rebecca Schiller aus Potsdam unterrichtet am Marie-Curie-Gymnasium im Havelland. Als „Frau Lehrerin“ ist sie auf Twitter eine kleine Berühmtheit – vor allem, seit sie dort eine unkonventionelle Unterrichtsmethode veröffentlicht hat.\",\"service_name\":\"KN - Kieler Nachrichten\",\"service_icon\":\"http://www.kn-online.de/bundles/molasset/images/sites/desktop/kn/apple-touch-icon.png\",\"image_width\":500,\"image_url\":\"http://www.kn-online.de/var/storage/images/rnd/nachrichten/panorama/uebersicht/lehrerin-fuehrt-netflix-experiment-durch-das-ergebnis-erschreckt/712106427-8-ger-DE/Lehrerin-fuehrt-Netflix-Experiment-durch-das-Ergebnis-erschreckt_reference_2_1.jpg\",\"image_height\":250,\"image_bytes\":65450,\"from_url\":\"http://www.kn-online.de/Nachrichten/Panorama/Lehrerin-fuehrt-Netflix-Experiment-durch-das-Ergebnis-erschreckt\"}"
).map {