Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
A
AloqaIM-Android
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
AloqaIM-Android
Commits
0e76e49a
Commit
0e76e49a
authored
Nov 27, 2018
by
Samer Alabi
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'develop' into room-info
parents
771dadee
4c9ae11a
Changes
46
Expand all
Show whitespace changes
Inline
Side-by-side
Showing
46 changed files
with
989 additions
and
324 deletions
+989
-324
file_paths.xml
app/src/debug/res/xml/file_paths.xml
+6
-0
AndroidManifest.xml
app/src/main/AndroidManifest.xml
+10
-1
ServerFragment.kt
...rocket/android/authentication/server/ui/ServerFragment.kt
+37
-8
ChatRoomFragmentModule.kt
...chat/rocket/android/chatroom/di/ChatRoomFragmentModule.kt
+33
-0
ChatRoomPresenter.kt
...rocket/android/chatroom/presentation/ChatRoomPresenter.kt
+112
-79
ChatRoomView.kt
...chat/rocket/android/chatroom/presentation/ChatRoomView.kt
+3
-10
ChatRoomFragment.kt
.../java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
+66
-23
RoomUiModelMapper.kt
...hat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt
+15
-6
RoomUiModel.kt
...hat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt
+3
-0
ChatRoomsFragmentModule.kt
...at/rocket/android/chatrooms/di/ChatRoomsFragmentModule.kt
+4
-2
ChatRoomsRepository.kt
...t/android/chatrooms/infrastructure/ChatRoomsRepository.kt
+7
-3
ChatRoomsPresenter.kt
...cket/android/chatrooms/presentation/ChatRoomsPresenter.kt
+22
-1
ChatRoomsFragment.kt
...ava/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
+1
-2
DatabaseManager.kt
app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
+43
-37
FavoriteMessagesPresenter.kt
...avoritemessages/presentation/FavoriteMessagesPresenter.kt
+2
-1
FilesPresenter.kt
.../chat/rocket/android/files/presentation/FilesPresenter.kt
+1
-0
MainActivity.kt
...src/main/java/chat/rocket/android/main/ui/MainActivity.kt
+0
-3
MembersPresenter.kt
...t/rocket/android/members/presentation/MembersPresenter.kt
+2
-1
PinnedMessagesPresenter.kt
...id/pinnedmessages/presentation/PinnedMessagesPresenter.kt
+2
-1
ProfilePresenter.kt
...t/rocket/android/profile/presentation/ProfilePresenter.kt
+22
-21
ProfileFragment.kt
...in/java/chat/rocket/android/profile/ui/ProfileFragment.kt
+1
-1
PushManager.kt
app/src/main/java/chat/rocket/android/push/PushManager.kt
+2
-5
ConnectionManager.kt
...ocket/android/server/infraestructure/ConnectionManager.kt
+22
-0
DatabaseMessageMapper.kt
...t/android/server/infraestructure/DatabaseMessageMapper.kt
+7
-34
DatabaseMessagesRepository.kt
...roid/server/infraestructure/DatabaseMessagesRepository.kt
+30
-17
IO.kt
app/src/main/java/chat/rocket/android/util/IO.kt
+29
-0
message_attachment_options.xml
app/src/main/res/layout/message_attachment_options.xml
+12
-2
update_avatar_options.xml
app/src/main/res/layout/update_avatar_options.xml
+2
-2
strings.xml
app/src/main/res/values-de/strings.xml
+2
-2
strings.xml
app/src/main/res/values-es/strings.xml
+2
-2
strings.xml
app/src/main/res/values-fr/strings.xml
+2
-2
strings.xml
app/src/main/res/values-hi-rIN/strings.xml
+2
-2
strings.xml
app/src/main/res/values-it/strings.xml
+323
-0
strings.xml
app/src/main/res/values-ja/strings.xml
+3
-3
strings.xml
app/src/main/res/values-pt-rBR/strings.xml
+2
-2
strings.xml
app/src/main/res/values-ru-rRU/strings.xml
+2
-2
strings.xml
app/src/main/res/values-tr/strings.xml
+2
-2
strings.xml
app/src/main/res/values-uk/strings.xml
+2
-2
strings.xml
app/src/main/res/values/strings.xml
+2
-2
file_paths.xml
app/src/main/res/xml/file_paths.xml
+6
-0
FirebaseMessagingService.kt
...java/chat/rocket/android/push/FirebaseMessagingService.kt
+7
-3
EmojiKeyboardPopup.kt
...main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
+29
-38
bg_skin_tone.xml
emoji/src/main/res/drawable/bg_skin_tone.xml
+3
-1
dialog_skin_tone_chooser.xml
emoji/src/main/res/layout/dialog_skin_tone_chooser.xml
+85
-0
emoji_keyboard.xml
emoji/src/main/res/layout/emoji_keyboard.xml
+1
-1
Image.kt
...src/main/java/chat/rocket/android/util/extension/Image.kt
+18
-0
No files found.
app/src/debug/res/xml/file_paths.xml
0 → 100644
View file @
0e76e49a
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name=
"rocket_chat_images"
path=
"Android/data/chat.rocket.android.dev/files/Pictures"
/>
</paths>
\ No newline at end of file
app/src/main/AndroidManifest.xml
View file @
0e76e49a
...
@@ -110,6 +110,15 @@
...
@@ -110,6 +110,15 @@
<meta-data
<meta-data
android:name=
"io.fabric.ApiKey"
android:name=
"io.fabric.ApiKey"
android:value=
"12ac6e94f850aaffcdff52001af77ca415d06a43"
/>
android:value=
"12ac6e94f850aaffcdff52001af77ca415d06a43"
/>
</application>
<provider
android:name=
"androidx.core.content.FileProvider"
android:authorities=
"chat.rocket.android.fileprovider"
android:exported=
"false"
android:grantUriPermissions=
"true"
>
<meta-data
android:name=
"android.support.FILE_PROVIDER_PATHS"
android:resource=
"@xml/file_paths"
/>
</provider>
</application>
</manifest>
</manifest>
app/src/main/java/chat/rocket/android/authentication/server/ui/ServerFragment.kt
View file @
0e76e49a
package
chat.rocket.android.authentication.server.ui
package
chat.rocket.android.authentication.server.ui
import
android.os.Bundle
import
android.os.Bundle
import
android.text.SpannableStringBuilder
import
android.view.LayoutInflater
import
android.view.LayoutInflater
import
android.view.View
import
android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
...
@@ -11,6 +12,7 @@ import android.widget.ScrollView
...
@@ -11,6 +12,7 @@ import android.widget.ScrollView
import
android.widget.Toast
import
android.widget.Toast
import
androidx.core.content.ContextCompat
import
androidx.core.content.ContextCompat
import
androidx.core.net.toUri
import
androidx.core.net.toUri
import
androidx.core.text.color
import
androidx.core.view.ViewCompat
import
androidx.core.view.ViewCompat
import
androidx.core.view.isVisible
import
androidx.core.view.isVisible
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
...
@@ -51,6 +53,8 @@ class ServerFragment : Fragment(), ServerView {
...
@@ -51,6 +53,8 @@ class ServerFragment : Fragment(), ServerView {
lateinit
var
analyticsManager
:
AnalyticsManager
lateinit
var
analyticsManager
:
AnalyticsManager
private
var
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
private
var
deepLinkInfo
:
LoginDeepLinkInfo
?
=
null
private
var
protocol
=
"https://"
private
var
protocol
=
"https://"
private
var
isDomainAppended
=
false
private
var
appendedText
=
""
private
lateinit
var
serverUrlDisposable
:
Disposable
private
lateinit
var
serverUrlDisposable
:
Disposable
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
private
val
layoutListener
=
ViewTreeObserver
.
OnGlobalLayoutListener
{
if
(
KeyboardHelper
.
isSoftKeyboardShown
(
scroll_view
.
rootView
))
{
if
(
KeyboardHelper
.
isSoftKeyboardShown
(
scroll_view
.
rootView
))
{
...
@@ -131,7 +135,7 @@ class ServerFragment : Fragment(), ServerView {
...
@@ -131,7 +135,7 @@ class ServerFragment : Fragment(), ServerView {
}
}
private
fun
setupOnClickListener
()
=
private
fun
setupOnClickListener
()
=
ui
{
_
->
ui
{
button_connect
.
setOnClickListener
{
button_connect
.
setOnClickListener
{
presenter
.
checkServer
(
"$protocol${text_server_url.textContent.sanitize()}"
)
presenter
.
checkServer
(
"$protocol${text_server_url.textContent.sanitize()}"
)
}
}
...
@@ -244,16 +248,41 @@ class ServerFragment : Fragment(), ServerView {
...
@@ -244,16 +248,41 @@ class ServerFragment : Fragment(), ServerView {
private
fun
subscribeEditText
()
{
private
fun
subscribeEditText
()
{
serverUrlDisposable
=
text_server_url
.
asObservable
()
serverUrlDisposable
=
text_server_url
.
asObservable
()
.
filter
{
it
.
isNotBlank
()
}
.
filter
{
it
.
isNotBlank
()
}
.
subscribe
{
.
subscribe
{
processUserInput
(
it
.
toString
())
}
if
(
"$protocol${it.toString()}"
.
isValidUrl
())
{
}
private
fun
unsubscribeEditText
()
=
serverUrlDisposable
.
dispose
()
private
fun
processUserInput
(
text
:
String
)
{
if
(
text
.
last
().
toString
()
==
"."
&&
!
isDomainAppended
)
{
addDomain
()
}
else
if
(
isDomainAppended
&&
text
!=
appendedText
)
{
removeDomain
()
}
if
(
"$protocol$text"
.
isValidUrl
())
{
enableButtonConnect
()
enableButtonConnect
()
}
else
{
}
else
{
disableButtonConnect
()
disableButtonConnect
()
}
}
}
}
private
fun
addDomain
()
{
val
cursorPosition
=
text_server_url
.
length
()
text_server_url
.
append
(
SpannableStringBuilder
()
.
color
(
R
.
color
.
colorAuthenticationSecondaryText
)
{
append
(
"rocket.chat"
)
})
text_server_url
.
setSelection
(
cursorPosition
)
appendedText
=
text_server_url
.
text
.
toString
()
isDomainAppended
=
true
}
}
private
fun
unsubscribeEditText
()
=
serverUrlDisposable
.
dispose
()
private
fun
removeDomain
()
{
text_server_url
.
setText
(
text_server_url
.
text
.
toString
().
substring
(
0
,
text_server_url
.
selectionEnd
)
)
text_server_url
.
setSelection
(
text_server_url
.
length
())
isDomainAppended
=
false
}
private
fun
enableUserInput
()
{
private
fun
enableUserInput
()
{
enableButtonConnect
()
enableButtonConnect
()
...
...
app/src/main/java/chat/rocket/android/chatroom/di/ChatRoomFragmentModule.kt
View file @
0e76e49a
package
chat.rocket.android.chatroom.di
package
chat.rocket.android.chatroom.di
import
android.app.Application
import
androidx.lifecycle.LifecycleOwner
import
androidx.lifecycle.LifecycleOwner
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.presentation.ChatRoomView
import
chat.rocket.android.chatroom.ui.ChatRoomFragment
import
chat.rocket.android.chatroom.ui.ChatRoomFragment
import
chat.rocket.android.chatrooms.adapter.RoomUiModelMapper
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.ChatRoomDao
import
chat.rocket.android.db.ChatRoomDao
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.DatabaseManagerFactory
import
chat.rocket.android.db.DatabaseManagerFactory
import
chat.rocket.android.db.UserDao
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetCurrentServerInteractor
import
chat.rocket.android.server.domain.GetCurrentUserInteractor
import
chat.rocket.android.server.domain.PermissionsInteractor
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.TokenRepository
import
dagger.Module
import
dagger.Module
import
dagger.Provides
import
dagger.Provides
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.experimental.Job
...
@@ -42,4 +49,30 @@ class ChatRoomFragmentModule {
...
@@ -42,4 +49,30 @@ class ChatRoomFragmentModule {
@Provides
@Provides
@PerFragment
@PerFragment
fun
provideChatRoomDao
(
manager
:
DatabaseManager
):
ChatRoomDao
=
manager
.
chatRoomDao
()
fun
provideChatRoomDao
(
manager
:
DatabaseManager
):
ChatRoomDao
=
manager
.
chatRoomDao
()
@Provides
@PerFragment
fun
provideUserDao
(
manager
:
DatabaseManager
):
UserDao
=
manager
.
userDao
()
@Provides
@PerFragment
fun
provideGetCurrentUserInteractor
(
tokenRepository
:
TokenRepository
,
@Named
(
"currentServer"
)
serverUrl
:
String
,
userDao
:
UserDao
):
GetCurrentUserInteractor
{
return
GetCurrentUserInteractor
(
tokenRepository
,
serverUrl
,
userDao
)
}
@Provides
@PerFragment
fun
provideRoomMapper
(
context
:
Application
,
repository
:
SettingsRepository
,
userInteractor
:
GetCurrentUserInteractor
,
@Named
(
"currentServer"
)
serverUrl
:
String
,
permissionsInteractor
:
PermissionsInteractor
):
RoomUiModelMapper
{
return
RoomUiModelMapper
(
context
,
repository
.
get
(
serverUrl
),
userInteractor
,
serverUrl
,
permissionsInteractor
)
}
}
}
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomPresenter.kt
View file @
0e76e49a
...
@@ -15,6 +15,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
...
@@ -15,6 +15,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatrooms.adapter.RoomUiModelMapper
import
chat.rocket.android.core.behaviours.showMessage
import
chat.rocket.android.core.behaviours.showMessage
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.DatabaseManager
...
@@ -34,11 +35,10 @@ import chat.rocket.android.server.domain.uploadMimeTypeFilter
...
@@ -34,11 +35,10 @@ import chat.rocket.android.server.domain.uploadMimeTypeFilter
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.server.domain.useRealName
import
chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.android.server.infraestructure.ConnectionManagerFactory
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.server.infraestructure.state
import
chat.rocket.android.util.extension.compressImageAndGetByteArray
import
chat.rocket.android.util.extension.getByteArray
import
chat.rocket.android.util.extension.getByteArray
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.
extensions.exhaustive
import
chat.rocket.android.util.
retryDB
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
...
@@ -74,6 +74,7 @@ import chat.rocket.core.model.ChatRoom
...
@@ -74,6 +74,7 @@ import chat.rocket.core.model.ChatRoom
import
chat.rocket.core.model.ChatRoomRole
import
chat.rocket.core.model.ChatRoomRole
import
chat.rocket.core.model.Command
import
chat.rocket.core.model.Command
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Room
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.experimental.android.UI
...
@@ -82,7 +83,6 @@ import kotlinx.coroutines.experimental.launch
...
@@ -82,7 +83,6 @@ import kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.withContext
import
org.threeten.bp.Instant
import
org.threeten.bp.Instant
import
timber.log.Timber
import
timber.log.Timber
import
java.io.InputStream
import
java.util.*
import
java.util.*
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -98,6 +98,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -98,6 +98,7 @@ class ChatRoomPresenter @Inject constructor(
private
val
analyticsManager
:
AnalyticsManager
,
private
val
analyticsManager
:
AnalyticsManager
,
private
val
userHelper
:
UserHelper
,
private
val
userHelper
:
UserHelper
,
private
val
mapper
:
UiModelMapper
,
private
val
mapper
:
UiModelMapper
,
private
val
roomMapper
:
RoomUiModelMapper
,
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
,
private
val
jobSchedulerInteractor
:
JobSchedulerInteractor
,
private
val
messageHelper
:
MessageHelper
,
private
val
messageHelper
:
MessageHelper
,
private
val
dbManager
:
DatabaseManager
,
private
val
dbManager
:
DatabaseManager
,
...
@@ -120,6 +121,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -120,6 +121,7 @@ class ChatRoomPresenter @Inject constructor(
private
var
typingStatusSubscriptionId
:
String
?
=
null
private
var
typingStatusSubscriptionId
:
String
?
=
null
private
var
lastState
=
manager
.
state
private
var
lastState
=
manager
.
state
private
var
typingStatusList
=
arrayListOf
<
String
>()
private
var
typingStatusList
=
arrayListOf
<
String
>()
private
val
roomChangesChannel
=
Channel
<
Room
>(
Channel
.
CONFLATED
)
fun
setupChatRoom
(
fun
setupChatRoom
(
roomId
:
String
,
roomId
:
String
,
...
@@ -127,7 +129,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -127,7 +129,7 @@ class ChatRoomPresenter @Inject constructor(
roomType
:
String
,
roomType
:
String
,
chatRoomMessage
:
String
?
=
null
chatRoomMessage
:
String
?
=
null
)
{
)
{
launch
UI
(
strategy
)
{
launch
(
CommonPool
+
strategy
.
jobs
)
{
try
{
try
{
chatRoles
=
if
(
roomTypeOf
(
roomType
)
!
is
RoomType
.
DirectMessage
)
{
chatRoles
=
if
(
roomTypeOf
(
roomType
)
!
is
RoomType
.
DirectMessage
)
{
client
.
chatRoomRoles
(
roomType
=
roomTypeOf
(
roomType
),
roomName
=
roomName
)
client
.
chatRoomRoles
(
roomType
=
roomTypeOf
(
roomType
),
roomName
=
roomName
)
...
@@ -137,16 +139,21 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -137,16 +139,21 @@ class ChatRoomPresenter @Inject constructor(
chatRoles
=
emptyList
()
chatRoles
=
emptyList
()
}
finally
{
}
finally
{
// User has at least an 'owner' or 'moderator' role.
// User has at least an 'owner' or 'moderator' role.
val
userCanMod
=
isOwnerOrMod
()
val
canModerate
=
isOwnerOrMod
()
val
chatRoom
=
dbManager
.
getRoom
(
roomId
)
val
muted
=
chatRoom
?.
chatRoom
?.
muted
?:
emptyList
()
// Can post anyway if has the 'post-readonly' permission on server.
// Can post anyway if has the 'post-readonly' permission on server.
val
userCanPost
=
userCanMod
||
permissions
.
canPostToReadOnlyChannels
()
||
val
room
=
dbManager
.
getRoom
(
roomId
)
!
muted
.
contains
(
currentLoggedUsername
)
room
?.
let
{
chatIsBroadcast
=
chatRoom
?.
chatRoom
?.
run
{
chatIsBroadcast
=
it
.
chatRoom
.
broadcast
?:
false
broadcast
val
roomUiModel
=
roomMapper
.
map
(
it
,
true
)
}
?:
false
launchUI
(
strategy
)
{
view
.
onRoomUpdated
(
userCanPost
,
chatIsBroadcast
,
userCanMod
)
view
.
onRoomUpdated
(
roomUiModel
=
roomUiModel
.
copy
(
broadcast
=
chatIsBroadcast
,
canModerate
=
canModerate
,
writable
=
roomUiModel
.
writable
||
canModerate
))
}
}
loadMessages
(
roomId
,
roomType
,
clearDataSet
=
true
)
loadMessages
(
roomId
,
roomType
,
clearDataSet
=
true
)
chatRoomMessage
?.
let
{
messageHelper
.
messageIdFromPermalink
(
it
)
}
chatRoomMessage
?.
let
{
messageHelper
.
messageIdFromPermalink
(
it
)
}
?.
let
{
messageId
->
?.
let
{
messageId
->
...
@@ -158,10 +165,26 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -158,10 +165,26 @@ class ChatRoomPresenter @Inject constructor(
true
true
)
)
}
}
subscribeRoomChanges
()
}
}
}
private
suspend
fun
subscribeRoomChanges
()
{
chatRoomId
?.
let
{
manager
.
addRoomChannel
(
it
,
roomChangesChannel
)
for
(
room
in
roomChangesChannel
)
{
dbManager
.
getRoom
(
room
.
id
)
?.
let
{
view
.
onRoomUpdated
(
roomMapper
.
map
(
chatRoom
=
it
,
showLastMessage
=
true
))
}
}
}
}
}
}
}
private
fun
unsubscribeRoomChanges
()
{
chatRoomId
?.
let
{
manager
.
removeRoomChannel
(
it
)
}
}
private
fun
isOwnerOrMod
():
Boolean
{
private
fun
isOwnerOrMod
():
Boolean
{
return
chatRoles
.
firstOrNull
{
it
.
user
.
username
==
currentLoggedUsername
}
?.
roles
?.
any
{
return
chatRoles
.
firstOrNull
{
it
.
user
.
username
==
currentLoggedUsername
}
?.
roles
?.
any
{
it
==
"owner"
||
it
==
"moderator"
it
==
"owner"
||
it
==
"moderator"
...
@@ -898,7 +921,8 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -898,7 +921,8 @@ class ChatRoomPresenter @Inject constructor(
// TODO: move this to new interactor or FetchChatRoomsInteractor?
// TODO: move this to new interactor or FetchChatRoomsInteractor?
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
CommonPool
)
{
private
suspend
fun
getChatRoomAsync
(
roomId
:
String
):
ChatRoom
?
=
withContext
(
CommonPool
)
{
return
@withContext
dbManager
.
chatRoomDao
().
getSync
(
roomId
)
?.
let
{
retryDB
(
"getRoom($roomId)"
)
{
dbManager
.
chatRoomDao
().
getSync
(
roomId
)
?.
let
{
with
(
it
.
chatRoom
)
{
with
(
it
.
chatRoom
)
{
ChatRoom
(
ChatRoom
(
id
=
id
,
id
=
id
,
...
@@ -931,10 +955,12 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -931,10 +955,12 @@ class ChatRoomPresenter @Inject constructor(
}
}
}
}
}
}
}
// TODO: move this to new interactor or FetchChatRoomsInteractor?
// TODO: move this to new interactor or FetchChatRoomsInteractor?
private
suspend
fun
getChatRoomsAsync
(
name
:
String
?
=
null
):
List
<
ChatRoom
>
=
withContext
(
CommonPool
)
{
private
suspend
fun
getChatRoomsAsync
(
name
:
String
?
=
null
):
List
<
ChatRoom
>
=
withContext
(
CommonPool
)
{
return
@withContext
dbManager
.
chatRoomDao
().
getAllSync
().
filter
{
retryDB
(
"getAllSync()"
)
{
dbManager
.
chatRoomDao
().
getAllSync
().
filter
{
if
(
name
==
null
)
{
if
(
name
==
null
)
{
return
@filter
true
return
@filter
true
}
}
...
@@ -972,13 +998,19 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -972,13 +998,19 @@ class ChatRoomPresenter @Inject constructor(
}
}
}
}
}
}
}
fun
joinChat
(
chatRoomId
:
String
)
{
fun
joinChat
(
chatRoomId
:
String
)
{
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
try
{
try
{
retryIO
(
"joinChat($chatRoomId)"
)
{
client
.
joinChat
(
chatRoomId
)
}
retryIO
(
"joinChat($chatRoomId)"
)
{
client
.
joinChat
(
chatRoomId
)
}
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
val
canPost
=
permissions
.
canPostToReadOnlyChannels
()
view
.
onJoined
(
canPost
)
dbManager
.
getRoom
(
chatRoomId
)
?.
let
{
val
roomUiModel
=
roomMapper
.
map
(
it
,
true
).
copy
(
writable
=
canPost
)
view
.
onJoined
(
roomUiModel
=
roomUiModel
)
view
.
onRoomUpdated
(
roomUiModel
=
roomUiModel
)
}
}
catch
(
ex
:
RocketChatException
)
{
}
catch
(
ex
:
RocketChatException
)
{
Timber
.
e
(
ex
)
Timber
.
e
(
ex
)
}
}
...
@@ -1148,6 +1180,7 @@ class ChatRoomPresenter @Inject constructor(
...
@@ -1148,6 +1180,7 @@ class ChatRoomPresenter @Inject constructor(
}
}
fun
disconnect
()
{
fun
disconnect
()
{
unsubscribeRoomChanges
()
unsubscribeTypingStatus
()
unsubscribeTypingStatus
()
if
(
chatRoomId
!=
null
)
{
if
(
chatRoomId
!=
null
)
{
unsubscribeMessages
(
chatRoomId
.
toString
())
unsubscribeMessages
(
chatRoomId
.
toString
())
...
...
app/src/main/java/chat/rocket/android/chatroom/presentation/ChatRoomView.kt
View file @
0e76e49a
...
@@ -5,6 +5,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
...
@@ -5,6 +5,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import
chat.rocket.android.core.behaviours.LoadingView
import
chat.rocket.android.core.behaviours.LoadingView
import
chat.rocket.android.core.behaviours.MessageView
import
chat.rocket.android.core.behaviours.MessageView
import
chat.rocket.core.internal.realtime.socket.model.State
import
chat.rocket.core.internal.realtime.socket.model.State
...
@@ -131,12 +132,7 @@ interface ChatRoomView : LoadingView, MessageView {
...
@@ -131,12 +132,7 @@ interface ChatRoomView : LoadingView, MessageView {
fun
populateEmojiSuggestions
(
emojis
:
List
<
EmojiSuggestionUiModel
>)
fun
populateEmojiSuggestions
(
emojis
:
List
<
EmojiSuggestionUiModel
>)
/**
fun
onJoined
(
roomUiModel
:
RoomUiModel
)
* This user has joined the chat callback.
*
* @param userCanPost Whether the user can post a message or not.
*/
fun
onJoined
(
userCanPost
:
Boolean
)
fun
showReactionsPopup
(
messageId
:
String
)
fun
showReactionsPopup
(
messageId
:
String
)
...
@@ -147,9 +143,6 @@ interface ChatRoomView : LoadingView, MessageView {
...
@@ -147,9 +143,6 @@ interface ChatRoomView : LoadingView, MessageView {
*/
*/
fun
populateCommandSuggestions
(
commands
:
List
<
CommandSuggestionUiModel
>)
fun
populateCommandSuggestions
(
commands
:
List
<
CommandSuggestionUiModel
>)
/**
fun
onRoomUpdated
(
roomUiModel
:
RoomUiModel
)
* Communicate whether it's a broadcast channel and if current user can post to it.
*/
fun
onRoomUpdated
(
userCanPost
:
Boolean
,
channelIsBroadcast
:
Boolean
,
userCanMod
:
Boolean
)
}
}
app/src/main/java/chat/rocket/android/chatroom/ui/ChatRoomFragment.kt
View file @
0e76e49a
...
@@ -8,8 +8,10 @@ import android.content.Context
...
@@ -8,8 +8,10 @@ import android.content.Context
import
android.content.Intent
import
android.content.Intent
import
android.content.res.Configuration
import
android.content.res.Configuration
import
android.graphics.drawable.Drawable
import
android.graphics.drawable.Drawable
import
android.net.Uri
import
android.os.Bundle
import
android.os.Bundle
import
android.os.Handler
import
android.os.Handler
import
android.provider.MediaStore
import
android.text.SpannableStringBuilder
import
android.text.SpannableStringBuilder
import
android.view.KeyEvent
import
android.view.KeyEvent
import
android.view.LayoutInflater
import
android.view.LayoutInflater
...
@@ -23,6 +25,7 @@ import android.widget.FrameLayout
...
@@ -23,6 +25,7 @@ import android.widget.FrameLayout
import
android.widget.ImageView
import
android.widget.ImageView
import
android.widget.TextView
import
android.widget.TextView
import
androidx.annotation.DrawableRes
import
androidx.annotation.DrawableRes
import
androidx.core.content.FileProvider
import
androidx.core.text.bold
import
androidx.core.text.bold
import
androidx.core.view.isVisible
import
androidx.core.view.isVisible
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
...
@@ -48,6 +51,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
...
@@ -48,6 +51,7 @@ import chat.rocket.android.chatroom.uimodel.suggestion.ChatRoomSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.CommandSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.EmojiSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatroom.uimodel.suggestion.PeopleSuggestionUiModel
import
chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import
chat.rocket.android.draw.main.ui.DRAWING_BYTE_ARRAY_EXTRA_DATA
import
chat.rocket.android.draw.main.ui.DRAWING_BYTE_ARRAY_EXTRA_DATA
import
chat.rocket.android.draw.main.ui.DrawingActivity
import
chat.rocket.android.draw.main.ui.DrawingActivity
import
chat.rocket.android.emoji.ComposerEditText
import
chat.rocket.android.emoji.ComposerEditText
...
@@ -73,6 +77,8 @@ import chat.rocket.android.util.extensions.rotateBy
...
@@ -73,6 +77,8 @@ import chat.rocket.android.util.extensions.rotateBy
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.showToast
import
chat.rocket.android.util.extensions.textContent
import
chat.rocket.android.util.extensions.textContent
import
chat.rocket.android.util.extensions.ui
import
chat.rocket.android.util.extensions.ui
import
chat.rocket.android.util.extension.createImageFile
import
chat.rocket.android.util.extensions.getBitmpap
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.core.internal.realtime.socket.model.State
import
chat.rocket.core.internal.realtime.socket.model.State
...
@@ -86,6 +92,9 @@ import kotlinx.android.synthetic.main.fragment_chat_room.*
...
@@ -86,6 +92,9 @@ import kotlinx.android.synthetic.main.fragment_chat_room.*
import
kotlinx.android.synthetic.main.message_attachment_options.*
import
kotlinx.android.synthetic.main.message_attachment_options.*
import
kotlinx.android.synthetic.main.message_composer.*
import
kotlinx.android.synthetic.main.message_composer.*
import
kotlinx.android.synthetic.main.message_list.*
import
kotlinx.android.synthetic.main.message_list.*
import
timber.log.Timber
import
java.io.File
import
java.io.IOException
import
kotlinx.android.synthetic.main.reaction_praises_list_item.*
import
kotlinx.android.synthetic.main.reaction_praises_list_item.*
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.TimeUnit
import
java.util.concurrent.atomic.AtomicInteger
import
java.util.concurrent.atomic.AtomicInteger
...
@@ -125,6 +134,7 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
...
@@ -125,6 +134,7 @@ private const val BUNDLE_CHAT_ROOM_TYPE = "chat_room_type"
private
const
val
BUNDLE_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
BUNDLE_IS_CHAT_ROOM_READ_ONLY
=
"is_chat_room_read_only"
private
const
val
REQUEST_CODE_FOR_PERFORM_SAF
=
42
private
const
val
REQUEST_CODE_FOR_PERFORM_SAF
=
42
private
const
val
REQUEST_CODE_FOR_DRAW
=
101
private
const
val
REQUEST_CODE_FOR_DRAW
=
101
private
const
val
REQUEST_CODE_FOR_PERFORM_CAMERA
=
102
private
const
val
BUNDLE_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
BUNDLE_CHAT_ROOM_LAST_SEEN
=
"chat_room_last_seen"
private
const
val
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
=
"chat_room_is_subscribed"
private
const
val
BUNDLE_CHAT_ROOM_IS_SUBSCRIBED
=
"chat_room_is_subscribed"
private
const
val
BUNDLE_CHAT_ROOM_IS_CREATOR
=
"chat_room_is_creator"
private
const
val
BUNDLE_CHAT_ROOM_IS_CREATOR
=
"chat_room_is_creator"
...
@@ -192,6 +202,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -192,6 +202,7 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
internal
val
description
by
lazy
{
dialogView
.
findViewById
<
EditText
>(
R
.
id
.
text_file_description
)
}
internal
val
description
by
lazy
{
dialogView
.
findViewById
<
EditText
>(
R
.
id
.
text_file_description
)
}
internal
val
audioVideoAttachment
by
lazy
{
dialogView
.
findViewById
<
FrameLayout
>(
R
.
id
.
audio_video_attachment
)
}
internal
val
audioVideoAttachment
by
lazy
{
dialogView
.
findViewById
<
FrameLayout
>(
R
.
id
.
audio_video_attachment
)
}
internal
val
textFile
by
lazy
{
dialogView
.
findViewById
<
TextView
>(
R
.
id
.
text_file_name
)
}
internal
val
textFile
by
lazy
{
dialogView
.
findViewById
<
TextView
>(
R
.
id
.
text_file_name
)
}
private
var
takenPhotoUri
:
Uri
?
=
null
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
override
fun
onCreate
(
savedInstanceState
:
Bundle
?)
{
super
.
onCreate
(
savedInstanceState
)
super
.
onCreate
(
savedInstanceState
)
...
@@ -280,12 +291,19 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -280,12 +291,19 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
resultData
:
Intent
?)
{
override
fun
onActivityResult
(
requestCode
:
Int
,
resultCode
:
Int
,
resultData
:
Intent
?)
{
if
(
result
Data
!=
null
&&
result
Code
==
Activity
.
RESULT_OK
)
{
if
(
resultCode
==
Activity
.
RESULT_OK
)
{
when
(
requestCode
)
{
when
(
requestCode
)
{
REQUEST_CODE_FOR_PERFORM_SAF
->
showFileAttachmentDialog
(
resultData
.
data
)
REQUEST_CODE_FOR_PERFORM_CAMERA
->
takenPhotoUri
?.
let
{
uri
->
REQUEST_CODE_FOR_DRAW
->
showDrawAttachmentDialog
(
uri
.
getBitmpap
(
requireContext
())
?.
let
{
bitmap
->
resultData
.
getByteArrayExtra
(
DRAWING_BYTE_ARRAY_EXTRA_DATA
)
presenter
.
uploadImage
(
chatRoomId
,
"image/png"
,
uri
,
bitmap
,
""
)
)
}
}
REQUEST_CODE_FOR_PERFORM_SAF
->
resultData
?.
data
?.
let
{
showFileAttachmentDialog
(
it
)
}
REQUEST_CODE_FOR_DRAW
->
resultData
?.
getByteArrayExtra
(
DRAWING_BYTE_ARRAY_EXTRA_DATA
)
?.
let
{
showDrawAttachmentDialog
(
it
)
}
}
}
}
}
}
}
...
@@ -380,17 +398,14 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -380,17 +398,14 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
empty_chat_view
.
isVisible
=
adapter
.
itemCount
==
0
empty_chat_view
.
isVisible
=
adapter
.
itemCount
==
0
}
}
override
fun
onRoomUpdated
(
override
fun
onRoomUpdated
(
roomUiModel
:
RoomUiModel
)
{
userCanPost
:
Boolean
,
channelIsBroadcast
:
Boolean
,
userCanMod
:
Boolean
)
{
// TODO: We should rely solely on the user being able to post, but we cannot guarantee
// TODO: We should rely solely on the user being able to post, but we cannot guarantee
// that the "(channels|groups).roles" endpoint is supported by the server in use.
// that the "(channels|groups).roles" endpoint is supported by the server in use.
ui
{
ui
{
setupMessageComposer
(
userCanPost
)
setupToolbar
(
roomUiModel
.
name
.
toString
())
isBroadcastChannel
=
channelIsBroadcast
setupMessageComposer
(
roomUiModel
)
if
(
isBroadcastChannel
&&
!
userCanMod
)
{
isBroadcastChannel
=
roomUiModel
.
broadcast
if
(
isBroadcastChannel
&&
!
roomUiModel
.
canModerate
)
{
disableMenu
=
true
disableMenu
=
true
activity
?.
invalidateOptionsMenu
()
activity
?.
invalidateOptionsMenu
()
}
}
...
@@ -527,7 +542,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -527,7 +542,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
ui
{
ui
{
button_send
.
isEnabled
=
true
button_send
.
isEnabled
=
true
text_message
.
isEnabled
=
true
text_message
.
isEnabled
=
true
clearMessageComposition
(
true
)
}
}
}
}
...
@@ -769,12 +783,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -769,12 +783,11 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
}
}
override
fun
onJoined
(
userCanPost
:
Boolean
)
{
override
fun
onJoined
(
roomUiModel
:
RoomUiModel
)
{
ui
{
ui
{
input_container
.
isVisible
=
true
input_container
.
isVisible
=
true
button_join_chat
.
isVisible
=
false
button_join_chat
.
isVisible
=
false
isSubscribed
=
true
isSubscribed
=
true
setupMessageComposer
(
userCanPost
)
}
}
}
}
...
@@ -807,8 +820,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -807,8 +820,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
}
}
private
fun
setupMessageComposer
(
canPost
:
Boolean
)
{
private
fun
setupMessageComposer
(
roomUiModel
:
RoomUiModel
)
{
if
(
!
canPost
)
{
if
(
isReadOnly
||
!
roomUiModel
.
writable
)
{
text_room_is_read_only
.
isVisible
=
true
text_room_is_read_only
.
isVisible
=
true
input_container
.
isVisible
=
false
input_container
.
isVisible
=
false
text_room_is_read_only
.
setText
(
text_room_is_read_only
.
setText
(
...
@@ -824,6 +837,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -824,6 +837,8 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
button_join_chat
.
isVisible
=
true
button_join_chat
.
isVisible
=
true
button_join_chat
.
setOnClickListener
{
presenter
.
joinChat
(
chatRoomId
)
}
button_join_chat
.
setOnClickListener
{
presenter
.
joinChat
(
chatRoomId
)
}
}
else
{
}
else
{
input_container
.
isVisible
=
true
text_room_is_read_only
.
isVisible
=
false
button_send
.
isVisible
=
false
button_send
.
isVisible
=
false
button_show_attachment_options
.
alpha
=
1f
button_show_attachment_options
.
alpha
=
1f
button_show_attachment_options
.
isVisible
=
true
button_show_attachment_options
.
isVisible
=
true
...
@@ -880,7 +895,19 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -880,7 +895,19 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
hideAttachmentOptions
()
hideAttachmentOptions
()
}
}
button_files
.
setOnClickListener
{
button_add_reaction
.
setOnClickListener
{
_
->
openEmojiKeyboardPopup
()
}
button_take_a_photo
.
setOnClickListener
{
dispatchTakePictureIntent
()
handler
.
postDelayed
({
hideAttachmentOptions
()
},
400
)
}
button_attach_a_file
.
setOnClickListener
{
handler
.
postDelayed
({
handler
.
postDelayed
({
presenter
.
selectFile
()
presenter
.
selectFile
()
},
200
)
},
200
)
...
@@ -890,10 +917,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -890,10 +917,6 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
},
400
)
},
400
)
}
}
button_add_reaction
.
setOnClickListener
{
_
->
openEmojiKeyboardPopup
()
}
button_drawing
.
setOnClickListener
{
button_drawing
.
setOnClickListener
{
activity
?.
let
{
fragmentActivity
->
activity
?.
let
{
fragmentActivity
->
if
(!
ImageHelper
.
canWriteToExternalStorage
(
fragmentActivity
))
{
if
(!
ImageHelper
.
canWriteToExternalStorage
(
fragmentActivity
))
{
...
@@ -911,6 +934,26 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
...
@@ -911,6 +934,26 @@ class ChatRoomFragment : Fragment(), ChatRoomView, EmojiKeyboardListener, EmojiR
}
}
}
}
private
fun
dispatchTakePictureIntent
()
{
Intent
(
MediaStore
.
ACTION_IMAGE_CAPTURE
).
also
{
takePictureIntent
->
// Create the File where the photo should go
val
photoFile
:
File
?
=
try
{
activity
?.
createImageFile
()
}
catch
(
ex
:
IOException
)
{
Timber
.
e
(
ex
)
null
}
// Continue only if the File was successfully created
photoFile
?.
also
{
takenPhotoUri
=
FileProvider
.
getUriForFile
(
requireContext
(),
"chat.rocket.android.fileprovider"
,
it
)
takePictureIntent
.
putExtra
(
MediaStore
.
EXTRA_OUTPUT
,
takenPhotoUri
)
startActivityForResult
(
takePictureIntent
,
REQUEST_CODE_FOR_PERFORM_CAMERA
)
}
}
}
private
fun
getUnfinishedMessage
()
{
private
fun
getUnfinishedMessage
()
{
val
unfinishedMessage
=
presenter
.
getUnfinishedMessage
(
chatRoomId
)
val
unfinishedMessage
=
presenter
.
getUnfinishedMessage
(
chatRoomId
)
if
(
unfinishedMessage
.
isNotBlank
())
{
if
(
unfinishedMessage
.
isNotBlank
())
{
...
...
app/src/main/java/chat/rocket/android/chatrooms/adapter/RoomUiModelMapper.kt
View file @
0e76e49a
...
@@ -8,9 +8,8 @@ import androidx.core.text.color
...
@@ -8,9 +8,8 @@ import androidx.core.text.color
import
chat.rocket.android.R
import
chat.rocket.android.R
import
chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import
chat.rocket.android.chatrooms.adapter.model.RoomUiModel
import
chat.rocket.android.db.model.ChatRoom
import
chat.rocket.android.db.model.ChatRoom
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.checkIfMyself
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.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
...
@@ -30,7 +29,8 @@ class RoomUiModelMapper(
...
@@ -30,7 +29,8 @@ 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
serverUrl
:
String
private
val
serverUrl
:
String
,
private
val
permissions
:
PermissionsInteractor
)
{
)
{
private
val
nameUnreadColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorPrimaryText
)
private
val
nameUnreadColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorPrimaryText
)
private
val
nameColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
private
val
nameColor
=
ContextCompat
.
getColor
(
context
,
R
.
color
.
colorSecondaryText
)
...
@@ -97,7 +97,9 @@ class RoomUiModelMapper(
...
@@ -97,7 +97,9 @@ class RoomUiModelMapper(
avatar
=
serverUrl
.
avatarUrl
(
name
!!
,
isGroupOrChannel
=
true
),
avatar
=
serverUrl
.
avatarUrl
(
name
!!
,
isGroupOrChannel
=
true
),
lastMessage
=
if
(
showLastMessage
)
{
mapLastMessage
(
lastMessage
?.
sender
?.
id
,
lastMessage
?.
sender
?.
username
,
lastMessage
=
if
(
showLastMessage
)
{
mapLastMessage
(
lastMessage
?.
sender
?.
id
,
lastMessage
?.
sender
?.
username
,
lastMessage
?.
sender
?.
name
,
lastMessage
?.
message
,
lastMessage
?.
sender
?.
name
,
lastMessage
?.
message
,
isDirectMessage
=
type
is
RoomType
.
DirectMessage
)}
else
{
null
}
isDirectMessage
=
type
is
RoomType
.
DirectMessage
)}
else
{
null
},
muted
=
muted
.
orEmpty
(),
writable
=
isChannelWritable
(
muted
)
)
)
}
}
}
}
...
@@ -133,11 +135,18 @@ class RoomUiModelMapper(
...
@@ -133,11 +135,18 @@ class RoomUiModelMapper(
alert
=
isUnread
,
alert
=
isUnread
,
lastMessage
=
lastMessageMarkdown
,
lastMessage
=
lastMessageMarkdown
,
status
=
status
,
status
=
status
,
username
=
if
(
type
is
RoomType
.
DirectMessage
)
name
else
null
username
=
if
(
type
is
RoomType
.
DirectMessage
)
name
else
null
,
muted
=
muted
.
orEmpty
(),
writable
=
isChannelWritable
(
muted
)
)
)
}
}
}
}
private
fun
isChannelWritable
(
muted
:
List
<
String
>?):
Boolean
{
val
canWriteToReadOnlyChannels
=
permissions
.
canPostToReadOnlyChannels
()
return
canWriteToReadOnlyChannels
||
!
muted
.
orEmpty
().
contains
(
currentUser
?.
username
)
}
private
fun
roomType
(
type
:
String
):
String
{
private
fun
roomType
(
type
:
String
):
String
{
val
resources
=
context
.
resources
val
resources
=
context
.
resources
return
when
(
type
)
{
return
when
(
type
)
{
...
...
app/src/main/java/chat/rocket/android/chatrooms/adapter/model/RoomUiModel.kt
View file @
0e76e49a
...
@@ -15,5 +15,8 @@ data class RoomUiModel(
...
@@ -15,5 +15,8 @@ data class RoomUiModel(
val
lastMessage
:
CharSequence
?
=
null
,
val
lastMessage
:
CharSequence
?
=
null
,
val
status
:
UserStatus
?
=
null
,
val
status
:
UserStatus
?
=
null
,
val
username
:
String
?
=
null
,
val
username
:
String
?
=
null
,
val
broadcast
:
Boolean
=
false
,
val
canModerate
:
Boolean
=
false
,
val
writable
:
Boolean
=
true
,
val
muted
:
List
<
String
>
=
emptyList
()
val
muted
:
List
<
String
>
=
emptyList
()
)
)
app/src/main/java/chat/rocket/android/chatrooms/di/ChatRoomsFragmentModule.kt
View file @
0e76e49a
...
@@ -12,6 +12,7 @@ import chat.rocket.android.db.DatabaseManager
...
@@ -12,6 +12,7 @@ import chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.UserDao
import
chat.rocket.android.db.UserDao
import
chat.rocket.android.infrastructure.LocalRepository
import
chat.rocket.android.infrastructure.LocalRepository
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.PublicSettings
import
chat.rocket.android.server.domain.PublicSettings
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.SettingsRepository
import
chat.rocket.android.server.domain.TokenRepository
import
chat.rocket.android.server.domain.TokenRepository
...
@@ -88,9 +89,10 @@ class ChatRoomsFragmentModule {
...
@@ -88,9 +89,10 @@ class ChatRoomsFragmentModule {
context
:
Application
,
context
:
Application
,
repository
:
SettingsRepository
,
repository
:
SettingsRepository
,
userInteractor
:
GetCurrentUserInteractor
,
userInteractor
:
GetCurrentUserInteractor
,
@Named
(
"currentServer"
)
serverUrl
:
String
@Named
(
"currentServer"
)
serverUrl
:
String
,
permissionsInteractor
:
PermissionsInteractor
):
RoomUiModelMapper
{
):
RoomUiModelMapper
{
return
RoomUiModelMapper
(
context
,
repository
.
get
(
serverUrl
),
userInteractor
,
serverUrl
)
return
RoomUiModelMapper
(
context
,
repository
.
get
(
serverUrl
),
userInteractor
,
serverUrl
,
permissionsInteractor
)
}
}
@Provides
@Provides
...
...
app/src/main/java/chat/rocket/android/chatrooms/infrastructure/ChatRoomsRepository.kt
View file @
0e76e49a
...
@@ -3,9 +3,12 @@ package chat.rocket.android.chatrooms.infrastructure
...
@@ -3,9 +3,12 @@ package chat.rocket.android.chatrooms.infrastructure
import
androidx.lifecycle.LiveData
import
androidx.lifecycle.LiveData
import
chat.rocket.android.db.ChatRoomDao
import
chat.rocket.android.db.ChatRoomDao
import
chat.rocket.android.db.model.ChatRoom
import
chat.rocket.android.db.model.ChatRoom
import
chat.rocket.android.util.retryDB
import
javax.inject.Inject
import
javax.inject.Inject
class
ChatRoomsRepository
@Inject
constructor
(
private
val
dao
:
ChatRoomDao
){
class
ChatRoomsRepository
@Inject
constructor
(
private
val
dao
:
ChatRoomDao
)
{
// TODO - check how to use retryDB here - suspend
fun
getChatRooms
(
order
:
Order
):
LiveData
<
List
<
ChatRoom
>>
{
fun
getChatRooms
(
order
:
Order
):
LiveData
<
List
<
ChatRoom
>>
{
return
when
(
order
)
{
return
when
(
order
)
{
Order
.
ACTIVITY
->
dao
.
getAll
()
Order
.
ACTIVITY
->
dao
.
getAll
()
...
@@ -15,9 +18,10 @@ class ChatRoomsRepository @Inject constructor(private val dao: ChatRoomDao){
...
@@ -15,9 +18,10 @@ class ChatRoomsRepository @Inject constructor(private val dao: ChatRoomDao){
}
}
}
}
fun
search
(
query
:
String
)
=
dao
.
searchSync
(
query
)
suspend
fun
search
(
query
:
String
)
=
retryDB
(
"roomSearch($query)"
)
{
dao
.
searchSync
(
query
)
}
fun
count
()
=
dao
.
count
()
suspend
fun
count
()
=
retryDB
(
"roomsCount"
)
{
dao
.
count
()
}
enum
class
Order
{
enum
class
Order
{
ACTIVITY
,
ACTIVITY
,
...
...
app/src/main/java/chat/rocket/android/chatrooms/presentation/ChatRoomsPresenter.kt
View file @
0e76e49a
...
@@ -13,6 +13,7 @@ import chat.rocket.android.server.domain.useRealName
...
@@ -13,6 +13,7 @@ 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.infraestructure.ConnectionManager
import
chat.rocket.android.server.infraestructure.ConnectionManager
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.retryDB
import
chat.rocket.android.util.retryIO
import
chat.rocket.android.util.retryIO
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
...
@@ -41,11 +42,31 @@ class ChatRoomsPresenter @Inject constructor(
...
@@ -41,11 +42,31 @@ class ChatRoomsPresenter @Inject constructor(
private
val
client
=
manager
.
client
private
val
client
=
manager
.
client
private
val
settings
=
settingsRepository
.
get
(
currentServer
)
private
val
settings
=
settingsRepository
.
get
(
currentServer
)
fun
loadChatRoom
(
roomId
:
String
)
{
launchUI
(
strategy
)
{
view
.
showLoadingRoom
(
""
)
try
{
val
room
=
dbManager
.
getRoom
(
roomId
)
if
(
room
!=
null
)
{
loadChatRoom
(
room
.
chatRoom
,
true
)
}
else
{
Timber
.
d
(
"Error loading channel"
)
view
.
showGenericErrorMessage
()
}
}
catch
(
ex
:
Exception
)
{
Timber
.
d
(
ex
,
"Error loading channel"
)
view
.
showGenericErrorMessage
()
}
finally
{
view
.
hideLoadingRoom
()
}
}
}
fun
loadChatRoom
(
chatRoom
:
RoomUiModel
)
{
fun
loadChatRoom
(
chatRoom
:
RoomUiModel
)
{
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoadingRoom
(
chatRoom
.
name
)
view
.
showLoadingRoom
(
chatRoom
.
name
)
try
{
try
{
val
room
=
dbManager
.
getRoom
(
chatRoom
.
id
)
val
room
=
retryDB
(
"getRoom(${chatRoom.id}"
)
{
dbManager
.
getRoom
(
chatRoom
.
id
)
}
if
(
room
!=
null
)
{
if
(
room
!=
null
)
{
loadChatRoom
(
room
.
chatRoom
,
true
)
loadChatRoom
(
room
.
chatRoom
,
true
)
}
else
{
}
else
{
...
...
app/src/main/java/chat/rocket/android/chatrooms/ui/ChatRoomsFragment.kt
View file @
0e76e49a
...
@@ -84,8 +84,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
...
@@ -84,8 +84,7 @@ class ChatRoomsFragment : Fragment(), ChatRoomsView {
if
(
bundle
!=
null
)
{
if
(
bundle
!=
null
)
{
chatRoomId
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_ID
)
chatRoomId
=
bundle
.
getString
(
BUNDLE_CHAT_ROOM_ID
)
chatRoomId
?.
let
{
chatRoomId
?.
let
{
// TODO - bring back support to load a room from id.
presenter
.
loadChatRoom
(
it
)
//presenter.goToChatRoomWithId(it)
chatRoomId
=
null
chatRoomId
=
null
}
}
}
}
...
...
app/src/main/java/chat/rocket/android/db/DatabaseManager.kt
View file @
0e76e49a
...
@@ -19,6 +19,7 @@ import chat.rocket.android.util.extensions.exhaustive
...
@@ -19,6 +19,7 @@ import chat.rocket.android.util.extensions.exhaustive
import
chat.rocket.android.util.extensions.removeTrailingSlash
import
chat.rocket.android.util.extensions.removeTrailingSlash
import
chat.rocket.android.util.extensions.toEntity
import
chat.rocket.android.util.extensions.toEntity
import
chat.rocket.android.util.extensions.userId
import
chat.rocket.android.util.extensions.userId
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.model.BaseRoom
import
chat.rocket.common.model.BaseRoom
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.RoomType
import
chat.rocket.common.model.SimpleUser
import
chat.rocket.common.model.SimpleUser
...
@@ -91,13 +92,15 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -91,13 +92,15 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
}
}
fun
logout
()
{
suspend
fun
logout
()
{
database
.
clearAllTables
()
retryDB
(
"clearAllTables"
)
{
database
.
clearAllTables
()
}
}
}
suspend
fun
getRoom
(
id
:
String
)
=
withContext
(
dbManagerContext
)
{
suspend
fun
getRoom
(
id
:
String
)
=
withContext
(
dbManagerContext
)
{
retryDB
(
"getRoom($id)"
)
{
chatRoomDao
().
getSync
(
id
)
chatRoomDao
().
getSync
(
id
)
}
}
}
fun
processUsersBatch
(
users
:
List
<
User
>)
{
fun
processUsersBatch
(
users
:
List
<
User
>)
{
launch
(
dbManagerContext
)
{
launch
(
dbManagerContext
)
{
...
@@ -151,7 +154,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -151,7 +154,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
fun
updateSelfUser
(
myself
:
Myself
)
{
fun
updateSelfUser
(
myself
:
Myself
)
{
launch
(
dbManagerContext
)
{
launch
(
dbManagerContext
)
{
val
user
=
userDao
().
getUser
(
myself
.
id
)
val
user
=
retryDB
(
"getUser(${myself.id})"
)
{
userDao
().
getUser
(
myself
.
id
)
}
val
entity
=
user
?.
copy
(
val
entity
=
user
?.
copy
(
name
=
myself
.
name
?:
user
.
name
,
name
=
myself
.
name
?:
user
.
name
,
username
=
myself
.
username
?:
user
.
username
,
username
=
myself
.
username
?:
user
.
username
,
...
@@ -335,7 +338,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -335,7 +338,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
private
suspend
fun
updateRoom
(
data
:
Room
):
ChatRoomEntity
?
{
private
suspend
fun
updateRoom
(
data
:
Room
):
ChatRoomEntity
?
{
return
chatRoomDao
().
getSync
(
data
.
id
)
?.
let
{
current
->
return
retryDB
(
"getChatRoom(${data.id})"
)
{
chatRoomDao
().
getSync
(
data
.
id
)
}
?.
let
{
current
->
with
(
data
)
{
with
(
data
)
{
val
chatRoom
=
current
.
chatRoom
val
chatRoom
=
current
.
chatRoom
...
@@ -376,7 +379,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -376,7 +379,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
context
.
getString
(
R
.
string
.
msg_sent_attachment
)
context
.
getString
(
R
.
string
.
msg_sent_attachment
)
private
suspend
fun
updateSubscription
(
data
:
Subscription
):
ChatRoomEntity
?
{
private
suspend
fun
updateSubscription
(
data
:
Subscription
):
ChatRoomEntity
?
{
return
chatRoomDao
().
getSync
(
data
.
roomId
)
?.
let
{
current
->
return
retryDB
(
"getRoom(${data.roomId}"
)
{
chatRoomDao
().
getSync
(
data
.
roomId
)
}
?.
let
{
current
->
with
(
data
)
{
with
(
data
)
{
val
userId
=
if
(
type
is
RoomType
.
DirectMessage
)
{
val
userId
=
if
(
type
is
RoomType
.
DirectMessage
)
{
...
@@ -551,9 +554,11 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -551,9 +554,11 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
}
}
private
fun
findUser
(
userId
:
String
):
String
?
=
userDao
().
findUser
(
userId
)
private
suspend
fun
findUser
(
userId
:
String
):
String
?
=
retryDB
(
"findUser($userId)"
)
{
userDao
().
findUser
(
userId
)
}
private
fun
doOperation
(
operation
:
Operation
)
{
private
suspend
fun
doOperation
(
operation
:
Operation
)
{
retryDB
(
description
=
"doOperation($operation)"
)
{
when
(
operation
)
{
when
(
operation
)
{
is
Operation
.
ClearStatus
->
userDao
().
clearStatus
()
is
Operation
.
ClearStatus
->
userDao
().
clearStatus
()
is
Operation
.
UpdateRooms
->
{
is
Operation
.
UpdateRooms
->
{
...
@@ -585,6 +590,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
...
@@ -585,6 +590,7 @@ class DatabaseManager(val context: Application, val serverUrl: String) {
}
}
}.
exhaustive
}.
exhaustive
}
}
}
}
}
sealed
class
Operation
{
sealed
class
Operation
{
...
...
app/src/main/java/chat/rocket/android/favoritemessages/presentation/FavoriteMessagesPresenter.kt
View file @
0e76e49a
...
@@ -5,6 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
...
@@ -5,6 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
...
...
app/src/main/java/chat/rocket/android/files/presentation/FilesPresenter.kt
View file @
0e76e49a
...
@@ -7,6 +7,7 @@ import chat.rocket.android.files.uimodel.FileUiModel
...
@@ -7,6 +7,7 @@ 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.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
...
...
app/src/main/java/chat/rocket/android/main/ui/MainActivity.kt
View file @
0e76e49a
...
@@ -62,10 +62,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
...
@@ -62,10 +62,7 @@ class MainActivity : AppCompatActivity(), MainView, HasActivityInjector,
setContentView
(
R
.
layout
.
activity_main
)
setContentView
(
R
.
layout
.
activity_main
)
refreshPushToken
()
refreshPushToken
()
chatRoomId
=
intent
.
getStringExtra
(
INTENT_CHAT_ROOM_ID
)
chatRoomId
=
intent
.
getStringExtra
(
INTENT_CHAT_ROOM_ID
)
println
(
"ChatRoomId: $chatRoomId"
)
presenter
.
clearNotificationsForChatroom
(
chatRoomId
)
presenter
.
clearNotificationsForChatroom
(
chatRoomId
)
presenter
.
connect
()
presenter
.
connect
()
...
...
app/src/main/java/chat/rocket/android/members/presentation/MembersPresenter.kt
View file @
0e76e49a
...
@@ -6,6 +6,7 @@ import chat.rocket.android.members.uimodel.MemberUiModel
...
@@ -6,6 +6,7 @@ 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.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
...
...
app/src/main/java/chat/rocket/android/pinnedmessages/presentation/PinnedMessagesPresenter.kt
View file @
0e76e49a
...
@@ -5,6 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
...
@@ -5,6 +5,7 @@ import chat.rocket.android.core.lifecycle.CancelStrategy
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.server.infraestructure.RocketChatClientFactory
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.extension.launchUI
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.RocketChatException
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.model.roomTypeOf
import
chat.rocket.common.util.ifNull
import
chat.rocket.common.util.ifNull
...
...
app/src/main/java/chat/rocket/android/profile/presentation/ProfilePresenter.kt
View file @
0e76e49a
...
@@ -29,7 +29,6 @@ import chat.rocket.core.internal.rest.setAvatar
...
@@ -29,7 +29,6 @@ import chat.rocket.core.internal.rest.setAvatar
import
chat.rocket.core.internal.rest.updateProfile
import
chat.rocket.core.internal.rest.updateProfile
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.withContext
import
java.lang.Exception
import
java.util.*
import
java.util.*
import
javax.inject.Inject
import
javax.inject.Inject
...
@@ -58,20 +57,17 @@ class ProfilePresenter @Inject constructor(
...
@@ -58,20 +57,17 @@ class ProfilePresenter @Inject constructor(
)
{
)
{
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
serverUrl
=
serverInteractor
.
get
()
!!
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverUrl
)
private
val
client
:
RocketChatClient
=
factory
.
create
(
serverUrl
)
private
val
myselfId
=
userHelper
.
user
()
?.
id
?:
""
private
val
user
=
userHelper
.
user
()
private
var
myselfName
=
userHelper
.
user
()
?.
name
?:
""
private
var
myselfUsername
=
userHelper
.
username
()
?:
""
private
var
myselfEmailAddress
=
userHelper
.
user
()
?.
emails
?.
getOrNull
(
0
)
?.
address
?:
""
fun
loadUserProfile
()
{
fun
loadUserProfile
()
{
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
view
.
showProfile
(
view
.
showProfile
(
serverUrl
.
avatarUrl
(
myselfUsername
),
serverUrl
.
avatarUrl
(
user
?.
username
?:
""
),
myselfName
,
user
?.
name
?:
""
,
myselfUsername
,
user
?.
username
?:
""
,
myselfEmailAddress
user
?.
emails
?.
getOrNull
(
0
)
?.
address
?:
""
)
)
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
view
.
showMessage
(
exception
)
view
.
showMessage
(
exception
)
...
@@ -85,14 +81,16 @@ class ProfilePresenter @Inject constructor(
...
@@ -85,14 +81,16 @@ class ProfilePresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
retryIO
{
client
.
updateProfile
(
myselfId
,
email
,
name
,
username
)
}
user
?.
id
?.
let
{
id
->
retryIO
{
client
.
updateProfile
(
id
,
email
,
name
,
username
)
}
myselfEmailAddress
=
email
myselfName
=
name
myselfUsername
=
username
view
.
showProfileUpdateSuccessfullyMessage
()
view
.
showProfileUpdateSuccessfullyMessage
()
loadUserProfile
()
view
.
showProfile
(
serverUrl
.
avatarUrl
(
user
.
username
?:
""
),
name
,
username
,
email
)
}
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
view
.
showMessage
(
it
)
...
@@ -117,7 +115,7 @@ class ProfilePresenter @Inject constructor(
...
@@ -117,7 +115,7 @@ class ProfilePresenter @Inject constructor(
uriInteractor
.
getInputStream
(
uri
)
uriInteractor
.
getInputStream
(
uri
)
}
}
}
}
view
.
reloadUserAvatar
(
serverUrl
.
avatarUrl
(
myselfUsername
))
user
?.
username
?.
let
{
view
.
reloadUserAvatar
(
it
)
}
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
view
.
showMessage
(
it
)
...
@@ -144,7 +142,8 @@ class ProfilePresenter @Inject constructor(
...
@@ -144,7 +142,8 @@ class ProfilePresenter @Inject constructor(
byteArray
?.
inputStream
()
byteArray
?.
inputStream
()
}
}
}
}
view
.
reloadUserAvatar
(
serverUrl
.
avatarUrl
(
myselfUsername
))
user
?.
username
?.
let
{
view
.
reloadUserAvatar
(
it
)
}
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
view
.
showMessage
(
it
)
...
@@ -161,8 +160,10 @@ class ProfilePresenter @Inject constructor(
...
@@ -161,8 +160,10 @@ class ProfilePresenter @Inject constructor(
launchUI
(
strategy
)
{
launchUI
(
strategy
)
{
view
.
showLoading
()
view
.
showLoading
()
try
{
try
{
retryIO
{
client
.
resetAvatar
(
myselfId
)
}
user
?.
id
?.
let
{
id
->
view
.
reloadUserAvatar
(
serverUrl
.
avatarUrl
(
myselfUsername
))
retryIO
{
client
.
resetAvatar
(
id
)
}
}
user
?.
username
?.
let
{
view
.
reloadUserAvatar
(
it
)
}
}
catch
(
exception
:
RocketChatException
)
{
}
catch
(
exception
:
RocketChatException
)
{
exception
.
message
?.
let
{
exception
.
message
?.
let
{
view
.
showMessage
(
it
)
view
.
showMessage
(
it
)
...
...
app/src/main/java/chat/rocket/android/profile/ui/ProfileFragment.kt
View file @
0e76e49a
...
@@ -217,7 +217,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
...
@@ -217,7 +217,7 @@ class ProfileFragment : Fragment(), ProfileView, ActionMode.Callback {
hideUpdateAvatarOptions
()
hideUpdateAvatarOptions
()
}
}
button_take_photo
.
setOnClickListener
{
button_take_
a_
photo
.
setOnClickListener
{
dispatchTakePicture
(
REQUEST_CODE_FOR_PERFORM_CAMERA
)
dispatchTakePicture
(
REQUEST_CODE_FOR_PERFORM_CAMERA
)
hideUpdateAvatarOptions
()
hideUpdateAvatarOptions
()
}
}
...
...
app/src/main/java/chat/rocket/android/push/PushManager.kt
View file @
0e76e49a
...
@@ -296,11 +296,8 @@ class PushManager @Inject constructor(
...
@@ -296,11 +296,8 @@ class PushManager @Inject constructor(
}
}
private
fun
getContentIntent
(
context
:
Context
,
notificationId
:
Int
,
pushMessage
:
PushMessage
,
grouped
:
Boolean
=
false
):
PendingIntent
{
private
fun
getContentIntent
(
context
:
Context
,
notificationId
:
Int
,
pushMessage
:
PushMessage
,
grouped
:
Boolean
=
false
):
PendingIntent
{
val
notificationIntent
=
context
.
changeServerIntent
(
pushMessage
.
info
.
host
,
chatRoomId
=
pushMessage
.
info
.
roomId
)
val
roomId
=
if
(!
grouped
)
pushMessage
.
info
.
roomId
else
null
// TODO - add support to go directly to the chatroom
val
notificationIntent
=
context
.
changeServerIntent
(
pushMessage
.
info
.
host
,
chatRoomId
=
roomId
)
/*if (!isGrouped) {
notificationIntent.putExtra(EXTRA_ROOM_ID, pushMessage.info.roomId)
}*/
return
PendingIntent
.
getActivity
(
context
,
random
.
nextInt
(),
notificationIntent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
)
return
PendingIntent
.
getActivity
(
context
,
random
.
nextInt
(),
notificationIntent
,
PendingIntent
.
FLAG_UPDATE_CURRENT
)
}
}
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/ConnectionManager.kt
View file @
0e76e49a
...
@@ -22,6 +22,7 @@ import chat.rocket.core.internal.realtime.unsubscribe
...
@@ -22,6 +22,7 @@ import chat.rocket.core.internal.realtime.unsubscribe
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
chat.rocket.core.model.Myself
import
chat.rocket.core.model.Room
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.experimental.Job
import
kotlinx.coroutines.experimental.channels.Channel
import
kotlinx.coroutines.experimental.channels.Channel
...
@@ -45,6 +46,7 @@ class ConnectionManager(
...
@@ -45,6 +46,7 @@ class ConnectionManager(
private
val
roomMessagesChannels
=
LinkedHashMap
<
String
,
Channel
<
Message
>>()
private
val
roomMessagesChannels
=
LinkedHashMap
<
String
,
Channel
<
Message
>>()
private
val
userDataChannels
=
ArrayList
<
Channel
<
Myself
>>()
private
val
userDataChannels
=
ArrayList
<
Channel
<
Myself
>>()
private
val
roomsChannels
=
LinkedHashMap
<
String
,
Channel
<
Room
>>()
private
val
subscriptionIdMap
=
HashMap
<
String
,
String
>()
private
val
subscriptionIdMap
=
HashMap
<
String
,
String
>()
private
var
subscriptionId
:
String
?
=
null
private
var
subscriptionId
:
String
?
=
null
...
@@ -127,6 +129,18 @@ class ConnectionManager(
...
@@ -127,6 +129,18 @@ class ConnectionManager(
maxSize
=
10
)
{
batch
->
maxSize
=
10
)
{
batch
->
Timber
.
d
(
"processing Stream batch: ${batch.size} - $batch"
)
Timber
.
d
(
"processing Stream batch: ${batch.size} - $batch"
)
dbManager
.
processChatRoomsBatch
(
batch
)
dbManager
.
processChatRoomsBatch
(
batch
)
batch
.
forEach
{
//TODO - Do we need to handle Type.Removed and Type.Inserted here?
if
(
it
.
type
==
Type
.
Updated
)
{
if
(
it
.
data
is
Room
)
{
val
room
=
it
.
data
as
Room
roomsChannels
[
it
.
data
.
id
]
?.
let
{
channel
->
channel
.
offer
(
room
)
}
}
}
}
}
}
val
messagesActor
=
createBatchActor
<
Message
>(
messagesContext
,
parent
=
connectJob
,
val
messagesActor
=
createBatchActor
<
Message
>(
messagesContext
,
parent
=
connectJob
,
...
@@ -241,6 +255,14 @@ class ConnectionManager(
...
@@ -241,6 +255,14 @@ class ConnectionManager(
fun
removeUserDataChannel
(
channel
:
Channel
<
Myself
>)
=
userDataChannels
.
remove
(
channel
)
fun
removeUserDataChannel
(
channel
:
Channel
<
Myself
>)
=
userDataChannels
.
remove
(
channel
)
fun
addRoomChannel
(
roomId
:
String
,
channel
:
Channel
<
Room
>)
{
roomsChannels
[
roomId
]
=
channel
}
fun
removeRoomChannel
(
roomId
:
String
)
{
roomsChannels
.
remove
(
roomId
)
}
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
)
{
...
...
app/src/main/java/chat/rocket/android/server/infraestructure/DatabaseMessageMapper.kt
View file @
0e76e49a
...
@@ -7,6 +7,7 @@ import chat.rocket.android.db.model.FullMessage
...
@@ -7,6 +7,7 @@ import chat.rocket.android.db.model.FullMessage
import
chat.rocket.android.db.model.ReactionEntity
import
chat.rocket.android.db.model.ReactionEntity
import
chat.rocket.android.db.model.UrlEntity
import
chat.rocket.android.db.model.UrlEntity
import
chat.rocket.android.db.model.UserEntity
import
chat.rocket.android.db.model.UserEntity
import
chat.rocket.android.util.retryDB
import
chat.rocket.common.model.SimpleRoom
import
chat.rocket.common.model.SimpleRoom
import
chat.rocket.common.model.SimpleUser
import
chat.rocket.common.model.SimpleUser
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
...
@@ -135,14 +136,18 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -135,14 +136,18 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
with
(
attachment
)
{
with
(
attachment
)
{
val
fields
=
if
(
hasFields
)
{
val
fields
=
if
(
hasFields
)
{
withContext
(
CommonPool
)
{
withContext
(
CommonPool
)
{
retryDB
(
"getAttachmentFields(${attachment._id})"
)
{
dbManager
.
messageDao
().
getAttachmentFields
(
attachment
.
_id
)
dbManager
.
messageDao
().
getAttachmentFields
(
attachment
.
_id
)
}
}.
map
{
Field
(
it
.
title
,
it
.
value
)
}
}.
map
{
Field
(
it
.
title
,
it
.
value
)
}
}
else
{
}
else
{
null
null
}
}
val
actions
=
if
(
hasActions
)
{
val
actions
=
if
(
hasActions
)
{
withContext
(
CommonPool
)
{
withContext
(
CommonPool
)
{
retryDB
(
"getAttachmentActions(${attachment._id})"
)
{
dbManager
.
messageDao
().
getAttachmentActions
(
attachment
.
_id
)
dbManager
.
messageDao
().
getAttachmentActions
(
attachment
.
_id
)
}
}.
mapNotNull
{
mapAction
(
it
)
}
}.
mapNotNull
{
mapAction
(
it
)
}
}
else
{
}
else
{
null
null
...
@@ -183,29 +188,6 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -183,29 +188,6 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
return
list
return
list
}
}
/*private suspend fun mapColorAttachmentWithFields(entity: AttachmentEntity): ColorAttachment {
val fields = withContext(CommonPool) {
dbManager.messageDao().getAttachmentFields(entity._id)
}.map { Field(it.title, it.value) }
return with(entity) {
ColorAttachment(
color = Color.Custom(color ?: DEFAULT_COLOR_STR),
text = text ?: "",
fallback = fallback,
fields = fields)
}
}
private suspend fun mapActionAttachment(attachment: AttachmentEntity): ActionsAttachment {
val actions = withContext(CommonPool) {
dbManager.messageDao().getAttachmentActions(attachment._id)
}.mapNotNull { mapAction(it) }
return with(attachment) {
// TODO - remove the default "vertical" value from here...
ActionsAttachment(title, actions, buttonAlignment ?: "vertical")
}
}*/
private
fun
mapAction
(
action
:
AttachmentActionEntity
):
Action
?
{
private
fun
mapAction
(
action
:
AttachmentActionEntity
):
Action
?
{
return
when
(
action
.
type
)
{
return
when
(
action
.
type
)
{
"button"
->
ButtonAction
(
action
.
type
,
action
.
text
,
action
.
url
,
action
.
isWebView
,
"button"
->
ButtonAction
(
action
.
type
,
action
.
text
,
action
.
url
,
action
.
isWebView
,
...
@@ -214,13 +196,4 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
...
@@ -214,13 +196,4 @@ class DatabaseMessageMapper(private val dbManager: DatabaseManager) {
else
->
null
else
->
null
}
}
}
}
/*private suspend fun mapAuthorAttachment(attachment: AttachmentEntity): AuthorAttachment {
val fields = withContext(CommonPool) {
dbManager.messageDao().getAttachmentFields(attachment._id)
}.map { Field(it.title, it.value) }
return with(attachment) {
AuthorAttachment(authorLink!!, authorIcon, authorName, fields)
}
}*/
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/server/infraestructure/DatabaseMessagesRepository.kt
View file @
0e76e49a
...
@@ -4,6 +4,7 @@ import chat.rocket.android.db.DatabaseManager
...
@@ -4,6 +4,7 @@ import chat.rocket.android.db.DatabaseManager
import
chat.rocket.android.db.Operation
import
chat.rocket.android.db.Operation
import
chat.rocket.android.db.model.MessagesSync
import
chat.rocket.android.db.model.MessagesSync
import
chat.rocket.android.server.domain.MessagesRepository
import
chat.rocket.android.server.domain.MessagesRepository
import
chat.rocket.android.util.retryDB
import
chat.rocket.core.model.Message
import
chat.rocket.core.model.Message
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.CommonPool
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.withContext
...
@@ -14,26 +15,32 @@ class DatabaseMessagesRepository(
...
@@ -14,26 +15,32 @@ class DatabaseMessagesRepository(
)
:
MessagesRepository
{
)
:
MessagesRepository
{
override
suspend
fun
getById
(
id
:
String
):
Message
?
=
withContext
(
CommonPool
)
{
override
suspend
fun
getById
(
id
:
String
):
Message
?
=
withContext
(
CommonPool
)
{
retryDB
(
"getMessageById($id)"
)
{
dbManager
.
messageDao
().
getMessageById
(
id
)
?.
let
{
message
->
mapper
.
map
(
message
)
}
dbManager
.
messageDao
().
getMessageById
(
id
)
?.
let
{
message
->
mapper
.
map
(
message
)
}
}
}
}
override
suspend
fun
getByRoomId
(
roomId
:
String
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getByRoomId
(
roomId
:
String
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
// FIXME - investigate how to avoid this distinctBy here, since DAO is returning a lot of
// FIXME - investigate how to avoid this distinctBy here, since DAO is returning a lot of
// duplicate rows (something related to our JOINS and relations on Room)
// duplicate rows (something related to our JOINS and relations on Room)
retryDB
(
"getMessagesByRoomId($roomId)"
)
{
dbManager
.
messageDao
().
getMessagesByRoomId
(
roomId
)
dbManager
.
messageDao
().
getMessagesByRoomId
(
roomId
)
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
messages
->
.
let
{
messages
->
mapper
.
map
(
messages
)
mapper
.
map
(
messages
)
}
}
}
}
}
override
suspend
fun
getRecentMessages
(
roomId
:
String
,
count
:
Long
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getRecentMessages
(
roomId
:
String
,
count
:
Long
):
List
<
Message
>
=
withContext
(
CommonPool
)
{
retryDB
(
"getRecentMessagesByRoomId($roomId, $count)"
)
{
dbManager
.
messageDao
().
getRecentMessagesByRoomId
(
roomId
,
count
)
dbManager
.
messageDao
().
getRecentMessagesByRoomId
(
roomId
,
count
)
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
messages
->
.
let
{
messages
->
mapper
.
map
(
messages
)
mapper
.
map
(
messages
)
}
}
}
}
}
override
suspend
fun
save
(
message
:
Message
)
{
override
suspend
fun
save
(
message
:
Message
)
{
dbManager
.
processMessagesBatch
(
listOf
(
message
)).
join
()
dbManager
.
processMessagesBatch
(
listOf
(
message
)).
join
()
...
@@ -45,27 +52,33 @@ class DatabaseMessagesRepository(
...
@@ -45,27 +52,33 @@ class DatabaseMessagesRepository(
override
suspend
fun
removeById
(
id
:
String
)
{
override
suspend
fun
removeById
(
id
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
CommonPool
)
{
dbManager
.
messageDao
().
delete
(
id
)
retryDB
(
"delete($id)"
)
{
dbManager
.
messageDao
().
delete
(
id
)
}
}
}
}
}
override
suspend
fun
removeByRoomId
(
roomId
:
String
)
{
override
suspend
fun
removeByRoomId
(
roomId
:
String
)
{
withContext
(
CommonPool
)
{
withContext
(
CommonPool
)
{
retryDB
(
"deleteByRoomId($roomId)"
)
{
dbManager
.
messageDao
().
deleteByRoomId
(
roomId
)
dbManager
.
messageDao
().
deleteByRoomId
(
roomId
)
}
}
}
}
}
override
suspend
fun
getAllUnsent
():
List
<
Message
>
=
withContext
(
CommonPool
)
{
override
suspend
fun
getAllUnsent
():
List
<
Message
>
=
withContext
(
CommonPool
)
{
retryDB
(
"getUnsentMessages"
)
{
dbManager
.
messageDao
().
getUnsentMessages
()
dbManager
.
messageDao
().
getUnsentMessages
()
.
distinctBy
{
it
.
message
.
message
.
id
}
.
distinctBy
{
it
.
message
.
message
.
id
}
.
let
{
mapper
.
map
(
it
)
}
.
let
{
mapper
.
map
(
it
)
}
}
}
}
override
suspend
fun
saveLastSyncDate
(
roomId
:
String
,
timeMillis
:
Long
)
{
override
suspend
fun
saveLastSyncDate
(
roomId
:
String
,
timeMillis
:
Long
)
{
dbManager
.
sendOperation
(
Operation
.
SaveLastSync
(
MessagesSync
(
roomId
,
timeMillis
)))
dbManager
.
sendOperation
(
Operation
.
SaveLastSync
(
MessagesSync
(
roomId
,
timeMillis
)))
}
}
override
suspend
fun
getLastSyncDate
(
roomId
:
String
):
Long
?
=
withContext
(
CommonPool
)
{
override
suspend
fun
getLastSyncDate
(
roomId
:
String
):
Long
?
=
withContext
(
CommonPool
)
{
retryDB
(
"getLastSync($roomId)"
)
{
dbManager
.
messageDao
().
getLastSync
(
roomId
)
?.
let
{
it
.
timestamp
}
dbManager
.
messageDao
().
getLastSync
(
roomId
)
?.
let
{
it
.
timestamp
}
}
}
}
}
}
\ No newline at end of file
app/src/main/java/chat/rocket/android/util/IO.kt
View file @
0e76e49a
package
chat.rocket.android.util
package
chat.rocket.android.util
import
android.database.sqlite.SQLiteDatabaseLockedException
import
chat.rocket.common.RocketChatNetworkErrorException
import
chat.rocket.common.RocketChatNetworkErrorException
import
kotlinx.coroutines.experimental.TimeoutCancellationException
import
kotlinx.coroutines.experimental.TimeoutCancellationException
import
kotlinx.coroutines.experimental.delay
import
kotlinx.coroutines.experimental.delay
...
@@ -8,6 +9,7 @@ import timber.log.Timber
...
@@ -8,6 +9,7 @@ import timber.log.Timber
import
kotlin.coroutines.experimental.coroutineContext
import
kotlin.coroutines.experimental.coroutineContext
const
val
DEFAULT_RETRY
=
3
const
val
DEFAULT_RETRY
=
3
private
const
val
DEFAULT_DB_RETRY
=
5
suspend
fun
<
T
>
retryIO
(
suspend
fun
<
T
>
retryIO
(
description
:
String
=
"<missing description>"
,
description
:
String
=
"<missing description>"
,
...
@@ -35,3 +37,30 @@ suspend fun <T> retryIO(
...
@@ -35,3 +37,30 @@ suspend fun <T> retryIO(
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled"
)
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled"
)
return
block
()
// last attempt
return
block
()
// last attempt
}
}
suspend
fun
<
T
>
retryDB
(
description
:
String
=
"<missing description>"
,
times
:
Int
=
DEFAULT_DB_RETRY
,
initialDelay
:
Long
=
100
,
// 0.1 second
maxDelay
:
Long
=
500
,
// 0.5 second
factor
:
Double
=
1.2
,
block
:
suspend
()
->
T
):
T
{
var
currentDelay
=
initialDelay
repeat
(
times
-
1
)
{
currentTry
->
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled"
)
try
{
return
block
()
}
catch
(
e
:
SQLiteDatabaseLockedException
)
{
Timber
.
d
(
e
,
"failed call($currentTry): $description"
)
e
.
printStackTrace
()
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled"
)
delay
(
currentDelay
)
currentDelay
=
(
currentDelay
*
factor
).
toLong
().
coerceAtMost
(
maxDelay
)
}
if
(!
coroutineContext
.
isActive
)
throw
TimeoutCancellationException
(
"job canceled"
)
return
block
()
// last attempt
}
\ No newline at end of file
app/src/main/res/layout/message_attachment_options.xml
View file @
0e76e49a
...
@@ -6,14 +6,24 @@
...
@@ -6,14 +6,24 @@
android:orientation=
"vertical"
>
android:orientation=
"vertical"
>
<Button
<Button
android:id=
"@+id/button_files"
android:id=
"@+id/button_take_a_photo"
style=
"?android:attr/borderlessButtonStyle"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:drawablePadding=
"20dp"
android:drawableStart=
"@drawable/ic_photo_camera_black_24dp"
android:gravity=
"start|center"
android:text=
"@string/action_take_a_photo"
/>
<Button
android:id=
"@+id/button_attach_a_file"
style=
"?android:attr/borderlessButtonStyle"
style=
"?android:attr/borderlessButtonStyle"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:drawablePadding=
"20dp"
android:drawablePadding=
"20dp"
android:drawableStart=
"@drawable/ic_files_24dp"
android:drawableStart=
"@drawable/ic_files_24dp"
android:gravity=
"start|center"
android:gravity=
"start|center"
android:text=
"@string/action_files"
/>
android:text=
"@string/action_
attach_a_
files"
/>
<Button
<Button
android:id=
"@+id/button_drawing"
android:id=
"@+id/button_drawing"
...
...
app/src/main/res/layout/update_avatar_options.xml
View file @
0e76e49a
...
@@ -16,14 +16,14 @@
...
@@ -16,14 +16,14 @@
android:text=
"@string/action_select_photo_from_gallery"
/>
android:text=
"@string/action_select_photo_from_gallery"
/>
<Button
<Button
android:id=
"@+id/button_take_photo"
android:id=
"@+id/button_take_
a_
photo"
style=
"?android:attr/borderlessButtonStyle"
style=
"?android:attr/borderlessButtonStyle"
android:layout_width=
"match_parent"
android:layout_width=
"match_parent"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:drawableStart=
"@drawable/ic_photo_camera_black_24dp"
android:drawableStart=
"@drawable/ic_photo_camera_black_24dp"
android:drawablePadding=
"20dp"
android:drawablePadding=
"20dp"
android:gravity=
"start|center"
android:gravity=
"start|center"
android:text=
"@string/action_take_photo"
/>
android:text=
"@string/action_take_
a_
photo"
/>
<Button
<Button
android:id=
"@+id/button_reset_avatar"
android:id=
"@+id/button_reset_avatar"
...
...
app/src/main/res/values-de/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Erstelle Raum
</string>
<string
name=
"action_create_channel"
>
Erstelle Raum
</string>
<string
name=
"action_create"
>
Erstelle
</string>
<string
name=
"action_create"
>
Erstelle
</string>
<string
name=
"action_logout"
>
Abmelden
</string>
<string
name=
"action_logout"
>
Abmelden
</string>
<string
name=
"action_
files"
>
Dateien
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Bestätige Passwort Änderung
</string>
<string
name=
"action_confirm_password"
>
Bestätige Passwort Änderung
</string>
<string
name=
"action_join_chat"
>
Trete Chat bei
</string>
<string
name=
"action_join_chat"
>
Trete Chat bei
</string>
<string
name=
"action_add_account"
>
Erstelle Account
</string>
<string
name=
"action_add_account"
>
Erstelle Account
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Zeichnung
</string>
<string
name=
"action_drawing"
>
Zeichnung
</string>
<string
name=
"action_save_to_gallery"
>
Sichern in Gallerie
</string>
<string
name=
"action_save_to_gallery"
>
Sichern in Gallerie
</string>
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<!-- TODO Add translation -->
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<!-- TODO Add translation -->
<string
name=
"action_take_
photo"
>
Select photo from gal
lery
</string>
<!-- TODO Add translation -->
<string
name=
"action_take_
a_photo"
>
Take a photo from ga
lery
</string>
<!-- TODO Add translation -->
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<!-- TODO Add translation -->
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
...
...
app/src/main/res/values-es/strings.xml
View file @
0e76e49a
...
@@ -38,7 +38,7 @@
...
@@ -38,7 +38,7 @@
<string
name=
"action_create_channel"
>
Crear canal
</string>
<string
name=
"action_create_channel"
>
Crear canal
</string>
<string
name=
"action_create"
>
Create
</string>
<string
name=
"action_create"
>
Create
</string>
<string
name=
"action_logout"
>
Cerrar sesión
</string>
<string
name=
"action_logout"
>
Cerrar sesión
</string>
<string
name=
"action_
files"
>
Archivos
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Confirmar cambio de contraseña
</string>
<string
name=
"action_confirm_password"
>
Confirmar cambio de contraseña
</string>
<string
name=
"action_join_chat"
>
Unirse al chat
</string>
<string
name=
"action_join_chat"
>
Unirse al chat
</string>
<string
name=
"action_add_account"
>
Añadir cuenta
</string>
<string
name=
"action_add_account"
>
Añadir cuenta
</string>
...
@@ -49,7 +49,7 @@
...
@@ -49,7 +49,7 @@
<string
name=
"action_drawing"
>
Dibujo
</string>
<string
name=
"action_drawing"
>
Dibujo
</string>
<string
name=
"action_save_to_gallery"
>
Guardar en la galería
</string>
<string
name=
"action_save_to_gallery"
>
Guardar en la galería
</string>
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<!-- TODO Add translation -->
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<!-- TODO Add translation -->
<string
name=
"action_take_
photo"
>
Select photo from gallery
</string>
<!-- TODO Add translation -->
<string
name=
"action_take_
a_photo"
>
Take a photo
</string>
<!-- TODO Add translation -->
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<!-- TODO Add translation -->
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
...
...
app/src/main/res/values-fr/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Créer salon
</string>
<string
name=
"action_create_channel"
>
Créer salon
</string>
<string
name=
"action_create"
>
Créer
</string>
<string
name=
"action_create"
>
Créer
</string>
<string
name=
"action_logout"
>
Se déconnecter
</string>
<string
name=
"action_logout"
>
Se déconnecter
</string>
<string
name=
"action_
files"
>
Fichiers
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Confirmer le mot de passe
</string>
<string
name=
"action_confirm_password"
>
Confirmer le mot de passe
</string>
<string
name=
"action_join_chat"
>
Rejoignez le chat
</string>
<string
name=
"action_join_chat"
>
Rejoignez le chat
</string>
<string
name=
"action_add_account"
>
Ajouter un compte
</string>
<string
name=
"action_add_account"
>
Ajouter un compte
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Dessin
</string>
<string
name=
"action_drawing"
>
Dessin
</string>
<string
name=
"action_save_to_gallery"
>
Sauvegarder vers la gallerie
</string>
<string
name=
"action_save_to_gallery"
>
Sauvegarder vers la gallerie
</string>
<string
name=
"action_select_photo_from_gallery"
>
Sélectionner depuis la gallerie
</string>
<string
name=
"action_select_photo_from_gallery"
>
Sélectionner depuis la gallerie
</string>
<string
name=
"action_take_photo"
>
Prendre une photo
</string>
<string
name=
"action_take_
a_
photo"
>
Prendre une photo
</string>
<string
name=
"action_reset_avatar"
>
Réinitialiser l\'avatar
</string>
<string
name=
"action_reset_avatar"
>
Réinitialiser l\'avatar
</string>
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
...
...
app/src/main/res/values-hi-rIN/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
चैनल बनाएं
</string>
<string
name=
"action_create_channel"
>
चैनल बनाएं
</string>
<string
name=
"action_create"
>
बनाएं
</string>
<string
name=
"action_create"
>
बनाएं
</string>
<string
name=
"action_logout"
>
लोग आउट करें
</string>
<string
name=
"action_logout"
>
लोग आउट करें
</string>
<string
name=
"action_
files"
>
फ़ाइलें
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
पासवर्ड परिवर्तन की पुष्टि करें
</string>
<string
name=
"action_confirm_password"
>
पासवर्ड परिवर्तन की पुष्टि करें
</string>
<string
name=
"action_join_chat"
>
चैट में शामिल हों
</string>
<string
name=
"action_join_chat"
>
चैट में शामिल हों
</string>
<string
name=
"action_add_account"
>
खाता जोड़ो
</string>
<string
name=
"action_add_account"
>
खाता जोड़ो
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_save_to_gallery"
>
गैलरी में सहेजें
</string>
<string
name=
"action_save_to_gallery"
>
गैलरी में सहेजें
</string>
<string
name=
"action_drawing"
>
चित्रकारी
</string>
<string
name=
"action_drawing"
>
चित्रकारी
</string>
<string
name=
"action_select_photo_from_gallery"
>
गैलरी से फोटो का चयन करें
</string>
<string
name=
"action_select_photo_from_gallery"
>
गैलरी से फोटो का चयन करें
</string>
<string
name=
"action_take_photo"
>
फोटो खेचिये
</string>
<string
name=
"action_take_
a_
photo"
>
फोटो खेचिये
</string>
<string
name=
"action_reset_avatar"
>
अवतार रीसेट करें
</string>
<string
name=
"action_reset_avatar"
>
अवतार रीसेट करें
</string>
<string
name=
"action_connect_server"
>
सर्वर से कनेक्ट करें
</string>
<string
name=
"action_connect_server"
>
सर्वर से कनेक्ट करें
</string>
<string
name=
"action_join_community"
>
समुदाय में शामिल हों
</string>
<string
name=
"action_join_community"
>
समुदाय में शामिल हों
</string>
...
...
app/src/main/res/values-it/strings.xml
0 → 100644
View file @
0e76e49a
This diff is collapsed.
Click to expand it.
app/src/main/res/values-ja/strings.xml
View file @
0e76e49a
...
@@ -41,7 +41,7 @@
...
@@ -41,7 +41,7 @@
<string
name=
"action_create_channel"
>
チャンネル作成
</string>
<string
name=
"action_create_channel"
>
チャンネル作成
</string>
<string
name=
"action_create"
>
作ります
</string>
<string
name=
"action_create"
>
作ります
</string>
<string
name=
"action_logout"
>
ログアウト
</string>
<string
name=
"action_logout"
>
ログアウト
</string>
<string
name=
"action_
files"
>
ファイル
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
変更したパスワードの確認
</string>
<string
name=
"action_confirm_password"
>
変更したパスワードの確認
</string>
<string
name=
"action_join_chat"
>
チャットに参加
</string>
<string
name=
"action_join_chat"
>
チャットに参加
</string>
<string
name=
"action_add_account"
>
サーバーの追加
</string>
<string
name=
"action_add_account"
>
サーバーの追加
</string>
...
@@ -52,7 +52,7 @@
...
@@ -52,7 +52,7 @@
<string
name=
"action_drawing"
>
絵を描く
</string>
<string
name=
"action_drawing"
>
絵を描く
</string>
<string
name=
"action_save_to_gallery"
>
ギャラリーに保存
</string>
<string
name=
"action_save_to_gallery"
>
ギャラリーに保存
</string>
<string
name=
"action_select_photo_from_gallery"
>
ギャラリーの写真を選択
</string>
<string
name=
"action_select_photo_from_gallery"
>
ギャラリーの写真を選択
</string>
<string
name=
"action_take_photo"
>
写真を撮る
</string>
<string
name=
"action_take_
a_
photo"
>
写真を撮る
</string>
<string
name=
"action_reset_avatar"
>
アバターをリセット
</string>
<string
name=
"action_reset_avatar"
>
アバターをリセット
</string>
<string
name=
"action_connect_server"
>
サーバーに接続
</string>
<string
name=
"action_connect_server"
>
サーバーに接続
</string>
<string
name=
"action_join_community"
>
コミュニティに参加
</string>
<string
name=
"action_join_community"
>
コミュニティに参加
</string>
...
...
app/src/main/res/values-pt-rBR/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Criar chat
</string>
<string
name=
"action_create_channel"
>
Criar chat
</string>
<string
name=
"action_create"
>
Criar
</string>
<string
name=
"action_create"
>
Criar
</string>
<string
name=
"action_logout"
>
Sair
</string>
<string
name=
"action_logout"
>
Sair
</string>
<string
name=
"action_
files"
>
Arquivos
</string>
<string
name=
"action_
attach_a_files"
>
Anexar um arquivo
</string>
<string
name=
"action_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"action_confirm_password"
>
Confirme a nova senha
</string>
<string
name=
"action_join_chat"
>
Entrar no Chat
</string>
<string
name=
"action_join_chat"
>
Entrar no Chat
</string>
<string
name=
"action_add_account"
>
Adicionar conta
</string>
<string
name=
"action_add_account"
>
Adicionar conta
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Desenhando
</string>
<string
name=
"action_drawing"
>
Desenhando
</string>
<string
name=
"action_save_to_gallery"
>
Salvar na galeria
</string>
<string
name=
"action_save_to_gallery"
>
Salvar na galeria
</string>
<string
name=
"action_select_photo_from_gallery"
>
Escolher foto da galeria
</string>
<string
name=
"action_select_photo_from_gallery"
>
Escolher foto da galeria
</string>
<string
name=
"action_take_
photo"
>
Tirar
foto
</string>
<string
name=
"action_take_
a_photo"
>
Tirar uma
foto
</string>
<string
name=
"action_reset_avatar"
>
Resetar avatar
</string>
<string
name=
"action_reset_avatar"
>
Resetar avatar
</string>
<string
name=
"action_connect_server"
>
Conectar com um servidor
</string>
<string
name=
"action_connect_server"
>
Conectar com um servidor
</string>
<string
name=
"action_join_community"
>
Junte-se à comunidade
</string>
<string
name=
"action_join_community"
>
Junte-se à comunidade
</string>
...
...
app/src/main/res/values-ru-rRU/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Создать канал
</string>
<string
name=
"action_create_channel"
>
Создать канал
</string>
<string
name=
"action_create"
>
Создать
</string>
<string
name=
"action_create"
>
Создать
</string>
<string
name=
"action_logout"
>
Выйти
</string>
<string
name=
"action_logout"
>
Выйти
</string>
<string
name=
"action_
files"
>
Файлы
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Подтверждение изменения пароля
</string>
<string
name=
"action_confirm_password"
>
Подтверждение изменения пароля
</string>
<string
name=
"action_join_chat"
>
Присоединиться к чату
</string>
<string
name=
"action_join_chat"
>
Присоединиться к чату
</string>
<string
name=
"action_add_account"
>
Добавить аккаунт
</string>
<string
name=
"action_add_account"
>
Добавить аккаунт
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Рисунок
</string>
<string
name=
"action_drawing"
>
Рисунок
</string>
<string
name=
"action_save_to_gallery"
>
Сохранить в галерею
</string>
<string
name=
"action_save_to_gallery"
>
Сохранить в галерею
</string>
<string
name=
"action_select_photo_from_gallery"
>
Выбрать из галереи
</string>
<string
name=
"action_select_photo_from_gallery"
>
Выбрать из галереи
</string>
<string
name=
"action_take_photo"
>
Сделать снимок
</string>
<string
name=
"action_take_
a_
photo"
>
Сделать снимок
</string>
<string
name=
"action_reset_avatar"
>
Восстановить аватар
</string>
<string
name=
"action_reset_avatar"
>
Восстановить аватар
</string>
<string
name=
"action_connect_server"
>
Соединиться с сервером
</string>
<string
name=
"action_connect_server"
>
Соединиться с сервером
</string>
<string
name=
"action_join_community"
>
Сообщество
</string>
<string
name=
"action_join_community"
>
Сообщество
</string>
...
...
app/src/main/res/values-tr/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Yeni Kanal Oluştur
</string>
<string
name=
"action_create_channel"
>
Yeni Kanal Oluştur
</string>
<string
name=
"action_create"
>
Oluştur
</string>
<string
name=
"action_create"
>
Oluştur
</string>
<string
name=
"action_logout"
>
Çıkış Yap
</string>
<string
name=
"action_logout"
>
Çıkış Yap
</string>
<string
name=
"action_
files"
>
Dosyalar
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Şifre Değişikliğini Onaylayın
</string>
<string
name=
"action_confirm_password"
>
Şifre Değişikliğini Onaylayın
</string>
<string
name=
"action_join_chat"
>
Sohbete Bağlan
</string>
<string
name=
"action_join_chat"
>
Sohbete Bağlan
</string>
<string
name=
"action_add_account"
>
Hesap Ekle
</string>
<string
name=
"action_add_account"
>
Hesap Ekle
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Çizim
</string>
<string
name=
"action_drawing"
>
Çizim
</string>
<string
name=
"action_save_to_gallery"
>
Galeriye kaydet
</string>
<string
name=
"action_save_to_gallery"
>
Galeriye kaydet
</string>
<string
name=
"action_select_photo_from_gallery"
>
Galeriden resim seç
</string>
<string
name=
"action_select_photo_from_gallery"
>
Galeriden resim seç
</string>
<string
name=
"action_take_photo"
>
Fotoğraf çek
</string>
<string
name=
"action_take_
a_
photo"
>
Fotoğraf çek
</string>
<string
name=
"action_reset_avatar"
>
Avatarı kaldır
</string>
<string
name=
"action_reset_avatar"
>
Avatarı kaldır
</string>
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
...
...
app/src/main/res/values-uk/strings.xml
View file @
0e76e49a
...
@@ -39,7 +39,7 @@
...
@@ -39,7 +39,7 @@
<string
name=
"action_create_channel"
>
Створити канал
</string>
<string
name=
"action_create_channel"
>
Створити канал
</string>
<string
name=
"action_create"
>
Створити
</string>
<string
name=
"action_create"
>
Створити
</string>
<string
name=
"action_logout"
>
Вийти
</string>
<string
name=
"action_logout"
>
Вийти
</string>
<string
name=
"action_
files"
>
Файли
</string
>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<!-- TODO Add translation --
>
<string
name=
"action_confirm_password"
>
Підтвердження зміни пароля
</string>
<string
name=
"action_confirm_password"
>
Підтвердження зміни пароля
</string>
<string
name=
"action_join_chat"
>
Приєднатися до чату
</string>
<string
name=
"action_join_chat"
>
Приєднатися до чату
</string>
<string
name=
"action_add_account"
>
Додати аккаунт
</string>
<string
name=
"action_add_account"
>
Додати аккаунт
</string>
...
@@ -50,7 +50,7 @@
...
@@ -50,7 +50,7 @@
<string
name=
"action_drawing"
>
Малюнок
</string>
<string
name=
"action_drawing"
>
Малюнок
</string>
<string
name=
"action_save_to_gallery"
>
Зберегти до галереї
</string>
<string
name=
"action_save_to_gallery"
>
Зберегти до галереї
</string>
<string
name=
"action_select_photo_from_gallery"
>
Вибрати з галереї
</string>
<string
name=
"action_select_photo_from_gallery"
>
Вибрати з галереї
</string>
<string
name=
"action_take_photo"
>
Зробити знімок
</string>
<string
name=
"action_take_
a_
photo"
>
Зробити знімок
</string>
<string
name=
"action_reset_avatar"
>
Відновити аватар
</string>
<string
name=
"action_reset_avatar"
>
Відновити аватар
</string>
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
<string
name=
"action_join_community"
>
Join in the community
</string>
<!-- TODO Add translation -->
...
...
app/src/main/res/values/strings.xml
View file @
0e76e49a
...
@@ -51,7 +51,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
...
@@ -51,7 +51,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string
name=
"action_create_channel"
>
Create channel
</string>
<string
name=
"action_create_channel"
>
Create channel
</string>
<string
name=
"action_create"
>
Create
</string>
<string
name=
"action_create"
>
Create
</string>
<string
name=
"action_logout"
>
Logout
</string>
<string
name=
"action_logout"
>
Logout
</string>
<string
name=
"action_
files"
>
Files
</string>
<string
name=
"action_
attach_a_files"
>
Attach a file
</string>
<string
name=
"action_confirm_password"
>
Confirm Password Change
</string>
<string
name=
"action_confirm_password"
>
Confirm Password Change
</string>
<string
name=
"action_join_chat"
>
Join Chat
</string>
<string
name=
"action_join_chat"
>
Join Chat
</string>
<string
name=
"action_add_account"
>
Add account
</string>
<string
name=
"action_add_account"
>
Add account
</string>
...
@@ -62,7 +62,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
...
@@ -62,7 +62,7 @@ https://github.com/RocketChat/java-code-styles/blob/master/CODING_STYLE.md#strin
<string
name=
"action_drawing"
>
Drawing
</string>
<string
name=
"action_drawing"
>
Drawing
</string>
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<string
name=
"action_save_to_gallery"
>
Save to gallery
</string>
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<string
name=
"action_select_photo_from_gallery"
>
Select photo from gallery
</string>
<string
name=
"action_take_
photo"
>
Take
photo
</string>
<string
name=
"action_take_
a_photo"
>
Take a
photo
</string>
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<string
name=
"action_reset_avatar"
>
Reset avatar
</string>
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<string
name=
"action_connect_server"
>
Connect with a server
</string>
<string
name=
"action_join_community"
>
Join in the community
</string>
<string
name=
"action_join_community"
>
Join in the community
</string>
...
...
app/src/main/res/xml/file_paths.xml
0 → 100644
View file @
0e76e49a
<?xml version="1.0" encoding="utf-8"?>
<paths>
<external-path
name=
"rocket_chat_images"
path=
"Android/data/chat.rocket.android/files/Pictures"
/>
</paths>
\ No newline at end of file
app/src/play/java/chat/rocket/android/push/FirebaseMessagingService.kt
View file @
0e76e49a
package
chat.rocket.android.push
package
chat.rocket.android.push
import
android.os.Bundle
import
androidx.core.os.bundleOf
import
androidx.core.os.bundleOf
import
androidx.work.Constraints
import
androidx.work.Constraints
import
androidx.work.NetworkType
import
androidx.work.NetworkType
...
@@ -23,9 +24,12 @@ class FirebaseMessagingService : FirebaseMessagingService() {
...
@@ -23,9 +24,12 @@ class FirebaseMessagingService : FirebaseMessagingService() {
}
}
override
fun
onMessageReceived
(
message
:
RemoteMessage
)
{
override
fun
onMessageReceived
(
message
:
RemoteMessage
)
{
// XXX - for now this is ok, if we start to do network calls, use a Worker instead
message
.
data
?.
let
{
data
->
message
.
data
?.
let
{
val
bundle
=
Bundle
()
pushManager
.
handle
(
bundleOf
(*(
it
.
map
{
Pair
(
it
.
key
,
it
.
value
)
}).
toTypedArray
()))
data
.
entries
.
forEach
{
entry
->
bundle
.
putString
(
entry
.
key
,
entry
.
value
)
}
pushManager
.
handle
(
bundle
)
}
}
}
}
...
...
emoji/src/main/java/chat/rocket/android/emoji/EmojiKeyboardPopup.kt
View file @
0e76e49a
...
@@ -10,7 +10,6 @@ import android.view.View
...
@@ -10,7 +10,6 @@ import android.view.View
import
android.view.ViewGroup
import
android.view.ViewGroup
import
android.widget.EditText
import
android.widget.EditText
import
android.widget.ImageView
import
android.widget.ImageView
import
android.widget.TextView
import
androidx.annotation.ColorInt
import
androidx.annotation.ColorInt
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AlertDialog
import
androidx.appcompat.app.AppCompatActivity
import
androidx.appcompat.app.AppCompatActivity
...
@@ -22,6 +21,7 @@ import chat.rocket.android.emoji.internal.EmojiCategory
...
@@ -22,6 +21,7 @@ import chat.rocket.android.emoji.internal.EmojiCategory
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.EmojiPagerAdapter
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
chat.rocket.android.emoji.internal.PREF_EMOJI_SKIN_TONE
import
com.google.android.material.tabs.TabLayout
import
com.google.android.material.tabs.TabLayout
import
kotlinx.android.synthetic.main.dialog_skin_tone_chooser.view.*
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.experimental.android.UI
import
kotlinx.coroutines.experimental.launch
import
kotlinx.coroutines.experimental.launch
...
@@ -77,59 +77,50 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
...
@@ -77,59 +77,50 @@ class EmojiKeyboardPopup(context: Context, view: View) : OverKeyboardPopupWindow
}
}
private
fun
showSkinToneChooser
()
{
private
fun
showSkinToneChooser
()
{
val
view
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
color_select_popup
,
null
)
val
view
=
LayoutInflater
.
from
(
context
).
inflate
(
R
.
layout
.
dialog_skin_tone_chooser
,
null
)
val
dialog
=
AlertDialog
.
Builder
(
context
,
R
.
style
.
Dialog
)
val
dialog
=
AlertDialog
.
Builder
(
context
,
R
.
style
.
Dialog
)
.
setView
(
view
)
.
setView
(
view
)
.
setTitle
(
context
.
getString
(
R
.
string
.
alert_title_default_skin_tone
))
.
setTitle
(
context
.
getString
(
R
.
string
.
alert_title_default_skin_tone
))
.
setCancelable
(
true
)
.
setCancelable
(
true
)
.
create
()
.
create
()
view
.
findViewById
<
TextView
>(
R
.
id
.
default_tone_text
).
also
{
with
(
view
)
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
image_view_default_tone
.
setOnClickListener
{
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
Default
)
changeSkinTone
(
Fitzpatrick
.
Default
)
}
}
view
.
findViewById
<
TextView
>(
R
.
id
.
light_tone_text
).
also
{
image_view_light_tone
.
setOnClickListener
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
LightTone
)
changeSkinTone
(
Fitzpatrick
.
LightTone
)
}
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_light_text
).
also
{
image_view_medium_light
.
setOnClickListener
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumLightTone
)
changeSkinTone
(
Fitzpatrick
.
MediumLightTone
)
}
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_tone_text
).
also
{
image_view_medium_tone
.
setOnClickListener
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumTone
)
changeSkinTone
(
Fitzpatrick
.
MediumTone
)
}
}
view
.
findViewById
<
TextView
>(
R
.
id
.
medium_dark_tone_text
).
also
{
image_view_medium_dark_tone
.
setOnClickListener
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
MediumDarkTone
)
changeSkinTone
(
Fitzpatrick
.
MediumDarkTone
)
}
}
view
.
findViewById
<
TextView
>(
R
.
id
.
dark_tone_text
).
also
{
image_view_dark_tone
.
setOnClickListener
{
it
.
text
=
EmojiParser
.
parse
(
context
,
it
.
text
)
}.
setOnClickListener
{
dialog
.
dismiss
()
dialog
.
dismiss
()
changeSkinTone
(
Fitzpatrick
.
DarkTone
)
changeSkinTone
(
Fitzpatrick
.
DarkTone
)
}
}
}
dialog
.
show
()
dialog
.
show
()
}
}
private
fun
changeSkinTone
(
tone
:
Fitzpatrick
)
{
private
fun
changeSkinTone
(
tone
:
Fitzpatrick
)
{
val
drawable
=
ContextCompat
.
getDrawable
(
context
,
R
.
drawable
.
color_change_circl
e
)
!!
val
drawable
=
ContextCompat
.
getDrawable
(
context
,
R
.
drawable
.
bg_skin_ton
e
)
!!
val
wrappedDrawable
=
DrawableCompat
.
wrap
(
drawable
)
val
wrappedDrawable
=
DrawableCompat
.
wrap
(
drawable
)
DrawableCompat
.
setTint
(
wrappedDrawable
,
getFitzpatrickColor
(
tone
))
DrawableCompat
.
setTint
(
wrappedDrawable
,
getFitzpatrickColor
(
tone
))
(
changeColorView
as
ImageView
).
setImageDrawable
(
wrappedDrawable
)
(
changeColorView
as
ImageView
).
setImageDrawable
(
wrappedDrawable
)
...
...
emoji/src/main/res/drawable/
color_change_circl
e.xml
→
emoji/src/main/res/drawable/
bg_skin_ton
e.xml
View file @
0e76e49a
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
<shape
xmlns:android=
"http://schemas.android.com/apk/res/android"
android:shape=
"oval"
>
android:shape=
"oval"
>
<solid
android:color=
"@color/tone_default"
/>
<solid
android:color=
"@color/tone_default"
/>
<size
<size
android:width=
"24dp"
android:width=
"24dp"
android:height=
"24dp"
/>
android:height=
"24dp"
/>
...
...
emoji/src/main/res/layout/
color_select_popup
.xml
→
emoji/src/main/res/layout/
dialog_skin_tone_chooser
.xml
View file @
0e76e49a
<?xml version="1.0" encoding="utf-8"?>
<?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:android=
"http://schemas.android.com/apk/res/android"
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"
android:layout_width=
"match_parent"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
>
android:layout_height=
"wrap_content"
>
<
Text
View
<
Image
View
android:id=
"@+id/
default_tone_text
"
android:id=
"@+id/
image_view_default_tone
"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:text=
"👌"
android:layout_marginBottom=
"16dp"
android:textSize=
"32sp"
android:tint=
"@color/tone_default"
android:tint=
"@color/tone_default"
app:layout_constraintEnd_toStartOf=
"@+id/light_tone_text"
app:layout_constraintBottom_toTopOf=
"@+id/image_view_medium_tone"
app:layout_constraintEnd_toStartOf=
"@+id/image_view_light_tone"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_chainStyle=
"
packed
"
app:layout_constraintHorizontal_chainStyle=
"
spread_inside
"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/
color_change_circl
e"
/>
app:srcCompat=
"@drawable/
bg_skin_ton
e"
/>
<
Text
View
<
Image
View
android:id=
"@+id/
light_tone_text
"
android:id=
"@+id/
image_view_light_tone
"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:layout_marginEnd=
"24dp"
android:text=
"👌🏻"
android:textSize=
"32sp"
android:tint=
"@color/tone_light"
android:tint=
"@color/tone_light"
app:layout_constraintEnd_toStartOf=
"@+id/
medium_light_tex
t"
app:layout_constraintEnd_toStartOf=
"@+id/
image_view_medium_ligh
t"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/
default_tone_text
"
app:layout_constraintStart_toEndOf=
"@+id/
image_view_default_tone
"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
app:srcCompat=
"@drawable/bg_skin_tone"
/>
tools:text=
"👌"
/>
<
Text
View
<
Image
View
android:id=
"@+id/
medium_light_tex
t"
android:id=
"@+id/
image_view_medium_ligh
t"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"16dp"
android:layout_marginTop=
"16dp"
android:text=
"👌🏼"
android:layout_marginEnd=
"24dp"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium_light"
android:tint=
"@color/tone_medium_light"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/
light_tone_text
"
app:layout_constraintStart_toEndOf=
"@+id/
image_view_light_tone
"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/color_change_circle"
app:srcCompat=
"@drawable/bg_skin_tone"
/>
tools:text=
"👌"
/>
<
Text
View
<
Image
View
android:id=
"@+id/
medium_tone_text
"
android:id=
"@+id/
image_view_medium_tone
"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:layout_marginTop=
"8dp"
android:layout_marginBottom=
"16dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏽"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium"
android:tint=
"@color/tone_medium"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintEnd_toStartOf=
"@+id/medium_dark_tone_text"
app:layout_constraintEnd_toStartOf=
"@+id/image_view_medium_dark_tone"
app:layout_constraintHorizontal_chainStyle=
"packed"
app:layout_constraintHorizontal_chainStyle=
"spread_inside"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"@+id/image_view_default_tone"
app:layout_constraintTop_toBottomOf=
"@+id/default_tone_text"
app:layout_constraintTop_toBottomOf=
"@+id/image_view_default_tone"
app:srcCompat=
"@drawable/color_change_circle"
app:srcCompat=
"@drawable/bg_skin_tone"
/>
tools:text=
"👌"
/>
<
Text
View
<
Image
View
android:id=
"@+id/
medium_dark_tone_text
"
android:id=
"@+id/
image_view_medium_dark_tone
"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginStart=
"24dp"
android:layout_marginTop=
"8dp"
android:layout_marginEnd=
"24dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏾"
android:textSize=
"32sp"
android:tint=
"@color/tone_medium_dark"
android:tint=
"@color/tone_medium_dark"
app:layout_constraintBottom_toBottomOf=
"
parent
"
app:layout_constraintBottom_toBottomOf=
"
@+id/image_view_medium_tone
"
app:layout_constraintEnd_toStartOf=
"@+id/
dark_tone_text
"
app:layout_constraintEnd_toStartOf=
"@+id/
image_view_dark_tone
"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintHorizontal_bias=
"0.5"
app:layout_constraintStart_toEndOf=
"@+id/medium_tone_text"
app:layout_constraintStart_toEndOf=
"@+id/image_view_medium_tone"
app:layout_constraintTop_toBottomOf=
"@+id/light_tone_text"
app:layout_constraintTop_toTopOf=
"@+id/image_view_medium_tone"
app:srcCompat=
"@drawable/color_change_circle"
app:srcCompat=
"@drawable/bg_skin_tone"
/>
tools:text=
"👌"
/>
<
Text
View
<
Image
View
android:id=
"@+id/
dark_tone_text
"
android:id=
"@+id/
image_view_dark_tone
"
android:layout_width=
"wrap_content"
android:layout_width=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_height=
"wrap_content"
android:layout_marginTop=
"8dp"
android:layout_marginBottom=
"16dp"
android:text=
"👌🏿"
android:textSize=
"32sp"
android:tint=
"@color/tone_dark"
android:tint=
"@color/tone_dark"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintBottom_toBottomOf=
"@+id/image_view_medium_dark_tone"
app:layout_constraintEnd_toEndOf=
"parent"
app:layout_constraintEnd_toEndOf=
"@+id/image_view_medium_light"
app:layout_constraintStart_toEndOf=
"@+id/medium_dark_tone_text"
app:layout_constraintStart_toEndOf=
"@+id/image_view_medium_dark_tone"
app:layout_constraintTop_toBottomOf=
"@+id/medium_light_text"
app:layout_constraintTop_toTopOf=
"@+id/image_view_medium_dark_tone"
app:srcCompat=
"@drawable/color_change_circle"
app:srcCompat=
"@drawable/bg_skin_tone"
/>
tools:text=
"👌"
/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
emoji/src/main/res/layout/emoji_keyboard.xml
View file @
0e76e49a
...
@@ -43,7 +43,7 @@
...
@@ -43,7 +43,7 @@
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintBottom_toBottomOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintStart_toStartOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:layout_constraintTop_toTopOf=
"parent"
app:srcCompat=
"@drawable/
color_change_circl
e"
/>
app:srcCompat=
"@drawable/
bg_skin_ton
e"
/>
<ImageView
<ImageView
android:id=
"@+id/emoji_search"
android:id=
"@+id/emoji_search"
...
...
util/src/main/java/chat/rocket/android/util/extension/Image.kt
View file @
0e76e49a
...
@@ -2,13 +2,19 @@ package chat.rocket.android.util.extension
...
@@ -2,13 +2,19 @@ package chat.rocket.android.util.extension
import
android.content.Intent
import
android.content.Intent
import
android.graphics.Bitmap
import
android.graphics.Bitmap
import
android.os.Environment
import
android.provider.MediaStore
import
android.provider.MediaStore
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.Fragment
import
androidx.fragment.app.FragmentActivity
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.DefaultDispatcher
import
kotlinx.coroutines.experimental.withContext
import
kotlinx.coroutines.experimental.withContext
import
java.io.ByteArrayInputStream
import
java.io.ByteArrayInputStream
import
java.io.ByteArrayOutputStream
import
java.io.ByteArrayOutputStream
import
java.io.InputStream
import
java.io.InputStream
import
java.io.IOException
import
java.io.File
import
java.text.SimpleDateFormat
import
java.util.*
/**
/**
* Compress a [Bitmap] image.
* Compress a [Bitmap] image.
...
@@ -105,3 +111,15 @@ fun Fragment.dispatchTakePicture(requestCode: Int) {
...
@@ -105,3 +111,15 @@ fun Fragment.dispatchTakePicture(requestCode: Int) {
startActivityForResult
(
takePictureIntent
,
requestCode
)
startActivityForResult
(
takePictureIntent
,
requestCode
)
}
}
}
}
@Throws
(
IOException
::
class
)
fun
FragmentActivity
.
createImageFile
():
File
{
// Create an image file name
val
timeStamp
:
String
=
SimpleDateFormat
(
"yyyyMMdd_HHmmss"
).
format
(
Date
())
val
storageDir
:
File
=
getExternalFilesDir
(
Environment
.
DIRECTORY_PICTURES
)
return
File
.
createTempFile
(
"PNG_${timeStamp}_"
,
/* prefix */
".png"
,
/* suffix */
storageDir
/* directory */
)
}
\ No newline at end of file
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment