reformat kotlin code to comply with ktlint

Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
Andy Scherzinger 2021-04-27 16:32:08 +02:00
parent 0b1ca971dd
commit e82808080d
No known key found for this signature in database
GPG Key ID: 6CADC7E3523C308B
35 changed files with 1801 additions and 1232 deletions

View File

@ -104,7 +104,6 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
@Inject
var eventBus: EventBus? = null
override fun onCreate() {
super.onCreate()
sharedApplication!!.componentApplication.inject(this)
@ -148,18 +147,26 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
val pushUtils = PushUtils()
val privateKey = pushUtils.readKeyFromFile(false) as PrivateKey
try {
signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
base64DecodedSubject)
signatureVerification = pushUtils.verifySignature(
base64DecodedSignature,
base64DecodedSubject
)
if (signatureVerification!!.signatureValid) {
val cipher = Cipher.getInstance("RSA/None/PKCS1Padding")
cipher.init(Cipher.DECRYPT_MODE, privateKey)
val decryptedSubject = cipher.doFinal(base64DecodedSubject)
decryptedPushMessage = LoganSquare.parse(String(decryptedSubject),
DecryptedPushMessage::class.java)
decryptedPushMessage = LoganSquare.parse(
String(decryptedSubject),
DecryptedPushMessage::class.java
)
decryptedPushMessage?.apply {
timestamp = System.currentTimeMillis()
if (delete) {
cancelExistingNotificationWithId(applicationContext, signatureVerification!!.userEntity, notificationId)
cancelExistingNotificationWithId(
applicationContext,
signatureVerification!!.userEntity,
notificationId
)
} else if (deleteAll) {
cancelAllNotificationsForAccount(applicationContext, signatureVerification!!.userEntity)
} else if (type == "call") {
@ -171,39 +178,66 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
fullScreenIntent.putExtras(bundle)
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
val fullScreenPendingIntent = PendingIntent.getActivity(this@MagicFirebaseMessagingService, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT)
val fullScreenPendingIntent = PendingIntent.getActivity(
this@MagicFirebaseMessagingService,
0,
fullScreenIntent,
PendingIntent.FLAG_UPDATE_CURRENT
)
val audioAttributesBuilder = AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
val audioAttributesBuilder =
AudioAttributes.Builder().setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
audioAttributesBuilder.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST)
val ringtonePreferencesString: String? = appPreferences!!.callRingtoneUri
val soundUri = if (TextUtils.isEmpty(ringtonePreferencesString)) {
Uri.parse("android.resource://" + applicationContext.packageName +
"/raw/librem_by_feandesign_call")
Uri.parse(
"android.resource://" + applicationContext.packageName +
"/raw/librem_by_feandesign_call"
)
} else {
try {
val ringtoneSettings = LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
val ringtoneSettings =
LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
ringtoneSettings.ringtoneUri
} catch (exception: IOException) {
Uri.parse("android.resource://" + applicationContext.packageName + "/raw/librem_by_feandesign_call")
}
}
val notificationChannelId = NotificationUtils.getNotificationChannelId(applicationContext.resources
.getString(R.string.nc_notification_channel_calls), applicationContext.resources
.getString(R.string.nc_notification_channel_calls_description), true,
NotificationManagerCompat.IMPORTANCE_HIGH, soundUri!!, audioAttributesBuilder.build(), null, false)
val notificationChannelId = NotificationUtils.getNotificationChannelId(
applicationContext.resources
.getString(R.string.nc_notification_channel_calls),
applicationContext.resources
.getString(R.string.nc_notification_channel_calls_description),
true,
NotificationManagerCompat.IMPORTANCE_HIGH,
soundUri!!,
audioAttributesBuilder.build(),
null,
false
)
createNotificationChannel(applicationContext!!,
notificationChannelId, applicationContext.resources
.getString(R.string.nc_notification_channel_calls), applicationContext.resources
.getString(R.string.nc_notification_channel_calls_description), true,
NotificationManagerCompat.IMPORTANCE_HIGH, soundUri, audioAttributesBuilder.build(), null, false)
createNotificationChannel(
applicationContext!!,
notificationChannelId,
applicationContext.resources
.getString(R.string.nc_notification_channel_calls),
applicationContext.resources
.getString(R.string.nc_notification_channel_calls_description),
true,
NotificationManagerCompat.IMPORTANCE_HIGH,
soundUri,
audioAttributesBuilder.build(),
null,
false
)
val uri = Uri.parse(signatureVerification!!.userEntity.baseUrl)
val baseUrl = uri.host
val notification = NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId)
val notification =
NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setCategory(NotificationCompat.CATEGORY_CALL)
.setSmallIcon(R.drawable.ic_call_black_24dp)
@ -213,7 +247,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
.setContentTitle(EmojiCompat.get().process(decryptedPushMessage!!.subject))
.setAutoCancel(true)
.setOngoing(true)
//.setTimeoutAfter(45000L)
// .setTimeoutAfter(45000L)
.setContentIntent(fullScreenPendingIntent)
.setFullScreenIntent(fullScreenPendingIntent, true)
.setSound(soundUri)
@ -227,7 +261,9 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, subject)
.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, signature)
.build()
val pushNotificationWork = OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData).build()
val pushNotificationWork =
OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData)
.build()
WorkManager.getInstance().enqueue(pushNotificationWork)
}
}
@ -244,14 +280,23 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
}
}
private fun checkIfCallIsActive(signatureVerification: SignatureVerification, decryptedPushMessage: DecryptedPushMessage) {
val ncApi = retrofit!!.newBuilder().client(okHttpClient!!.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build()).build().create(NcApi::class.java)
private fun checkIfCallIsActive(
signatureVerification: SignatureVerification,
decryptedPushMessage: DecryptedPushMessage
) {
val ncApi = retrofit!!.newBuilder()
.client(okHttpClient!!.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build()).build()
.create(NcApi::class.java)
var hasParticipantsInCall = false
var inCallOnDifferentDevice = false
ncApi.getPeersForCall(ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token),
ApiUtils.getUrlForCall(signatureVerification.userEntity.baseUrl,
decryptedPushMessage.id))
ncApi.getPeersForCall(
ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token),
ApiUtils.getUrlForCall(
signatureVerification.userEntity.baseUrl,
decryptedPushMessage.id
)
)
.takeWhile {
isServiceInForeground
}
@ -276,9 +321,12 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
stopForeground(true)
handler.removeCallbacksAndMessages(null)
} else if (isServiceInForeground) {
handler.postDelayed({
handler.postDelayed(
{
checkIfCallIsActive(signatureVerification, decryptedPushMessage)
}, 5000)
},
5000
)
}
}

View File

@ -76,8 +76,11 @@ open class BaseActivity : AppCompatActivity() {
}
}
fun showCertificateDialog(cert: X509Certificate, magicTrustManager: MagicTrustManager,
sslErrorHandler: SslErrorHandler?) {
fun showCertificateDialog(
cert: X509Certificate,
magicTrustManager: MagicTrustManager,
sslErrorHandler: SslErrorHandler?
) {
val formatter = DateFormat.getDateInstance(DateFormat.LONG)
val validFrom = formatter.format(cert.notBefore)
val validUntil = formatter.format(cert.notAfter)
@ -101,9 +104,11 @@ open class BaseActivity : AppCompatActivity() {
issuedFor = cert.subjectDN.name
}
@SuppressLint("StringFormatMatches") val dialogText = String.format(resources
@SuppressLint("StringFormatMatches") val dialogText = String.format(
resources
.getString(R.string.nc_certificate_dialog_text),
issuedBy, issuedFor, validFrom, validUntil)
issuedBy, issuedFor, validFrom, validUntil
)
LovelyStandardDialog(this)
.setTopColorRes(R.color.nc_darkRed)
@ -120,11 +125,9 @@ open class BaseActivity : AppCompatActivity() {
sslErrorHandler?.cancel()
}
.show()
} catch (e: CertificateParsingException) {
Log.d(TAG, "Failed to parse the certificate")
}
}
@Subscribe(threadMode = ThreadMode.MAIN)

View File

@ -38,7 +38,6 @@ import pl.droidsonroids.gif.GifDrawable
import pl.droidsonroids.gif.GifImageView
import java.io.File
class FullScreenImageActivity : AppCompatActivity() {
private lateinit var path: String
@ -55,9 +54,11 @@ class FullScreenImageActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.share) {
val shareUri = FileProvider.getUriForFile(this,
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path))
File(path)
)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
@ -78,19 +79,19 @@ class FullScreenImageActivity : AppCompatActivity() {
setContentView(R.layout.activity_full_screen_image)
setSupportActionBar(findViewById(R.id.imageview_toolbar))
supportActionBar?.setDisplayShowTitleEnabled(false);
supportActionBar?.setDisplayShowTitleEnabled(false)
imageWrapperView = findViewById(R.id.image_wrapper_view)
photoView = findViewById(R.id.photo_view)
gifView = findViewById(R.id.gif_view)
photoView.setOnPhotoTapListener{ view, x, y ->
photoView.setOnPhotoTapListener { view, x, y ->
toggleFullscreen()
}
photoView.setOnOutsidePhotoTapListener{
photoView.setOnOutsidePhotoTapListener {
toggleFullscreen()
}
gifView.setOnClickListener{
gifView.setOnClickListener {
toggleFullscreen()
}
@ -115,29 +116,33 @@ class FullScreenImageActivity : AppCompatActivity() {
}
}
private fun toggleFullscreen(){
showFullscreen = !showFullscreen;
if (showFullscreen){
private fun toggleFullscreen() {
showFullscreen = !showFullscreen
if (showFullscreen) {
hideSystemUI()
supportActionBar?.hide()
} else{
} else {
showSystemUI()
supportActionBar?.show()
}
}
private fun hideSystemUI() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_IMMERSIVE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN)
or View.SYSTEM_UI_FLAG_FULLSCREEN
)
}
private fun showSystemUI() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
)
}
}

View File

@ -22,7 +22,6 @@ package com.nextcloud.talk.activities
import android.content.Intent
import android.os.Bundle
import android.util.Log
import android.view.Menu
import android.view.MenuItem
import android.view.View
@ -33,7 +32,6 @@ import autodagger.AutoInjector
import com.google.android.exoplayer2.MediaItem
import com.google.android.exoplayer2.Player
import com.google.android.exoplayer2.SimpleExoPlayer
import com.google.android.exoplayer2.ui.PlayerControlView
import com.google.android.exoplayer2.ui.StyledPlayerView
import com.nextcloud.talk.BuildConfig
import com.nextcloud.talk.R
@ -54,9 +52,11 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.share) {
val shareUri = FileProvider.getUriForFile(this,
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path))
File(path)
)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
@ -82,11 +82,11 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
setContentView(R.layout.activity_full_screen_media)
setSupportActionBar(findViewById(R.id.mediaview_toolbar))
supportActionBar?.setDisplayShowTitleEnabled(false);
supportActionBar?.setDisplayShowTitleEnabled(false)
playerView = findViewById(R.id.player_view)
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
playerView.showController()
if (isAudioOnly) {
@ -121,7 +121,7 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
private fun initializePlayer() {
player = SimpleExoPlayer.Builder(applicationContext).build()
playerView.player = player;
playerView.player = player
player.playWhenReady = true
player.addListener(this)
}
@ -131,17 +131,21 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
}
private fun hideSystemUI() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_IMMERSIVE
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_IMMERSIVE
or View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_FULLSCREEN)
or View.SYSTEM_UI_FLAG_FULLSCREEN
)
}
private fun showSystemUI() {
window.decorView.systemUiVisibility = (View.SYSTEM_UI_FLAG_LAYOUT_STABLE
window.decorView.systemUiVisibility = (
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
)
}
}

View File

@ -34,7 +34,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
import io.noties.markwon.Markwon
import java.io.File
@AutoInjector(NextcloudTalkApplication::class)
class FullScreenTextViewerActivity : AppCompatActivity() {
@ -48,9 +47,11 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
override fun onOptionsItemSelected(item: MenuItem): Boolean {
return if (item.itemId == R.id.share) {
val shareUri = FileProvider.getUriForFile(this,
val shareUri = FileProvider.getUriForFile(
this,
BuildConfig.APPLICATION_ID,
File(path))
File(path)
)
val shareIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
@ -71,8 +72,7 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
setContentView(R.layout.activity_full_screen_text)
setSupportActionBar(findViewById(R.id.textview_toolbar))
supportActionBar?.setDisplayShowTitleEnabled(false);
supportActionBar?.setDisplayShowTitleEnabled(false)
textView = findViewById(R.id.text_view)
val fileName = intent.getStringExtra("FILE_NAME")
@ -81,13 +81,12 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
var text = readFile(path)
if (isMarkdown) {
val markwon = Markwon.create(applicationContext);
markwon.setMarkdown(textView, text);
val markwon = Markwon.create(applicationContext)
markwon.setMarkdown(textView, text)
} else {
textView.text = text
}
}
private fun readFile(fileName: String) = File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
}

View File

@ -60,10 +60,12 @@ class MagicCallActivity : BaseActivity() {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
requestWindowFeature(Window.FEATURE_NO_TITLE)
window.addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN or
window.addFlags(
WindowManager.LayoutParams.FLAG_FULLSCREEN or
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
)
window.decorView.systemUiVisibility = systemUiVisibility
setContentView(R.layout.activity_magic_call)
@ -74,13 +76,17 @@ class MagicCallActivity : BaseActivity() {
if (!router!!.hasRootController()) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.setRoot(RouterTransaction.with(CallNotificationController(intent.extras))
router!!.setRoot(
RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
} else {
router!!.setRoot(RouterTransaction.with(CallController(intent.extras))
router!!.setRoot(
RouterTransaction.with(CallController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
}
@ -89,9 +95,11 @@ class MagicCallActivity : BaseActivity() {
chatController = ChatController(extras)
chatRouter = Conductor.attachRouter(this, chatContainer, savedInstanceState)
chatRouter!!.setRoot(RouterTransaction.with(chatController)
chatRouter!!.setRoot(
RouterTransaction.with(chatController)
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
fun showChat() {

View File

@ -79,23 +79,31 @@ class MainActivity : BaseActivity(), ActionBarProvider {
@BindView(R.id.appBar)
lateinit var appBar: AppBarLayout
@BindView(R.id.toolbar)
lateinit var toolbar: MaterialToolbar
@BindView(R.id.home_toolbar)
lateinit var searchCardView: MaterialCardView
@BindView(R.id.search_text)
lateinit var searchInputText: MaterialTextView
@BindView(R.id.switch_account_button)
lateinit var settingsButton: MaterialButton
@BindView(R.id.controller_container)
lateinit var container: ViewGroup
@Inject
lateinit var userUtils: UserUtils
@Inject
lateinit var dataStore: ReactiveEntityStore<Persistable>
@Inject
lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource
@Inject
lateinit var ncApi: NcApi
@ -124,39 +132,53 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (!router!!.hasRootController()) {
router!!.setRoot(RouterTransaction.with(ConversationsListController())
router!!.setRoot(
RouterTransaction.with(ConversationsListController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
onNewIntent(intent)
} else if (!router!!.hasRootController()) {
if (hasDb) {
if (userUtils.anyUserExists()) {
router!!.setRoot(RouterTransaction.with(ConversationsListController())
router!!.setRoot(
RouterTransaction.with(ConversationsListController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
} else {
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
router!!.pushController(RouterTransaction.with(
WebViewLoginController(resources.getString(R.string.weblogin_url), false))
router!!.pushController(
RouterTransaction.with(
WebViewLoginController(resources.getString(R.string.weblogin_url), false)
)
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
} else {
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
router!!.setRoot(
RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
}
} else {
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
router!!.pushController(RouterTransaction.with(
WebViewLoginController(resources.getString(R.string.weblogin_url), false))
router!!.pushController(
RouterTransaction.with(
WebViewLoginController(resources.getString(R.string.weblogin_url), false)
)
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
} else {
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
router!!.setRoot(
RouterTransaction.with(ServerSelectionController())
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
}
}
@ -193,8 +215,10 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (userUtils.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
startConversation(user)
} else {
Snackbar.make(container, R.string.nc_phone_book_integration_account_not_found, Snackbar
.LENGTH_LONG).show()
Snackbar.make(
container, R.string.nc_phone_book_integration_account_not_found,
Snackbar.LENGTH_LONG
).show()
}
}
}
@ -206,10 +230,14 @@ class MainActivity : BaseActivity(), ActionBarProvider {
val currentUser = userUtils.currentUser ?: return
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.baseUrl, roomType,
userId, null)
ncApi.createRoom(credentials,
retrofitBucket.url, retrofitBucket.queryMap)
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
currentUser.baseUrl, roomType,
userId, null
)
ncApi.createRoom(
credentials,
retrofitBucket.url, retrofitBucket.queryMap
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<RoomOverall> {
@ -221,18 +249,26 @@ class MainActivity : BaseActivity(), ActionBarProvider {
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs.data.token)
bundle.putString(KEY_ROOM_ID, roomOverall.ocs.data.roomId)
if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
ncApi.getRoom(credentials,
ApiUtils.getRoom(currentUser.baseUrl,
roomOverall.ocs.data.token))
ncApi.getRoom(
credentials,
ApiUtils.getRoom(
currentUser.baseUrl,
roomOverall.ocs.data.token
)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<RoomOverall> {
override fun onSubscribe(d: Disposable) {}
override fun onNext(roomOverall: RoomOverall) {
bundle.putParcelable(KEY_ACTIVE_CONVERSATION,
Parcels.wrap(roomOverall.ocs.data))
remapChatController(router!!, currentUser.id,
roomOverall.ocs.data.token, bundle, true)
bundle.putParcelable(
KEY_ACTIVE_CONVERSATION,
Parcels.wrap(roomOverall.ocs.data)
)
remapChatController(
router!!, currentUser.id,
roomOverall.ocs.data.token, bundle, true
)
}
override fun onError(e: Throwable) {}
@ -241,11 +277,14 @@ class MainActivity : BaseActivity(), ActionBarProvider {
} else {
conversationIntent.putExtras(bundle)
startActivity(conversationIntent)
Handler().postDelayed({
Handler().postDelayed(
{
if (!isDestroyed) {
router!!.popCurrentController()
}
}, 100)
},
100
)
}
}
@ -260,16 +299,17 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) {
router!!.pushController(RouterTransaction.with(LockedController())
router!!.pushController(
RouterTransaction.with(LockedController())
.pushChangeHandler(VerticalChangeHandler())
.popChangeHandler(VerticalChangeHandler())
.tag(LockedController.TAG))
.tag(LockedController.TAG)
)
}
}
}
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
@ -277,12 +317,16 @@ class MainActivity : BaseActivity(), ActionBarProvider {
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
router!!.pushController(RouterTransaction.with(CallNotificationController(intent.extras))
router!!.pushController(
RouterTransaction.with(CallNotificationController(intent.extras))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
} else {
ConductorRemapping.remapChatController(router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false)
ConductorRemapping.remapChatController(
router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false
)
}
}
}

View File

@ -39,7 +39,6 @@ import autodagger.AutoInjector
import butterknife.BindView
import butterknife.ButterKnife
import coil.load
import coil.transform.CircleCropTransformation
import com.amulyakhare.textdrawable.TextDrawable
import com.facebook.drawee.view.SimpleDraweeView
import com.nextcloud.talk.R
@ -51,7 +50,6 @@ import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.TextMatchers
import com.nextcloud.talk.utils.preferences.AppPreferences
import com.stfalcon.chatkit.messages.MessageHolders
import com.stfalcon.chatkit.utils.DateFormatter
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -231,7 +229,10 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
parentChatMessage.imageUrl?.let {
quotedMessagePreview?.visibility = View.VISIBLE
quotedMessagePreview?.load(it) {
addHeader("Authorization", ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token))
addHeader(
"Authorization",
ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
)
}
} ?: run {
quotedMessagePreview?.visibility = View.GONE
@ -242,7 +243,7 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
quotedUserName?.setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast))
if(parentChatMessage.actorId?.equals(message.activeUser.userId) == true) {
if (parentChatMessage.actorId?.equals(message.activeUser.userId) == true) {
quoteColoredView?.setBackgroundResource(R.color.colorPrimary)
} else {
quoteColoredView?.setBackgroundResource(R.color.textColorMaxContrast)

View File

@ -36,7 +36,6 @@ import autodagger.AutoInjector
import butterknife.BindView
import butterknife.ButterKnife
import coil.load
import coil.transform.CircleCropTransformation
import com.google.android.flexbox.FlexboxLayout
import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
@ -48,8 +47,7 @@ import com.nextcloud.talk.utils.DisplayUtils.getMessageSelector
import com.nextcloud.talk.utils.DisplayUtils.searchAndReplaceWithMentionSpan
import com.nextcloud.talk.utils.TextMatchers
import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
import com.stfalcon.chatkit.utils.DateFormatter
import java.util.*
import java.util.HashMap
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -57,6 +55,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
@JvmField
@BindView(R.id.messageText)
var messageText: EmojiTextView? = null
@JvmField
@BindView(R.id.messageTime)
var messageTimeView: TextView? = null
@ -104,20 +103,26 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
for (key in messageParameters.keys) {
val individualHashMap: HashMap<String, String>? = message.messageParameters[key]
if (individualHashMap != null) {
if (individualHashMap["type"] == "user" || (individualHashMap["type"]
== "guest") || individualHashMap["type"] == "call") {
messageString = searchAndReplaceWithMentionSpan(messageText!!.context,
if (individualHashMap["type"] == "user" || (
individualHashMap["type"] == "guest"
) || individualHashMap["type"] == "call"
) {
messageString = searchAndReplaceWithMentionSpan(
messageText!!.context,
messageString,
individualHashMap["id"]!!,
individualHashMap["name"]!!,
individualHashMap["type"]!!,
message.activeUser,
R.xml.chip_others)
R.xml.chip_others
)
} else if (individualHashMap["type"] == "file") {
realView.setOnClickListener(View.OnClickListener { v: View? ->
realView.setOnClickListener(
View.OnClickListener { v: View? ->
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
context!!.startActivity(browserIntent)
})
}
)
}
}
}
@ -138,14 +143,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
bgBubbleColor,
resources.getColor(R.color.transparent),
bgBubbleColor,
R.drawable.shape_grouped_outcoming_message)
R.drawable.shape_grouped_outcoming_message
)
ViewCompat.setBackground(bubble, bubbleDrawable)
} else {
val bubbleDrawable = getMessageSelector(
bgBubbleColor,
resources.getColor(R.color.transparent),
bgBubbleColor,
R.drawable.shape_outcoming_message)
R.drawable.shape_outcoming_message
)
ViewCompat.setBackground(bubble, bubbleDrawable)
}
messageText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
@ -160,7 +167,10 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
parentChatMessage.imageUrl?.let {
quotedMessagePreview?.visibility = View.VISIBLE
quotedMessagePreview?.load(it) {
addHeader("Authorization", ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token))
addHeader(
"Authorization",
ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
)
}
} ?: run {
quotedMessagePreview?.visibility = View.GONE

View File

@ -90,6 +90,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
@Inject
lateinit var appPreferences: AppPreferences
@Inject
lateinit var okHttpClient: OkHttpClient
//endregion
@ -105,8 +106,10 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
}
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
.createInitializationOptions())
PeerConnectionFactory.initialize(
PeerConnectionFactory.InitializationOptions.builder(this)
.createInitializationOptions()
)
} catch (e: UnsatisfiedLinkError) {
Log.w(TAG, e)
}
@ -137,11 +140,13 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
.setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
.setMainDiskCacheConfig(
DiskCacheConfig.newBuilder(this)
.setMaxCacheSize(0)
.setMaxCacheSizeOnLowDiskSpace(0)
.setMaxCacheSizeOnVeryLowDiskSpace(0)
.build())
.build()
)
.build()
Fresco.initialize(this, imagePipelineConfig)
@ -152,8 +157,10 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(CapabilitiesWorker::class.java,
12, TimeUnit.HOURS).build()
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(
CapabilitiesWorker::class.java,
12, TimeUnit.HOURS
).build()
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::class.java).build()
@ -161,7 +168,11 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
WorkManager.getInstance().enqueue(accountRemovalWork)
WorkManager.getInstance().enqueue(capabilitiesUpdateWork)
WorkManager.getInstance().enqueue(signalingSettingsWork)
WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, periodicCapabilitiesUpdateWork)
WorkManager.getInstance().enqueueUniquePeriodicWork(
"DailyCapabilitiesUpdateWork",
ExistingPeriodicWorkPolicy.REPLACE,
periodicCapabilitiesUpdateWork
)
val config = BundledEmojiCompatConfig(this)
config.setReplaceAll(true)
@ -176,7 +187,6 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
}
//endregion
//region Protected methods
protected fun buildComponent() {
componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
@ -209,6 +219,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
.okHttpClient(okHttpClient)
.build()
}
companion object {
private val TAG = NextcloudTalkApplication::class.java.simpleName
//region Singleton

View File

@ -44,10 +44,6 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import com.bluelinelabs.conductor.RouterTransaction;
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
import com.bluelinelabs.logansquare.LoganSquare;
@ -71,7 +67,6 @@ import com.nextcloud.talk.models.RingtoneSettings;
import com.nextcloud.talk.models.database.UserEntity;
import com.nextcloud.talk.models.json.conversations.Conversation;
import com.nextcloud.talk.models.json.conversations.RoomOverall;
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
import com.nextcloud.talk.models.json.participants.Participant;
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
import com.nextcloud.talk.utils.ApiUtils;
@ -94,6 +89,9 @@ import java.util.List;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.constraintlayout.widget.ConstraintLayout;
import autodagger.AutoInjector;
import butterknife.BindView;
import butterknife.OnClick;
@ -261,7 +259,7 @@ public class CallNotificationController extends BaseController {
private void handleFromNotification() {
boolean isConversationApiV3 = userBeingCalled.hasSpreedFeatureCapability("conversation-v3");
if(isConversationApiV3) {
if (isConversationApiV3) {
ncApi.getRoom(credentials, ApiUtils.getRoomV3(userBeingCalled.getBaseUrl(), roomId))
.subscribeOn(Schedulers.io())
.retry(3)
@ -279,7 +277,7 @@ public class CallNotificationController extends BaseController {
boolean hasCallFlags = userBeingCalled.hasSpreedFeatureCapability("conversation-call-flags");
if (hasCallFlags) {
if (isInCallWithVideo(currentConversation.callFlag)){
if (isInCallWithVideo(currentConversation.callFlag)) {
incomingCallVoiceOrVideoTextView.setText(String.format(getResources().getString(R.string.nc_call_video),
getResources().getString(R.string.nc_app_name)));
} else {

View File

@ -40,8 +40,22 @@ import android.text.TextUtils
import android.text.TextWatcher
import android.util.Log
import android.util.TypedValue
import android.view.*
import android.widget.*
import android.view.Gravity
import android.view.LayoutInflater
import android.view.Menu
import android.view.MenuInflater
import android.view.MenuItem
import android.view.View
import android.view.ViewGroup
import android.widget.AbsListView
import android.widget.ImageButton
import android.widget.ImageView
import android.widget.PopupMenu
import android.widget.ProgressBar
import android.widget.RelativeLayout
import android.widget.Space
import android.widget.TextView
import android.widget.Toast
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
import androidx.emoji.text.EmojiCompat
import androidx.emoji.widget.EmojiEditText
@ -55,7 +69,6 @@ import autodagger.AutoInjector
import butterknife.BindView
import butterknife.OnClick
import coil.load
import coil.transform.CircleCropTransformation
import com.bluelinelabs.conductor.RouterTransaction
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
@ -69,7 +82,12 @@ import com.facebook.imagepipeline.image.CloseableImage
import com.google.android.flexbox.FlexboxLayout
import com.nextcloud.talk.R
import com.nextcloud.talk.activities.MagicCallActivity
import com.nextcloud.talk.adapters.messages.*
import com.nextcloud.talk.adapters.messages.MagicIncomingTextMessageViewHolder
import com.nextcloud.talk.adapters.messages.MagicOutcomingTextMessageViewHolder
import com.nextcloud.talk.adapters.messages.MagicPreviewMessageViewHolder
import com.nextcloud.talk.adapters.messages.MagicSystemMessageViewHolder
import com.nextcloud.talk.adapters.messages.MagicUnreadNoticeMessageViewHolder
import com.nextcloud.talk.adapters.messages.TalkMessagesListAdapter
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.callbacks.MentionAutocompleteCallback
@ -91,7 +109,14 @@ import com.nextcloud.talk.models.json.generic.GenericOverall
import com.nextcloud.talk.models.json.mention.Mention
import com.nextcloud.talk.presenters.MentionAutocompletePresenter
import com.nextcloud.talk.ui.dialog.AttachmentDialog
import com.nextcloud.talk.utils.*
import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.ConductorRemapping
import com.nextcloud.talk.utils.DateUtils
import com.nextcloud.talk.utils.DisplayUtils
import com.nextcloud.talk.utils.KeyboardUtils
import com.nextcloud.talk.utils.MagicCharPolicy
import com.nextcloud.talk.utils.NotificationUtils
import com.nextcloud.talk.utils.UriUtils
import com.nextcloud.talk.utils.bundle.BundleKeys
import com.nextcloud.talk.utils.database.user.UserUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
@ -121,14 +146,20 @@ import org.parceler.Parcels
import retrofit2.HttpException
import retrofit2.Response
import java.net.HttpURLConnection
import java.util.*
import java.util.ArrayList
import java.util.Date
import java.util.HashMap
import java.util.Objects
import java.util.concurrent.TimeUnit
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
.OnLoadMoreListener, MessagesListAdapter.Formatter<Date>, MessagesListAdapter
.OnMessageViewLongClickListener<IMessage>, MessageHolders.ContentChecker<IMessage> {
class ChatController(args: Bundle) :
BaseController(args),
MessagesListAdapter.OnLoadMoreListener,
MessagesListAdapter.Formatter<Date>,
MessagesListAdapter.OnMessageViewLongClickListener<IMessage>,
MessageHolders.ContentChecker<IMessage> {
@Inject
@JvmField
@ -236,7 +267,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
this.roomToken = args.getString(BundleKeys.KEY_ROOM_TOKEN, "")
if (args.containsKey(BundleKeys.KEY_ACTIVE_CONVERSATION)) {
this.currentConversation = Parcels.unwrap<Conversation>(args.getParcelable<Parcelable>(BundleKeys.KEY_ACTIVE_CONVERSATION))
this.currentConversation =
Parcels.unwrap<Conversation>(args.getParcelable<Parcelable>(BundleKeys.KEY_ACTIVE_CONVERSATION))
}
this.roomPassword = args.getString(BundleKeys.KEY_CONVERSATION_PASSWORD, "")
@ -260,9 +292,9 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
checkingLobbyStatus = true
}
if (conversationUser != null) {
ncApi?.getRoom(credentials, ApiUtils.getRoom(conversationUser.baseUrl, roomToken))?.subscribeOn(Schedulers.io())
ncApi?.getRoom(credentials, ApiUtils.getRoom(conversationUser.baseUrl, roomToken))
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<RoomOverall> {
override fun onSubscribe(d: Disposable) {
@ -281,11 +313,9 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
if (!inConversation) {
joinRoomWithPassword()
}
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
@ -303,7 +333,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun handleFromNotification() {
ncApi?.getRooms(credentials, ApiUtils.getUrlForGetRooms(conversationUser?.baseUrl))
?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())?.subscribe(object : Observer<RoomsOverall> {
?.subscribeOn(Schedulers.io())?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<RoomsOverall> {
override fun onSubscribe(d: Disposable) {
disposableList.add(d)
}
@ -321,11 +352,9 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
}
})
}
@ -336,16 +365,25 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun loadAvatarForStatusBar() {
if (inOneToOneCall() && activity != null && conversationVoiceCallMenuItem != null) {
val avatarSize = DisplayUtils.convertDpToPixel(conversationVoiceCallMenuItem?.icon!!
.intrinsicWidth.toFloat(), activity).toInt()
val avatarSize = DisplayUtils.convertDpToPixel(
conversationVoiceCallMenuItem?.icon!!
.intrinsicWidth.toFloat(),
activity
).toInt()
val imageRequest = DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithNameAndPixels(conversationUser?.baseUrl,
currentConversation?.name, avatarSize / 2), conversationUser!!)
val imageRequest = DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithNameAndPixels(
conversationUser?.baseUrl,
currentConversation?.name, avatarSize / 2
),
conversationUser!!
)
val imagePipeline = Fresco.getImagePipeline()
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
dataSource.subscribe(object : BaseBitmapDataSubscriber() {
dataSource.subscribe(
object : BaseBitmapDataSubscriber() {
override fun onNewResultImpl(bitmap: Bitmap?) {
if (actionBar != null && bitmap != null && resources != null) {
val roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(resources!!, bitmap)
@ -356,7 +394,9 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {}
}, UiThreadImmediateExecutorService.getInstance())
},
UiThreadImmediateExecutorService.getInstance()
)
}
}
@ -374,21 +414,40 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
adapterWasNull = true
val messageHolders = MessageHolders()
messageHolders.setIncomingTextConfig(MagicIncomingTextMessageViewHolder::class.java, R.layout.item_custom_incoming_text_message)
messageHolders.setOutcomingTextConfig(MagicOutcomingTextMessageViewHolder::class.java, R.layout.item_custom_outcoming_text_message)
messageHolders.setIncomingTextConfig(
MagicIncomingTextMessageViewHolder::class.java,
R.layout.item_custom_incoming_text_message
)
messageHolders.setOutcomingTextConfig(
MagicOutcomingTextMessageViewHolder::class.java,
R.layout.item_custom_outcoming_text_message
)
messageHolders.setIncomingImageConfig(MagicPreviewMessageViewHolder::class.java, R.layout.item_custom_incoming_preview_message)
messageHolders.setOutcomingImageConfig(MagicPreviewMessageViewHolder::class.java, R.layout.item_custom_outcoming_preview_message)
messageHolders.setIncomingImageConfig(
MagicPreviewMessageViewHolder::class.java,
R.layout.item_custom_incoming_preview_message
)
messageHolders.setOutcomingImageConfig(
MagicPreviewMessageViewHolder::class.java,
R.layout.item_custom_outcoming_preview_message
)
messageHolders.registerContentType(CONTENT_TYPE_SYSTEM_MESSAGE, MagicSystemMessageViewHolder::class.java,
messageHolders.registerContentType(
CONTENT_TYPE_SYSTEM_MESSAGE, MagicSystemMessageViewHolder::class.java,
R.layout.item_system_message, MagicSystemMessageViewHolder::class.java, R.layout.item_system_message,
this)
this
)
messageHolders.registerContentType(CONTENT_TYPE_UNREAD_NOTICE_MESSAGE,
messageHolders.registerContentType(
CONTENT_TYPE_UNREAD_NOTICE_MESSAGE,
MagicUnreadNoticeMessageViewHolder::class.java, R.layout.item_date_header,
MagicUnreadNoticeMessageViewHolder::class.java, R.layout.item_date_header, this)
MagicUnreadNoticeMessageViewHolder::class.java, R.layout.item_date_header, this
)
adapter = TalkMessagesListAdapter(conversationUser?.userId, messageHolders, ImageLoader { imageView, url, payload ->
adapter = TalkMessagesListAdapter(
conversationUser?.userId,
messageHolders,
ImageLoader { imageView, url, payload ->
val draweeController = Fresco.newDraweeControllerBuilder()
.setImageRequest(DisplayUtils.getImageRequestForUrl(url, conversationUser))
.setControllerListener(DisplayUtils.getImageControllerListener(imageView))
@ -396,7 +455,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
.setAutoPlayAnimations(true)
.build()
imageView.controller = draweeController
})
}
)
} else {
messagesListView?.visibility = View.VISIBLE
}
@ -449,7 +509,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
})
val filters = arrayOfNulls<InputFilter>(1)
val lengthFilter = conversationUser?.messageMaxLength ?: 1000
@ -458,27 +517,34 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
messageInput?.addTextChangedListener(object : TextWatcher {
override fun beforeTextChanged(s: CharSequence, start: Int, count: Int, after: Int) {
}
override fun onTextChanged(s: CharSequence, start: Int, before: Int, count: Int) {
if (s.length >= lengthFilter) {
messageInput?.error = String.format(Objects.requireNonNull<Resources>
(resources).getString(R.string.nc_limit_hit), Integer.toString(lengthFilter))
messageInput?.error = String.format(
Objects.requireNonNull<Resources>
(resources).getString(R.string.nc_limit_hit),
Integer.toString(lengthFilter)
)
} else {
messageInput?.error = null
}
val editable = messageInput?.editableText
if (editable != null && messageInput != null) {
val mentionSpans = editable.getSpans(0, messageInput!!.length(),
Spans.MentionChipSpan::class.java)
val mentionSpans = editable.getSpans(
0, messageInput!!.length(),
Spans.MentionChipSpan::class.java
)
var mentionSpan: Spans.MentionChipSpan
for (i in mentionSpans.indices) {
mentionSpan = mentionSpans[i]
if (start >= editable.getSpanStart(mentionSpan) && start < editable.getSpanEnd(mentionSpan)) {
if (editable.subSequence(editable.getSpanStart(mentionSpan),
editable.getSpanEnd(mentionSpan)).toString().trim { it <= ' ' } != mentionSpan.label) {
if (editable.subSequence(
editable.getSpanStart(mentionSpan),
editable.getSpanEnd(mentionSpan)
).toString().trim { it <= ' ' } != mentionSpan.label
) {
editable.removeSpan(mentionSpan)
}
}
@ -487,18 +553,19 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun afterTextChanged(s: Editable) {
}
})
messageInputView?.setAttachmentsListener {
activity?.let { AttachmentDialog(it, this).show() };
activity?.let { AttachmentDialog(it, this).show() }
}
messageInputView?.button?.setOnClickListener { v -> submitMessage() }
messageInputView?.button?.contentDescription = resources?.getString(R.string
.nc_description_send_message_button)
messageInputView?.button?.contentDescription = resources?.getString(
R.string
.nc_description_send_message_button
)
if (currentConversation != null && currentConversation?.roomId != null) {
loadAvatarForStatusBar()
@ -516,7 +583,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
super.onViewBound(view)
}
private fun checkReadOnlyState() {
if (currentConversation != null) {
if (currentConversation?.shouldShowLobby(conversationUser) ?: false || currentConversation?.conversationReadOnlyState != null && currentConversation?.conversationReadOnlyState == Conversation.ConversationReadOnlyState.CONVERSATION_READ_ONLY) {
@ -524,7 +590,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
conversationVoiceCallMenuItem?.icon?.alpha = 99
conversationVideoMenuItem?.icon?.alpha = 99
messageInputView?.visibility = View.GONE
} else {
if (conversationVoiceCallMenuItem != null) {
conversationVoiceCallMenuItem?.icon?.alpha = 255
@ -535,7 +600,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
if (currentConversation != null && currentConversation!!.shouldShowLobby
(conversationUser)) {
(conversationUser)
) {
messageInputView?.visibility = View.GONE
} else {
messageInputView?.visibility = View.VISIBLE
@ -558,9 +624,15 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
loadingProgressBar?.visibility = View.GONE
if (currentConversation?.lobbyTimer != null && currentConversation?.lobbyTimer !=
0L) {
conversationLobbyText?.text = String.format(resources!!.getString(R.string.nc_lobby_waiting_with_date), DateUtils.getLocalDateStringFromTimestampForLobby(currentConversation?.lobbyTimer
?: 0))
0L
) {
conversationLobbyText?.text = String.format(
resources!!.getString(R.string.nc_lobby_waiting_with_date),
DateUtils.getLocalDateStringFromTimestampForLobby(
currentConversation?.lobbyTimer
?: 0
)
)
} else {
conversationLobbyText?.setText(R.string.nc_lobby_waiting)
}
@ -607,7 +679,7 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
filenamesWithLinebreaks += filename + "\n"
}
val confirmationQuestion = when(files.size) {
val confirmationQuestion = when (files.size) {
1 -> context?.resources?.getString(R.string.nc_upload_confirm_send_single)?.let {
String.format(it, title)
}
@ -622,16 +694,20 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
.setMessage(filenamesWithLinebreaks)
.setPositiveButton(R.string.nc_yes) { v ->
uploadFiles(files)
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_in_progess), Toast
.LENGTH_LONG).show();
Toast.makeText(
context, context?.resources?.getString(R.string.nc_upload_in_progess),
Toast.LENGTH_LONG
).show()
}
.setNegativeButton(R.string.nc_no) {}
.show()
} catch (e: IllegalStateException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG).show()
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
.show()
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
} catch (e: IllegalArgumentException) {
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG).show()
Toast.makeText(context, context?.resources?.getString(R.string.nc_upload_failed), Toast.LENGTH_LONG)
.show()
Log.e(javaClass.simpleName, "Something went wrong when trying to upload file", e)
}
}
@ -662,8 +738,15 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
addCategory(Intent.CATEGORY_OPENABLE)
putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true)
}
startActivityForResult(Intent.createChooser(action, context?.resources?.getString(
R.string.nc_upload_choose_local_files)), REQUEST_CODE_CHOOSE_FILE);
startActivityForResult(
Intent.createChooser(
action,
context?.resources?.getString(
R.string.nc_upload_choose_local_files
)
),
REQUEST_CODE_CHOOSE_FILE
)
}
fun showBrowserScreen(browserType: BrowserController.BrowserType) {
@ -671,19 +754,23 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
bundle.putParcelable(BundleKeys.KEY_BROWSER_TYPE, Parcels.wrap<BrowserController.BrowserType>(browserType))
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, Parcels.wrap<UserEntity>(conversationUser))
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
router.pushController(RouterTransaction.with(BrowserForSharingController(bundle))
router.pushController(
RouterTransaction.with(BrowserForSharingController(bundle))
.pushChangeHandler(VerticalChangeHandler())
.popChangeHandler(VerticalChangeHandler()))
.popChangeHandler(VerticalChangeHandler())
)
}
private fun showConversationInfoScreen() {
val bundle = Bundle()
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, conversationUser)
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomToken)
bundle.putBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, inOneToOneCall());
router.pushController(RouterTransaction.with(ConversationInfoController(bundle))
bundle.putBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, inOneToOneCall())
router.pushController(
RouterTransaction.with(ConversationInfoController(bundle))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()))
.popChangeHandler(HorizontalChangeHandler())
)
}
private fun setupMentionAutocomplete() {
@ -691,8 +778,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
resources?.let {
val backgroundDrawable = ColorDrawable(it.getColor(R.color.bg_default))
val presenter = MentionAutocompletePresenter(applicationContext, roomToken)
val callback = MentionAutocompleteCallback(activity,
conversationUser, messageInput)
val callback = MentionAutocompleteCallback(
activity,
conversationUser, messageInput
)
if (mentionAutocomplete == null && messageInput != null) {
mentionAutocomplete = Autocomplete.on<Mention>(messageInput)
@ -730,8 +819,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
smileyButton?.setColorFilter(resources!!.getColor(R.color.colorPrimary), PorterDuff.Mode.SRC_IN)
}
}.setOnEmojiPopupDismissListener {
smileyButton?.setColorFilter(resources!!.getColor(R.color.emoji_icons),
PorterDuff.Mode.SRC_IN)
smileyButton?.setColorFilter(
resources!!.getColor(R.color.emoji_icons),
PorterDuff.Mode.SRC_IN
)
}.setOnEmojiClickListener { emoji, imageView -> messageInput?.editableText?.append(" ") }.build(it)
}
@ -753,11 +844,15 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun cancelNotificationsForCurrentConversation() {
if (conversationUser != null) {
if (!conversationUser.hasSpreedFeatureCapability("no-ping") && !TextUtils.isEmpty(roomId)) {
NotificationUtils.cancelExistingNotificationsForRoom(applicationContext,
conversationUser, roomId)
NotificationUtils.cancelExistingNotificationsForRoom(
applicationContext,
conversationUser, roomId
)
} else if (!TextUtils.isEmpty(roomToken)) {
NotificationUtils.cancelExistingNotificationsForRoom(applicationContext,
conversationUser, roomToken!!)
NotificationUtils.cancelExistingNotificationsForRoom(
applicationContext,
conversationUser, roomToken!!
)
}
}
}
@ -775,8 +870,12 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
activity?.findViewById<View>(R.id.toolbar)?.setOnClickListener(null)
}
if (conversationUser != null && conversationUser?.hasSpreedFeatureCapability("no-ping")
&& activity != null && !activity?.isChangingConfigurations!! && !isLeavingForConversation) {
if (conversationUser != null &&
conversationUser.hasSpreedFeatureCapability("no-ping") &&
activity != null &&
!activity?.isChangingConfigurations!! &&
!isLeavingForConversation
) {
wasDetached = true
leaveRoom()
}
@ -819,8 +918,13 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun startPing() {
if (conversationUser != null && !conversationUser.hasSpreedFeatureCapability("no-ping")) {
ncApi?.pingCall(credentials, ApiUtils.getUrlForCallPing(conversationUser.baseUrl,
roomToken))
ncApi?.pingCall(
credentials,
ApiUtils.getUrlForCallPing(
conversationUser.baseUrl,
roomToken
)
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.repeatWhen { observable -> observable.delay(5000, TimeUnit.MILLISECONDS) }
@ -832,7 +936,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onNext(genericOverall: GenericOverall) {
}
override fun onError(e: Throwable) {}
@ -850,9 +953,12 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun joinRoomWithPassword() {
if (currentConversation == null || TextUtils.isEmpty(currentConversation?.sessionId) ||
currentConversation?.sessionId == "0") {
ncApi?.joinRoom(credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(conversationUser?.baseUrl, roomToken), roomPassword)
currentConversation?.sessionId == "0"
) {
ncApi?.joinRoom(
credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(conversationUser?.baseUrl, roomToken), roomPassword
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.retry(3)
@ -879,7 +985,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
if (magicWebSocketInstance != null) {
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession(roomToken, currentConversation?.sessionId)
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession(
roomToken,
currentConversation?.sessionId
)
}
if (startCallFromNotification != null && startCallFromNotification ?: false) {
startCallFromNotification = false
@ -888,19 +997,19 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
}
})
} else {
inConversation = true
ApplicationWideCurrentRoomHolder.getInstance().session = currentConversation?.sessionId
if (magicWebSocketInstance != null) {
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession(roomToken,
currentConversation?.sessionId)
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession(
roomToken,
currentConversation?.sessionId
)
}
startPing()
if (isFirstMessagesProcessing) {
@ -912,9 +1021,13 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
private fun leaveRoom() {
ncApi?.leaveRoom(credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(conversationUser?.baseUrl,
roomToken))
ncApi?.leaveRoom(
credentials,
ApiUtils.getUrlForSettingMyselfAsActiveParticipant(
conversationUser?.baseUrl,
roomToken
)
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<GenericOverall> {
@ -930,8 +1043,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
if (magicWebSocketInstance != null && currentConversation != null) {
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession("",
currentConversation?.sessionId)
magicWebSocketInstance?.joinRoomWithRoomTokenAndSession(
"",
currentConversation?.sessionId
)
}
if (!isDestroyed && !isBeingDestroyed && !wasDetached) {
@ -957,14 +1072,15 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
} catch (e: IllegalAccessException) {
Log.w(TAG, "Failed to access and set field")
}
}
private fun submitMessage() {
if (messageInput != null) {
val editable = messageInput!!.editableText
val mentionSpans = editable.getSpans(0, editable.length,
Spans.MentionChipSpan::class.java)
val mentionSpans = editable.getSpans(
0, editable.length,
Spans.MentionChipSpan::class.java
)
var mentionSpan: Spans.MentionChipSpan
for (i in mentionSpans.indices) {
mentionSpan = mentionSpans[i]
@ -977,7 +1093,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
messageInput?.setText("")
val replyMessageId: Int? = view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.tag as Int?
sendMessage(editable, if (view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.visibility == View.VISIBLE) replyMessageId else null)
sendMessage(
editable,
if (view?.findViewById<RelativeLayout>(R.id.quotedChatMessageView)?.visibility == View.VISIBLE) replyMessageId else null
)
cancelReply()
}
}
@ -996,7 +1115,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<GenericOverall> {
override fun onSubscribe(d: Disposable) {
}
override fun onNext(genericOverall: GenericOverall) {
@ -1025,7 +1143,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onComplete() {
}
})
}
@ -1034,7 +1151,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
private fun setupWebsocket() {
if (conversationUser != null) {
if (WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id) != null) {
magicWebSocketInstance = WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id)
magicWebSocketInstance =
WebSocketConnectionHelper.getMagicWebSocketInstanceForUserId(conversationUser.id)
} else {
magicWebSocketInstance = null
}
@ -1047,7 +1165,7 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
if (currentConversation != null && currentConversation!!.shouldShowLobby(conversationUser)) {
//return
// return
}
val fieldMap = HashMap<String, Int>()
@ -1090,8 +1208,10 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
if (!wasDetached) {
if (lookIntoFuture > 0) {
val finalTimeout = timeout
ncApi?.pullChatMessages(credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap)
ncApi?.pullChatMessages(
credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.takeWhile { observable -> inConversation && !wasDetached }
@ -1114,13 +1234,13 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onComplete() {
}
})
} else {
ncApi?.pullChatMessages(credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap)
ncApi?.pullChatMessages(
credentials,
ApiUtils.getUrlForChat(conversationUser?.baseUrl, roomToken), fieldMap
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.takeWhile { observable -> inConversation && !wasDetached }
@ -1141,7 +1261,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onComplete() {
}
})
}
@ -1180,7 +1299,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
loadingProgressBar?.visibility = View.GONE
messagesListView?.visibility = View.VISIBLE
}
var countGroupedMessages = 0
@ -1191,9 +1309,12 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
if (TextUtils.isEmpty(chatMessageList[i].systemMessage) &&
TextUtils.isEmpty(chatMessageList[i + 1].systemMessage) &&
chatMessageList[i + 1].actorId == chatMessageList[i].actorId &&
countGroupedMessages < 4 && DateFormatter.isSameDay(chatMessageList[i].createdAt,
chatMessageList[i + 1].createdAt)) {
chatMessageList[i].isGrouped = true;
countGroupedMessages < 4 && DateFormatter.isSameDay(
chatMessageList[i].createdAt,
chatMessageList[i + 1].createdAt
)
) {
chatMessageList[i].isGrouped = true
countGroupedMessages++
} else {
countGroupedMessages = 0
@ -1201,7 +1322,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
val chatMessage = chatMessageList[i]
chatMessage.isOneToOneConversation = currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
chatMessage.isOneToOneConversation =
currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
chatMessage.isLinkPreviewAllowed = isLinkPreviewAllowed
chatMessage.activeUser = conversationUser
}
@ -1209,7 +1331,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
if (adapter != null) {
adapter?.addToEnd(chatMessageList, false)
}
} else {
var chatMessage: ChatMessage
@ -1225,7 +1346,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
adapter?.addToStart(unreadChatMessage, false)
}
val isThereANewNotice = shouldAddNewMessagesNotice || adapter?.getMessagePositionByIdInReverse("-1") != -1
val isThereANewNotice =
shouldAddNewMessagesNotice || adapter?.getMessagePositionByIdInReverse("-1") != -1
for (i in chatMessageList.indices) {
chatMessage = chatMessageList[i]
@ -1241,7 +1363,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
}
val shouldScroll = !isThereANewNotice && !shouldAddNewMessagesNotice && layoutManager?.findFirstVisibleItemPosition() == 0 || adapter != null && adapter?.itemCount == 0
val shouldScroll =
!isThereANewNotice && !shouldAddNewMessagesNotice && layoutManager?.findFirstVisibleItemPosition() == 0 || adapter != null && adapter?.itemCount == 0
if (!shouldAddNewMessagesNotice && !shouldScroll && popupBubble != null) {
if (!popupBubble!!.isShown) {
@ -1255,18 +1378,24 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
if (adapter != null) {
chatMessage.isGrouped = (adapter!!.isPreviousSameAuthor(chatMessage
.actorId, -1) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) % 5 > 0)
chatMessage.isOneToOneConversation = (currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
chatMessage.isGrouped = (
adapter!!.isPreviousSameAuthor(
chatMessage.actorId,
-1
) && adapter!!.getSameAuthorLastMessagesCount(chatMessage.actorId) % 5 > 0
)
chatMessage.isOneToOneConversation =
(currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL)
adapter?.addToStart(chatMessage, shouldScroll)
}
}
if (shouldAddNewMessagesNotice && adapter != null && messagesListView != null) {
layoutManager?.scrollToPositionWithOffset(adapter!!.getMessagePositionByIdInReverse("-1"), messagesListView!!.height / 2)
layoutManager?.scrollToPositionWithOffset(
adapter!!.getMessagePositionByIdInReverse("-1"),
messagesListView!!.height / 2
)
}
}
// update read status of all messages
@ -1310,7 +1439,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
}
override fun format(date: Date): String {
return if (DateFormatter.isToday(date)) {
resources!!.getString(R.string.nc_date_header_today)
@ -1344,7 +1472,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
}
override fun onOptionsItemSelected(item: MenuItem): Boolean {
when (item.itemId) {
android.R.id.home -> {
@ -1397,7 +1524,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
.SystemMessageType.PARENT_MESSAGE_DELETED
}
private fun startACall(isVoiceOnlyCall: Boolean) {
isLeavingForConversation = true
val callIntent = getIntentForCall(isVoiceOnlyCall)
@ -1427,7 +1553,7 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
} else {
null
}
} ?:run {
} ?: run {
return null
}
}
@ -1440,7 +1566,11 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
}
override fun onMessageViewLongClick(view: View?, message: IMessage?) {
PopupMenu(this.context, view, if (message?.user?.id == conversationUser?.userId) Gravity.END else Gravity.START).apply {
PopupMenu(
this.context,
view,
if (message?.user?.id == conversationUser?.userId) Gravity.END else Gravity.START
).apply {
setOnMenuItemClickListener { item ->
when (item?.itemId) {
@ -1456,28 +1586,40 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
chatMessage?.let {
messageInputView?.findViewById<ImageButton>(R.id.attachmentButton)?.visibility = View.GONE
messageInputView?.findViewById<Space>(R.id.attachmentButtonSpace)?.visibility = View.GONE
messageInputView?.findViewById<ImageButton>(R.id.cancelReplyButton)?.visibility = View.VISIBLE
messageInputView?.findViewById<ImageButton>(R.id.cancelReplyButton)?.visibility =
View.VISIBLE
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.maxLines = 2
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize = TextUtils.TruncateAt.END
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.ellipsize =
TextUtils.TruncateAt.END
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessage)?.text = it.text
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text = it.actorDisplayName
?: context!!.getText(R.string.nc_nick_guest)
messageInputView?.findViewById<EmojiTextView>(R.id.quotedMessageAuthor)?.text =
it.actorDisplayName ?: context!!.getText(R.string.nc_nick_guest)
conversationUser?.let { currentUser ->
chatMessage.imageUrl?.let { previewImageUrl ->
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility = View.VISIBLE
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility =
View.VISIBLE
val px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 96f, resources?.displayMetrics)
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.maxHeight = px.toInt()
val layoutParams = messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.layoutParams as FlexboxLayout.LayoutParams
val px = TypedValue.applyDimension(
TypedValue.COMPLEX_UNIT_DIP,
96f,
resources?.displayMetrics
)
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.maxHeight =
px.toInt()
val layoutParams =
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.layoutParams as FlexboxLayout.LayoutParams
layoutParams.flexGrow = 0f
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.layoutParams = layoutParams
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.load(previewImageUrl) {
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.layoutParams =
layoutParams
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)
?.load(previewImageUrl) {
addHeader("Authorization", credentials!!)
}
} ?: run {
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility = View.GONE
messageInputView?.findViewById<ImageView>(R.id.quotedMessageImage)?.visibility =
View.GONE
}
}
@ -1498,14 +1640,20 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
override fun onNext(t: ChatOverallSingleMessage) {
if (t.ocs.meta.statusCode == HttpURLConnection.HTTP_ACCEPTED) {
Toast.makeText(context, R.string.nc_delete_message_leaked_to_matterbridge,
Toast.LENGTH_LONG).show()
Toast.makeText(
context, R.string.nc_delete_message_leaked_to_matterbridge,
Toast.LENGTH_LONG
).show()
}
}
override fun onError(e: Throwable) {
Log.e(TAG, "Something went wrong when trying to delete message with id " +
message?.id, e)
Log.e(
TAG,
"Something went wrong when trying to delete message with id " +
message?.id,
e
)
Toast.makeText(context, R.string.nc_common_error_sorry, Toast.LENGTH_LONG).show()
}
@ -1531,7 +1679,8 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
val messageTemp = message as ChatMessage
messageTemp.isDeleted = true
messageTemp.isOneToOneConversation = currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
messageTemp.isOneToOneConversation =
currentConversation?.type == Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL
messageTemp.isLinkPreviewAllowed = isLinkPreviewAllowed
messageTemp.activeUser = conversationUser
@ -1561,7 +1710,6 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
return true
}
override fun hasContentFor(message: IMessage, type: Byte): Boolean {
when (type) {
CONTENT_TYPE_SYSTEM_MESSAGE -> return !TextUtils.isEmpty(message.systemMessage)
@ -1589,19 +1737,22 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
@Subscribe(threadMode = ThreadMode.BACKGROUND)
fun onMessageEvent(userMentionClickEvent: UserMentionClickEvent) {
if (currentConversation?.type != Conversation.ConversationType
.ROOM_TYPE_ONE_TO_ONE_CALL || currentConversation?.name !=
userMentionClickEvent.userId) {
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(conversationUser?.baseUrl, "1",
userMentionClickEvent.userId, null)
if (currentConversation?.type != Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL ||
currentConversation?.name != userMentionClickEvent.userId
) {
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
conversationUser?.baseUrl, "1",
userMentionClickEvent.userId, null
)
ncApi?.createRoom(credentials,
retrofitBucket.url, retrofitBucket.queryMap)
ncApi?.createRoom(
credentials,
retrofitBucket.url, retrofitBucket.queryMap
)
?.subscribeOn(Schedulers.io())
?.observeOn(AndroidSchedulers.mainThread())
?.subscribe(object : Observer<RoomOverall> {
override fun onSubscribe(d: Disposable) {
}
override fun onNext(roomOverall: RoomOverall) {
@ -1613,27 +1764,32 @@ class ChatController(args: Bundle) : BaseController(args), MessagesListAdapter
if (conversationUser != null) {
if (conversationUser.hasSpreedFeatureCapability("chat-v2")) {
bundle.putParcelable(BundleKeys.KEY_ACTIVE_CONVERSATION,
Parcels.wrap(roomOverall.ocs.data))
bundle.putParcelable(
BundleKeys.KEY_ACTIVE_CONVERSATION,
Parcels.wrap(roomOverall.ocs.data)
)
conversationIntent.putExtras(bundle)
ConductorRemapping.remapChatController(router, conversationUser.id,
roomOverall.ocs.data.token, bundle, false)
ConductorRemapping.remapChatController(
router, conversationUser.id,
roomOverall.ocs.data.token, bundle, false
)
}
} else {
conversationIntent.putExtras(bundle)
startActivity(conversationIntent)
Handler().postDelayed({
Handler().postDelayed(
{
if (!isDestroyed && !isBeingDestroyed) {
router.popCurrentController()
}
}, 100)
},
100
)
}
}
override fun onError(e: Throwable) {
}
override fun onComplete() {}

View File

@ -85,50 +85,69 @@ import io.reactivex.schedulers.Schedulers
import org.greenrobot.eventbus.EventBus
import org.greenrobot.eventbus.Subscribe
import org.greenrobot.eventbus.ThreadMode
import java.util.*
import java.util.Calendar
import java.util.Collections
import java.util.Comparator
import java.util.Locale
import javax.inject.Inject
import kotlin.collections.ArrayList
@AutoInjector(NextcloudTalkApplication::class)
class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleAdapter.OnItemClickListener {
@BindView(R.id.notification_settings)
lateinit var notificationsPreferenceScreen: MaterialPreferenceScreen
@BindView(R.id.progressBar)
lateinit var progressBar: ProgressBar
@BindView(R.id.conversation_info_message_notifications)
lateinit var messageNotificationLevel: MaterialChoicePreference
@BindView(R.id.webinar_settings)
lateinit var conversationInfoWebinar: MaterialPreferenceScreen
@BindView(R.id.conversation_info_lobby)
lateinit var conversationInfoLobby: MaterialSwitchPreference
@BindView(R.id.conversation_info_name)
lateinit var nameCategoryView: MaterialPreferenceCategory
@BindView(R.id.start_time_preferences)
lateinit var startTimeView: MaterialStandardPreference
@BindView(R.id.avatar_image)
lateinit var conversationAvatarImageView: SimpleDraweeView
@BindView(R.id.display_name_text)
lateinit var conversationDisplayName: EmojiTextView
@BindView(R.id.participants_list_category)
lateinit var participantsListCategory: MaterialPreferenceCategory
@BindView(R.id.addParticipantsAction)
lateinit var addParticipantsAction: MaterialStandardPreference;
lateinit var addParticipantsAction: MaterialStandardPreference
@BindView(R.id.recycler_view)
lateinit var recyclerView: RecyclerView
@BindView(R.id.deleteConversationAction)
lateinit var deleteConversationAction: MaterialStandardPreference
@BindView(R.id.leaveConversationAction)
lateinit var leaveConversationAction: MaterialStandardPreference
@BindView(R.id.ownOptions)
lateinit var ownOptionsCategory: MaterialPreferenceCategory
@BindView(R.id.muteCalls)
lateinit var muteCalls: MaterialSwitchPreference
@set:Inject
lateinit var ncApi: NcApi
@set:Inject
lateinit var context: Context
@set:Inject
lateinit var eventBus: EventBus
@ -164,7 +183,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
hasAvatarSpacing = args.getBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, false);
hasAvatarSpacing = args.getBoolean(BundleKeys.KEY_ROOM_ONE_TO_ONE, false)
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
}
@ -207,12 +226,17 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
private fun setupWebinaryView() {
if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") && (conversation!!.type
== Conversation.ConversationType.ROOM_GROUP_CALL || conversation!!.type ==
Conversation.ConversationType.ROOM_PUBLIC_CALL) && conversation!!.canModerate(conversationUser)) {
if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") &&
(
conversation!!.type == Conversation.ConversationType.ROOM_GROUP_CALL ||
conversation!!.type == Conversation.ConversationType.ROOM_PUBLIC_CALL
) &&
conversation!!.canModerate(conversationUser)
) {
conversationInfoWebinar.visibility = View.VISIBLE
val isLobbyOpenToModeratorsOnly = conversation!!.lobbyState == Conversation.LobbyState.LOBBY_STATE_MODERATORS_ONLY
val isLobbyOpenToModeratorsOnly =
conversation!!.lobbyState == Conversation.LobbyState.LOBBY_STATE_MODERATORS_ONLY
(conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat)
.isChecked = isLobbyOpenToModeratorsOnly
@ -225,12 +249,17 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * 1000
}
dateTimePicker(minDateTime = Calendar.getInstance(), requireFutureDateTime =
true, currentDateTime = currentTimeCalendar, dateTimeCallback = { _,
dateTimePicker(
minDateTime = Calendar.getInstance(),
requireFutureDateTime =
true,
currentDateTime = currentTimeCalendar,
dateTimeCallback = { _,
dateTime ->
reconfigureLobbyTimerView(dateTime)
submitLobbyChanges()
})
}
)
}
}
@ -269,11 +298,19 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
fun submitLobbyChanges() {
val state = if ((conversationInfoLobby.findViewById<View>(R.id
.mp_checkable) as SwitchCompat).isChecked) 1 else 0
ncApi.setLobbyForConversation(ApiUtils.getCredentials(conversationUser!!.username,
conversationUser.token), ApiUtils.getUrlForLobbyForConversation
(conversationUser.baseUrl, conversation!!.token), state, conversation!!.lobbyTimer)
val state = if (
(
conversationInfoLobby.findViewById<View>(
R.id.mp_checkable
) as SwitchCompat
).isChecked
) 1 else 0
ncApi.setLobbyForConversation(
ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token),
ApiUtils.getUrlForLobbyForConversation(conversationUser.baseUrl, conversation!!.token),
state,
conversation!!.lobbyTimer
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<GenericOverall> {
@ -288,7 +325,6 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
override fun onError(e: Throwable) {
}
})
}
@ -314,8 +350,12 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
if (activity != null) {
LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL)
.setTopColorRes(R.color.nc_darkRed)
.setIcon(DisplayUtils.getTintedDrawable(context!!.resources,
R.drawable.ic_delete_black_24dp, R.color.bg_default))
.setIcon(
DisplayUtils.getTintedDrawable(
context!!.resources,
R.drawable.ic_delete_black_24dp, R.color.bg_default
)
)
.setPositiveButtonColor(context!!.resources.getColor(R.color.nc_darkRed))
.setTitle(R.string.nc_delete_call)
.setMessage(conversation!!.deleteWarningMessage)
@ -335,8 +375,8 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
super.onRestoreViewState(view, savedViewState)
if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
//Dialog won't be restarted automatically, so we need to call this method.
//Each dialog knows how to restore its state
// Dialog won't be restarted automatically, so we need to call this method.
// Each dialog knows how to restore its state
showLovelyDialog(LovelySaveStateHandler.getSavedDialogId(savedViewState), savedViewState)
}
}
@ -397,7 +437,10 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
private fun getListOfParticipants() {
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken))
ncApi.getPeersForCall(
credentials,
ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<ParticipantsOverall> {
@ -410,14 +453,12 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
participantsDisposable!!.dispose()
}
})
}
@OnClick(R.id.addParticipantsAction)
@ -430,21 +471,33 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
existingParticipantsId.add(userItem.model.userId)
}
bundle.putBoolean(BundleKeys.KEY_ADD_PARTICIPANTS, true);
bundle.putBoolean(BundleKeys.KEY_ADD_PARTICIPANTS, true)
bundle.putStringArrayList(BundleKeys.KEY_EXISTING_PARTICIPANTS, existingParticipantsId)
bundle.putString(BundleKeys.KEY_TOKEN, conversation!!.token)
getRouter().pushController((RouterTransaction.with(ContactsController(bundle))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler())))
getRouter().pushController(
(
RouterTransaction.with(
ContactsController(bundle)
)
.pushChangeHandler(
HorizontalChangeHandler()
)
.popChangeHandler(
HorizontalChangeHandler()
)
)
)
}
@OnClick(R.id.leaveConversationAction)
internal fun leaveConversation() {
workerData?.let {
WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
(LeaveConversationWorker::class
.java).setInputData(it).build()
WorkManager.getInstance().enqueue(
OneTimeWorkRequest.Builder(
LeaveConversationWorker::class
.java
).setInputData(it).build()
)
popTwoLastControllers()
}
@ -452,8 +505,11 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
private fun deleteConversation() {
workerData?.let {
WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
(DeleteConversationWorker::class.java).setInputData(it).build())
WorkManager.getInstance().enqueue(
OneTimeWorkRequest.Builder(
DeleteConversationWorker::class.java
).setInputData(it).build()
)
popTwoLastControllers()
}
}
@ -518,7 +574,6 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
conversationDisplayName.text = conversation!!.displayName
loadConversationAvatar()
adjustNotificationLevelUI()
@ -527,7 +582,6 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
override fun onError(e: Throwable) {
}
override fun onComplete() {
@ -543,7 +597,8 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
messageNotificationLevel.alpha = 1.0f
if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) {
val stringValue: String = when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
val stringValue: String =
when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
1 -> "always"
2 -> "mention"
3 -> "never"
@ -577,22 +632,38 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
private fun loadConversationAvatar() {
when (conversation!!.type) {
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty
(conversation!!.name)) {
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (
!TextUtils.isEmpty(conversation!!.name)
) {
val draweeController = Fresco.newDraweeControllerBuilder()
.setOldController(conversationAvatarImageView.controller)
.setAutoPlayAnimations(true)
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(conversationUser!!.baseUrl,
conversation!!.name, R.dimen.avatar_size_big), conversationUser))
.setImageRequest(
DisplayUtils.getImageRequestForUrl(
ApiUtils.getUrlForAvatarWithName(
conversationUser!!.baseUrl,
conversation!!.name, R.dimen.avatar_size_big
),
conversationUser
)
)
.build()
conversationAvatarImageView.controller = draweeController
}
Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
.getRoundedBitmapDrawableFromVectorDrawableResource(resources,
R.drawable.ic_people_group_white_24px))
Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
.getRoundedBitmapDrawableFromVectorDrawableResource(resources,
R.drawable.ic_link_white_24px))
Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
DisplayUtils
.getRoundedBitmapDrawableFromVectorDrawableResource(
resources,
R.drawable.ic_people_group_white_24px
)
)
Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
DisplayUtils
.getRoundedBitmapDrawableFromVectorDrawableResource(
resources,
R.drawable.ic_link_white_24px
)
)
Conversation.ConversationType.ROOM_SYSTEM -> {
val layers = arrayOfNulls<Drawable>(2)
layers[0] = context.getDrawable(R.drawable.ic_launcher_background)
@ -610,13 +681,14 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
val userItem = adapter?.getItem(position) as UserItem
val participant = userItem.model
if (participant.userId != conversationUser!!.userId) {
var items = mutableListOf(
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_promote)),
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
BasicListItemWithImage(R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_participant))
BasicListItemWithImage(
R.drawable.ic_delete_grey600_24dp,
context.getString(R.string.nc_remove_participant)
)
)
if (!conversation!!.canModerate(conversationUser)) {
@ -629,7 +701,6 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
}
if (items.isNotEmpty()) {
MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
cornerRadius(res = R.dimen.corner_radius)
@ -639,14 +710,22 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
if (index == 0) {
if (participant.type == Participant.ParticipantType.MODERATOR) {
ncApi.demoteModeratorToUser(credentials, ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), participant.userId)
ncApi.demoteModeratorToUser(
credentials,
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token),
participant.userId
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
getListOfParticipants()
}
} else if (participant.type == Participant.ParticipantType.USER) {
ncApi.promoteUserToModerator(credentials, ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), participant.userId)
ncApi.promoteUserToModerator(
credentials,
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token),
participant.userId
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
@ -655,16 +734,32 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
} else if (index == 1) {
if (participant.type == Participant.ParticipantType.GUEST ||
participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK) {
ncApi.removeParticipantFromConversation(credentials, ApiUtils.getUrlForRemovingParticipantFromConversation(conversationUser.baseUrl, conversation!!.token, true), participant.sessionId)
participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK
) {
ncApi.removeParticipantFromConversation(
credentials,
ApiUtils.getUrlForRemovingParticipantFromConversation(
conversationUser.baseUrl,
conversation!!.token,
true
),
participant.sessionId
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
getListOfParticipants()
}
} else {
ncApi.removeParticipantFromConversation(credentials, ApiUtils.getUrlForRemovingParticipantFromConversation(conversationUser.baseUrl, conversation!!.token, false), participant.userId)
ncApi.removeParticipantFromConversation(
credentials,
ApiUtils.getUrlForRemovingParticipantFromConversation(
conversationUser.baseUrl,
conversation!!.token,
false
),
participant.userId
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe {
@ -678,7 +773,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
}
}
return true;
return true
}
companion object {

View File

@ -53,5 +53,4 @@ abstract class ButterKnifeController : Controller {
unbinder!!.unbind()
unbinder = null
}
}

View File

@ -30,7 +30,8 @@ interface ListItemWithImage {
data class BasicListItemWithImage(
@DrawableRes val iconRes: Int,
override val title: String) : ListItemWithImage {
override val title: String
) : ListItemWithImage {
override fun populateIcon(imageView: ImageView) {
imageView.setImageResource(iconRes)

View File

@ -23,7 +23,6 @@ package com.nextcloud.talk.controllers.bottomsheet.items
import android.view.View
import android.view.ViewGroup
import android.widget.ImageView
import android.widget.TextView
import androidx.recyclerview.widget.RecyclerView
import com.afollestad.materialdialogs.MaterialDialog
import com.afollestad.materialdialogs.WhichButton
@ -34,14 +33,14 @@ import com.afollestad.materialdialogs.internal.rtl.RtlTextView
import com.afollestad.materialdialogs.list.getItemSelector
import com.afollestad.materialdialogs.utils.MDUtil.inflate
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
import com.google.android.material.textview.MaterialTextView
import com.nextcloud.talk.R
private const val KEY_ACTIVATED_INDEX = "activated_index"
internal class ListItemViewHolder(
itemView: View,
private val adapter: ListIconDialogAdapter<*>) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
private val adapter: ListIconDialogAdapter<*>
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
init {
itemView.setOnClickListener(this)
}
@ -57,7 +56,8 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
private var items: List<IT>,
disabledItems: IntArray?,
private var waitForPositiveButton: Boolean,
private var selection: ListItemListener<IT>) : RecyclerView.Adapter<ListItemViewHolder>(), DialogAdapter<IT, ListItemListener<IT>> {
private var selection: ListItemListener<IT>
) : RecyclerView.Adapter<ListItemViewHolder>(), DialogAdapter<IT, ListItemListener<IT>> {
private var disabledIndices: IntArray = disabledItems ?: IntArray(0)
@ -82,7 +82,8 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
override fun onCreateViewHolder(
parent: ViewGroup,
viewType: Int): ListItemViewHolder {
viewType: Int
): ListItemViewHolder {
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
val viewHolder = ListItemViewHolder(
itemView = listItemView,
@ -96,7 +97,8 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
override fun onBindViewHolder(
holder: ListItemViewHolder,
position: Int) {
position: Int
) {
holder.itemView.isEnabled = !disabledIndices.contains(position)
val currentItem = items[position]
@ -122,7 +124,8 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
override fun replaceItems(
items: List<IT>,
listener: ListItemListener<IT>) {
listener: ListItemListener<IT>
) {
this.items = items
if (listener != null) {
this.selection = listener

View File

@ -30,11 +30,13 @@ import com.afollestad.materialdialogs.list.getListAdapter
typealias ListItemListener<IT> =
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
@CheckResult fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
@CheckResult
fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
items: List<IT>,
disabledIndices: IntArray? = null,
waitForPositiveButton: Boolean = true,
selection: ListItemListener<IT> = null): MaterialDialog {
selection: ListItemListener<IT> = null
): MaterialDialog {
if (getListAdapter() != null) {
return updateListItemsWithImage(
@ -58,7 +60,8 @@ typealias ListItemListener<IT> =
fun MaterialDialog.updateListItemsWithImage(
items: List<ListItemWithImage>,
disabledIndices: IntArray? = null): MaterialDialog {
disabledIndices: IntArray? = null
): MaterialDialog {
val adapter = getListAdapter()
check(adapter != null) {
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."

View File

@ -20,6 +20,4 @@
package com.nextcloud.talk.events
class CallNotificationClick {
}
class CallNotificationClick

View File

@ -33,7 +33,11 @@ import android.provider.ContactsContract
import android.util.Log
import androidx.core.content.ContextCompat
import androidx.core.os.ConfigurationCompat
import androidx.work.*
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import autodagger.AutoInjector
import com.bluelinelabs.conductor.Controller
import com.google.gson.Gson
@ -54,7 +58,6 @@ import okhttp3.MediaType
import okhttp3.RequestBody
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class ContactAddressBookWorker(val context: Context, workerParameters: WorkerParameters) :
Worker(context, workerParameters) {
@ -85,7 +88,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
}
val deleteAll = inputData.getBoolean(DELETE_ALL, false)
if(deleteAll){
if (deleteAll) {
deleteAllLinkedAccounts()
return Result.success()
}
@ -99,7 +102,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
}
}
if(AccountManager.get(context).getAccountsByType(accountType).isEmpty()){
if (AccountManager.get(context).getAccountsByType(accountType).isEmpty()) {
AccountManager.get(context).addAccountExplicitly(Account(accountName, accountType), "", null)
} else {
Log.d(TAG, "Account already exists")
@ -107,7 +110,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
val deviceContactsWithNumbers = collectContactsWithPhoneNumbersFromDevice()
if(deviceContactsWithNumbers.isNotEmpty()){
if (deviceContactsWithNumbers.isNotEmpty()) {
val currentLocale = ConfigurationCompat.getLocales(context.resources.configuration)[0].country
val map = mutableMapOf<String, Any>()
@ -119,7 +122,8 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
ncApi.searchContactsByPhoneNumber(
ApiUtils.getCredentials(currentUser.username, currentUser.token),
ApiUtils.getUrlForSearchByNumber(currentUser.baseUrl),
RequestBody.create(MediaType.parse("application/json"), json))
RequestBody.create(MediaType.parse("application/json"), json)
)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(object : Observer<ContactsByNumberOverall> {
@ -163,7 +167,8 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
contactCursor.moveToFirst()
for (i in 0 until contactCursor.count) {
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
val lookup = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
val lookup =
contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY))
deviceContactsWithNumbers[lookup] = getPhoneNumbersFromDeviceContact(id)
contactCursor.moveToNext()
}
@ -183,8 +188,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.build()
val count = context.contentResolver.delete(rawContactUri, ContactsContract.RawContacts.CONTACT_ID + " " +
"LIKE \"" + id + "\"", null)
val count = context.contentResolver.delete(
rawContactUri,
ContactsContract.RawContacts.CONTACT_ID + " " + "LIKE \"" + id + "\"",
null
)
Log.d(TAG, "deleted $count linked accounts for id $id")
}
@ -193,7 +201,10 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
.appendQueryParameter(
ContactsContract.Data.MIMETYPE,
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
)
.build()
val rawContactsCursor = context.contentResolver.query(
@ -207,10 +218,15 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
if (rawContactsCursor != null) {
if (rawContactsCursor.count > 0) {
while (rawContactsCursor.moveToNext()) {
val lookupKey = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))
val contactId = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
val lookupKey =
rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))
val contactId =
rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
if (contactsWithAssociatedPhoneNumbers == null || !contactsWithAssociatedPhoneNumbers.containsKey(lookupKey)) {
if (contactsWithAssociatedPhoneNumbers == null || !contactsWithAssociatedPhoneNumbers.containsKey(
lookupKey
)
) {
deleteLinkedAccount(contactId)
}
}
@ -222,9 +238,10 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
}
private fun createLinkedAccounts(contactsWithAssociatedPhoneNumbers: Map<String, String>?) {
fun hasLinkedAccount(id: String) : Boolean {
fun hasLinkedAccount(id: String): Boolean {
var hasLinkedAccount = false
val where = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
val where =
ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
val params = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
val rawContactUri = ContactsContract.Data.CONTENT_URI
@ -232,7 +249,10 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
.appendQueryParameter(
ContactsContract.Data.MIMETYPE,
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
)
.build()
val rawContactsCursor = context.contentResolver.query(
@ -263,14 +283,15 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
null,
null,
null,
null)
null
)
if (contactCursor != null) {
if (contactCursor.count > 0) {
contactCursor.moveToFirst()
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
if(hasLinkedAccount(id)){
if (hasLinkedAccount(id)) {
return
}
@ -285,34 +306,60 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
ops.add(ContentProviderOperation
ops.add(
ContentProviderOperation
.newInsert(rawContactsUri)
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
.withValue(
ContactsContract.RawContacts.AGGREGATION_MODE,
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT
)
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
.build())
ops.add(ContentProviderOperation
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.Phone.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers[0])
.build())
ops.add(ContentProviderOperation
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE)
.withValue(
ContactsContract.Data.MIMETYPE,
ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE
)
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
.build())
ops.add(ContentProviderOperation
.build()
)
ops.add(
ContentProviderOperation
.newInsert(dataUri)
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
.withValue(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
.withValue(
ContactsContract.Data.MIMETYPE,
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
)
.withValue(ContactsContract.Data.DATA1, cloudId)
.withValue(ContactsContract.Data.DATA2, String.format(context.resources.getString(R
.string.nc_phone_book_integration_chat_via), accountName))
.build())
.withValue(
ContactsContract.Data.DATA2,
String.format(
context.resources.getString(
R.string.nc_phone_book_integration_chat_via
),
accountName
)
)
.build()
)
try {
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
@ -322,8 +369,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
Log.e(javaClass.simpleName, "", e)
}
Log.d(TAG, "added new entry for contact $displayName (cloudId: $cloudId | lookupKey: $lookupKey" +
" | id: $id)")
Log.d(
TAG,
"added new entry for contact $displayName (cloudId: $cloudId | lookupKey: $lookupKey" +
" | id: $id)"
)
}
contactCursor.close()
}
@ -341,18 +391,21 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
}
private fun getDisplayNameFromDeviceContact(id: String?): String? {
var displayName:String? = null
val whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
var displayName: String? = null
val whereName =
ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
val nameCursor = context.contentResolver.query(
ContactsContract.Data.CONTENT_URI,
null,
whereName,
whereNameParams,
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
)
if (nameCursor != null) {
while (nameCursor.moveToNext()) {
displayName = nameCursor.getString(nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME))
displayName =
nameCursor.getString(nameCursor.getColumnIndex(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME))
}
nameCursor.close()
}
@ -366,7 +419,8 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
null,
ContactsContract.Data.CONTACT_ID + " = " + id,
null,
null)
null
)
if (phonesNumbersCursor != null) {
while (phonesNumbersCursor.moveToNext()) {
@ -374,7 +428,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
}
phonesNumbersCursor.close()
}
if(numbers.size > 0){
if (numbers.size > 0) {
Log.d(TAG, "Found ${numbers.size} phone numbers for contact with id $id")
}
return numbers
@ -398,32 +452,51 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
const val DELETE_ALL = "DELETE_ALL"
fun run(context: Context) {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.WRITE_CONTACTS
) == PackageManager.PERMISSION_GRANTED &&
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_CONTACTS
) == PackageManager.PERMISSION_GRANTED
) {
WorkManager
.getInstance()
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.enqueue(
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.setInputData(Data.Builder().putBoolean(KEY_FORCE, false).build())
.build())
.build()
)
}
}
fun checkPermission(controller: Controller, context: Context): Boolean {
if (ContextCompat.checkSelfPermission(context,
Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(context,
Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
controller.requestPermissions(arrayOf(Manifest.permission.WRITE_CONTACTS,
Manifest.permission.READ_CONTACTS), REQUEST_PERMISSION)
if (ContextCompat.checkSelfPermission(
context,
Manifest.permission.WRITE_CONTACTS
) != PackageManager.PERMISSION_GRANTED ||
ContextCompat.checkSelfPermission(
context,
Manifest.permission.READ_CONTACTS
) != PackageManager.PERMISSION_GRANTED
) {
controller.requestPermissions(
arrayOf(
Manifest.permission.WRITE_CONTACTS,
Manifest.permission.READ_CONTACTS
),
REQUEST_PERMISSION
)
return false
} else {
WorkManager
.getInstance()
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.enqueue(
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.setInputData(Data.Builder().putBoolean(KEY_FORCE, true).build())
.build())
.build()
)
return true
}
}
@ -431,9 +504,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
fun deleteAll() {
WorkManager
.getInstance()
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.enqueue(
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
.setInputData(Data.Builder().putBoolean(DELETE_ALL, true).build())
.build())
.build()
)
}
}
}

View File

@ -33,10 +33,13 @@ import com.nextcloud.talk.utils.ApiUtils
import com.nextcloud.talk.utils.database.user.UserUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import okhttp3.ResponseBody
import java.io.*
import java.io.BufferedInputStream
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.io.OutputStream
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerParameters) :
Worker(context, workerParameters) {
@ -87,7 +90,8 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
private fun downloadFile(currentUser: UserEntity, url: String, fileName: String): Result {
val downloadCall = ncApi.downloadFile(
ApiUtils.getCredentials(currentUser.username, currentUser.token),
url)
url
)
return executeDownload(downloadCall.execute().body(), fileName)
}
@ -152,6 +156,5 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
const val KEY_FILE_SIZE = "KEY_FILE_SIZE"
const val PROGRESS = "PROGRESS"
const val SUCCESS = "SUCCESS"
}
}

View File

@ -23,7 +23,11 @@ package com.nextcloud.talk.jobs
import android.content.Context
import android.net.Uri
import android.util.Log
import androidx.work.*
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import androidx.work.Worker
import androidx.work.WorkerParameters
import autodagger.AutoInjector
import com.nextcloud.talk.api.NcApi
import com.nextcloud.talk.application.NextcloudTalkApplication
@ -46,10 +50,9 @@ import retrofit2.Response
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import java.util.*
import java.util.ArrayList
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerParameters) :
Worker(context, workerParameters) {
@ -107,8 +110,14 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
return requestBody
}
private fun uploadFile(currentUser: UserEntity, ncTargetpath: String?, filename: String, roomToken: String?,
requestBody: RequestBody?, sourcefileUri: Uri) {
private fun uploadFile(
currentUser: UserEntity,
ncTargetpath: String?,
filename: String,
roomToken: String?,
requestBody: RequestBody?,
sourcefileUri: Uri
) {
ncApi.uploadFile(
ApiUtils.getCredentials(currentUser.username, currentUser.token),
ApiUtils.getUrlForFileUpload(currentUser.baseUrl, currentUser.userId, ncTargetpath, filename),

View File

@ -46,4 +46,3 @@ class ChatUtils {
}
}
}

View File

@ -22,11 +22,28 @@ package com.nextcloud.talk.models.json.converters
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
import com.nextcloud.talk.models.json.chat.ChatMessage
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.*
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_ENDED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_JOINED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_LEFT
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_STARTED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CONVERSATION_CREATED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CONVERSATION_RENAMED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.DUMMY
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.FILE_SHARED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.GUESTS_ALLOWED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.GUESTS_DISALLOWED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.LOBBY_NONE
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.LOBBY_NON_MODERATORS
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.LOBBY_OPEN_TO_EVERYONE
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.MODERATOR_DEMOTED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.MODERATOR_PROMOTED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.PARENT_MESSAGE_DELETED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.PASSWORD_REMOVED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.PASSWORD_SET
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.USER_ADDED
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.USER_REMOVED
/*
conversation_created - {actor} created the conversation
conversation_renamed - {actor} renamed the conversation from "foo" to "bar"
call_joined - {actor} joined the call
@ -40,7 +57,6 @@ import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.*
user_removed - {actor} removed {user} from the conversation
moderator_promoted - {actor} promoted {user} to moderator
moderator_demoted - {actor} demoted {user} from moderator
*/
class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() {
override fun getFromString(string: String): ChatMessage.SystemMessageType {

View File

@ -20,12 +20,10 @@
package com.nextcloud.talk.receivers
import android.app.NotificationChannelGroup
import android.app.NotificationManager
import android.content.BroadcastReceiver
import android.content.Context
import android.content.Intent
import android.content.pm.PackageInfo
import android.content.pm.PackageManager
import android.os.Build
import android.util.Log
@ -34,7 +32,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.utils.NotificationUtils
import com.nextcloud.talk.utils.database.user.UserUtils
import com.nextcloud.talk.utils.preferences.AppPreferences
import javax.inject.Inject
@AutoInjector(NextcloudTalkApplication::class)
@ -50,16 +47,20 @@ class PackageReplacedReceiver : BroadcastReceiver() {
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
if (intent != null && intent.action != null &&
intent.action == "android.intent.action.MY_PACKAGE_REPLACED") {
intent.action == "android.intent.action.MY_PACKAGE_REPLACED"
) {
try {
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
if (packageInfo.versionCode > 43 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = context.getSystemService(Context
.NOTIFICATION_SERVICE) as NotificationManager
val notificationManager = context.getSystemService(
Context
.NOTIFICATION_SERVICE
) as NotificationManager
if (!appPreferences.isNotificationChannelUpgradedToV2) {
for (notificationChannelGroup in notificationManager
.notificationChannelGroups) {
for (
notificationChannelGroup in notificationManager.notificationChannelGroups
) {
notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id)
}
@ -80,7 +81,6 @@ class PackageReplacedReceiver : BroadcastReceiver() {
} catch (e: PackageManager.NameNotFoundException) {
Log.e(TAG, "Failed to fetch package info")
}
}
}

View File

@ -32,7 +32,6 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.components.filebrowser.controllers.BrowserController
import com.nextcloud.talk.controllers.ChatController
class AttachmentDialog(val activity: Activity, var chatController: ChatController) : BottomSheetDialog(activity) {
@BindView(R.id.txt_attach_file_from_local)
@ -54,7 +53,7 @@ class AttachmentDialog(val activity: Activity, var chatController: ChatControlle
var serverName = chatController.conversationUser?.serverName
attachFromCloud?.text = chatController.resources?.let {
if(serverName.isNullOrEmpty()){
if (serverName.isNullOrEmpty()) {
serverName = it.getString(R.string.nc_server_product_name)
}
String.format(it.getString(R.string.nc_upload_from_cloud), serverName)

View File

@ -30,11 +30,12 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.controllers.ProfileController
import com.nextcloud.talk.models.json.userprofile.Scope
class ScopeDialog(con: Context,
class ScopeDialog(
con: Context,
private val userInfoAdapter: ProfileController.UserInfoAdapter,
private val field: ProfileController.Field,
private val position: Int) :
private val position: Int
) :
BottomSheetDialog(con) {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

View File

@ -32,7 +32,8 @@ import com.nextcloud.talk.R
import com.nextcloud.talk.application.NextcloudTalkApplication
import com.nextcloud.talk.models.ImportAccount
import com.nextcloud.talk.models.database.UserEntity
import java.util.*
import java.util.ArrayList
import java.util.Arrays
object AccountUtils {
@ -60,14 +61,15 @@ object AccountUtils {
break
}
} else {
if (internalUserEntity.username == importAccount.username && (internalUserEntity
.baseUrl == "http://" + importAccount.baseUrl ||
internalUserEntity.baseUrl == "https://" + importAccount
.baseUrl)) {
if (internalUserEntity.username == importAccount.username &&
(
internalUserEntity.baseUrl == "http://" + importAccount.baseUrl ||
internalUserEntity.baseUrl == "https://" + importAccount.baseUrl
)
) {
accountFound = true
break
}
}
} else {
accountFound = true
@ -88,8 +90,12 @@ object AccountUtils {
val packageManager = context.packageManager
var appName = ""
try {
appName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName,
PackageManager.GET_META_DATA)) as String
appName = packageManager.getApplicationLabel(
packageManager.getApplicationInfo(
packageName,
PackageManager.GET_META_DATA
)
) as String
} catch (e: PackageManager.NameNotFoundException) {
Log.e(TAG, "Failed to get app name based on package")
}
@ -103,7 +109,10 @@ object AccountUtils {
val packageInfo = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0)
if (packageInfo.versionCode >= 30060151) {
val ownSignatures = pm.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES).signatures
val filesAppSignatures = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), PackageManager.GET_SIGNATURES).signatures
val filesAppSignatures = pm.getPackageInfo(
context.getString(R.string.nc_import_accounts_from),
PackageManager.GET_SIGNATURES
).signatures
if (Arrays.equals(ownSignatures, filesAppSignatures)) {
val accMgr = AccountManager.get(context)
@ -118,7 +127,7 @@ object AccountUtils {
}
}
} catch (appNotFoundException: PackageManager.NameNotFoundException) {
// ignore
}
return false
@ -146,4 +155,3 @@ object AccountUtils {
return ImportAccount(username, password, urlString)
}
}

View File

@ -27,7 +27,13 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
import com.nextcloud.talk.controllers.ChatController
object ConductorRemapping {
fun remapChatController(router: Router, internalUserId: Long, roomTokenOrId: String, bundle: Bundle, replaceTop: Boolean) {
fun remapChatController(
router: Router,
internalUserId: Long,
roomTokenOrId: String,
bundle: Bundle,
replaceTop: Boolean
) {
val tag = "$internalUserId@$roomTokenOrId"
if (router.getControllerWithTag(tag) != null) {
val backstack = router.backstack
@ -44,13 +50,17 @@ object ConductorRemapping {
router.setBackstack(backstack, HorizontalChangeHandler())
} else {
if (!replaceTop) {
router.pushController(RouterTransaction.with(ChatController(bundle))
router.pushController(
RouterTransaction.with(ChatController(bundle))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()).tag(tag))
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
)
} else {
router.replaceTopController(RouterTransaction.with(ChatController(bundle))
router.replaceTopController(
RouterTransaction.with(ChatController(bundle))
.pushChangeHandler(HorizontalChangeHandler())
.popChangeHandler(HorizontalChangeHandler()).tag(tag))
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
)
}
}
}

View File

@ -21,8 +21,9 @@
package com.nextcloud.talk.utils
import java.text.DateFormat
import java.util.*
import java.util.Calendar
import java.util.Date
import java.util.Locale
object DateUtils {
fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
@ -30,14 +31,16 @@ object DateUtils {
val tz = cal.timeZone
/* date formatter in local timezone */
val format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT, Locale
.getDefault())
val format = DateFormat.getDateTimeInstance(
DateFormat.DEFAULT, DateFormat.SHORT,
Locale.getDefault()
)
format.timeZone = tz
return format.format(Date(timestamp))
}
fun getLocalDateStringFromTimestampForLobby(timestamp: Long): String {
return getLocalDateTimeStringFromTimestamp(timestamp * 1000);
return getLocalDateTimeStringFromTimestamp(timestamp * 1000)
}
}

View File

@ -21,12 +21,10 @@
package com.nextcloud.talk.utils
import com.nextcloud.talk.R
import java.util.HashMap
object DrawableUtils {
fun getDrawableResourceIdForMimeType(mimetype: String): Int {
var localMimetype = mimetype
val drawableMap = HashMap<String, Int>()
@ -55,15 +53,20 @@ object DrawableUtils {
drawableMap["application/vnd.google-earth.kmz"] = R.drawable.ic_mimetype_location
drawableMap["application/vnd.ms-excel"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-excel.addin.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-excel.sheet.binary.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-excel.sheet.binary.macroEnabled.12"] =
R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-excel.sheet.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-excel.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.ms-fontobject"] = R.drawable.ic_mimetype_image
drawableMap["application/vnd.ms-powerpoint"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.addin.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.addin.macroEnabled.12"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.slideshow.macroEnabled.12"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-powerpoint.template.macroEnabled.12"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.ms-visio.drawing.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.ms-visio.drawing"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.ms-visio.stencil.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
@ -72,20 +75,29 @@ object DrawableUtils {
drawableMap["application/vnd.ms-visio.template"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.ms-word.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.oasis.opendocument.presentation"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.oasis.opendocument.presentation-template"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.oasis.opendocument.presentation-template"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.oasis.opendocument.spreadsheet"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.oasis.opendocument.spreadsheet-template"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.oasis.opendocument.spreadsheet-template"] =
R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.oasis.opendocument.text"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.oasis.opendocument.text-master"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.oasis.opendocument.text-template"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.oasis.opendocument.text-web"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.presentation"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.template"] = R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] = R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.presentation"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.template"] =
R.drawable.ic_mimetype_x_office_presentation
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] =
R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] =
R.drawable.ic_mimetype_x_office_spreadsheet
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] =
R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] =
R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.visio"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/vnd.wordperfect"] = R.drawable.ic_mimetype_x_office_document
drawableMap["application/x-7z-compressed"] = R.drawable.ic_mimetype_package_x_generic

View File

@ -29,7 +29,7 @@ import com.nextcloud.talk.BuildConfig
import java.io.FileNotFoundException
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import java.util.Date
object LoggingUtils {
fun writeLogEntryToFile(context: Context, logEntry: String) {
@ -38,8 +38,10 @@ object LoggingUtils {
val logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n"
try {
val outputStream = context.openFileOutput("nc_log.txt",
Context.MODE_PRIVATE or Context.MODE_APPEND)
val outputStream = context.openFileOutput(
"nc_log.txt",
Context.MODE_PRIVATE or Context.MODE_APPEND
)
outputStream.write(logEntryWithDateTime.toByteArray())
outputStream.flush()
outputStream.close()
@ -48,13 +50,12 @@ object LoggingUtils {
} catch (e: IOException) {
e.printStackTrace()
}
}
fun sendMailWithAttachment(context: Context) {
val logFile = context.getFileStreamPath("nc_log.txt")
val emailIntent = Intent(Intent.ACTION_SEND)
val mailto = "mario@nextcloud.com"
val mailto = "android@nextcloud.com"
emailIntent.putExtra(Intent.EXTRA_EMAIL, arrayOf(mailto))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs")
emailIntent.type = "text/plain"

View File

@ -33,7 +33,7 @@ import android.service.notification.StatusBarNotification
import com.nextcloud.talk.R
import com.nextcloud.talk.models.database.UserEntity
import com.nextcloud.talk.utils.bundle.BundleKeys
import java.util.*
import java.util.Objects
object NotificationUtils {
val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
@ -47,25 +47,50 @@ object NotificationUtils {
return longArrayOf(0L, 400L, 800L, 600L, 800L, 800L, 800L, 1000L)
}
fun getNotificationChannelId(channelName: String,
channelDescription: String, enableLights: Boolean,
importance: Int, sound: Uri, audioAttributes: AudioAttributes, vibrationPattern: LongArray?, bypassDnd: Boolean): String {
return Objects.hash(channelName, channelDescription, enableLights, importance, sound, audioAttributes, vibrationPattern, bypassDnd).toString()
fun getNotificationChannelId(
channelName: String,
channelDescription: String,
enableLights: Boolean,
importance: Int,
sound: Uri,
audioAttributes: AudioAttributes,
vibrationPattern: LongArray?,
bypassDnd: Boolean
): String {
return Objects.hash(
channelName,
channelDescription,
enableLights,
importance,
sound,
audioAttributes,
vibrationPattern,
bypassDnd
).toString()
}
@TargetApi(Build.VERSION_CODES.O)
fun createNotificationChannel(context: Context,
channelId: String, channelName: String,
channelDescription: String, enableLights: Boolean,
importance: Int, sound: Uri, audioAttributes: AudioAttributes,
vibrationPattern: LongArray?, bypassDnd: Boolean = false) {
fun createNotificationChannel(
context: Context,
channelId: String,
channelName: String,
channelDescription: String,
enableLights: Boolean,
importance: Int,
sound: Uri,
audioAttributes: AudioAttributes,
vibrationPattern: LongArray?,
bypassDnd: Boolean = false
) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(channelId) == null) {
val channel = NotificationChannel(channelId, channelName,
importance)
val channel = NotificationChannel(
channelId, channelName,
importance
)
channel.description = channelDescription
channel.enableLights(enableLights)
@ -84,8 +109,11 @@ object NotificationUtils {
}
@TargetApi(Build.VERSION_CODES.O)
fun createNotificationChannelGroup(context: Context,
groupId: String, groupName: CharSequence) {
fun createNotificationChannelGroup(
context: Context,
groupId: String,
groupName: CharSequence
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -113,12 +141,12 @@ object NotificationUtils {
}
}
}
}
fun cancelExistingNotificationWithId(context: Context?, conversationUser: UserEntity, notificationId: Long) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
context != null) {
context != null
) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -128,7 +156,10 @@ object NotificationUtils {
notification = statusBarNotification.notification
if (notification != null && !notification.extras.isEmpty) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && notificationId == notification.extras.getLong(BundleKeys.KEY_NOTIFICATION_ID)) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && notificationId == notification.extras.getLong(
BundleKeys.KEY_NOTIFICATION_ID
)
) {
notificationManager.cancel(statusBarNotification.id)
}
}
@ -136,11 +167,14 @@ object NotificationUtils {
}
}
fun findNotificationForRoom(context: Context?,
fun findNotificationForRoom(
context: Context?,
conversationUser: UserEntity,
roomTokenOrId: String): StatusBarNotification? {
roomTokenOrId: String
): StatusBarNotification? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
context != null) {
context != null
) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -150,7 +184,10 @@ object NotificationUtils {
notification = statusBarNotification.notification
if (notification != null && !notification.extras.isEmpty) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && roomTokenOrId == statusBarNotification.notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN)) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && roomTokenOrId == statusBarNotification.notification.extras.getString(
BundleKeys.KEY_ROOM_TOKEN
)
) {
return statusBarNotification
}
}
@ -160,10 +197,14 @@ object NotificationUtils {
return null
}
fun cancelExistingNotificationsForRoom(context: Context?, conversationUser: UserEntity,
roomTokenOrId: String) {
fun cancelExistingNotificationsForRoom(
context: Context?,
conversationUser: UserEntity,
roomTokenOrId: String
) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
context != null) {
context != null
) {
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
@ -173,7 +214,11 @@ object NotificationUtils {
notification = statusBarNotification.notification
if (notification != null && !notification.extras.isEmpty) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) && roomTokenOrId == statusBarNotification.notification.extras.getString(BundleKeys.KEY_ROOM_TOKEN)) {
if (conversationUser.id == notification.extras.getLong(BundleKeys.KEY_INTERNAL_USER_ID) &&
roomTokenOrId == statusBarNotification.notification.extras.getString(
BundleKeys.KEY_ROOM_TOKEN
)
) {
notificationManager.cancel(statusBarNotification.id)
}
}

View File

@ -25,7 +25,6 @@ import android.database.Cursor
import android.net.Uri
import android.provider.OpenableColumns
import android.util.Log
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
object UriUtils {
@ -51,5 +50,4 @@ object UriUtils {
}
return filename
}
}

View File

@ -21,8 +21,8 @@
package com.nextcloud.talk.utils.bundle
object BundleKeys {
val KEY_SELECTED_USERS = "KEY_SELECTED_USERS";
val KEY_SELECTED_GROUPS = "KEY_SELECTED_GROUPS";
val KEY_SELECTED_USERS = "KEY_SELECTED_USERS"
val KEY_SELECTED_GROUPS = "KEY_SELECTED_GROUPS"
val KEY_USERNAME = "KEY_USERNAME"
val KEY_TOKEN = "KEY_TOKEN"
val KEY_BASE_URL = "KEY_BASE_URL"

View File

@ -13,11 +13,17 @@ import java.io.IOException
import java.net.InetAddress
import java.net.Socket
import java.security.GeneralSecurityException
import java.util.*
import javax.net.ssl.*
import java.util.LinkedList
import javax.net.ssl.KeyManager
import javax.net.ssl.SSLContext
import javax.net.ssl.SSLSocket
import javax.net.ssl.SSLSocketFactory
import javax.net.ssl.X509TrustManager
class SSLSocketFactoryCompat(keyManager: KeyManager?,
trustManager: X509TrustManager) : SSLSocketFactory() {
class SSLSocketFactoryCompat(
keyManager: KeyManager?,
trustManager: X509TrustManager
) : SSLSocketFactory() {
private var delegate: SSLSocketFactory
@ -95,14 +101,14 @@ class SSLSocketFactoryCompat(keyManager: KeyManager?,
}
}
init {
try {
val sslContext = SSLContext.getInstance("TLS")
sslContext.init(
if (keyManager != null) arrayOf(keyManager) else null,
arrayOf(trustManager),
null)
null
)
delegate = sslContext.socketFactory
} catch (e: GeneralSecurityException) {
throw IllegalStateException() // system has no TLS
@ -150,10 +156,8 @@ class SSLSocketFactoryCompat(keyManager: KeyManager?,
return ssl
}
private fun upgradeTLS(ssl: SSLSocket) {
protocols?.let { ssl.enabledProtocols = it }
cipherSuites?.let { ssl.enabledCipherSuites = it }
}
}