Unverified Commit c0b2083b authored by Ergashev Adizbek's avatar Ergashev Adizbek Committed by GitHub

Merge branch 'develop' into swipe-to-reply

parents 38c960d8 fdf25924
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"formatVersion": 1, "formatVersion": 1,
"database": { "database": {
"version": 11, "version": 11,
"identityHash": "fb9f1c815809b0217d326452aeb34e92", "identityHash": "f0e15bc95a0bb09b052c484704dd3abd",
"entities": [ "entities": [
{ {
"tableName": "users", "tableName": "users",
...@@ -59,7 +59,7 @@ ...@@ -59,7 +59,7 @@
}, },
{ {
"tableName": "chatrooms", "tableName": "chatrooms",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` TEXT NOT NULL, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `topic` TEXT, `announcement` TEXT, `description` TEXT, `open` INTEGER NOT NULL, `alert` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`ownerId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`lastMessageUserId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )", "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` TEXT NOT NULL, `subscriptionId` TEXT NOT NULL, `parentId` TEXT, `type` TEXT NOT NULL, `name` TEXT NOT NULL, `fullname` TEXT, `userId` TEXT, `ownerId` TEXT, `readonly` INTEGER, `isDefault` INTEGER, `favorite` INTEGER, `topic` TEXT, `announcement` TEXT, `description` TEXT, `open` INTEGER NOT NULL, `alert` INTEGER NOT NULL, `unread` INTEGER NOT NULL, `userMentions` INTEGER, `groupMentions` INTEGER, `updatedAt` INTEGER, `timestamp` INTEGER, `lastSeen` INTEGER, `lastMessageText` TEXT, `lastMessageUserId` TEXT, `lastMessageTimestamp` INTEGER, `broadcast` INTEGER, `muted` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`ownerId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`userId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION , FOREIGN KEY(`lastMessageUserId`) REFERENCES `users`(`id`) ON UPDATE NO ACTION ON DELETE NO ACTION )",
"fields": [ "fields": [
{ {
"fieldPath": "id", "fieldPath": "id",
...@@ -73,6 +73,12 @@ ...@@ -73,6 +73,12 @@
"affinity": "TEXT", "affinity": "TEXT",
"notNull": true "notNull": true
}, },
{
"fieldPath": "parentId",
"columnName": "parentId",
"affinity": "TEXT",
"notNull": false
},
{ {
"fieldPath": "type", "fieldPath": "type",
"columnName": "type", "columnName": "type",
...@@ -1099,7 +1105,7 @@ ...@@ -1099,7 +1105,7 @@
], ],
"setupQueries": [ "setupQueries": [
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"fb9f1c815809b0217d326452aeb34e92\")" "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"f0e15bc95a0bb09b052c484704dd3abd\")"
] ]
} }
} }
\ No newline at end of file
This diff is collapsed.
...@@ -15,6 +15,7 @@ import chat.rocket.android.server.domain.favicon ...@@ -15,6 +15,7 @@ import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.isLdapAuthenticationEnabled import chat.rocket.android.server.domain.isLdapAuthenticationEnabled
import chat.rocket.android.server.domain.isPasswordResetEnabled import chat.rocket.android.server.domain.isPasswordResetEnabled
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.siteName
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -50,6 +51,7 @@ class LoginPresenter @Inject constructor( ...@@ -50,6 +51,7 @@ class LoginPresenter @Inject constructor(
) { ) {
// TODO - we should validate the current server when opening the app, and have a nonnull get() // TODO - we should validate the current server when opening the app, and have a nonnull get()
private var currentServer = serverInteractor.get()!! private var currentServer = serverInteractor.get()!!
private val token = tokenRepository.get(currentServer)
private lateinit var client: RocketChatClient private lateinit var client: RocketChatClient
private lateinit var settings: PublicSettings private lateinit var settings: PublicSettings
...@@ -140,8 +142,15 @@ class LoginPresenter @Inject constructor( ...@@ -140,8 +142,15 @@ class LoginPresenter @Inject constructor(
val logo = settings.wideTile()?.let { val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val thumb = currentServer.avatarUrl(username) val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(currentServer, icon, logo, username, thumb) val account = Account(
settings.siteName() ?: currentServer,
currentServer,
icon,
logo,
username,
thumb
)
saveAccountInteractor.save(account) saveAccountInteractor.save(account)
} }
......
...@@ -14,6 +14,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor ...@@ -14,6 +14,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.siteName
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -54,6 +55,7 @@ class LoginOptionsPresenter @Inject constructor( ...@@ -54,6 +55,7 @@ class LoginOptionsPresenter @Inject constructor(
) { ) {
// TODO - we should validate the current server when opening the app, and have a nonnull get() // TODO - we should validate the current server when opening the app, and have a nonnull get()
private var currentServer = serverInteractor.get()!! private var currentServer = serverInteractor.get()!!
private val token = tokenRepository.get(currentServer)
private lateinit var client: RocketChatClient private lateinit var client: RocketChatClient
private lateinit var settings: PublicSettings private lateinit var settings: PublicSettings
private lateinit var credentialToken: String private lateinit var credentialToken: String
...@@ -180,8 +182,15 @@ class LoginOptionsPresenter @Inject constructor( ...@@ -180,8 +182,15 @@ class LoginOptionsPresenter @Inject constructor(
val logo = settings.wideTile()?.let { val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val thumb = currentServer.avatarUrl(username) val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(currentServer, icon, logo, username, thumb) val account = Account(
settings.siteName() ?: currentServer,
currentServer,
icon,
logo,
username,
thumb
)
saveAccountInteractor.save(account) saveAccountInteractor.save(account)
} }
......
...@@ -12,6 +12,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor ...@@ -12,6 +12,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.siteName
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -39,7 +40,8 @@ class RegisterUsernamePresenter @Inject constructor( ...@@ -39,7 +40,8 @@ class RegisterUsernamePresenter @Inject constructor(
) { ) {
private val currentServer = serverInteractor.get()!! private val currentServer = serverInteractor.get()!!
private val client: RocketChatClient = factory.get(currentServer) private val client: RocketChatClient = factory.get(currentServer)
private var settings: PublicSettings = settingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = settingsInteractor.get(currentServer)
private val token = tokenRepository.get(currentServer)
fun registerUsername(username: String, userId: String, authToken: String) { fun registerUsername(username: String, userId: String, authToken: String) {
launchUI(strategy) { launchUI(strategy) {
...@@ -72,15 +74,22 @@ class RegisterUsernamePresenter @Inject constructor( ...@@ -72,15 +74,22 @@ class RegisterUsernamePresenter @Inject constructor(
} }
} }
private suspend fun saveAccount(username: String) { private fun saveAccount(username: String) {
val icon = settings.favicon()?.let { val icon = settings.favicon()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val logo = settings.wideTile()?.let { val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val thumb = currentServer.avatarUrl(username) val thumb = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val account = Account(currentServer, icon, logo, username, thumb) val account = Account(
settings.siteName() ?: currentServer,
currentServer,
icon,
logo,
username,
thumb
)
saveAccountInteractor.save(account) saveAccountInteractor.save(account)
} }
} }
\ No newline at end of file
...@@ -10,8 +10,10 @@ import chat.rocket.android.server.domain.GetSettingsInteractor ...@@ -10,8 +10,10 @@ 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.SaveAccountInteractor import chat.rocket.android.server.domain.SaveAccountInteractor
import chat.rocket.android.server.domain.SaveCurrentServerInteractor import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.siteName
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -38,10 +40,12 @@ class SignupPresenter @Inject constructor( ...@@ -38,10 +40,12 @@ class SignupPresenter @Inject constructor(
private val analyticsManager: AnalyticsManager, private val analyticsManager: AnalyticsManager,
private val factory: RocketChatClientFactory, private val factory: RocketChatClientFactory,
private val saveAccountInteractor: SaveAccountInteractor, private val saveAccountInteractor: SaveAccountInteractor,
tokenRepository: TokenRepository,
settingsInteractor: GetSettingsInteractor settingsInteractor: GetSettingsInteractor
) { ) {
private val currentServer = serverInteractor.get()!! private val currentServer = serverInteractor.get()!!
private var settings: PublicSettings = settingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = settingsInteractor.get(currentServer)
private val token = tokenRepository.get(currentServer)
fun signup(name: String, username: String, password: String, email: String) { fun signup(name: String, username: String, password: String, email: String) {
val client = factory.get(currentServer) val client = factory.get(currentServer)
...@@ -98,8 +102,15 @@ class SignupPresenter @Inject constructor( ...@@ -98,8 +102,15 @@ class SignupPresenter @Inject constructor(
val logo = settings.wideTile()?.let { val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val thumb = currentServer.avatarUrl(me.username!!) val thumb = currentServer.avatarUrl(me.username!!, token?.userId, token?.authToken)
val account = Account(currentServer, icon, logo, me.username!!, thumb) val account = Account(
settings.siteName() ?: currentServer,
currentServer,
icon,
logo,
me.username!!,
thumb
)
saveAccountInteractor.save(account) saveAccountInteractor.save(account)
} }
} }
\ No newline at end of file
...@@ -13,6 +13,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor ...@@ -13,6 +13,7 @@ import chat.rocket.android.server.domain.SaveCurrentServerInteractor
import chat.rocket.android.server.domain.TokenRepository import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.favicon import chat.rocket.android.server.domain.favicon
import chat.rocket.android.server.domain.model.Account import chat.rocket.android.server.domain.model.Account
import chat.rocket.android.server.domain.siteName
import chat.rocket.android.server.domain.wideTile import chat.rocket.android.server.domain.wideTile
import chat.rocket.android.server.infrastructure.RocketChatClientFactory import chat.rocket.android.server.infrastructure.RocketChatClientFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
...@@ -43,7 +44,8 @@ class TwoFAPresenter @Inject constructor( ...@@ -43,7 +44,8 @@ class TwoFAPresenter @Inject constructor(
val settingsInteractor: GetSettingsInteractor val settingsInteractor: GetSettingsInteractor
) { ) {
private val currentServer = serverInteractor.get()!! private val currentServer = serverInteractor.get()!!
private var settings: PublicSettings = settingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = settingsInteractor.get(currentServer)
private val token = tokenRepository.get(currentServer)
fun authenticate( fun authenticate(
usernameOrEmail: String, usernameOrEmail: String,
...@@ -101,8 +103,15 @@ class TwoFAPresenter @Inject constructor( ...@@ -101,8 +103,15 @@ class TwoFAPresenter @Inject constructor(
val logo = settings.wideTile()?.let { val logo = settings.wideTile()?.let {
currentServer.serverLogoUrl(it) currentServer.serverLogoUrl(it)
} }
val thumb = currentServer.avatarUrl(me.username!!) val thumb = currentServer.avatarUrl(me.username!!, token?.userId, token?.authToken)
val account = Account(currentServer, icon, logo, me.username!!, thumb) val account = Account(
settings.siteName() ?: currentServer,
currentServer,
icon,
logo,
me.username!!,
thumb
)
saveAccountInteractor.save(account) saveAccountInteractor.save(account)
} }
} }
\ No newline at end of file
...@@ -56,6 +56,7 @@ class ChatRoomFragmentModule { ...@@ -56,6 +56,7 @@ class ChatRoomFragmentModule {
context: Application, context: Application,
repository: SettingsRepository, repository: SettingsRepository,
userInteractor: GetCurrentUserInteractor, userInteractor: GetCurrentUserInteractor,
tokenRepository: TokenRepository,
@Named("currentServer") serverUrl: String, @Named("currentServer") serverUrl: String,
permissionsInteractor: PermissionsInteractor permissionsInteractor: PermissionsInteractor
): RoomUiModelMapper { ): RoomUiModelMapper {
...@@ -63,6 +64,7 @@ class ChatRoomFragmentModule { ...@@ -63,6 +64,7 @@ class ChatRoomFragmentModule {
context, context,
repository.get(serverUrl), repository.get(serverUrl),
userInteractor, userInteractor,
tokenRepository,
serverUrl, serverUrl,
permissionsInteractor permissionsInteractor
) )
......
...@@ -29,6 +29,7 @@ import chat.rocket.android.server.domain.JobSchedulerInteractor ...@@ -29,6 +29,7 @@ import chat.rocket.android.server.domain.JobSchedulerInteractor
import chat.rocket.android.server.domain.MessagesRepository import chat.rocket.android.server.domain.MessagesRepository
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.UsersRepository import chat.rocket.android.server.domain.UsersRepository
import chat.rocket.android.server.domain.uploadMaxFileSize import chat.rocket.android.server.domain.uploadMaxFileSize
import chat.rocket.android.server.domain.uploadMimeTypeFilter import chat.rocket.android.server.domain.uploadMimeTypeFilter
...@@ -101,6 +102,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -101,6 +102,7 @@ class ChatRoomPresenter @Inject constructor(
private val jobSchedulerInteractor: JobSchedulerInteractor, private val jobSchedulerInteractor: JobSchedulerInteractor,
private val messageHelper: MessageHelper, private val messageHelper: MessageHelper,
private val dbManager: DatabaseManager, private val dbManager: DatabaseManager,
tokenRepository: TokenRepository,
getSettingsInteractor: GetSettingsInteractor, getSettingsInteractor: GetSettingsInteractor,
serverInteractor: GetCurrentServerInteractor, serverInteractor: GetCurrentServerInteractor,
factory: ConnectionManagerFactory factory: ConnectionManagerFactory
...@@ -109,6 +111,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -109,6 +111,7 @@ class ChatRoomPresenter @Inject constructor(
private val manager = factory.create(currentServer) private val manager = factory.create(currentServer)
private val client = manager.client private val client = manager.client
private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: PublicSettings = getSettingsInteractor.get(serverInteractor.get()!!)
private val token = tokenRepository.get(currentServer)
private val currentLoggedUsername = userHelper.username() private val currentLoggedUsername = userHelper.username()
private val messagesChannel = Channel<Message>() private val messagesChannel = Channel<Message>()
...@@ -327,7 +330,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -327,7 +330,7 @@ class ChatRoomPresenter @Inject constructor(
timestamp = Instant.now().toEpochMilli(), timestamp = Instant.now().toEpochMilli(),
sender = SimpleUser(user?.id, user?.username ?: username, user?.name), sender = SimpleUser(user?.id, user?.username ?: username, user?.name),
attachments = null, attachments = null,
avatar = currentServer.avatarUrl(username ?: ""), avatar = currentServer.avatarUrl(username!!, token?.userId, token?.authToken),
channels = null, channels = null,
editedAt = null, editedAt = null,
editedBy = null, editedBy = null,
...@@ -812,7 +815,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -812,7 +815,7 @@ class ChatRoomPresenter @Inject constructor(
val sender = it.sender val sender = it.sender
val username = sender?.username ?: "" val username = sender?.username ?: ""
val name = sender?.name ?: "" val name = sender?.name ?: ""
val avatarUrl = currentServer.avatarUrl(username) val avatarUrl = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val found = members.firstOrNull { member -> member.username == username } val found = members.firstOrNull { member -> member.username == username }
val status = if (found != null) found.status else UserStatus.Offline() val status = if (found != null) found.status else UserStatus.Offline()
val searchList = mutableListOf(username, name) val searchList = mutableListOf(username, name)
...@@ -833,7 +836,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -833,7 +836,7 @@ class ChatRoomPresenter @Inject constructor(
activeUsers.addAll(others.map { activeUsers.addAll(others.map {
val username = it.username ?: "" val username = it.username ?: ""
val name = it.name ?: "" val name = it.name ?: ""
val avatarUrl = currentServer.avatarUrl(username) val avatarUrl = currentServer.avatarUrl(username, token?.userId, token?.authToken)
val searchList = mutableListOf(username, name) val searchList = mutableListOf(username, name)
PeopleSuggestionUiModel( PeopleSuggestionUiModel(
avatarUrl, avatarUrl,
...@@ -869,7 +872,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -869,7 +872,7 @@ class ChatRoomPresenter @Inject constructor(
val searchList = mutableListOf(username, name) val searchList = mutableListOf(username, name)
it.emails?.forEach { email -> searchList.add(email.address) } it.emails?.forEach { email -> searchList.add(email.address) }
PeopleSuggestionUiModel( PeopleSuggestionUiModel(
currentServer.avatarUrl(username), currentServer.avatarUrl(username, token?.userId, token?.authToken),
username, username, name, it.status, false, searchList username, username, name, it.status, false, searchList
) )
}.filterNot { filterSelfOut && self != null && self == it.text }) }.filterNot { filterSelfOut && self != null && self == it.text })
...@@ -931,6 +934,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -931,6 +934,7 @@ class ChatRoomPresenter @Inject constructor(
ChatRoom( ChatRoom(
id = id, id = id,
subscriptionId = subscriptionId, subscriptionId = subscriptionId,
parentId = parentId,
type = roomTypeOf(type), type = roomTypeOf(type),
unread = unread, unread = unread,
broadcast = broadcast ?: false, broadcast = broadcast ?: false,
...@@ -974,6 +978,7 @@ class ChatRoomPresenter @Inject constructor( ...@@ -974,6 +978,7 @@ class ChatRoomPresenter @Inject constructor(
ChatRoom( ChatRoom(
id = id, id = id,
subscriptionId = subscriptionId, subscriptionId = subscriptionId,
parentId = parentId,
type = roomTypeOf(type), type = roomTypeOf(type),
unread = unread, unread = unread,
broadcast = broadcast ?: false, broadcast = broadcast ?: false,
......
...@@ -108,7 +108,7 @@ class UiModelMapper @Inject constructor( ...@@ -108,7 +108,7 @@ class UiModelMapper @Inject constructor(
readReceipts.forEach { readReceipts.forEach {
list.add( list.add(
ReadReceiptViewModel( ReadReceiptViewModel(
avatar = baseUrl.avatarUrl(it.user.username ?: ""), avatar = baseUrl.avatarUrl(it.user.username!!, token?.userId, token?.authToken),
name = userHelper.displayName(it.user), name = userHelper.displayName(it.user),
time = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(it.timestamp)) time = DateTimeHelper.getTime(DateTimeHelper.getLocalDateTime(it.timestamp))
) )
...@@ -173,6 +173,7 @@ class UiModelMapper @Inject constructor( ...@@ -173,6 +173,7 @@ class UiModelMapper @Inject constructor(
ChatRoom( ChatRoom(
id = id, id = id,
subscriptionId = subscriptionId, subscriptionId = subscriptionId,
parentId = parentId,
type = roomTypeOf(type), type = roomTypeOf(type),
unread = unread, unread = unread,
broadcast = broadcast ?: false, broadcast = broadcast ?: false,
...@@ -525,7 +526,7 @@ class UiModelMapper @Inject constructor( ...@@ -525,7 +526,7 @@ class UiModelMapper @Inject constructor(
val username = message.sender?.username ?: "?" val username = message.sender?.username ?: "?"
return baseUrl.let { return baseUrl.let {
baseUrl.avatarUrl(username) baseUrl.avatarUrl(username, token?.userId, token?.authToken)
} }
} }
......
...@@ -8,11 +8,13 @@ import chat.rocket.android.db.model.ChatRoom ...@@ -8,11 +8,13 @@ import chat.rocket.android.db.model.ChatRoom
import chat.rocket.android.server.domain.GetCurrentUserInteractor import chat.rocket.android.server.domain.GetCurrentUserInteractor
import chat.rocket.android.server.domain.PermissionsInteractor import chat.rocket.android.server.domain.PermissionsInteractor
import chat.rocket.android.server.domain.PublicSettings import chat.rocket.android.server.domain.PublicSettings
import chat.rocket.android.server.domain.TokenRepository
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.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.isNotNullNorEmpty
import chat.rocket.android.util.extensions.localDateTime import chat.rocket.android.util.extensions.localDateTime
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.User import chat.rocket.common.model.User
...@@ -26,10 +28,12 @@ class RoomUiModelMapper( ...@@ -26,10 +28,12 @@ class RoomUiModelMapper(
private val context: Application, private val context: Application,
private val settings: PublicSettings, private val settings: PublicSettings,
private val userInteractor: GetCurrentUserInteractor, private val userInteractor: GetCurrentUserInteractor,
private val tokenRepository: TokenRepository,
private val serverUrl: String, private val serverUrl: String,
private val permissions: PermissionsInteractor private val permissions: PermissionsInteractor
) { ) {
private val currentUser by lazy { userInteractor.get() } private val currentUser by lazy { userInteractor.get() }
private val token by lazy { tokenRepository.get(serverUrl) }
fun map( fun map(
rooms: List<ChatRoom>, rooms: List<ChatRoom>,
...@@ -80,7 +84,7 @@ class RoomUiModelMapper( ...@@ -80,7 +84,7 @@ class RoomUiModelMapper(
private fun mapUser(user: User): RoomUiModel = with(user) { private fun mapUser(user: User): RoomUiModel = with(user) {
val name = mapName(user.username!!, user.name) val name = mapName(user.username!!, user.name)
val status = user.status val status = user.status
val avatar = serverUrl.avatarUrl(user.username!!) val avatar = serverUrl.avatarUrl(user.username!!, token?.userId, token?.authToken)
val username = user.username!! val username = user.username!!
RoomUiModel( RoomUiModel(
...@@ -98,7 +102,7 @@ class RoomUiModelMapper( ...@@ -98,7 +102,7 @@ class RoomUiModelMapper(
id = id, id = id,
name = name!!, name = name!!,
type = type, type = type,
avatar = serverUrl.avatarUrl(name!!, isGroupOrChannel = true), avatar = serverUrl.avatarUrl(name!!, token?.userId, token?.authToken, isGroupOrChannel = true),
lastMessage = if (showLastMessage) { lastMessage = if (showLastMessage) {
mapLastMessage( mapLastMessage(
lastMessage?.sender?.id, lastMessage?.sender?.username, lastMessage?.sender?.id, lastMessage?.sender?.username,
...@@ -113,17 +117,19 @@ class RoomUiModelMapper( ...@@ -113,17 +117,19 @@ class RoomUiModelMapper(
) )
} }
fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel = with(chatRoom.chatRoom) { fun map(chatRoom: ChatRoom, showLastMessage: Boolean = true): RoomUiModel =
with(chatRoom.chatRoom) {
val isUnread = alert || unread > 0 val isUnread = alert || unread > 0
val type = roomTypeOf(type) val type = roomTypeOf(type)
val status = chatRoom.status?.let { userStatusOf(it) } val status = chatRoom.status?.let { userStatusOf(it) }
val roomName = mapName(name, fullname) val roomName = mapName(name, fullname)
val favorite = favorite val favorite = favorite
val timestamp = mapDate(lastMessageTimestamp ?: updatedAt) val timestamp = mapDate(lastMessageTimestamp ?: updatedAt)
val avatar = if (type is RoomType.DirectMessage) { val avatar =
serverUrl.avatarUrl(name) if (type is RoomType.DirectMessage) {
serverUrl.avatarUrl(name, token?.userId, token?.authToken)
} else { } else {
serverUrl.avatarUrl(name, isGroupOrChannel = true) serverUrl.avatarUrl(name, token?.userId, token?.authToken, isGroupOrChannel = true)
} }
val unread = mapUnread(unread) val unread = mapUnread(unread)
val lastMessage = if (showLastMessage) { val lastMessage = if (showLastMessage) {
...@@ -139,10 +145,12 @@ class RoomUiModelMapper( ...@@ -139,10 +145,12 @@ class RoomUiModelMapper(
} }
val hasMentions = mapMentions(userMentions, groupMentions) val hasMentions = mapMentions(userMentions, groupMentions)
val open = open val open = open
val lastMessageMarkdown = lastMessage?.let { Markwon.markdown(context, it.toString()).toString() } val lastMessageMarkdown =
lastMessage?.let { Markwon.markdown(context, it.toString()).toString() }
RoomUiModel( RoomUiModel(
id = id, id = id,
isDiscussion = parentId.isNotNullNorEmpty(),
name = roomName, name = roomName,
type = type, type = type,
avatar = avatar, avatar = avatar,
......
...@@ -11,6 +11,9 @@ import chat.rocket.android.chatrooms.adapter.model.RoomUiModel ...@@ -11,6 +11,9 @@ import chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import chat.rocket.android.util.extension.setTextViewAppearance import chat.rocket.android.util.extension.setTextViewAppearance
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import com.bumptech.glide.Glide
import com.bumptech.glide.load.resource.bitmap.RoundedCorners
import com.bumptech.glide.request.RequestOptions
import kotlinx.android.synthetic.main.item_chat.view.* import kotlinx.android.synthetic.main.item_chat.view.*
import kotlinx.android.synthetic.main.unread_messages_badge.view.* import kotlinx.android.synthetic.main.unread_messages_badge.view.*
...@@ -19,6 +22,7 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -19,6 +22,7 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
private val resources: Resources = itemView.resources private val resources: Resources = itemView.resources
private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp, null) private val channelIcon: Drawable = resources.getDrawable(R.drawable.ic_hashtag_12dp, null)
private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp, null) private val groupIcon: Drawable = resources.getDrawable(R.drawable.ic_lock_12_dp, null)
private val discussionIcon: Drawable = resources.getDrawable(R.drawable.ic_discussion_20dp, null)
private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp, null) private val onlineIcon: Drawable = resources.getDrawable(R.drawable.ic_status_online_12dp, null)
private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp, null) private val awayIcon: Drawable = resources.getDrawable(R.drawable.ic_status_away_12dp, null)
private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp, null) private val busyIcon: Drawable = resources.getDrawable(R.drawable.ic_status_busy_12dp, null)
...@@ -27,10 +31,18 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit ...@@ -27,10 +31,18 @@ class RoomViewHolder(itemView: View, private val listener: (RoomUiModel) -> Unit
override fun bindViews(data: RoomItemHolder) { override fun bindViews(data: RoomItemHolder) {
val room = data.data val room = data.data
with(itemView) { with(itemView) {
image_avatar.setImageURI(room.avatar) val avatar = room.avatar
Glide.with(image_avatar.context)
.load(room.avatar)
.apply(RequestOptions.bitmapTransform(RoundedCorners(10)))
.into(image_avatar)
text_chat_name.text = room.name text_chat_name.text = room.name
if (room.status != null && room.type is RoomType.DirectMessage) { if (room.isDiscussion) {
image_chat_icon.setImageDrawable(discussionIcon)
} else if (room.status != null && room.type is RoomType.DirectMessage) {
image_chat_icon.setImageDrawable(getStatusDrawable(room.status)) image_chat_icon.setImageDrawable(getStatusDrawable(room.status))
} else { } else {
image_chat_icon.setImageDrawable(getRoomDrawable(room.type)) image_chat_icon.setImageDrawable(getRoomDrawable(room.type))
......
...@@ -5,6 +5,7 @@ import chat.rocket.common.model.UserStatus ...@@ -5,6 +5,7 @@ import chat.rocket.common.model.UserStatus
data class RoomUiModel( data class RoomUiModel(
val id: String, val id: String,
val isDiscussion: Boolean = false,
val type: RoomType, val type: RoomType,
val name: CharSequence, val name: CharSequence,
val avatar: String, val avatar: String,
......
...@@ -86,12 +86,20 @@ class ChatRoomsFragmentModule { ...@@ -86,12 +86,20 @@ class ChatRoomsFragmentModule {
@PerFragment @PerFragment
fun provideRoomMapper( fun provideRoomMapper(
context: Application, context: Application,
repository: SettingsRepository, settingsRepository: SettingsRepository,
userInteractor: GetCurrentUserInteractor, userInteractor: GetCurrentUserInteractor,
tokenRepository: TokenRepository,
@Named("currentServer") serverUrl: String, @Named("currentServer") serverUrl: String,
permissionsInteractor: PermissionsInteractor permissionsInteractor: PermissionsInteractor
): RoomUiModelMapper { ): RoomUiModelMapper {
return RoomUiModelMapper(context, repository.get(serverUrl), userInteractor, serverUrl, permissionsInteractor) return RoomUiModelMapper(
context,
settingsRepository.get(serverUrl),
userInteractor,
tokenRepository,
serverUrl,
permissionsInteractor
)
} }
@Provides @Provides
......
...@@ -11,6 +11,7 @@ import chat.rocket.android.infrastructure.LocalRepository ...@@ -11,6 +11,7 @@ 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.SortingAndGroupingInteractor import chat.rocket.android.server.domain.SortingAndGroupingInteractor
import chat.rocket.android.server.domain.siteName
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.server.domain.useSpecialCharsOnRoom
import chat.rocket.android.server.infrastructure.ConnectionManager import chat.rocket.android.server.infrastructure.ConnectionManager
...@@ -52,7 +53,7 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -52,7 +53,7 @@ class ChatRoomsPresenter @Inject constructor(
fun toDirectory() = navigator.toDirectory() fun toDirectory() = navigator.toDirectory()
fun getCurrentServerName() = view.setupToolbar(currentServer) fun getCurrentServerName() = view.setupToolbar(settings.siteName() ?: currentServer)
fun getSortingAndGroupingPreferences() { fun getSortingAndGroupingPreferences() {
with(sortingAndGroupingInteractor) { with(sortingAndGroupingInteractor) {
...@@ -93,6 +94,7 @@ class ChatRoomsPresenter @Inject constructor( ...@@ -93,6 +94,7 @@ class ChatRoomsPresenter @Inject constructor(
val entity = ChatRoomEntity( val entity = ChatRoomEntity(
id = id, id = id,
subscriptionId = "", subscriptionId = "",
parentId = null,
type = type.toString(), type = type.toString(),
name = username ?: name.toString(), name = username ?: name.toString(),
fullname = name.toString(), fullname = name.toString(),
......
...@@ -475,6 +475,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -475,6 +475,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
return ChatRoomEntity( return ChatRoomEntity(
id = room.id, id = room.id,
subscriptionId = subscription.id, subscriptionId = subscription.id,
parentId = subscription.parentId,
type = room.type.toString(), type = room.type.toString(),
name = room.name ?: subscription.name name = room.name ?: subscription.name
?: throw NullPointerException(), // this should be filtered on the SDK ?: throw NullPointerException(), // this should be filtered on the SDK
...@@ -516,6 +517,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) { ...@@ -516,6 +517,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
return ChatRoomEntity( return ChatRoomEntity(
id = id, id = id,
subscriptionId = subscriptionId, subscriptionId = subscriptionId,
parentId = parentId,
type = type.toString(), type = type.toString(),
name = name, name = name,
fullname = fullName, fullname = fullName,
......
...@@ -25,7 +25,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter ...@@ -25,7 +25,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter
AttachmentFieldEntity::class, AttachmentActionEntity::class, UrlEntity::class, AttachmentFieldEntity::class, AttachmentActionEntity::class, UrlEntity::class,
ReactionEntity::class, MessagesSync::class ReactionEntity::class, MessagesSync::class
], ],
version = 11, version = 12,
exportSchema = true exportSchema = true
) )
@TypeConverters(StringListConverter::class) @TypeConverters(StringListConverter::class)
......
...@@ -26,6 +26,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter ...@@ -26,6 +26,7 @@ import chat.rocket.android.emoji.internal.db.StringListConverter
data class ChatRoomEntity( data class ChatRoomEntity(
@PrimaryKey var id: String, @PrimaryKey var id: String,
var subscriptionId: String, var subscriptionId: String,
var parentId: String?,
var type: String, var type: String,
var name: String, var name: String,
var fullname: String? = null, var fullname: String? = null,
......
...@@ -146,6 +146,7 @@ class DirectoryPresenter @Inject constructor( ...@@ -146,6 +146,7 @@ class DirectoryPresenter @Inject constructor(
val chatRoomEntity = ChatRoomEntity( val chatRoomEntity = ChatRoomEntity(
id = directMessage.id, id = directMessage.id,
parentId = null,
name = username, name = username,
description = null, description = null,
type = RoomType.DIRECT_MESSAGE, type = RoomType.DIRECT_MESSAGE,
......
package chat.rocket.android.directory.uimodel package chat.rocket.android.directory.uimodel
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.common.model.Token
import chat.rocket.core.model.DirectoryResult import chat.rocket.core.model.DirectoryResult
class DirectoryUiModel( class DirectoryUiModel(
private val directoryResult: DirectoryResult, private val directoryResult: DirectoryResult,
private val baseUrl: String? private val baseUrl: String?,
private val token: Token?
) { ) {
val id: String = directoryResult.id val id: String = directoryResult.id
val channelAvatarUri: String? val channelAvatarUri: String?
...@@ -22,12 +24,12 @@ class DirectoryUiModel( ...@@ -22,12 +24,12 @@ class DirectoryUiModel(
} }
private fun getChannelAvatar(): String? { private fun getChannelAvatar(): String? {
return baseUrl?.avatarUrl(name, isGroupOrChannel = true) return baseUrl?.avatarUrl(name, token?.userId, token?.authToken, isGroupOrChannel = true)
} }
private fun getUserAvatar(): String? { private fun getUserAvatar(): String? {
return directoryResult.username?.let { return directoryResult.username?.let {
baseUrl?.avatarUrl(it) baseUrl?.avatarUrl(it, token?.userId, token?.authToken)
} }
} }
} }
package chat.rocket.android.directory.uimodel package chat.rocket.android.directory.uimodel
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.baseUrl import chat.rocket.android.server.domain.baseUrl
import chat.rocket.core.model.DirectoryResult import chat.rocket.core.model.DirectoryResult
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
...@@ -9,13 +10,14 @@ import javax.inject.Named ...@@ -9,13 +10,14 @@ import javax.inject.Named
class DirectoryUiModelMapper @Inject constructor( class DirectoryUiModelMapper @Inject constructor(
getSettingsInteractor: GetSettingsInteractor, getSettingsInteractor: GetSettingsInteractor,
@Named("currentServer") private val currentServer: String @Named("currentServer") private val currentServer: String,
tokenRepository: TokenRepository
) { ) {
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(currentServer) private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(currentServer)
private val baseUrl = settings.baseUrl() private val baseUrl = settings.baseUrl()
private val token = tokenRepository.get(currentServer)
fun mapToUiModelList(directoryList: List<DirectoryResult>): List<DirectoryUiModel> { fun mapToUiModelList(directoryList: List<DirectoryResult>): List<DirectoryUiModel> {
return directoryList.map { DirectoryUiModel(it, baseUrl) } return directoryList.map { DirectoryUiModel(it, baseUrl, token) }
} }
} }
\ No newline at end of file
...@@ -26,7 +26,7 @@ object AndroidPermissionsHelper { ...@@ -26,7 +26,7 @@ object AndroidPermissionsHelper {
} }
fun hasCameraPermission(context: Context): Boolean { fun hasCameraPermission(context: Context): Boolean {
return AndroidPermissionsHelper.checkPermission(context, Manifest.permission.CAMERA) return checkPermission(context, Manifest.permission.CAMERA)
} }
fun getCameraPermission(fragment: Fragment) { fun getCameraPermission(fragment: Fragment) {
...@@ -50,10 +50,10 @@ object AndroidPermissionsHelper { ...@@ -50,10 +50,10 @@ object AndroidPermissionsHelper {
fun checkWritingPermission(context: Context) { fun checkWritingPermission(context: Context) {
if (context is ContextThemeWrapper) { if (context is ContextThemeWrapper) {
val activity = if (context.baseContext is Activity) context.baseContext as Activity else context as Activity val activity = if (context.baseContext is Activity) context.baseContext as Activity else context as Activity
AndroidPermissionsHelper.requestPermission( requestPermission(
activity, activity,
Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.WRITE_EXTERNAL_STORAGE,
AndroidPermissionsHelper.WRITE_EXTERNAL_STORAGE_CODE WRITE_EXTERNAL_STORAGE_CODE
) )
} }
} }
......
...@@ -2,6 +2,7 @@ package chat.rocket.android.members.uimodel ...@@ -2,6 +2,7 @@ package chat.rocket.android.members.uimodel
import chat.rocket.android.server.domain.useRealName import chat.rocket.android.server.domain.useRealName
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.common.model.Token
import chat.rocket.common.model.User import chat.rocket.common.model.User
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
...@@ -9,7 +10,8 @@ import chat.rocket.core.model.Value ...@@ -9,7 +10,8 @@ import chat.rocket.core.model.Value
class MemberUiModel( class MemberUiModel(
private val member: User, private val member: User,
private val settings: Map<String, Value<Any>>, private val settings: Map<String, Value<Any>>,
private val baseUrl: String? private val baseUrl: String?,
private val token: Token?
) { ) {
val userId: String = member.id val userId: String = member.id
val avatarUri: String? val avatarUri: String?
...@@ -33,7 +35,7 @@ class MemberUiModel( ...@@ -33,7 +35,7 @@ class MemberUiModel(
private fun getUserAvatar(): String? { private fun getUserAvatar(): String? {
val username = member.username ?: "?" val username = member.username ?: "?"
return baseUrl?.let { return baseUrl?.let {
baseUrl.avatarUrl(username, format = "png") baseUrl.avatarUrl(username, token?.userId, token?.authToken, format = "png")
} }
} }
......
...@@ -2,19 +2,24 @@ package chat.rocket.android.members.uimodel ...@@ -2,19 +2,24 @@ package chat.rocket.android.members.uimodel
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.TokenRepository
import chat.rocket.android.server.domain.baseUrl import chat.rocket.android.server.domain.baseUrl
import chat.rocket.common.model.User import chat.rocket.common.model.User
import chat.rocket.core.model.Value import chat.rocket.core.model.Value
import javax.inject.Inject import javax.inject.Inject
import javax.inject.Named
class MemberUiModelMapper @Inject constructor( class MemberUiModelMapper @Inject constructor(
serverInteractor: GetCurrentServerInteractor, serverInteractor: GetCurrentServerInteractor,
getSettingsInteractor: GetSettingsInteractor getSettingsInteractor: GetSettingsInteractor,
@Named("currentServer") private val currentServer: String,
tokenRepository: TokenRepository
) { ) {
private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!) private var settings: Map<String, Value<Any>> = getSettingsInteractor.get(serverInteractor.get()!!)
private val baseUrl = settings.baseUrl() private val baseUrl = settings.baseUrl()
private val token = tokenRepository.get(currentServer)
fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> { fun mapToUiModelList(memberList: List<User>): List<MemberUiModel> {
return memberList.map { MemberUiModel(it, settings, baseUrl) } return memberList.map { MemberUiModel(it, settings, baseUrl, token) }
} }
} }
...@@ -57,6 +57,7 @@ class ProfilePresenter @Inject constructor( ...@@ -57,6 +57,7 @@ class ProfilePresenter @Inject constructor(
private val serverUrl = serverInteractor.get()!! private val serverUrl = serverInteractor.get()!!
private val client: RocketChatClient = factory.get(serverUrl) private val client: RocketChatClient = factory.get(serverUrl)
private val user = userHelper.user() private val user = userHelper.user()
private val token = tokenRepository.get(serverUrl)
fun loadUserProfile() { fun loadUserProfile() {
launchUI(strategy) { launchUI(strategy) {
...@@ -68,7 +69,7 @@ class ProfilePresenter @Inject constructor( ...@@ -68,7 +69,7 @@ class ProfilePresenter @Inject constructor(
view.showProfile( view.showProfile(
me.status.toString(), me.status.toString(),
serverUrl.avatarUrl(me.username ?: ""), serverUrl.avatarUrl(me.username!!, token?.userId, token?.authToken),
me.name ?: "", me.name ?: "",
me.username ?: "", me.username ?: "",
me.emails?.getOrNull(0)?.address ?: "" me.emails?.getOrNull(0)?.address ?: ""
...@@ -97,7 +98,7 @@ class ProfilePresenter @Inject constructor( ...@@ -97,7 +98,7 @@ class ProfilePresenter @Inject constructor(
view.showProfileUpdateSuccessfullyMessage() view.showProfileUpdateSuccessfullyMessage()
view.showProfile( view.showProfile(
user.status.toString(), user.status.toString(),
serverUrl.avatarUrl(user.username ?: ""), serverUrl.avatarUrl(user.username!!, token?.userId, token?.authToken),
name, name,
username, username,
email email
...@@ -127,7 +128,15 @@ class ProfilePresenter @Inject constructor( ...@@ -127,7 +128,15 @@ class ProfilePresenter @Inject constructor(
uriInteractor.getInputStream(uri) uriInteractor.getInputStream(uri)
} }
} }
user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) } user?.username?.let {
view.reloadUserAvatar(
serverUrl.avatarUrl(
it,
token?.userId,
token?.authToken
)
)
}
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
...@@ -155,7 +164,15 @@ class ProfilePresenter @Inject constructor( ...@@ -155,7 +164,15 @@ class ProfilePresenter @Inject constructor(
} }
} }
user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) } user?.username?.let {
view.reloadUserAvatar(
serverUrl.avatarUrl(
it,
token?.userId,
token?.authToken
)
)
}
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
...@@ -175,7 +192,15 @@ class ProfilePresenter @Inject constructor( ...@@ -175,7 +192,15 @@ class ProfilePresenter @Inject constructor(
user?.id?.let { id -> user?.id?.let { id ->
retryIO { client.resetAvatar(id) } retryIO { client.resetAvatar(id) }
} }
user?.username?.let { view.reloadUserAvatar(serverUrl.avatarUrl(it)) } user?.username?.let {
view.reloadUserAvatar(
serverUrl.avatarUrl(
it,
token?.userId,
token?.authToken
)
)
}
} catch (exception: RocketChatException) { } catch (exception: RocketChatException) {
exception.message?.let { exception.message?.let {
view.showMessage(it) view.showMessage(it)
......
...@@ -3,6 +3,7 @@ package chat.rocket.android.profile.ui ...@@ -3,6 +3,7 @@ package chat.rocket.android.profile.ui
import DrawableHelper import DrawableHelper
import android.app.Activity import android.app.Activity
import android.content.Intent import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap import android.graphics.Bitmap
import android.os.Build import android.os.Build
import android.os.Bundle import android.os.Bundle
...@@ -21,6 +22,9 @@ import androidx.fragment.app.Fragment ...@@ -21,6 +22,9 @@ import androidx.fragment.app.Fragment
import chat.rocket.android.R import chat.rocket.android.R
import chat.rocket.android.analytics.AnalyticsManager import chat.rocket.android.analytics.AnalyticsManager
import chat.rocket.android.analytics.event.ScreenViewEvent import chat.rocket.android.analytics.event.ScreenViewEvent
import chat.rocket.android.helper.AndroidPermissionsHelper
import chat.rocket.android.helper.AndroidPermissionsHelper.getCameraPermission
import chat.rocket.android.helper.AndroidPermissionsHelper.hasCameraPermission
import chat.rocket.android.main.ui.MainActivity import chat.rocket.android.main.ui.MainActivity
import chat.rocket.android.profile.presentation.ProfilePresenter import chat.rocket.android.profile.presentation.ProfilePresenter
import chat.rocket.android.profile.presentation.ProfileView import chat.rocket.android.profile.presentation.ProfileView
...@@ -35,12 +39,15 @@ import chat.rocket.android.util.invalidateFirebaseToken ...@@ -35,12 +39,15 @@ import chat.rocket.android.util.invalidateFirebaseToken
import chat.rocket.common.model.UserStatus import chat.rocket.common.model.UserStatus
import chat.rocket.common.model.userStatusOf import chat.rocket.common.model.userStatusOf
import com.facebook.drawee.backends.pipeline.Fresco import com.facebook.drawee.backends.pipeline.Fresco
import com.google.android.material.snackbar.Snackbar
import dagger.android.support.AndroidSupportInjection import dagger.android.support.AndroidSupportInjection
import io.reactivex.disposables.CompositeDisposable import io.reactivex.disposables.CompositeDisposable
import io.reactivex.rxkotlin.Observables import io.reactivex.rxkotlin.Observables
import kotlinx.android.synthetic.main.app_bar.* import kotlinx.android.synthetic.main.app_bar.*
import kotlinx.android.synthetic.main.avatar_profile.* import kotlinx.android.synthetic.main.avatar_profile.*
import kotlinx.android.synthetic.main.fragment_profile.* import kotlinx.android.synthetic.main.fragment_profile.*
import kotlinx.android.synthetic.main.fragment_profile.view_dim
import kotlinx.android.synthetic.main.fragment_profile.view_loading
import kotlinx.android.synthetic.main.update_avatar_options.* import kotlinx.android.synthetic.main.update_avatar_options.*
import javax.inject.Inject import javax.inject.Inject
...@@ -52,8 +59,10 @@ private const val REQUEST_CODE_FOR_PERFORM_CAMERA = 2 ...@@ -52,8 +59,10 @@ private const val REQUEST_CODE_FOR_PERFORM_CAMERA = 2
fun newInstance() = ProfileFragment() fun newInstance() = ProfileFragment()
class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
@Inject lateinit var presenter: ProfilePresenter @Inject
@Inject lateinit var analyticsManager: AnalyticsManager lateinit var presenter: ProfilePresenter
@Inject
lateinit var analyticsManager: AnalyticsManager
private var currentStatus = "" private var currentStatus = ""
private var currentName = "" private var currentName = ""
private var currentUsername = "" private var currentUsername = ""
...@@ -223,7 +232,13 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -223,7 +232,13 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
} }
button_take_a_photo.setOnClickListener { button_take_a_photo.setOnClickListener {
context?.let {
if (hasCameraPermission(it)) {
dispatchTakePicture(REQUEST_CODE_FOR_PERFORM_CAMERA) dispatchTakePicture(REQUEST_CODE_FOR_PERFORM_CAMERA)
} else {
getCameraPermission(this)
}
}
hideUpdateAvatarOptions() hideUpdateAvatarOptions()
} }
...@@ -331,4 +346,28 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback { ...@@ -331,4 +346,28 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
}.show() }.show()
} }
} }
override fun onRequestPermissionsResult(
requestCode: Int,
permissions: Array<out String>,
grantResults: IntArray
) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults)
when (requestCode) {
AndroidPermissionsHelper.CAMERA_CODE -> {
if (grantResults.isNotEmpty() && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted
dispatchTakePicture(REQUEST_CODE_FOR_PERFORM_CAMERA)
} else {
// permission denied
Snackbar.make(
relative_layout,
R.string.msg_camera_permission_denied,
Snackbar.LENGTH_SHORT
).show()
}
return
}
}
}
} }
...@@ -4,6 +4,7 @@ import se.ansman.kotshi.JsonSerializable ...@@ -4,6 +4,7 @@ import se.ansman.kotshi.JsonSerializable
@JsonSerializable @JsonSerializable
data class Account( data class Account(
val serverName: String?,
val serverUrl: String, val serverUrl: String,
val serverLogo: String?, val serverLogo: String?,
val serverBg: String?, val serverBg: String?,
......
...@@ -13,7 +13,7 @@ class ServerViewHolder(itemView: View, private val currentServerUrl: String) : ...@@ -13,7 +13,7 @@ class ServerViewHolder(itemView: View, private val currentServerUrl: String) :
fun bind(account: Account) { fun bind(account: Account) {
with(itemView) { with(itemView) {
Glide.with(context).load(account.serverLogo).into(image_server) Glide.with(context).load(account.serverLogo).into(image_server)
text_server_name.text = account.serverUrl text_server_name.text = account.serverName ?: account.serverUrl
text_server_url.text = account.serverUrl text_server_url.text = account.serverUrl
image_check.isInvisible = currentServerUrl != account.serverUrl image_check.isInvisible = currentServerUrl != account.serverUrl
} }
......
...@@ -56,6 +56,7 @@ class SettingsPresenter @Inject constructor( ...@@ -56,6 +56,7 @@ class SettingsPresenter @Inject constructor(
tokenView = view, tokenView = view,
navigator = navigator navigator = navigator
) { ) {
private val token = tokenRepository.get(currentServer)
fun setupView() { fun setupView() {
launchUI(strategy) { launchUI(strategy) {
...@@ -70,7 +71,7 @@ class SettingsPresenter @Inject constructor( ...@@ -70,7 +71,7 @@ class SettingsPresenter @Inject constructor(
userHelper.user()?.let { user -> userHelper.user()?.let { user ->
view.setupSettingsView( view.setupSettingsView(
currentServer.avatarUrl(me.username ?: ""), currentServer.avatarUrl(me.username!!, token?.userId, token?.authToken),
userHelper.displayName(user) ?: me.username ?: "", userHelper.displayName(user) ?: me.username ?: "",
me.status.toString(), me.status.toString(),
permissions.isAdministrationEnabled(), permissions.isAdministrationEnabled(),
......
...@@ -8,12 +8,14 @@ import chat.rocket.android.db.model.ChatRoomEntity ...@@ -8,12 +8,14 @@ import chat.rocket.android.db.model.ChatRoomEntity
import chat.rocket.android.db.model.UserEntity import chat.rocket.android.db.model.UserEntity
import chat.rocket.android.server.domain.CurrentServerRepository import chat.rocket.android.server.domain.CurrentServerRepository
import chat.rocket.android.server.domain.GetSettingsInteractor import chat.rocket.android.server.domain.GetSettingsInteractor
import chat.rocket.android.server.domain.TokenRepository
import chat.rocket.android.server.domain.isJitsiEnabled import chat.rocket.android.server.domain.isJitsiEnabled
import chat.rocket.android.server.infrastructure.ConnectionManagerFactory import chat.rocket.android.server.infrastructure.ConnectionManagerFactory
import chat.rocket.android.util.extension.launchUI import chat.rocket.android.util.extension.launchUI
import chat.rocket.android.util.extensions.avatarUrl import chat.rocket.android.util.extensions.avatarUrl
import chat.rocket.android.util.retryIO import chat.rocket.android.util.retryIO
import chat.rocket.common.model.RoomType import chat.rocket.common.model.RoomType
import chat.rocket.common.model.Token
import chat.rocket.common.util.ifNull import chat.rocket.common.util.ifNull
import chat.rocket.core.internal.rest.createDirectMessage import chat.rocket.core.internal.rest.createDirectMessage
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
...@@ -26,6 +28,7 @@ class UserDetailsPresenter @Inject constructor( ...@@ -26,6 +28,7 @@ class UserDetailsPresenter @Inject constructor(
private val dbManager: DatabaseManager, private val dbManager: DatabaseManager,
private val strategy: CancelStrategy, private val strategy: CancelStrategy,
private val navigator: ChatRoomNavigator, private val navigator: ChatRoomNavigator,
tokenRepository: TokenRepository,
settingsInteractor: GetSettingsInteractor, settingsInteractor: GetSettingsInteractor,
serverInteractor: CurrentServerRepository, serverInteractor: CurrentServerRepository,
factory: ConnectionManagerFactory factory: ConnectionManagerFactory
...@@ -35,6 +38,7 @@ class UserDetailsPresenter @Inject constructor( ...@@ -35,6 +38,7 @@ class UserDetailsPresenter @Inject constructor(
private val client = manager.client private val client = manager.client
private val interactor = FetchChatRoomsInteractor(client, dbManager) private val interactor = FetchChatRoomsInteractor(client, dbManager)
private val settings = settingsInteractor.get(currentServer) private val settings = settingsInteractor.get(currentServer)
private val token = tokenRepository.get(currentServer)
private lateinit var userEntity: UserEntity private lateinit var userEntity: UserEntity
fun loadUserDetails(userId: String) { fun loadUserDetails(userId: String) {
...@@ -44,7 +48,13 @@ class UserDetailsPresenter @Inject constructor( ...@@ -44,7 +48,13 @@ class UserDetailsPresenter @Inject constructor(
dbManager.getUser(userId)?.let { dbManager.getUser(userId)?.let {
userEntity = it userEntity = it
val avatarUrl = val avatarUrl =
userEntity.username?.let { username -> currentServer.avatarUrl(avatar = username) } userEntity.username?.let { username ->
currentServer.avatarUrl(
username,
token?.userId,
token?.authToken
)
}
val username = userEntity.username val username = userEntity.username
val name = userEntity.name val name = userEntity.name
val utcOffset = val utcOffset =
...@@ -89,6 +99,7 @@ class UserDetailsPresenter @Inject constructor( ...@@ -89,6 +99,7 @@ class UserDetailsPresenter @Inject constructor(
val chatRoomEntity = ChatRoomEntity( val chatRoomEntity = ChatRoomEntity(
id = directMessage.id, id = directMessage.id,
name = userEntity.username ?: userEntity.name.orEmpty(), name = userEntity.username ?: userEntity.name.orEmpty(),
parentId = null,
description = null, description = null,
type = RoomType.DIRECT_MESSAGE, type = RoomType.DIRECT_MESSAGE,
fullname = userEntity.name, fullname = userEntity.name,
......
...@@ -21,13 +21,15 @@ fun String.sanitize(): String { ...@@ -21,13 +21,15 @@ fun String.sanitize(): String {
fun String.avatarUrl( fun String.avatarUrl(
avatar: String, avatar: String,
userId: String?,
token: String?,
isGroupOrChannel: Boolean = false, isGroupOrChannel: Boolean = false,
format: String = "jpeg" format: String = "jpeg"
): String { ): String {
return if (isGroupOrChannel) { return if (isGroupOrChannel) {
"${removeTrailingSlash()}/avatar/%23${avatar.removeTrailingSlash()}?format=$format" "${removeTrailingSlash()}/avatar/%23${avatar.removeTrailingSlash()}?format=$format&rc_uid=$userId&rc_token=$token"
} else { } else {
"${removeTrailingSlash()}/avatar/${avatar.removeTrailingSlash()}?format=$format" "${removeTrailingSlash()}/avatar/${avatar.removeTrailingSlash()}?format=$format&rc_uid=$userId&rc_token=$token"
} }
} }
......
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="20dp"
android:height="20dp"
android:viewportWidth="20"
android:viewportHeight="20">
<path
android:fillColor="#9EA2A8"
android:fillType="nonZero"
android:pathData="M17.0178,9.0088C17.4002,8.2308 17.479,7.9789 17.479,7.6459C17.479,4.8323 15.0667,2.5397 12.1027,2.5397C9.1391,2.5397 6.7273,4.832 6.7273,7.6459C6.7273,10.6045 9.2399,12.7514 12.8986,12.7514L13.0419,12.7522L13.2199,12.7522C15.7971,12.7522 17.3253,12.49 17.9955,12.099C17.4393,11.8181 17.312,11.7402 17.0644,11.4817C16.7269,11.1295 16.5447,10.6642 16.5903,10.1635C16.6148,9.8935 16.6686,9.7447 16.7751,9.5219C16.8362,9.3843 16.8928,9.2651 17.0178,9.0088ZM18.3011,10.1607C18.1916,10.3871 18.2091,10.4113 18.8615,10.7397C19.8228,11.2213 20.24,11.6696 19.8612,12.4352C19.1566,13.8599 16.8659,14.3395 13.2199,14.3395L13.0419,14.3395L12.8892,14.3387C8.3595,14.3387 5.0607,11.5237 5.0607,7.6459C5.0607,3.9545 8.2195,0.9524 12.1027,0.9524C15.9862,0.9524 19.1457,3.9547 19.1457,7.6459C19.1457,8.2881 18.979,8.7628 18.5273,9.6817C18.4105,9.9212 18.3589,10.0296 18.3011,10.1607ZM13.5847,16.3438C13.4018,16.575 13.2033,16.7931 12.9903,16.9977C12.7079,16.9977 12.4278,16.9894 12.1501,16.973L12.251,15.4273C12.2578,15.4187 12.2646,15.4102 12.2714,15.4016L13.5847,16.3438ZM12.2535,15.3888L12.2714,15.4016C12.2744,15.3979 12.2774,15.3941 12.2804,15.3903C12.5148,15.4037 12.7523,15.4104 12.9928,15.4104L13.1738,15.4114L13.3848,15.4114C13.6721,15.4114 13.9523,15.4089 14.2253,15.4036C13.9139,15.9928 13.5075,16.528 13.0195,16.9979L12.9928,16.9977C12.9919,16.9977 12.9911,16.9977 12.9903,16.9977C11.5566,18.3752 9.469,19.1391 7.111,19.1391L6.9581,19.1399L6.7801,19.1399C4.1004,19.1399 2.2612,18.8789 1.204,18.2903L0.9763,18.1635C0.5978,17.9163 0.3174,17.6159 0.1388,17.2549C-0.1741,16.6227 0.056,16.2068 0.6871,15.8098L1.263,15.5183C1.6568,15.319 1.6328,15.3349 1.7194,15.2446C1.7599,15.2023 1.7736,15.1649 1.7694,15.1185C1.7642,15.0606 1.772,15.0866 1.7081,14.9517C1.6576,14.8377 1.6095,14.736 1.491,14.4933C1.0219,13.5389 0.8746,13.0988 0.8746,12.4656C0.8746,11.0845 1.3214,9.7648 2.1303,8.6606C2.129,8.6512 2.1278,8.6417 2.1265,8.6322C2.5652,8.0375 3.1029,7.5134 3.7168,7.0817C3.713,7.1803 3.7112,7.2792 3.7112,7.3786C3.7112,7.962 3.7726,8.5253 3.8907,9.0644C3.8873,9.068 3.8839,9.0717 3.8805,9.0753L3.896,9.0884L3.8618,9.0953C3.0102,10.0132 2.521,11.2015 2.521,12.4656C2.521,12.7985 2.5998,13.0505 2.9842,13.8326C3.1146,14.0999 3.1702,14.2175 3.2126,14.3161C3.3274,14.5534 3.3842,14.703 3.4097,14.9832C3.4553,15.4839 3.2731,15.9492 2.9356,16.3014C2.6884,16.5596 2.561,16.6376 2.0044,16.9188C2.6743,17.3097 4.2025,17.5719 6.7801,17.5719L6.9487,17.5719L7.1108,17.5711C9.3389,17.5711 11.1786,16.7606 12.251,15.4273L12.2535,15.3888ZM1.9145,16.9641C1.6344,17.1044 1.5191,17.1878 1.5466,17.1462C1.6888,16.9311 1.6902,16.6667 1.6467,16.5786C1.7065,16.6996 1.8245,16.8138 2.0044,16.9188C1.9756,16.9333 1.9457,16.9484 1.9145,16.9641ZM2.2655,9.4174C2.2101,9.1681 2.165,8.9157 2.1303,8.6606C2.2904,8.4422 2.4646,8.2321 2.6523,8.0317L3.8805,9.0753C3.8743,9.0819 3.868,9.0886 3.8618,9.0953L2.2655,9.4174ZM2.8863,15.5497L2.0452,16.92L2.8273,18.3216C3.5014,17.9804 3.7692,17.8068 4.1368,17.4308C4.8511,17.5089 5.7278,17.5526 6.7801,17.5526L6.9581,17.5526L7.1013,17.5518C9.3708,17.5518 11.1972,16.724 12.2535,15.3888C12.4966,15.4031 12.7431,15.4104 12.9928,15.4104L13.1738,15.4114L13.3848,15.4114C13.6721,15.4114 13.9523,15.4089 14.2253,15.4036C13.0193,17.6858 10.387,19.1584 7.1108,19.1584L6.9581,19.1592L6.7801,19.1592C3.1341,19.1592 0.8434,18.6796 0.1388,17.2549C-0.24,16.4893 0.1772,16.041 1.1385,15.5594C1.7909,15.231 1.8084,15.2068 1.6989,14.9803C1.6411,14.8493 1.5895,14.7409 1.4727,14.5014C1.021,13.5824 0.8543,13.1078 0.8543,12.4656C0.8543,10.2609 1.9815,8.302 3.7168,7.0817C3.713,7.1803 3.7112,7.2792 3.7112,7.3786C3.7112,7.9706 3.7745,8.542 3.896,9.0884C3.0537,9.9876 2.5412,11.1713 2.5412,12.4656C2.5412,12.7951 2.6193,13.0447 3.0005,13.8203C3.1256,14.0767 3.1822,14.1961 3.2434,14.3338C3.3508,14.5585 3.405,14.7087 3.4299,14.9815C3.4528,15.2336 3.4186,15.4768 3.3365,15.7014C3.1322,15.6538 2.9811,15.6024 2.8863,15.5497Z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>
\ No newline at end of file
...@@ -8,21 +8,22 @@ ...@@ -8,21 +8,22 @@
android:paddingStart="@dimen/screen_edge_left_and_right_padding" android:paddingStart="@dimen/screen_edge_left_and_right_padding"
android:paddingTop="@dimen/chat_item_top_and_bottom_padding" android:paddingTop="@dimen/chat_item_top_and_bottom_padding"
android:paddingEnd="@dimen/screen_edge_left_and_right_padding" android:paddingEnd="@dimen/screen_edge_left_and_right_padding"
android:paddingBottom="@dimen/chat_item_top_and_bottom_padding"> android:paddingBottom="@dimen/chat_item_top_and_bottom_padding"
tools:context=".chatrooms.adapter.RoomsAdapter">
<com.facebook.drawee.view.SimpleDraweeView <ImageView
android:id="@+id/image_avatar" android:id="@+id/image_avatar"
android:layout_width="48dp" android:layout_width="48dp"
android:layout_height="48dp" android:layout_height="48dp"
android:layout_marginTop="5dp" android:layout_marginTop="2dp"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" app:layout_constraintTop_toTopOf="parent"
app:roundedCornerRadius="4dp" /> tools:src="@tools:sample/avatars" />
<ImageView <ImageView
android:id="@+id/image_chat_icon" android:id="@+id/image_chat_icon"
android:layout_width="12dp" android:layout_width="12dp"
android:layout_height="0dp" android:layout_height="12dp"
android:layout_marginStart="16dp" android:layout_marginStart="16dp"
app:layout_constraintBottom_toBottomOf="@+id/text_chat_name" app:layout_constraintBottom_toBottomOf="@+id/text_chat_name"
app:layout_constraintStart_toEndOf="@+id/image_avatar" app:layout_constraintStart_toEndOf="@+id/image_avatar"
...@@ -35,6 +36,7 @@ ...@@ -35,6 +36,7 @@
android:layout_width="0dp" android:layout_width="0dp"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_marginStart="@dimen/text_view_drawable_padding" android:layout_marginStart="@dimen/text_view_drawable_padding"
android:layout_marginEnd="@dimen/text_view_drawable_padding"
android:textDirection="locale" android:textDirection="locale"
app:layout_constraintEnd_toStartOf="@+id/text_timestamp" app:layout_constraintEnd_toStartOf="@+id/text_timestamp"
app:layout_constraintStart_toEndOf="@+id/image_chat_icon" app:layout_constraintStart_toEndOf="@+id/image_chat_icon"
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<string name="title_admin_panel">Панель админа</string> <string name="title_admin_panel">Панель админа</string>
<string name="title_password">Изменить пароль</string> <string name="title_password">Изменить пароль</string>
<string name="title_update_profile">Обновить профиль</string> <string name="title_update_profile">Обновить профиль</string>
<string name="title_choose_language">Choose Language</string> <!-- TODO Add translation --> <string name="title_choose_language">Изменить язык</string>
<string name="title_create_channel">Создать новый канал</string> <string name="title_create_channel">Создать новый канал</string>
<string name="title_channel_details">О канале</string> <string name="title_channel_details">О канале</string>
<string name="title_topic">Тема</string> <string name="title_topic">Тема</string>
...@@ -74,23 +74,23 @@ ...@@ -74,23 +74,23 @@
<string name="msg_delete_account">Удалить аккаунт</string> <string name="msg_delete_account">Удалить аккаунт</string>
<string name="msg_change_status">Изменить статус</string> <string name="msg_change_status">Изменить статус</string>
<string-array name="languages"> <!-- TODO Add translations --> <string-array name="languages">
<item>English</item> <item>Английский</item>
<item>Arabic</item> <item>Арабский</item>
<item>German</item> <item>Немецкий</item>
<item>Spanish</item> <item>Испанский</item>
<item>Persian</item> <item>Персидский</item>
<item>French</item> <item>Французский</item>
<item>Hindi (IN)</item> <item>Хинди (IN)</item>
<item>Italian</item> <item>Итальянский</item>
<item>Japanese</item> <item>Японский</item>
<item>Portuguese (BR)</item> <item>Португальский (BR)</item>
<item>Portuguese (PT)</item> <item>Португальский (PT)</item>
<item>Russian (RU)</item> <item>Русский (RU)</item>
<item>Turkish</item> <item>Турецкий</item>
<item>Ukrainian</item> <item>Украинский</item>
<item>Chinese (CN)</item> <item>Китайский (CN)</item>
<item>Chinese (TW)</item> <item>Китайский (TW)</item>
</string-array> </string-array>
<!-- Regular information messages --> <!-- Regular information messages -->
...@@ -203,7 +203,7 @@ ...@@ -203,7 +203,7 @@
<string name="msg_storage_permission_denied">Необходимо разрешение на использование хранилища</string> <string name="msg_storage_permission_denied">Необходимо разрешение на использование хранилища</string>
<string name="msg_server">Сервер</string> <string name="msg_server">Сервер</string>
<string name="msg_add_new_server">Добавить новый сервер</string> <string name="msg_add_new_server">Добавить новый сервер</string>
<string name="msg_directory">Директория</string> <string name="msg_directory">Каталог</string>
<!-- Create channel messages --> <!-- Create channel messages -->
<string name="msg_private_channel">Приватный</string> <string name="msg_private_channel">Приватный</string>
...@@ -344,7 +344,7 @@ ...@@ -344,7 +344,7 @@
<string name="msg_channels">Каналы</string> <string name="msg_channels">Каналы</string>
<string name="msg_users">Пользователи</string> <string name="msg_users">Пользователи</string>
<string name="msg_search_for_global_users">Поиск глобальных пользователей</string> <string name="msg_search_for_global_users">Поиск глобальных пользователей</string>
<string name="msg_search_for_global_users_description">При активации станет возможен поиск любого пользователя из других компаний или серверов.</string> <string name="msg_search_for_global_users_description">При активации станет возможен поиск пользователей на других серверах.</string>
<string name="header_private_groups">Приватные каналы</string> <string name="header_private_groups">Приватные каналы</string>
<string name="header_direct_messages">Личная переписка</string> <string name="header_direct_messages">Личная переписка</string>
<string name="header_live_chats">Живые чаты</string> <string name="header_live_chats">Живые чаты</string>
......
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