Commit 6d555753 authored by Leonardo Aramaki's avatar Leonardo Aramaki

Merge branch 'new/offline-sending' of...

Merge branch 'new/offline-sending' of github.com:RocketChat/Rocket.Chat.Android into new/offline-sending
parents 8017ab42 1961ae4c
...@@ -19,18 +19,12 @@ Since both the versions use `kotlin` for some or all of their classes, following ...@@ -19,18 +19,12 @@ Since both the versions use `kotlin` for some or all of their classes, following
- After checking out to `develop` branch as mentioned above, simply import the project in Android Studio. - After checking out to `develop` branch as mentioned above, simply import the project in Android Studio.
#### v2+ #### v2+
- This version requires the [Kotlin SDK](https://github.com/RocketChat/Rocket.Chat.Kotlin.SDK) for Rocket.Chat. Clone the Kotlin SDK in the **same directory** as the android repository by running `git clone https://github.com/RocketChat/Rocket.Chat.Kotlin.SDK.git`. Make sure that the android repository and the kotlin sdk have the same immediate parent directory. - This version requires the [Kotlin SDK](https://github.com/RocketChat/Rocket.Chat.Kotlin.SDK) for Rocket.Chat. Clone the Kotlin SDK in by running `git clone https://github.com/RocketChat/Rocket.Chat.Kotlin.SDK.git`.
- First, a build is required for the SDK. Change your directory to the SDK directory by running `cd Rocket.Chat.Kotlin.SDK/` in your terminal. Any of the following approaches can be followed to successfully build the SDK. - First, a build is required for the SDK, so that required jar files are generated. Make sure that the android repository and the kotlin sdk have the same immediate parent directory. Change the current directory to `Rocket.Chat.Android/app` and run the `build-sdk.sh` which will result in creating of the required jar file `core*.jar` and `common*.jar` in `Rocket.Chat.Android/app/libs`,by the following steps in your terminal window:
- **Command Line** - (Within the kotlin SDK directory) Run `./gradlew clean && ./gradlew assemble` to successfully build the project.
- **Android Studio** - Import the project in Android Studio. Go to `Build > Make Project` to build the SDK successfully.
After following the above methods, follow the following steps in your terminal window:
``` ```
cd .. cd Rocket.Chat.Android/app
cd Rocket.Chat.Android/app/libs ./build-sdk.sh
ls
``` ```
Two `jar` files will be found in this directory (the `common` and `core` jar files), this indicates that the SDK was built correctly.
- After the SDK has been built successfully, import the project in Android Studio and build it by following `Build > Make Project`.
## How to run ## How to run
### Command Line ### Command Line
......
...@@ -22,6 +22,10 @@ import chat.rocket.core.internal.realtime.setDefaultStatus ...@@ -22,6 +22,10 @@ import chat.rocket.core.internal.realtime.setDefaultStatus
import chat.rocket.core.internal.rest.logout import chat.rocket.core.internal.rest.logout
import chat.rocket.core.internal.rest.me import chat.rocket.core.internal.rest.me
import chat.rocket.core.internal.rest.unregisterPushToken import chat.rocket.core.internal.rest.unregisterPushToken
import chat.rocket.core.model.Myself
import kotlinx.coroutines.experimental.CommonPool
import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch
import timber.log.Timber import timber.log.Timber
import javax.inject.Inject import javax.inject.Inject
...@@ -45,6 +49,8 @@ class MainPresenter @Inject constructor( ...@@ -45,6 +49,8 @@ class MainPresenter @Inject constructor(
private val client: RocketChatClient = factory.create(currentServer) private val client: RocketChatClient = factory.create(currentServer)
private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!)
private val userDataChannel = Channel<Myself>()
fun toChatList() = navigator.toChatList() fun toChatList() = navigator.toChatList()
fun toUserProfile() = navigator.toUserProfile() fun toUserProfile() = navigator.toUserProfile()
...@@ -55,7 +61,9 @@ class MainPresenter @Inject constructor( ...@@ -55,7 +61,9 @@ class MainPresenter @Inject constructor(
checkServerInfo() checkServerInfo()
launchUI(strategy) { launchUI(strategy) {
try { try {
val me = retryIO("me") { client.me() } val me = retryIO("me") {
client.me()
}
val model = navHeaderMapper.mapToViewModel(me) val model = navHeaderMapper.mapToViewModel(me)
saveAccount(model) saveAccount(model)
view.setupNavHeader(model, getAccountsInteractor.get()) view.setupNavHeader(model, getAccountsInteractor.get())
...@@ -74,23 +82,10 @@ class MainPresenter @Inject constructor( ...@@ -74,23 +82,10 @@ class MainPresenter @Inject constructor(
} }
} }
} }
subscribeMyselfUpdates()
} }
} }
private suspend fun saveAccount(viewModel: NavHeaderViewModel) {
val icon = settings.favicon()?.let {
currentServer.serverLogoUrl(it)
}
val account = Account(
currentServer,
icon,
viewModel.serverLogo,
viewModel.userDisplayName,
viewModel.userAvatar
)
saveAccountInteractor.save(account)
}
/** /**
* Logout from current server. * Logout from current server.
*/ */
...@@ -121,24 +116,12 @@ class MainPresenter @Inject constructor( ...@@ -121,24 +116,12 @@ class MainPresenter @Inject constructor(
} }
} }
private suspend fun clearTokens() {
serverInteractor.clear()
val pushToken = localRepository.get(LocalRepository.KEY_PUSH_TOKEN)
if (pushToken != null) {
try {
retryIO("unregisterPushToken") { client.unregisterPushToken(pushToken) }
} catch (ex: Exception) {
Timber.d(ex, "Error unregistering push token")
}
}
localRepository.clearAllFromServer(currentServer)
}
fun connect() { fun connect() {
manager.connect() manager.connect()
} }
fun disconnect() { fun disconnect() {
manager.removeUserDataChannel(userDataChannel)
manager.disconnect() manager.disconnect()
} }
...@@ -175,4 +158,43 @@ class MainPresenter @Inject constructor( ...@@ -175,4 +158,43 @@ class MainPresenter @Inject constructor(
client.registerPushToken(token, getAccountsInteractor.get(), factory) client.registerPushToken(token, getAccountsInteractor.get(), factory)
} }
} }
private suspend fun saveAccount(viewModel: NavHeaderViewModel) {
val icon = settings.favicon()?.let {
currentServer.serverLogoUrl(it)
}
val account = Account(
currentServer,
icon,
viewModel.serverLogo,
viewModel.userDisplayName!!,
viewModel.userAvatar
)
saveAccountInteractor.save(account)
}
private suspend fun clearTokens() {
serverInteractor.clear()
val pushToken = localRepository.get(LocalRepository.KEY_PUSH_TOKEN)
if (pushToken != null) {
try {
retryIO("unregisterPushToken") { client.unregisterPushToken(pushToken) }
} catch (ex: Exception) {
Timber.d(ex, "Error unregistering push token")
}
}
localRepository.clearAllFromServer(currentServer)
}
private suspend fun subscribeMyselfUpdates() {
manager.addUserDataChannel(userDataChannel)
for (myself in userDataChannel) {
updateMyself(myself)
}
}
private suspend fun updateMyself(myself: Myself) {
val model = navHeaderMapper.mapToViewModel(myself)
view.setupNavHeader(model, getAccountsInteractor.get())
}
} }
\ No newline at end of file
...@@ -95,16 +95,23 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, HasSupp ...@@ -95,16 +95,23 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector, HasSupp
override fun setupNavHeader(viewModel: NavHeaderViewModel, accounts: List<Account>) { override fun setupNavHeader(viewModel: NavHeaderViewModel, accounts: List<Account>) {
Timber.d("Setting up nav header: $viewModel") Timber.d("Setting up nav header: $viewModel")
with(headerLayout) { with(headerLayout) {
image_user_status.setImageDrawable( with(viewModel) {
DrawableHelper.getUserStatusDrawable( if (userStatus != null) {
viewModel.userStatus!!, image_user_status.setImageDrawable(
this.context DrawableHelper.getUserStatusDrawable(userStatus, context)
) )
) }
text_user_name.text = viewModel.userDisplayName if (userDisplayName != null) {
text_server_url.text = viewModel.serverUrl text_user_name.text = userDisplayName
image_avatar.setImageURI(viewModel.userAvatar) }
server_logo.setImageURI(viewModel.serverLogo) if (userAvatar != null) {
image_avatar.setImageURI(userAvatar)
}
if (serverLogo != null) {
server_logo.setImageURI(serverLogo)
}
text_server_url.text = viewModel.serverUrl
}
setupAccountsList(headerLayout, accounts) setupAccountsList(headerLayout, accounts)
} }
} }
......
...@@ -4,7 +4,7 @@ import chat.rocket.common.model.UserStatus ...@@ -4,7 +4,7 @@ import chat.rocket.common.model.UserStatus
data class NavHeaderViewModel( data class NavHeaderViewModel(
val userDisplayName: String, val userDisplayName: String?,
val userStatus: UserStatus?, val userStatus: UserStatus?,
val userAvatar: String?, val userAvatar: String?,
val serverUrl: String, val serverUrl: String,
......
...@@ -23,10 +23,10 @@ class NavHeaderViewModelMapper @Inject constructor( ...@@ -23,10 +23,10 @@ class NavHeaderViewModelMapper @Inject constructor(
return NavHeaderViewModel(displayName, status, avatar, currentServer, logo) return NavHeaderViewModel(displayName, status, avatar, currentServer, logo)
} }
private fun mapDisplayName(me: Myself): String { private fun mapDisplayName(me: Myself): String? {
val username = me.username val username = me.username
val realName = me.name val realName = me.name
val senderName = if (settings.useRealName()) realName else username val senderName = if (settings.useRealName()) realName else username
return senderName ?: username.toString() return senderName ?: username
} }
} }
\ No newline at end of file
...@@ -27,7 +27,7 @@ class ProfilePresenter @Inject constructor(private val view: ProfileView, ...@@ -27,7 +27,7 @@ class ProfilePresenter @Inject constructor(private val view: ProfileView,
view.showLoading() view.showLoading()
try { try {
val myself = retryIO("me") { client.me() } val myself = retryIO("me") { client.me() }
myselfId = myself.id myselfId = myself.id!!
val avatarUrl = serverUrl.avatarUrl(myself.username!!) val avatarUrl = serverUrl.avatarUrl(myself.username!!)
view.showProfile( view.showProfile(
avatarUrl, avatarUrl,
......
...@@ -5,6 +5,7 @@ import chat.rocket.core.RocketChatClient ...@@ -5,6 +5,7 @@ import chat.rocket.core.RocketChatClient
import chat.rocket.core.internal.realtime.* import chat.rocket.core.internal.realtime.*
import chat.rocket.core.internal.rest.chatRooms import chat.rocket.core.internal.rest.chatRooms
import chat.rocket.core.model.Message import chat.rocket.core.model.Message
import chat.rocket.core.model.Myself
import kotlinx.coroutines.experimental.Job import kotlinx.coroutines.experimental.Job
import kotlinx.coroutines.experimental.channels.Channel import kotlinx.coroutines.experimental.channels.Channel
import kotlinx.coroutines.experimental.launch import kotlinx.coroutines.experimental.launch
...@@ -19,14 +20,15 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -19,14 +20,15 @@ class ConnectionManager(internal val client: RocketChatClient) {
private val roomAndSubscriptionChannels = ArrayList<Channel<StreamMessage<BaseRoom>>>() private val roomAndSubscriptionChannels = ArrayList<Channel<StreamMessage<BaseRoom>>>()
private val roomMessagesChannels = LinkedHashMap<String, Channel<Message>>() private val roomMessagesChannels = LinkedHashMap<String, Channel<Message>>()
private val userDataChannels = ArrayList<Channel<Myself>>()
private val subscriptionIdMap = HashMap<String, String>() private val subscriptionIdMap = HashMap<String, String>()
private var subscriptionId: String? = null private var subscriptionId: String? = null
private var roomsId: String? = null private var roomsId: String? = null
private var userId: String? = null
fun connect() { fun connect() {
if (connectJob?.isActive == true if (connectJob?.isActive == true && (state !is State.Disconnected)) {
&& (state !is State.Disconnected)) {
Timber.d("Already connected, just returning...") Timber.d("Already connected, just returning...")
return return
} }
...@@ -52,6 +54,11 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -52,6 +54,11 @@ class ConnectionManager(internal val client: RocketChatClient) {
roomsId = id roomsId = id
} }
client.subscribeUserDataChanges { _, id ->
Timber.d("Subscribed to the user: $id")
userId = id
}
resubscribeRooms() resubscribeRooms()
} }
is State.Waiting -> { is State.Waiting -> {
...@@ -92,6 +99,15 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -92,6 +99,15 @@ class ConnectionManager(internal val client: RocketChatClient) {
} }
} }
launch(parent = connectJob) {
for (myself in client.userDataChannel) {
Timber.d("Got userData")
for (channel in userDataChannels) {
channel.send(myself)
}
}
}
client.connect() client.connect()
// Broadcast initial state... // Broadcast initial state...
...@@ -125,6 +141,10 @@ class ConnectionManager(internal val client: RocketChatClient) { ...@@ -125,6 +141,10 @@ class ConnectionManager(internal val client: RocketChatClient) {
fun removeRoomsAndSubscriptionsChannel(channel: Channel<StreamMessage<BaseRoom>>) = roomAndSubscriptionChannels.remove(channel) fun removeRoomsAndSubscriptionsChannel(channel: Channel<StreamMessage<BaseRoom>>) = roomAndSubscriptionChannels.remove(channel)
fun addUserDataChannel(channel: Channel<Myself>) = userDataChannels.add(channel)
fun removeUserDataChannel(channel: Channel<Myself>) = userDataChannels.remove(channel)
fun subscribeRoomMessages(roomId: String, channel: Channel<Message>) { fun subscribeRoomMessages(roomId: String, channel: Channel<Message>) {
val oldSub = roomMessagesChannels.put(roomId, channel) val oldSub = roomMessagesChannels.put(roomId, channel)
if (oldSub != null) { if (oldSub != null) {
......
...@@ -25,7 +25,7 @@ class PasswordPresenter @Inject constructor (private val view: PasswordView, ...@@ -25,7 +25,7 @@ class PasswordPresenter @Inject constructor (private val view: PasswordView,
val me = retryIO("me") { client.me() } val me = retryIO("me") { client.me() }
retryIO("updateProfile(${me.id})") { retryIO("updateProfile(${me.id})") {
client.updateProfile(me.id, null, null, password, null) client.updateProfile(me.id!!, null, null, password, null)
} }
view.showPasswordSuccessfullyUpdatedMessage() view.showPasswordSuccessfullyUpdatedMessage()
......
...@@ -10,7 +10,7 @@ buildscript { ...@@ -10,7 +10,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.1.0' classpath 'com.android.tools.build:gradle:3.1.1'
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'
......
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