Unverified Commit 36598c5d authored by divyanshu bhargava's avatar divyanshu bhargava Committed by GitHub

Merge pull request #35 from RocketChat/develop

merge
parents 124b8519 35ed646c
...@@ -114,8 +114,6 @@ dependencies { ...@@ -114,8 +114,6 @@ dependencies {
implementation libraries.markwon implementation libraries.markwon
implementation libraries.sheetMenu
implementation libraries.aVLoadingIndicatorView implementation libraries.aVLoadingIndicatorView
implementation "com.github.luciofm:livedata-ktx:b1e8bbc25a" implementation "com.github.luciofm:livedata-ktx:b1e8bbc25a"
......
...@@ -79,11 +79,6 @@ ...@@ -79,11 +79,6 @@
android:name=".settings.password.ui.PasswordActivity" android:name=".settings.password.ui.PasswordActivity"
android:theme="@style/AppTheme" /> android:theme="@style/AppTheme" />
<!-- TODO: Change to fragment -->
<activity
android:name=".settings.about.ui.AboutActivity"
android:theme="@style/AppTheme" />
<receiver <receiver
android:name=".push.DirectReplyReceiver" android:name=".push.DirectReplyReceiver"
android:enabled="true" android:enabled="true"
......
package chat.rocket.android.about.ui
import android.os.Bundle
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
import androidx.fragment.app.Fragment
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
import chat.rocket.android.main.ui.MainActivity
import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.fragment_about.*
class AboutFragment : Fragment() {
companion object {
fun newInstance() = AboutFragment()
}
override fun onCreateView(inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? = inflater.inflate(R.layout.fragment_about, container, false)
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
setupToolbar()
setupViews()
}
private fun setupViews() {
text_version_name.text = getString(R.string.msg_version, BuildConfig.VERSION_NAME)
text_build_number.text = getString(R.string.msg_build, BuildConfig.VERSION_CODE)
}
private fun setupToolbar() {
val toolbar = (activity as MainActivity).toolbar
toolbar.title = getString(R.string.title_about)
toolbar.setNavigationIcon(R.drawable.ic_arrow_back_white_24dp)
toolbar.setNavigationOnClickListener {
this.activity?.onBackPressed()
}
}
override fun onStop() {
super.onStop()
(activity as MainActivity).toolbar.setNavigationIcon(R.drawable.ic_menu_white_24dp)
}
}
package chat.rocket.android.chatroom.adapter package chat.rocket.android.chatroom.adapter
import androidx.recyclerview.widget.RecyclerView import android.view.ContextThemeWrapper
import android.view.MenuItem import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.children import androidx.core.view.children
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.chatroom.ui.bottomsheet.BottomSheetMenu import chat.rocket.android.chatroom.ui.bottomsheet.MessageActionsBottomSheet
import chat.rocket.android.chatroom.ui.bottomsheet.adapter.ActionListAdapter
import chat.rocket.android.chatroom.uimodel.BaseUiModel import chat.rocket.android.chatroom.uimodel.BaseUiModel
import chat.rocket.android.emoji.Emoji import chat.rocket.android.emoji.Emoji
import chat.rocket.android.emoji.EmojiReactionListener import chat.rocket.android.emoji.EmojiReactionListener
import chat.rocket.android.util.extensions.inflate
import chat.rocket.android.util.extensions.toList
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
import chat.rocket.core.model.isSystemMessage import chat.rocket.core.model.isSystemMessage
import com.google.android.flexbox.FlexDirection import com.google.android.flexbox.FlexDirection
import com.google.android.flexbox.FlexboxLayoutManager import com.google.android.flexbox.FlexboxLayoutManager
import ru.whalemare.sheetmenu.extension.inflate
import ru.whalemare.sheetmenu.extension.toList
abstract class BaseViewHolder<T : BaseUiModel<*>>( abstract class BaseViewHolder<T : BaseUiModel<*>>(
itemView: View, itemView: View,
...@@ -89,8 +90,15 @@ abstract class BaseViewHolder<T : BaseUiModel<*>>( ...@@ -89,8 +90,15 @@ abstract class BaseViewHolder<T : BaseUiModel<*>>(
setTitle(if (isStarred) R.string.action_msg_unstar else R.string.action_msg_star) setTitle(if (isStarred) R.string.action_msg_unstar else R.string.action_msg_star)
isChecked = isStarred isChecked = isStarred
} }
val adapter = ActionListAdapter(menuItems, this@BaseViewHolder) view.context?.let {
BottomSheetMenu(adapter).show(view.context) if (it is ContextThemeWrapper && it.baseContext is AppCompatActivity) {
with(it.baseContext as AppCompatActivity) {
val actionsBottomSheet = MessageActionsBottomSheet()
actionsBottomSheet.addItems(menuItems, this@BaseViewHolder)
actionsBottomSheet.show(supportFragmentManager, null)
}
}
}
} }
} }
} }
......
package chat.rocket.android.chatroom.ui.bottomsheet
import com.google.android.material.bottomsheet.BottomSheetDialog
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import android.view.MenuItem
import ru.whalemare.sheetmenu.SheetMenu
import ru.whalemare.sheetmenu.adapter.MenuAdapter
class BottomSheetMenu(adapter: MenuAdapter) : SheetMenu(adapter = adapter) {
override fun processRecycler(recycler: RecyclerView, dialog: BottomSheetDialog) {
if (layoutManager == null) {
layoutManager = LinearLayoutManager(recycler.context)
}
// Superclass SheetMenu adapter property is nullable MenuAdapter? but this class enforces
// passing one at the constructor, so we assume it's always non-null.
val adapter = adapter!!
val callback = adapter.callback
adapter.callback = MenuItem.OnMenuItemClickListener {
callback?.onMenuItemClick(it)
dialog.cancel()
true
}
recycler.adapter = adapter
recycler.layoutManager = layoutManager
}
}
\ No newline at end of file
package chat.rocket.android.chatroom.ui.bottomsheet
import android.os.Bundle
import android.view.LayoutInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.RecyclerView
import chat.rocket.android.R
import com.google.android.material.bottomsheet.BottomSheetDialogFragment
import kotlinx.android.synthetic.main.message_action_item.view.*
import kotlinx.android.synthetic.main.message_bottomsheet.*
class MessageActionsBottomSheet : BottomSheetDialogFragment() {
private lateinit var adapter: MessageActionAdapter
override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle?): View {
return inflater.inflate(R.layout.message_bottomsheet, container, false)
}
fun addItems(items: List<MenuItem>, itemClickListener: MenuItem.OnMenuItemClickListener) {
adapter = MessageActionAdapter()
adapter.addItems(items, ActionItemClickListener(dismissAction = { dismiss() },
itemClickListener = itemClickListener))
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
bottomsheet_recycler_view.layoutManager = LinearLayoutManager(context)
bottomsheet_recycler_view.adapter = adapter
}
private class ActionItemClickListener(
val dismissAction: () -> Unit,
val itemClickListener: MenuItem.OnMenuItemClickListener
)
private class MessageActionAdapter : RecyclerView.Adapter<MessageActionViewHolder>() {
private lateinit var itemClickListener: ActionItemClickListener
private val menuItems = mutableListOf<MenuItem>()
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): MessageActionViewHolder {
return MessageActionViewHolder(
LayoutInflater.from(parent.context).inflate(R.layout.message_action_item, parent, false)
)
}
override fun getItemCount() = menuItems.size
override fun onBindViewHolder(holder: MessageActionViewHolder, position: Int) {
holder.bind(menuItems[position], itemClickListener)
}
fun addItems(items: List<MenuItem>, itemClickListener: ActionItemClickListener) {
this.itemClickListener = itemClickListener
menuItems.clear()
menuItems.addAll(items)
}
}
private class MessageActionViewHolder(itemView: View) : RecyclerView.ViewHolder(itemView) {
fun bind(item: MenuItem, itemClickListener: ActionItemClickListener) {
with(itemView) {
message_action_title.text = item.title
message_action_icon.setImageDrawable(item.icon)
setOnClickListener {
itemClickListener.itemClickListener.onMenuItemClick(item)
itemClickListener.dismissAction.invoke()
}
}
}
}
}
\ No newline at end of file
package chat.rocket.android.chatroom.ui.bottomsheet.adapter
import android.view.MenuItem
import chat.rocket.android.R
import chat.rocket.android.util.extensions.setVisible
/**
* An adapter for bottomsheet menu that lists all the actions that could be taken over a chat message.
*/
class ActionListAdapter(
menuItems: List<MenuItem> = emptyList(),
callback: MenuItem.OnMenuItemClickListener
) : ListBottomSheetAdapter(menuItems = menuItems, callback = callback) {
override fun onBindViewHolder(holder: ViewHolder, position: Int) {
val item = menuItems[position]
if (showIcons) {
holder.imageIcon.setVisible(item.icon != null)
} else {
holder.imageIcon.setVisible(false)
}
holder.imageIcon.setImageDrawable(item.icon)
holder.textTitle.text = item.title
holder.itemView.setOnClickListener {
callback?.onMenuItemClick(item)
}
val deleteTextColor = holder.itemView.context.resources.getColor(R.color.colorRed)
val color = if (item.itemId == R.id.action_message_delete) {
deleteTextColor
} else {
textColors.get(item.itemId)
}
holder.textTitle.setTextColor(color)
}
}
\ No newline at end of file
package chat.rocket.android.chatroom.ui.bottomsheet.adapter
import android.graphics.Color
import androidx.annotation.ColorInt
import androidx.annotation.IdRes
import android.util.SparseIntArray
import android.view.MenuItem
import chat.rocket.android.R
import ru.whalemare.sheetmenu.adapter.MenuAdapter
/**
* A regular bottomsheet adapter with added possibility to hide or show a menu item given its item id.
* Also added the possibility to change text colors for the menu items.
*/
open class ListBottomSheetAdapter(menuItems: List<MenuItem> = emptyList(), callback: MenuItem.OnMenuItemClickListener) :
MenuAdapter(menuItems = menuItems, callback = callback, itemLayoutId = R.layout.item_linear, showIcons = true) {
// Maps menu item ids to colors.
protected val textColors: SparseIntArray = SparseIntArray(menuItems.size)
init {
for (item in menuItems) {
textColors.put(item.itemId, Color.BLACK)
}
}
/**
* Hide a menu item and disable it.
*
* @param itemId The id of the menu item to disable and hide.
*/
fun hideMenuItem(@IdRes itemId: Int) {
menuItems.firstOrNull { it.itemId == itemId }?.apply {
setVisible(false)
setEnabled(false)
}
}
/**
* Show a menu item and enable it.
*
* @param itemId The id of the menu item to enable and show.
*/
fun showMenuItem(@IdRes itemId: Int) {
menuItems.firstOrNull { it.itemId == itemId }?.apply {
setVisible(true)
setEnabled(true)
}
}
/**
* Change a menu item text color given by its id to the given color.
*
* @param itemId The id of menu item.
* @param color The color (not the resource color id) of the menu item.
*/
fun setMenuItemTextColor(@IdRes itemId: Int, @ColorInt color: Int) {
val itemIndex = menuItems.indexOfFirst { it.itemId == itemId }
if (itemIndex > -1) {
textColors.put(itemId, color)
}
}
}
\ No newline at end of file
...@@ -13,6 +13,7 @@ import chat.rocket.android.infrastructure.checkIfMyself ...@@ -13,6 +13,7 @@ import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.extensions.date import chat.rocket.android.util.extensions.date
import chat.rocket.android.util.extensions.localDateTime import chat.rocket.android.util.extensions.localDateTime
...@@ -111,7 +112,7 @@ class RoomUiModelMapper( ...@@ -111,7 +112,7 @@ class RoomUiModelMapper(
} }
private fun mapName(name: String, fullName: String?, unread: Boolean): CharSequence { private fun mapName(name: String, fullName: String?, unread: Boolean): CharSequence {
val roomName = if (settings.useRealName()) { val roomName = if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
fullName ?: name fullName ?: name
} else { } else {
name name
......
...@@ -6,6 +6,7 @@ import chat.rocket.android.helper.UserHelper ...@@ -6,6 +6,7 @@ import chat.rocket.android.helper.UserHelper
import chat.rocket.android.infrastructure.LocalRepository import chat.rocket.android.infrastructure.LocalRepository
import chat.rocket.android.main.presentation.MainNavigator import chat.rocket.android.main.presentation.MainNavigator
import chat.rocket.android.server.domain.SettingsRepository import chat.rocket.android.server.domain.SettingsRepository
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.infraestructure.ConnectionManager import chat.rocket.android.server.infraestructure.ConnectionManager
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
...@@ -36,13 +37,11 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -36,13 +37,11 @@ class ChatRoomsPresenter @Inject constructor(
fun loadChatRoom(chatRoom: chat.rocket.android.db.model.ChatRoom) { fun loadChatRoom(chatRoom: chat.rocket.android.db.model.ChatRoom) {
with(chatRoom.chatRoom) { with(chatRoom.chatRoom) {
val isDirectMessage = roomTypeOf(type) is RoomType.DirectMessage val isDirectMessage = roomTypeOf(type) is RoomType.DirectMessage
val roomName = if (isDirectMessage val roomName = if (settings.useSpecialCharsOnRoom() || (isDirectMessage && settings.useRealName())) {
&& fullname != null fullname ?: name
&& settings.useRealName()) { } else {
fullname!! name
} else { }
name
}
launchUI(strategy) { launchUI(strategy) {
val myself = getCurrentUser() val myself = getCurrentUser()
......
...@@ -18,6 +18,7 @@ import chat.rocket.android.infrastructure.checkIfMyself ...@@ -18,6 +18,7 @@ import chat.rocket.android.infrastructure.checkIfMyself
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.showLastMessage import chat.rocket.android.server.domain.showLastMessage
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.util.extensions.* import chat.rocket.android.util.extensions.*
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom import chat.rocket.core.model.ChatRoom
...@@ -123,7 +124,7 @@ class ChatRoomsAdapter( ...@@ -123,7 +124,7 @@ class ChatRoomsAdapter(
} }
private fun chatRoomName(chatRoom: ChatRoom): String { private fun chatRoomName(chatRoom: ChatRoom): String {
return if (settings.useRealName()) { return if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
chatRoom.fullName ?: chatRoom.name chatRoom.fullName ?: chatRoom.name
} else { } else {
chatRoom.name chatRoom.name
......
...@@ -148,7 +148,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -148,7 +148,8 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
inflater.inflate(R.menu.chatrooms, menu) inflater.inflate(R.menu.chatrooms, menu)
val searchItem = menu.findItem(R.id.action_search) val searchItem = menu.findItem(R.id.action_search)
searchView = searchItem?.actionView as SearchView searchView = searchItem?.actionView as? SearchView
searchView?.setIconifiedByDefault(false)
searchView?.maxWidth = Integer.MAX_VALUE searchView?.maxWidth = Integer.MAX_VALUE
searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener { searchView?.setOnQueryTextListener(object : SearchView.OnQueryTextListener {
override fun onQueryTextSubmit(query: String?): Boolean { override fun onQueryTextSubmit(query: String?): Boolean {
...@@ -176,7 +177,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -176,7 +177,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
0 -> R.id.radio_sort_alphabetical 0 -> R.id.radio_sort_alphabetical
else -> R.id.radio_sort_activity else -> R.id.radio_sort_activity
}) })
radioGroup.setOnCheckedChangeListener({ _, checkedId -> radioGroup.setOnCheckedChangeListener { _, checkedId ->
run { run {
SharedPreferenceHelper.putInt(Constants.CHATROOM_SORT_TYPE_KEY, when (checkedId) { SharedPreferenceHelper.putInt(Constants.CHATROOM_SORT_TYPE_KEY, when (checkedId) {
R.id.radio_sort_alphabetical -> 0 R.id.radio_sort_alphabetical -> 0
...@@ -184,23 +185,21 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView { ...@@ -184,23 +185,21 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
else -> 1 else -> 1
}) })
} }
}) }
groupByTypeCheckBox.isChecked = groupByType groupByTypeCheckBox.isChecked = groupByType
groupByTypeCheckBox.setOnCheckedChangeListener({ _, isChecked -> groupByTypeCheckBox.setOnCheckedChangeListener { _, isChecked ->
SharedPreferenceHelper.putBoolean(Constants.CHATROOM_GROUP_BY_TYPE_KEY, isChecked) SharedPreferenceHelper.putBoolean(Constants.CHATROOM_GROUP_BY_TYPE_KEY, isChecked)
}) }
val dialogSort = AlertDialog.Builder(context) AlertDialog.Builder(context)
.setTitle(R.string.dialog_sort_title) .setTitle(R.string.dialog_sort_title)
.setView(dialogLayout) .setView(dialogLayout)
.setPositiveButton("Done", { dialog, _ -> .setPositiveButton("Done") { dialog, _ ->
invalidateQueryOnSearch() invalidateQueryOnSearch()
updateSort() updateSort()
dialog.dismiss() dialog.dismiss()
}) }.show()
dialogSort.show()
} }
} }
return super.onOptionsItemSelected(item) return super.onOptionsItemSelected(item)
......
...@@ -10,11 +10,11 @@ import chat.rocket.android.authentication.twofactor.di.TwoFAFragmentProvider ...@@ -10,11 +10,11 @@ import chat.rocket.android.authentication.twofactor.di.TwoFAFragmentProvider
import chat.rocket.android.authentication.ui.AuthenticationActivity import chat.rocket.android.authentication.ui.AuthenticationActivity
import chat.rocket.android.chatroom.di.ChatRoomFragmentProvider import chat.rocket.android.chatroom.di.ChatRoomFragmentProvider
import chat.rocket.android.chatroom.di.ChatRoomModule import chat.rocket.android.chatroom.di.ChatRoomModule
import chat.rocket.android.chatroom.di.FavoriteMessagesFragmentProvider
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider import chat.rocket.android.chatrooms.di.ChatRoomsFragmentProvider
import chat.rocket.android.createchannel.di.CreateChannelProvider import chat.rocket.android.createchannel.di.CreateChannelProvider
import chat.rocket.android.dagger.scope.PerActivity import chat.rocket.android.dagger.scope.PerActivity
import chat.rocket.android.favoritemessages.di.FavoriteMessagesFragmentProvider
import chat.rocket.android.files.di.FilesFragmentProvider import chat.rocket.android.files.di.FilesFragmentProvider
import chat.rocket.android.main.di.MainModule import chat.rocket.android.main.di.MainModule
import chat.rocket.android.main.ui.MainActivity import chat.rocket.android.main.ui.MainActivity
......
package chat.rocket.android.chatroom.di package chat.rocket.android.favoritemessages.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.favoritemessages.presentation.FavoriteMessagesView import chat.rocket.android.favoritemessages.presentation.FavoriteMessagesView
import chat.rocket.android.favoritemessages.ui.FavoriteMessagesFragment import chat.rocket.android.favoritemessages.ui.FavoriteMessagesFragment
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import javax.inject.Named
@Module @Module
class FavoriteMessagesFragmentModule { class FavoriteMessagesFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun provideJob() = Job() fun provideFavoriteMessagesView(frag: FavoriteMessagesFragment): FavoriteMessagesView {
return frag
}
@Provides @Provides
@PerFragment @PerFragment
fun provideLifecycleOwner(frag: FavoriteMessagesFragment): LifecycleOwner { @Named("currentServer")
return frag fun provideCurrentServer(currentServerInteractor: GetCurrentServerInteractor): String {
return currentServerInteractor.get()!!
} }
@Provides @Provides
@PerFragment @PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy { fun provideDatabaseManager(
return CancelStrategy(owner, jobs) factory: DatabaseManagerFactory,
@Named("currentServer") currentServer: String
): DatabaseManager {
return factory.create(currentServer)
} }
@Provides @Provides
@PerFragment @PerFragment
fun provideFavoriteMessagesView(frag: FavoriteMessagesFragment): FavoriteMessagesView { fun provideJob() = Job()
@Provides
@PerFragment
fun provideLifecycleOwner(frag: FavoriteMessagesFragment): LifecycleOwner {
return frag return frag
} }
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
} }
\ No newline at end of file
package chat.rocket.android.chatroom.di package chat.rocket.android.favoritemessages.di
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.favoritemessages.ui.FavoriteMessagesFragment import chat.rocket.android.favoritemessages.ui.FavoriteMessagesFragment
......
...@@ -2,26 +2,27 @@ package chat.rocket.android.favoritemessages.presentation ...@@ -2,26 +2,27 @@ package chat.rocket.android.favoritemessages.presentation
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.ChatRoomsInteractor import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.getFavoriteMessages import chat.rocket.core.internal.rest.getFavoriteMessages
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
class FavoriteMessagesPresenter @Inject constructor( class FavoriteMessagesPresenter @Inject constructor(
private val view: FavoriteMessagesView, private val view: FavoriteMessagesView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val roomsInteractor: ChatRoomsInteractor, private val dbManager: DatabaseManager,
@Named("currentServer") private val currentServer: String,
private val mapper: UiModelMapper, private val mapper: UiModelMapper,
val serverInteractor: GetCurrentServerInteractor,
val factory: RocketChatClientFactory val factory: RocketChatClientFactory
) { ) {
private val serverUrl = serverInteractor.get()!! private val client: RocketChatClient = factory.create(currentServer)
private val client = factory.create(serverUrl)
private var offset: Int = 0 private var offset: Int = 0
/** /**
...@@ -33,8 +34,9 @@ class FavoriteMessagesPresenter @Inject constructor( ...@@ -33,8 +34,9 @@ class FavoriteMessagesPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
try { try {
view.showLoading() view.showLoading()
roomsInteractor.getById(serverUrl, roomId)?.let { dbManager.getRoom(roomId)?.let {
val favoriteMessages = client.getFavoriteMessages(roomId, it.type, offset) val favoriteMessages =
client.getFavoriteMessages(roomId, roomTypeOf(it.chatRoom.type), offset)
val messageList = mapper.map(favoriteMessages.result, asNotReversed = true) val messageList = mapper.map(favoriteMessages.result, asNotReversed = true)
view.showFavoriteMessages(messageList) view.showFavoriteMessages(messageList)
offset += 1 * 30 offset += 1 * 30
......
...@@ -3,34 +3,54 @@ package chat.rocket.android.files.di ...@@ -3,34 +3,54 @@ package chat.rocket.android.files.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.files.presentation.FilesView import chat.rocket.android.files.presentation.FilesView
import chat.rocket.android.files.ui.FilesFragment import chat.rocket.android.files.ui.FilesFragment
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import javax.inject.Named
@Module @Module
class FilesFragmentModule { class FilesFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun provideJob() = Job() fun provideFilesView(frag: FilesFragment): FilesView {
return frag
}
@Provides @Provides
@PerFragment @PerFragment
fun provideLifecycleOwner(frag: FilesFragment): LifecycleOwner { @Named("currentServer")
return frag fun provideCurrentServer(currentServerInteractor: GetCurrentServerInteractor): String {
return currentServerInteractor.get()!!
} }
@Provides @Provides
@PerFragment @PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy { fun provideDatabaseManager(
return CancelStrategy(owner, jobs) factory: DatabaseManagerFactory,
@Named("currentServer") currentServer: String
): DatabaseManager {
return factory.create(currentServer)
} }
@Provides @Provides
@PerFragment @PerFragment
fun provideFilesView(frag: FilesFragment): FilesView { fun provideJob() = Job()
@Provides
@PerFragment
fun provideLifecycleOwner(frag: FilesFragment): LifecycleOwner {
return frag return frag
} }
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
} }
\ No newline at end of file
...@@ -2,28 +2,29 @@ package chat.rocket.android.files.presentation ...@@ -2,28 +2,29 @@ package chat.rocket.android.files.presentation
import androidx.core.net.toUri import androidx.core.net.toUri
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.files.uimodel.FileUiModel import chat.rocket.android.files.uimodel.FileUiModel
import chat.rocket.android.files.uimodel.FileUiModelMapper import chat.rocket.android.files.uimodel.FileUiModelMapper
import chat.rocket.android.server.domain.ChatRoomsInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.getFiles import chat.rocket.core.internal.rest.getFiles
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
class FilesPresenter @Inject constructor( class FilesPresenter @Inject constructor(
private val view: FilesView, private val view: FilesView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val roomsInteractor: ChatRoomsInteractor, private val dbManager: DatabaseManager,
private val mapper: FileUiModelMapper, @Named("currentServer") private val currentServer: String,
val serverInteractor: GetCurrentServerInteractor, private val mapper: FileUiModelMapper,
val factory: RocketChatClientFactory val factory: RocketChatClientFactory
) { ) {
private val serverUrl = serverInteractor.get()!! private val client: RocketChatClient = factory.create(currentServer)
private val client = factory.create(serverUrl)
private var offset: Int = 0 private var offset: Int = 0
/** /**
...@@ -35,8 +36,8 @@ class FilesPresenter @Inject constructor( ...@@ -35,8 +36,8 @@ class FilesPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
try { try {
view.showLoading() view.showLoading()
roomsInteractor.getById(serverUrl, roomId)?.let { dbManager.getRoom(roomId)?.let {
val files = client.getFiles(roomId, it.type, offset) val files = client.getFiles(roomId, roomTypeOf(it.chatRoom.type), offset)
val filesUiModel = mapper.mapToUiModelList(files.result) val filesUiModel = mapper.mapToUiModelList(files.result)
view.showFiles(filesUiModel, files.total) view.showFiles(filesUiModel, files.total)
offset += 1 * 30 offset += 1 * 30
......
...@@ -3,6 +3,7 @@ package chat.rocket.android.helper ...@@ -3,6 +3,7 @@ package chat.rocket.android.helper
import chat.rocket.android.server.domain.GetCurrentServerInteractor import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.core.model.ChatRoom import chat.rocket.core.model.ChatRoom
...@@ -24,7 +25,11 @@ class MessageHelper @Inject constructor( ...@@ -24,7 +25,11 @@ class MessageHelper @Inject constructor(
is RoomType.LiveChat -> "livechat" is RoomType.LiveChat -> "livechat"
else -> "custom" else -> "custom"
} }
val name = if (settings.useRealName()) chatRoom.fullName ?: chatRoom.name else chatRoom.name val name = if (settings.useSpecialCharsOnRoom() || settings.useRealName()) {
chatRoom.fullName ?: chatRoom.name
} else {
chatRoom.name
}
return "[ ]($currentServer/$type/$name?msg=${message.id}) " return "[ ]($currentServer/$type/$name?msg=${message.id}) "
} }
......
...@@ -4,19 +4,25 @@ import androidx.lifecycle.LifecycleOwner ...@@ -4,19 +4,25 @@ import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.chatroom.ui.ChatRoomActivity import chat.rocket.android.chatroom.ui.ChatRoomActivity
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.members.presentation.MembersNavigator import chat.rocket.android.members.presentation.MembersNavigator
import chat.rocket.android.members.presentation.MembersView import chat.rocket.android.members.presentation.MembersView
import chat.rocket.android.members.ui.MembersFragment import chat.rocket.android.members.ui.MembersFragment
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import javax.inject.Named
@Module @Module
class MembersFragmentModule { class MembersFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun provideJob() = Job() fun membersView(frag: MembersFragment): MembersView {
return frag
}
@Provides @Provides
@PerFragment @PerFragment
...@@ -24,10 +30,24 @@ class MembersFragmentModule { ...@@ -24,10 +30,24 @@ class MembersFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun membersView(frag: MembersFragment): MembersView { @Named("currentServer")
return frag fun provideCurrentServer(currentServerInteractor: GetCurrentServerInteractor): String {
return currentServerInteractor.get()!!
}
@Provides
@PerFragment
fun provideDatabaseManager(
factory: DatabaseManagerFactory,
@Named("currentServer") currentServer: String
): DatabaseManager {
return factory.create(currentServer)
} }
@Provides
@PerFragment
fun provideJob() = Job()
@Provides @Provides
@PerFragment @PerFragment
fun provideLifecycleOwner(frag: MembersFragment): LifecycleOwner { fun provideLifecycleOwner(frag: MembersFragment): LifecycleOwner {
......
package chat.rocket.android.members.presentation package chat.rocket.android.members.presentation
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.members.uimodel.MemberUiModel import chat.rocket.android.members.uimodel.MemberUiModel
import chat.rocket.android.members.uimodel.MemberUiModelMapper import chat.rocket.android.members.uimodel.MemberUiModelMapper
import chat.rocket.android.server.domain.ChatRoomsInteractor
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.getMembers import chat.rocket.core.internal.rest.getMembers
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
class MembersPresenter @Inject constructor( class MembersPresenter @Inject constructor(
private val view: MembersView, private val view: MembersView,
private val navigator: MembersNavigator, private val navigator: MembersNavigator,
private val dbManager: DatabaseManager,
@Named("currentServer") private val currentServer: String,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val roomsInteractor: ChatRoomsInteractor,
private val mapper: MemberUiModelMapper, private val mapper: MemberUiModelMapper,
val serverInteractor: GetCurrentServerInteractor,
val factory: RocketChatClientFactory val factory: RocketChatClientFactory
) { ) {
private val serverUrl = serverInteractor.get()!! private val client: RocketChatClient = factory.create(currentServer)
private val client: RocketChatClient = factory.create(serverUrl)
private var offset: Long = 0 private var offset: Long = 0
/**
* Loads all the chat room members for the given room id.
*
* @param roomId The id of the room to get chat room members from.
*/
fun loadChatRoomsMembers(roomId: String) { fun loadChatRoomsMembers(roomId: String) {
launchUI(strategy) { launchUI(strategy) {
try { try {
view.showLoading() view.showLoading()
roomsInteractor.getById(serverUrl, roomId)?.let { dbManager.getRoom(roomId)?.let {
val members = client.getMembers(it.id, it.type, offset, 60) val members =
client.getMembers(roomId, roomTypeOf(it.chatRoom.type), offset, 60)
val memberUiModels = mapper.mapToUiModelList(members.result) val memberUiModels = mapper.mapToUiModelList(members.result)
view.showMembers(memberUiModels, members.total) view.showMembers(memberUiModels, members.total)
offset += 1 * 60L offset += 1 * 60L
}.ifNull { }.ifNull {
Timber.e("Couldn't find a room with id: $roomId at current server") Timber.e("Couldn't find a room with id: $roomId at current server.")
} }
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
...@@ -52,12 +58,12 @@ class MembersPresenter @Inject constructor( ...@@ -52,12 +58,12 @@ class MembersPresenter @Inject constructor(
} }
fun toMemberDetails(memberUiModel: MemberUiModel) { fun toMemberDetails(memberUiModel: MemberUiModel) {
val avatarUri = memberUiModel.avatarUri.toString() navigator.toMemberDetails(
val realName = memberUiModel.realName.toString() memberUiModel.avatarUri.toString(),
val username = "@${memberUiModel.username}" memberUiModel.realName.toString(),
val email = memberUiModel.email ?: "" "@${memberUiModel.username}",
val utcOffset = memberUiModel.utcOffset.toString() memberUiModel.email ?: "",
memberUiModel.utcOffset.toString()
navigator.toMemberDetails(avatarUri, realName, username, email, utcOffset) )
} }
} }
\ No newline at end of file
...@@ -3,34 +3,54 @@ package chat.rocket.android.pinnedmessages.di ...@@ -3,34 +3,54 @@ package chat.rocket.android.pinnedmessages.di
import androidx.lifecycle.LifecycleOwner import androidx.lifecycle.LifecycleOwner
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.dagger.scope.PerFragment import chat.rocket.android.dagger.scope.PerFragment
import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.db.DatabaseManagerFactory
import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesView import chat.rocket.android.pinnedmessages.presentation.PinnedMessagesView
import chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment import chat.rocket.android.pinnedmessages.ui.PinnedMessagesFragment
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import dagger.Module import dagger.Module
import dagger.Provides import dagger.Provides
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import javax.inject.Named
@Module @Module
class PinnedMessagesFragmentModule { class PinnedMessagesFragmentModule {
@Provides @Provides
@PerFragment @PerFragment
fun provideJob() = Job() fun providePinnedMessagesView(frag: PinnedMessagesFragment): PinnedMessagesView {
return frag
}
@Provides @Provides
@PerFragment @PerFragment
fun provideLifecycleOwner(frag: PinnedMessagesFragment): LifecycleOwner { @Named("currentServer")
return frag fun provideCurrentServer(currentServerInteractor: GetCurrentServerInteractor): String {
return currentServerInteractor.get()!!
} }
@Provides @Provides
@PerFragment @PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy { fun provideDatabaseManager(
return CancelStrategy(owner, jobs) factory: DatabaseManagerFactory,
@Named("currentServer") currentServer: String
): DatabaseManager {
return factory.create(currentServer)
} }
@Provides @Provides
@PerFragment @PerFragment
fun providePinnedMessagesView(frag: PinnedMessagesFragment): PinnedMessagesView { fun provideJob() = Job()
@Provides
@PerFragment
fun provideLifecycleOwner(frag: PinnedMessagesFragment): LifecycleOwner {
return frag return frag
} }
@Provides
@PerFragment
fun provideCancelStrategy(owner: LifecycleOwner, jobs: Job): CancelStrategy {
return CancelStrategy(owner, jobs)
}
} }
\ No newline at end of file
...@@ -2,26 +2,27 @@ package chat.rocket.android.pinnedmessages.presentation ...@@ -2,26 +2,27 @@ package chat.rocket.android.pinnedmessages.presentation
import chat.rocket.android.chatroom.uimodel.UiModelMapper import chat.rocket.android.chatroom.uimodel.UiModelMapper
import chat.rocket.android.core.lifecycle.CancelStrategy import chat.rocket.android.core.lifecycle.CancelStrategy
import chat.rocket.android.server.domain.ChatRoomsInteractor import chat.rocket.android.db.DatabaseManager
import chat.rocket.android.server.domain.GetCurrentServerInteractor
import chat.rocket.android.server.infraestructure.RocketChatClientFactory import chat.rocket.android.server.infraestructure.RocketChatClientFactory
import chat.rocket.android.util.extensions.launchUI import chat.rocket.android.util.extensions.launchUI
import chat.rocket.common.RocketChatException import chat.rocket.common.RocketChatException
import chat.rocket.common.model.roomTypeOf
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.rest.getPinnedMessages import chat.rocket.core.internal.rest.getPinnedMessages
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
class PinnedMessagesPresenter @Inject constructor( class PinnedMessagesPresenter @Inject constructor(
private val view: PinnedMessagesView, private val view: PinnedMessagesView,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val roomsInteractor: ChatRoomsInteractor, private val dbManager: DatabaseManager,
@Named("currentServer") private val currentServer: String,
private val mapper: UiModelMapper, private val mapper: UiModelMapper,
val serverInteractor: GetCurrentServerInteractor,
val factory: RocketChatClientFactory val factory: RocketChatClientFactory
) { ) {
private val serverUrl = serverInteractor.get()!! private val client: RocketChatClient = factory.create(currentServer)
private val client = factory.create(serverUrl)
private var offset: Int = 0 private var offset: Int = 0
/** /**
...@@ -33,8 +34,9 @@ class PinnedMessagesPresenter @Inject constructor( ...@@ -33,8 +34,9 @@ class PinnedMessagesPresenter @Inject constructor(
launchUI(strategy) { launchUI(strategy) {
try { try {
view.showLoading() view.showLoading()
roomsInteractor.getById(serverUrl, roomId)?.let { dbManager.getRoom(roomId)?.let {
val pinnedMessages = client.getPinnedMessages(roomId, it.type, offset) val pinnedMessages =
client.getPinnedMessages(roomId, roomTypeOf(it.chatRoom.type), offset)
val messageList = mapper.map(pinnedMessages.result, asNotReversed = true) val messageList = mapper.map(pinnedMessages.result, asNotReversed = true)
view.showPinnedMessages(messageList) view.showPinnedMessages(messageList)
offset += 1 * 30 offset += 1 * 30
......
...@@ -71,6 +71,7 @@ fun PublicSettings.gitlabUrl(): String? = this[ACCOUNT_GITLAB_URL]?.value as Str ...@@ -71,6 +71,7 @@ fun PublicSettings.gitlabUrl(): String? = this[ACCOUNT_GITLAB_URL]?.value as Str
fun PublicSettings.isWordpressAuthenticationEnabled(): Boolean = this[ACCOUNT_WORDPRESS]?.value == true fun PublicSettings.isWordpressAuthenticationEnabled(): Boolean = this[ACCOUNT_WORDPRESS]?.value == true
fun PublicSettings.useRealName(): Boolean = this[USE_REALNAME]?.value == true fun PublicSettings.useRealName(): Boolean = this[USE_REALNAME]?.value == true
fun PublicSettings.useSpecialCharsOnRoom(): Boolean = this[ALLOW_ROOM_NAME_SPECIAL_CHARS]?.value == true
fun PublicSettings.faviconLarge(): String? = this[FAVICON_512]?.value as String? fun PublicSettings.faviconLarge(): String? = this[FAVICON_512]?.value as String?
fun PublicSettings.favicon(): String? = this[FAVICON_196]?.value as String? fun PublicSettings.favicon(): String? = this[FAVICON_196]?.value as String?
fun PublicSettings.wideTile(): String? = this[WIDE_TILE_310]?.value as String? fun PublicSettings.wideTile(): String? = this[WIDE_TILE_310]?.value as String?
......
package chat.rocket.android.server.infraestructure package chat.rocket.android.server.infraestructure
import android.os.Build
import chat.rocket.android.BuildConfig
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.common.util.PlatformLogger import chat.rocket.common.util.PlatformLogger
import chat.rocket.core.RocketChatClient import chat.rocket.core.RocketChatClient
import chat.rocket.android.server.domain.TokenRepository
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Singleton import javax.inject.Singleton
@Singleton @Singleton
class RocketChatClientFactory @Inject constructor(private val okHttpClient: OkHttpClient, class RocketChatClientFactory @Inject constructor(
private val repository: TokenRepository, private val okHttpClient: OkHttpClient,
private val logger: PlatformLogger) { private val repository: TokenRepository,
private val logger: PlatformLogger
) {
private val cache = HashMap<String, RocketChatClient>() private val cache = HashMap<String, RocketChatClient>()
fun create(url: String): RocketChatClient { fun create(url: String): RocketChatClient {
...@@ -23,6 +27,7 @@ class RocketChatClientFactory @Inject constructor(private val okHttpClient: OkHt ...@@ -23,6 +27,7 @@ class RocketChatClientFactory @Inject constructor(private val okHttpClient: OkHt
val client = RocketChatClient.create { val client = RocketChatClient.create {
httpClient = okHttpClient httpClient = okHttpClient
restUrl = url restUrl = url
userAgent = "RC Mobile; Android ${Build.VERSION.RELEASE}; v${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})"
tokenRepository = repository tokenRepository = repository
platformLogger = logger platformLogger = logger
} }
......
package chat.rocket.android.settings.about.ui
import android.os.Bundle
import androidx.appcompat.app.AppCompatActivity
import chat.rocket.android.BuildConfig
import chat.rocket.android.R
import chat.rocket.android.util.extensions.textContent
import kotlinx.android.synthetic.main.about_view.*
import kotlinx.android.synthetic.main.app_bar_password.*
class AboutActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_about)
setupToolbar()
setupViews()
}
private fun setupViews() {
text_version_name.text = getString(R.string.msg_version, BuildConfig.VERSION_NAME)
text_build_number.text = getString(R.string.msg_build, BuildConfig.VERSION_CODE)
}
private fun setupToolbar() {
setSupportActionBar(toolbar)
text_change_password.textContent = getString(R.string.title_about)
}
override fun onBackPressed() {
super.onBackPressed()
finish()
overridePendingTransition(R.anim.close_enter, R.anim.close_exit)
}
override fun onSupportNavigateUp(): Boolean {
onBackPressed()
return super.onNavigateUp()
}
}
...@@ -9,9 +9,10 @@ import android.view.View ...@@ -9,9 +9,10 @@ import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.widget.AdapterView import android.widget.AdapterView
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.settings.about.ui.AboutActivity import chat.rocket.android.about.ui.AboutFragment
import chat.rocket.android.settings.password.ui.PasswordActivity import chat.rocket.android.settings.password.ui.PasswordActivity
import chat.rocket.android.settings.presentation.SettingsView import chat.rocket.android.settings.presentation.SettingsView
import chat.rocket.android.util.extensions.addFragmentBackStack
import chat.rocket.android.util.extensions.inflate import chat.rocket.android.util.extensions.inflate
import kotlinx.android.synthetic.main.fragment_settings.* import kotlinx.android.synthetic.main.fragment_settings.*
import kotlin.reflect.KClass import kotlin.reflect.KClass
...@@ -39,7 +40,9 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen ...@@ -39,7 +40,9 @@ class SettingsFragment : Fragment(), SettingsView, AdapterView.OnItemClickListen
startNewActivity(PasswordActivity::class) startNewActivity(PasswordActivity::class)
} }
resources.getString(R.string.title_about) -> { resources.getString(R.string.title_about) -> {
startNewActivity(AboutActivity::class) (activity as AppCompatActivity).addFragmentBackStack("AboutFragmnet", R.id.fragment_container){
AboutFragment.newInstance()
}
} }
} }
} }
......
package chat.rocket.android.util.extensions package chat.rocket.android.util.extensions
import android.annotation.SuppressLint
import android.app.Activity import android.app.Activity
import android.content.Context import android.content.Context
import android.view.LayoutInflater import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuItem
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import android.view.inputmethod.InputMethodManager import android.view.inputmethod.InputMethodManager
import android.widget.Toast import android.widget.Toast
import androidx.annotation.LayoutRes import androidx.annotation.LayoutRes
import androidx.annotation.MenuRes
import androidx.annotation.StringRes import androidx.annotation.StringRes
import androidx.appcompat.app.AppCompatActivity import androidx.appcompat.app.AppCompatActivity
import androidx.appcompat.view.SupportMenuInflater
import androidx.appcompat.view.menu.MenuBuilder
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import chat.rocket.android.R import chat.rocket.android.R
...@@ -86,4 +92,23 @@ fun Fragment.showToast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SH ...@@ -86,4 +92,23 @@ fun Fragment.showToast(@StringRes resource: Int, duration: Int = Toast.LENGTH_SH
showToast(getString(resource), duration) showToast(getString(resource), duration)
fun Fragment.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) = fun Fragment.showToast(message: String, duration: Int = Toast.LENGTH_SHORT) =
activity?.showToast(message, duration) activity?.showToast(message, duration)
\ No newline at end of file
@SuppressLint("RestrictedApi")
fun Context.inflate(@MenuRes menuRes: Int): Menu {
val menu = MenuBuilder(this)
val menuInflater = SupportMenuInflater(this)
menuInflater.inflate(menuRes, menu)
return menu
}
/**
* Developed by Magora-Systems.com
* @since 2017
* @author Anton Vlasov - whalemare
*/
fun Menu.toList(): List<MenuItem> {
val menuItems = ArrayList<MenuItem>(this.size())
(0 until this.size()).mapTo(menuItems) { this.getItem(it) }
return menuItems
}
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
android:theme="@style/AppTheme"
tools:context="chat.rocket.android.settings.about.ui.AboutActivity">
<include
android:id="@+id/layout_app_bar"
layout="@layout/app_bar_password" />
<include layout="@layout/about_view"/>
</LinearLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
<androidx.constraintlayout.widget.ConstraintLayout xmlns:tools="http://schemas.android.com/tools"
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"> tools:context="chat.rocket.android.about.ui.AboutFragment">
<ImageView <ImageView
android:id="@+id/image_app_name" android:id="@+id/image_app_name"
...@@ -14,7 +13,7 @@ ...@@ -14,7 +13,7 @@
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"/> app:layout_constraintEnd_toEndOf="parent" />
<ImageView <ImageView
android:layout_width="160dp" android:layout_width="160dp"
...@@ -25,8 +24,7 @@ ...@@ -25,8 +24,7 @@
app:layout_constraintBottom_toTopOf="@id/image_app_name" app:layout_constraintBottom_toTopOf="@id/image_app_name"
android:adjustViewBounds="true" android:adjustViewBounds="true"
android:scaleX="1.5" android:scaleX="1.5"
android:scaleY="1.5" android:scaleY="1.5" />
/>
<TextView <TextView
android:id="@+id/text_version_name" android:id="@+id/text_version_name"
...@@ -37,7 +35,7 @@ ...@@ -37,7 +35,7 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/image_app_name" app:layout_constraintTop_toBottomOf="@+id/image_app_name"
android:layout_marginTop="16dp" android:layout_marginTop="16dp"
android:textColor="@color/colorSecondaryText"/> android:textColor="@color/colorSecondaryText" />
<TextView <TextView
android:id="@+id/text_build_number" android:id="@+id/text_build_number"
...@@ -48,6 +46,6 @@ ...@@ -48,6 +46,6 @@
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/text_version_name" app:layout_constraintTop_toBottomOf="@+id/text_version_name"
android:layout_marginTop="8dp" android:layout_marginTop="8dp"
android:textColor="@color/colorSecondaryText"/> android:textColor="@color/colorSecondaryText" />
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?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"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/selectableItemBackground"
android:paddingStart="16dp"
android:paddingTop="8dp"
android:paddingEnd="16dp"
android:paddingBottom="8dp">
<ImageView
android:id="@+id/message_action_icon"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="32dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toStartOf="@+id/message_action_title"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
tools:srcCompat="@drawable/ic_action_message_reply_24dp" />
<TextView
android:id="@+id/message_action_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
android:textSize="16sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.5"
app:layout_constraintStart_toEndOf="@+id/message_action_icon"
app:layout_constraintTop_toTopOf="parent"
tools:text="Responder" />
</androidx.constraintlayout.widget.ConstraintLayout>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="match_parent">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/bottomsheet_recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="8dp"
android:layout_marginBottom="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
\ No newline at end of file
...@@ -6,13 +6,13 @@ ...@@ -6,13 +6,13 @@
android:id="@+id/action_search" android:id="@+id/action_search"
android:icon="@drawable/ic_search_white_24px" android:icon="@drawable/ic_search_white_24px"
android:title="@string/action_search" android:title="@string/action_search"
android:actionViewClass="androidx.appcompat.widget.SearchView" app:actionViewClass="androidx.appcompat.widget.SearchView"
android:showAsAction="ifRoom|collapseActionView" /> app:showAsAction="ifRoom|collapseActionView" />
<item <item
android:id="@+id/action_sort" android:id="@+id/action_sort"
android:icon="@drawable/ic_sort" android:icon="@drawable/ic_sort"
android:title="@string/menu_chatroom_sort" android:title="@string/menu_chatroom_sort"
android:showAsAction="always" /> app:showAsAction="ifRoom" />
</menu> </menu>
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<menu xmlns:android="http://schemas.android.com/apk/res/android"> <menu xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<item <item
android:id="@+id/action_message_reply" android:id="@+id/action_message_reply"
......
...@@ -10,7 +10,7 @@ buildscript { ...@@ -10,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.2.0-alpha18' classpath 'com.android.tools.build:gradle:3.2.0-beta02'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}" classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}" classpath "org.jetbrains.dokka:dokka-gradle-plugin:${versions.dokka}"
classpath 'com.google.gms:google-services:3.2.0' classpath 'com.google.gms:google-services:3.2.0'
......
...@@ -34,7 +34,6 @@ ext { ...@@ -34,7 +34,6 @@ ext {
kotshi : '1.0.2', kotshi : '1.0.2',
frescoImageViewer : '0.5.1', frescoImageViewer : '0.5.1',
markwon : '1.0.3', markwon : '1.0.3',
sheetMenu : '5ff79ccf14',
aVLoadingIndicatorView: '2.1.3', aVLoadingIndicatorView: '2.1.3',
flexbox : '0.3.2', flexbox : '0.3.2',
...@@ -102,12 +101,8 @@ ext { ...@@ -102,12 +101,8 @@ ext {
markwon : "ru.noties:markwon:${versions.markwon}", markwon : "ru.noties:markwon:${versions.markwon}",
//sheetMenu : "com.github.whalemare:sheetmenu:${versions.sheetMenu}",
sheetMenu : "com.github.luciofm:sheetmenu:${versions.sheetMenu}",
aVLoadingIndicatorView: "com.wang.avi:library:${versions.aVLoadingIndicatorView}", aVLoadingIndicatorView: "com.wang.avi:library:${versions.aVLoadingIndicatorView}",
//For the wear app //For the wear app
wearable : "com.google.android.support:wearable:${versions.wear}", wearable : "com.google.android.support:wearable:${versions.wear}",
playServicesWearable : "com.google.android.gms:play-services-wearable:${versions.playServicesWearable}", playServicesWearable : "com.google.android.gms:play-services-wearable:${versions.playServicesWearable}",
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment