Skip to content
This repository has been archived by the owner on Jun 7, 2020. It is now read-only.

[NEW][RFC] Support receiving shared content (audio/video/text) #874

Closed
wants to merge 3 commits into from
Closed
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
1 change: 1 addition & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,7 @@ dependencies {
implementation libraries.room
kapt libraries.roomProcessor
implementation libraries.roomRxjava
implementation libraries.extensions

implementation libraries.rxKotlin
implementation libraries.rxAndroid
Expand Down
44 changes: 36 additions & 8 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -37,23 +37,51 @@

<activity
android:name=".main.ui.MainActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
android:excludeFromRecents="true"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="video/*" />
</intent-filter>
</activity>

<activity
android:name=".webview.WebViewActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />

<activity
android:name=".chatroom.ui.ChatRoomActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
android:excludeFromRecents="true"
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />

<activity
android:name=".chatroom.ui.PinnedMessagesActivity"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden"
android:theme="@style/AppTheme" />
android:theme="@style/AppTheme"
android:windowSoftInputMode="adjustResize|stateAlwaysHidden" />

<activity
android:name=".settings.password.ui.PasswordActivity"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,41 @@ package chat.rocket.android.chatroom.ui
import DrawableHelper
import android.content.Context
import android.content.Intent
import android.graphics.drawable.Drawable
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.support.v4.app.Fragment
import android.support.v7.app.AppCompatActivity
import chat.rocket.android.R
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import chat.rocket.android.util.extensions.addFragment
import chat.rocket.android.util.extensions.textContent
import chat.rocket.android.widget.share.ui.ShareBottomSheetDialog.Companion.ARGUMENT_SHARED_CONTENT
import chat.rocket.common.model.RoomType
import chat.rocket.common.model.roomTypeOf
import dagger.android.AndroidInjection
import dagger.android.AndroidInjector
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import kotlinx.android.synthetic.main.app_bar_chat_room.*
import java.util.*
import javax.inject.Inject


fun Context.chatRoomIntent(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean): Intent {
fun Context.chatRoomIntent(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean, contentToShare: Any?): Intent {
return Intent(this, ChatRoomActivity::class.java).apply {
putExtra(INTENT_CHAT_ROOM_ID, chatRoomId)
putExtra(INTENT_CHAT_ROOM_NAME, chatRoomName)
putExtra(INTENT_CHAT_ROOM_TYPE, chatRoomType)
putExtra(INTENT_IS_CHAT_ROOM_READ_ONLY, isChatRoomReadOnly)
if (contentToShare != null) {
when (contentToShare) {
is String -> putExtra(ARGUMENT_SHARED_CONTENT, contentToShare)
is Parcelable -> putExtra(ARGUMENT_SHARED_CONTENT, contentToShare)
is ArrayList<*> -> putExtra(ARGUMENT_SHARED_CONTENT, contentToShare)
}
}
}
}

Expand Down Expand Up @@ -68,10 +78,17 @@ class ChatRoomActivity : AppCompatActivity(), HasSupportFragmentInjector {
isChatRoomReadOnly = intent.getBooleanExtra(INTENT_IS_CHAT_ROOM_READ_ONLY, true)
requireNotNull(chatRoomType) { "no is_chat_room_read_only provided in Intent extras" }

val shareableContent = when (intent.extras.get(ARGUMENT_SHARED_CONTENT)) {
is String -> intent.extras.get(ARGUMENT_SHARED_CONTENT)
is Uri -> intent.extras.get(ARGUMENT_SHARED_CONTENT)
is ArrayList<*> -> intent.extras.get(ARGUMENT_SHARED_CONTENT)
else -> null
}

setupToolbar()

addFragment("ChatRoomFragment", R.id.fragment_container) {
newInstance(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly)
newInstance(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly, shareableContent)
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import android.content.Intent
import android.net.Uri
import android.os.Bundle
import android.os.Handler
import android.os.Parcelable
import android.support.annotation.DrawableRes
import android.support.v4.app.Fragment
import android.support.v7.widget.DefaultItemAnimator
Expand All @@ -28,22 +29,33 @@ import chat.rocket.android.widget.emoji.Emoji
import chat.rocket.android.widget.emoji.EmojiKeyboardPopup
import chat.rocket.android.widget.emoji.EmojiParser
import chat.rocket.core.internal.realtime.State
import chat.rocket.android.widget.share.ui.ShareBottomSheetDialog.Companion.ARGUMENT_SHARED_CONTENT
import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.CompositeDisposable
import kotlinx.android.synthetic.main.fragment_chat_room.*
import kotlinx.android.synthetic.main.message_attachment_options.*
import kotlinx.android.synthetic.main.message_composer.*
import kotlinx.android.synthetic.main.message_list.*
import timber.log.Timber
import java.util.ArrayList
import javax.inject.Inject

fun newInstance(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean): Fragment {
fun newInstance(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean, shareableContent: Any?): Fragment {
return ChatRoomFragment().apply {
arguments = Bundle(1).apply {
putString(BUNDLE_CHAT_ROOM_ID, chatRoomId)
putString(BUNDLE_CHAT_ROOM_NAME, chatRoomName)
putString(BUNDLE_CHAT_ROOM_TYPE, chatRoomType)
putBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY, isChatRoomReadOnly)
shareableContent?.let {
when (it) {
is String -> putString(ARGUMENT_SHARED_CONTENT, it)
is Uri -> putParcelable(ARGUMENT_SHARED_CONTENT, it)
is ArrayList<*> -> if (it.size > 0 && it[0] is Uri) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it.isNotEmpty()

putParcelableArrayList(ARGUMENT_SHARED_CONTENT, it as ArrayList<out Parcelable>)
}
}
}
}
}
}
Expand All @@ -63,6 +75,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardPopup.Listener {
private lateinit var chatRoomName: String
private lateinit var chatRoomType: String
private lateinit var emojiKeyboardPopup: EmojiKeyboardPopup
private var contentToShare: Any? = null
private var isChatRoomReadOnly: Boolean = false

private lateinit var actionSnackbar: ActionSnackbar
Expand All @@ -89,6 +102,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardPopup.Listener {
chatRoomName = bundle.getString(BUNDLE_CHAT_ROOM_NAME)
chatRoomType = bundle.getString(BUNDLE_CHAT_ROOM_TYPE)
isChatRoomReadOnly = bundle.getBoolean(BUNDLE_IS_CHAT_ROOM_READ_ONLY)
contentToShare = bundle.get(ARGUMENT_SHARED_CONTENT)
} else {
requireNotNull(bundle) { "no arguments supplied when the fragment was instantiated" }
}
Expand Down Expand Up @@ -174,6 +188,14 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardPopup.Listener {
if (oldMessagesCount == 0 && dataSet.isNotEmpty()) {
recycler_view.scrollToPosition(0)
}
contentToShare?.let {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't know if this is the right place to "plug" this...
Setting contentToShare as null seems like a code smell

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I know you are waiting the message list to be populated, but maybe we need a new callback on the View, to indicate the first messages are loaded.

when (it) {
is String -> sendMessage(it)
is Uri -> uploadFile(uri = it)
is ArrayList<*> -> it.forEach { uri -> uploadFile(uri as Uri) }
}
contentToShare = null
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,8 @@ import chat.rocket.android.main.ui.MainActivity

class ChatRoomsNavigator(private val activity: MainActivity, private val context: Context) {

fun toChatRoom(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean) {
activity.startActivity(context.chatRoomIntent(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly))
fun toChatRoom(chatRoomId: String, chatRoomName: String, chatRoomType: String, isChatRoomReadOnly: Boolean, contentToShare: Any?) {
activity.startActivity(context.chatRoomIntent(chatRoomId, chatRoomName, chatRoomType, isChatRoomReadOnly, contentToShare))
activity.overridePendingTransition(R.anim.open_enter, R.anim.open_exit)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
}
}

fun loadChatRoom(chatRoom: ChatRoom) {
fun loadChatRoom(chatRoom: ChatRoom, contentToShare: Any? = null) {
val roomName = if (chatRoom.type is RoomType.DirectMessage
&& chatRoom.fullName != null
&& settings.useRealName()) {
Expand All @@ -68,7 +68,8 @@ class ChatRoomsPresenter @Inject constructor(private val view: ChatRoomsView,
}

navigator.toChatRoom(chatRoom.id, roomName,
chatRoom.type.toString(), chatRoom.readonly ?: false)
chatRoom.type.toString(), chatRoom.readonly ?: false,
contentToShare)
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package chat.rocket.android.chatrooms.ui

import android.arch.lifecycle.Observer
import android.arch.lifecycle.ViewModelProviders
import android.os.Bundle
import android.os.Handler
import android.support.v4.app.Fragment
Expand All @@ -12,6 +14,7 @@ import android.view.*
import chat.rocket.android.R
import chat.rocket.android.chatrooms.presentation.ChatRoomsPresenter
import chat.rocket.android.chatrooms.presentation.ChatRoomsView
import chat.rocket.android.main.presentation.ChatRoomsViewModel
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.util.extensions.*
Expand All @@ -31,6 +34,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
@Inject lateinit var presenter: ChatRoomsPresenter
@Inject lateinit var serverInteractor: GetCurrentServerInteractor
@Inject lateinit var settingsRepository: SettingsRepository
private lateinit var chatRoomsViewModel: ChatRoomsViewModel
private var searchView: SearchView? = null
private val handler = Handler()

Expand All @@ -44,6 +48,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
super.onCreate(savedInstanceState)
AndroidSupportInjection.inject(this)
setHasOptionsMenu(true)
chatRoomsViewModel = ViewModelProviders.of(activity!!).get(ChatRoomsViewModel::class.java)
}

override fun onDestroy() {
Expand All @@ -60,6 +65,9 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
setupToolbar()
setupRecyclerView()
presenter.loadChatRooms()
chatRoomsViewModel.getSelectedChatRoom().observe(this, Observer { chatRoomContent ->
chatRoomContent?.let { presenter.loadChatRoom(chatRoomContent.first, chatRoomContent.second) }
})
}

override fun onDestroyView() {
Expand Down Expand Up @@ -99,6 +107,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
adapter.updateRooms(newDataSet)
diff.dispatchUpdatesTo(adapter)
}
chatRoomsViewModel.setChatRooms(adapter.dataSet)
}
}
}
Expand Down Expand Up @@ -145,8 +154,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
activity?.apply {
recycler_view.layoutManager = LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false)
recycler_view.addItemDecoration(DividerItemDecoration(this,
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_start),
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_end)))
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_start),
resources.getDimensionPixelSize(R.dimen.divider_item_decorator_bound_end)))
recycler_view.itemAnimator = DefaultItemAnimator()
// TODO - use a ViewModel Mapper instead of using settings on the adapter
recycler_view.adapter = ChatRoomsAdapter(this,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import chat.rocket.android.members.di.MembersFragmentProvider
import chat.rocket.android.profile.di.ProfileFragmentProvider
import chat.rocket.android.settings.password.di.PasswordFragmentProvider
import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.widget.share.di.ShareFragmentProvider
import dagger.Module
import dagger.android.ContributesAndroidInjector

Expand All @@ -40,7 +41,8 @@ abstract class ActivityBuilder {
MainActivityProvider::class,
ChatRoomsModule::class,
ChatRoomsFragmentProvider::class,
ProfileFragmentProvider::class
ProfileFragmentProvider::class,
ShareFragmentProvider::class
])
abstract fun bindMainActivity(): MainActivity

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package chat.rocket.android.main.presentation

import android.arch.lifecycle.LiveData
import android.arch.lifecycle.MutableLiveData
import android.arch.lifecycle.ViewModel
import chat.rocket.core.model.ChatRoom

class ChatRoomsViewModel : ViewModel() {
private val chatRoomsLiveData = MutableLiveData<List<ChatRoom>>()
private val selectedChatRoom = MutableLiveData<Pair<ChatRoom, Any>>()

fun setChatRooms(chatRooms: List<ChatRoom>) {
chatRoomsLiveData.setValue(chatRooms)
}

fun getChatRooms(): LiveData<List<ChatRoom>> = chatRoomsLiveData

fun selectChatRoom(chatRoom: ChatRoom, content: Any?) {
content?.let {
selectedChatRoom.value = Pair(chatRoom, it)
}
}

fun getSelectedChatRoom(): LiveData<Pair<ChatRoom, Any>> = selectedChatRoom
}
Loading