mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-10 06:14:10 +01:00
reformat kotlin code to comply with ktlint
Signed-off-by: Andy Scherzinger <info@andy-scherzinger.de>
This commit is contained in:
parent
0b1ca971dd
commit
e82808080d
@ -104,7 +104,6 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
@Inject
|
@Inject
|
||||||
var eventBus: EventBus? = null
|
var eventBus: EventBus? = null
|
||||||
|
|
||||||
|
|
||||||
override fun onCreate() {
|
override fun onCreate() {
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
@ -148,18 +147,26 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
val pushUtils = PushUtils()
|
val pushUtils = PushUtils()
|
||||||
val privateKey = pushUtils.readKeyFromFile(false) as PrivateKey
|
val privateKey = pushUtils.readKeyFromFile(false) as PrivateKey
|
||||||
try {
|
try {
|
||||||
signatureVerification = pushUtils.verifySignature(base64DecodedSignature,
|
signatureVerification = pushUtils.verifySignature(
|
||||||
base64DecodedSubject)
|
base64DecodedSignature,
|
||||||
|
base64DecodedSubject
|
||||||
|
)
|
||||||
if (signatureVerification!!.signatureValid) {
|
if (signatureVerification!!.signatureValid) {
|
||||||
val cipher = Cipher.getInstance("RSA/None/PKCS1Padding")
|
val cipher = Cipher.getInstance("RSA/None/PKCS1Padding")
|
||||||
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
cipher.init(Cipher.DECRYPT_MODE, privateKey)
|
||||||
val decryptedSubject = cipher.doFinal(base64DecodedSubject)
|
val decryptedSubject = cipher.doFinal(base64DecodedSubject)
|
||||||
decryptedPushMessage = LoganSquare.parse(String(decryptedSubject),
|
decryptedPushMessage = LoganSquare.parse(
|
||||||
DecryptedPushMessage::class.java)
|
String(decryptedSubject),
|
||||||
|
DecryptedPushMessage::class.java
|
||||||
|
)
|
||||||
decryptedPushMessage?.apply {
|
decryptedPushMessage?.apply {
|
||||||
timestamp = System.currentTimeMillis()
|
timestamp = System.currentTimeMillis()
|
||||||
if (delete) {
|
if (delete) {
|
||||||
cancelExistingNotificationWithId(applicationContext, signatureVerification!!.userEntity, notificationId)
|
cancelExistingNotificationWithId(
|
||||||
|
applicationContext,
|
||||||
|
signatureVerification!!.userEntity,
|
||||||
|
notificationId
|
||||||
|
)
|
||||||
} else if (deleteAll) {
|
} else if (deleteAll) {
|
||||||
cancelAllNotificationsForAccount(applicationContext, signatureVerification!!.userEntity)
|
cancelAllNotificationsForAccount(applicationContext, signatureVerification!!.userEntity)
|
||||||
} else if (type == "call") {
|
} else if (type == "call") {
|
||||||
@ -171,39 +178,66 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
fullScreenIntent.putExtras(bundle)
|
fullScreenIntent.putExtras(bundle)
|
||||||
|
|
||||||
fullScreenIntent.flags = Intent.FLAG_ACTIVITY_SINGLE_TOP or Intent.FLAG_ACTIVITY_NEW_TASK
|
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)
|
audioAttributesBuilder.setUsage(AudioAttributes.USAGE_NOTIFICATION_COMMUNICATION_REQUEST)
|
||||||
|
|
||||||
val ringtonePreferencesString: String? = appPreferences!!.callRingtoneUri
|
val ringtonePreferencesString: String? = appPreferences!!.callRingtoneUri
|
||||||
val soundUri = if (TextUtils.isEmpty(ringtonePreferencesString)) {
|
val soundUri = if (TextUtils.isEmpty(ringtonePreferencesString)) {
|
||||||
Uri.parse("android.resource://" + applicationContext.packageName +
|
Uri.parse(
|
||||||
"/raw/librem_by_feandesign_call")
|
"android.resource://" + applicationContext.packageName +
|
||||||
|
"/raw/librem_by_feandesign_call"
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
val ringtoneSettings = LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
|
val ringtoneSettings =
|
||||||
|
LoganSquare.parse(ringtonePreferencesString, RingtoneSettings::class.java)
|
||||||
ringtoneSettings.ringtoneUri
|
ringtoneSettings.ringtoneUri
|
||||||
} catch (exception: IOException) {
|
} catch (exception: IOException) {
|
||||||
Uri.parse("android.resource://" + applicationContext.packageName + "/raw/librem_by_feandesign_call")
|
Uri.parse("android.resource://" + applicationContext.packageName + "/raw/librem_by_feandesign_call")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
val notificationChannelId = NotificationUtils.getNotificationChannelId(applicationContext.resources
|
val notificationChannelId = NotificationUtils.getNotificationChannelId(
|
||||||
.getString(R.string.nc_notification_channel_calls), applicationContext.resources
|
applicationContext.resources
|
||||||
.getString(R.string.nc_notification_channel_calls_description), true,
|
.getString(R.string.nc_notification_channel_calls),
|
||||||
NotificationManagerCompat.IMPORTANCE_HIGH, soundUri!!, audioAttributesBuilder.build(), null, false)
|
applicationContext.resources
|
||||||
|
.getString(R.string.nc_notification_channel_calls_description),
|
||||||
|
true,
|
||||||
|
NotificationManagerCompat.IMPORTANCE_HIGH,
|
||||||
|
soundUri!!,
|
||||||
|
audioAttributesBuilder.build(),
|
||||||
|
null,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
|
||||||
createNotificationChannel(applicationContext!!,
|
createNotificationChannel(
|
||||||
notificationChannelId, applicationContext.resources
|
applicationContext!!,
|
||||||
.getString(R.string.nc_notification_channel_calls), applicationContext.resources
|
notificationChannelId,
|
||||||
.getString(R.string.nc_notification_channel_calls_description), true,
|
applicationContext.resources
|
||||||
NotificationManagerCompat.IMPORTANCE_HIGH, soundUri, audioAttributesBuilder.build(), null, false)
|
.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 uri = Uri.parse(signatureVerification!!.userEntity.baseUrl)
|
||||||
val baseUrl = uri.host
|
val baseUrl = uri.host
|
||||||
|
|
||||||
val notification = NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId)
|
val notification =
|
||||||
|
NotificationCompat.Builder(this@MagicFirebaseMessagingService, notificationChannelId)
|
||||||
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
.setPriority(NotificationCompat.PRIORITY_HIGH)
|
||||||
.setCategory(NotificationCompat.CATEGORY_CALL)
|
.setCategory(NotificationCompat.CATEGORY_CALL)
|
||||||
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
.setSmallIcon(R.drawable.ic_call_black_24dp)
|
||||||
@ -213,7 +247,7 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
.setContentTitle(EmojiCompat.get().process(decryptedPushMessage!!.subject))
|
.setContentTitle(EmojiCompat.get().process(decryptedPushMessage!!.subject))
|
||||||
.setAutoCancel(true)
|
.setAutoCancel(true)
|
||||||
.setOngoing(true)
|
.setOngoing(true)
|
||||||
//.setTimeoutAfter(45000L)
|
// .setTimeoutAfter(45000L)
|
||||||
.setContentIntent(fullScreenPendingIntent)
|
.setContentIntent(fullScreenPendingIntent)
|
||||||
.setFullScreenIntent(fullScreenPendingIntent, true)
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
||||||
.setSound(soundUri)
|
.setSound(soundUri)
|
||||||
@ -224,10 +258,12 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
startForeground(decryptedPushMessage!!.timestamp.toInt(), notification)
|
startForeground(decryptedPushMessage!!.timestamp.toInt(), notification)
|
||||||
} else {
|
} else {
|
||||||
val messageData = Data.Builder()
|
val messageData = Data.Builder()
|
||||||
.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, subject)
|
.putString(BundleKeys.KEY_NOTIFICATION_SUBJECT, subject)
|
||||||
.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, signature)
|
.putString(BundleKeys.KEY_NOTIFICATION_SIGNATURE, signature)
|
||||||
|
.build()
|
||||||
|
val pushNotificationWork =
|
||||||
|
OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData)
|
||||||
.build()
|
.build()
|
||||||
val pushNotificationWork = OneTimeWorkRequest.Builder(NotificationWorker::class.java).setInputData(messageData).build()
|
|
||||||
WorkManager.getInstance().enqueue(pushNotificationWork)
|
WorkManager.getInstance().enqueue(pushNotificationWork)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -244,47 +280,59 @@ class MagicFirebaseMessagingService : FirebaseMessagingService() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun checkIfCallIsActive(signatureVerification: SignatureVerification, decryptedPushMessage: DecryptedPushMessage) {
|
private fun checkIfCallIsActive(
|
||||||
val ncApi = retrofit!!.newBuilder().client(okHttpClient!!.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build()).build().create(NcApi::class.java)
|
signatureVerification: SignatureVerification,
|
||||||
|
decryptedPushMessage: DecryptedPushMessage
|
||||||
|
) {
|
||||||
|
val ncApi = retrofit!!.newBuilder()
|
||||||
|
.client(okHttpClient!!.newBuilder().cookieJar(JavaNetCookieJar(CookieManager())).build()).build()
|
||||||
|
.create(NcApi::class.java)
|
||||||
var hasParticipantsInCall = false
|
var hasParticipantsInCall = false
|
||||||
var inCallOnDifferentDevice = false
|
var inCallOnDifferentDevice = false
|
||||||
|
|
||||||
ncApi.getPeersForCall(ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token),
|
ncApi.getPeersForCall(
|
||||||
ApiUtils.getUrlForCall(signatureVerification.userEntity.baseUrl,
|
ApiUtils.getCredentials(signatureVerification.userEntity.username, signatureVerification.userEntity.token),
|
||||||
decryptedPushMessage.id))
|
ApiUtils.getUrlForCall(
|
||||||
.takeWhile {
|
signatureVerification.userEntity.baseUrl,
|
||||||
isServiceInForeground
|
decryptedPushMessage.id
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.takeWhile {
|
||||||
|
isServiceInForeground
|
||||||
|
}
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe(object : Observer<ParticipantsOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
}
|
}
|
||||||
.subscribeOn(Schedulers.io())
|
|
||||||
.subscribe(object : Observer<ParticipantsOverall> {
|
|
||||||
override fun onSubscribe(d: Disposable) {
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onNext(participantsOverall: ParticipantsOverall) {
|
override fun onNext(participantsOverall: ParticipantsOverall) {
|
||||||
val participantList: List<Participant> = participantsOverall.ocs.data
|
val participantList: List<Participant> = participantsOverall.ocs.data
|
||||||
hasParticipantsInCall = participantList.isNotEmpty()
|
hasParticipantsInCall = participantList.isNotEmpty()
|
||||||
if (!hasParticipantsInCall) {
|
if (!hasParticipantsInCall) {
|
||||||
for (participant in participantList) {
|
for (participant in participantList) {
|
||||||
if (participant.userId == signatureVerification.userEntity.userId) {
|
if (participant.userId == signatureVerification.userEntity.userId) {
|
||||||
inCallOnDifferentDevice = true
|
inCallOnDifferentDevice = true
|
||||||
break
|
break
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!hasParticipantsInCall || inCallOnDifferentDevice) {
|
if (!hasParticipantsInCall || inCallOnDifferentDevice) {
|
||||||
stopForeground(true)
|
stopForeground(true)
|
||||||
handler.removeCallbacksAndMessages(null)
|
handler.removeCallbacksAndMessages(null)
|
||||||
} else if (isServiceInForeground) {
|
} else if (isServiceInForeground) {
|
||||||
handler.postDelayed({
|
handler.postDelayed(
|
||||||
|
{
|
||||||
checkIfCallIsActive(signatureVerification, decryptedPushMessage)
|
checkIfCallIsActive(signatureVerification, decryptedPushMessage)
|
||||||
}, 5000)
|
},
|
||||||
}
|
5000
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {}
|
override fun onError(e: Throwable) {}
|
||||||
override fun onComplete() {
|
override fun onComplete() {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -76,8 +76,11 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showCertificateDialog(cert: X509Certificate, magicTrustManager: MagicTrustManager,
|
fun showCertificateDialog(
|
||||||
sslErrorHandler: SslErrorHandler?) {
|
cert: X509Certificate,
|
||||||
|
magicTrustManager: MagicTrustManager,
|
||||||
|
sslErrorHandler: SslErrorHandler?
|
||||||
|
) {
|
||||||
val formatter = DateFormat.getDateInstance(DateFormat.LONG)
|
val formatter = DateFormat.getDateInstance(DateFormat.LONG)
|
||||||
val validFrom = formatter.format(cert.notBefore)
|
val validFrom = formatter.format(cert.notBefore)
|
||||||
val validUntil = formatter.format(cert.notAfter)
|
val validUntil = formatter.format(cert.notAfter)
|
||||||
@ -101,30 +104,30 @@ open class BaseActivity : AppCompatActivity() {
|
|||||||
issuedFor = cert.subjectDN.name
|
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),
|
.getString(R.string.nc_certificate_dialog_text),
|
||||||
issuedBy, issuedFor, validFrom, validUntil)
|
issuedBy, issuedFor, validFrom, validUntil
|
||||||
|
)
|
||||||
|
|
||||||
LovelyStandardDialog(this)
|
LovelyStandardDialog(this)
|
||||||
.setTopColorRes(R.color.nc_darkRed)
|
.setTopColorRes(R.color.nc_darkRed)
|
||||||
.setNegativeButtonColorRes(R.color.nc_darkRed)
|
.setNegativeButtonColorRes(R.color.nc_darkRed)
|
||||||
.setPositiveButtonColorRes(R.color.colorPrimary)
|
.setPositiveButtonColorRes(R.color.colorPrimary)
|
||||||
.setIcon(R.drawable.ic_security_white_24dp)
|
.setIcon(R.drawable.ic_security_white_24dp)
|
||||||
.setTitle(R.string.nc_certificate_dialog_title)
|
.setTitle(R.string.nc_certificate_dialog_title)
|
||||||
.setMessage(dialogText)
|
.setMessage(dialogText)
|
||||||
.setPositiveButton(R.string.nc_yes) { v ->
|
.setPositiveButton(R.string.nc_yes) { v ->
|
||||||
magicTrustManager.addCertInTrustStore(cert)
|
magicTrustManager.addCertInTrustStore(cert)
|
||||||
sslErrorHandler?.proceed()
|
sslErrorHandler?.proceed()
|
||||||
}
|
}
|
||||||
.setNegativeButton(R.string.nc_no) { view1 ->
|
.setNegativeButton(R.string.nc_no) { view1 ->
|
||||||
sslErrorHandler?.cancel()
|
sslErrorHandler?.cancel()
|
||||||
}
|
}
|
||||||
.show()
|
.show()
|
||||||
|
|
||||||
} catch (e: CertificateParsingException) {
|
} catch (e: CertificateParsingException) {
|
||||||
Log.d(TAG, "Failed to parse the certificate")
|
Log.d(TAG, "Failed to parse the certificate")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Subscribe(threadMode = ThreadMode.MAIN)
|
@Subscribe(threadMode = ThreadMode.MAIN)
|
||||||
|
@ -38,7 +38,6 @@ import pl.droidsonroids.gif.GifDrawable
|
|||||||
import pl.droidsonroids.gif.GifImageView
|
import pl.droidsonroids.gif.GifImageView
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
class FullScreenImageActivity : AppCompatActivity() {
|
class FullScreenImageActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var path: String
|
private lateinit var path: String
|
||||||
@ -55,9 +54,11 @@ class FullScreenImageActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return if (item.itemId == R.id.share) {
|
return if (item.itemId == R.id.share) {
|
||||||
val shareUri = FileProvider.getUriForFile(this,
|
val shareUri = FileProvider.getUriForFile(
|
||||||
BuildConfig.APPLICATION_ID,
|
this,
|
||||||
File(path))
|
BuildConfig.APPLICATION_ID,
|
||||||
|
File(path)
|
||||||
|
)
|
||||||
|
|
||||||
val shareIntent: Intent = Intent().apply {
|
val shareIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
@ -78,19 +79,19 @@ class FullScreenImageActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
setContentView(R.layout.activity_full_screen_image)
|
setContentView(R.layout.activity_full_screen_image)
|
||||||
setSupportActionBar(findViewById(R.id.imageview_toolbar))
|
setSupportActionBar(findViewById(R.id.imageview_toolbar))
|
||||||
supportActionBar?.setDisplayShowTitleEnabled(false);
|
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||||
|
|
||||||
imageWrapperView = findViewById(R.id.image_wrapper_view)
|
imageWrapperView = findViewById(R.id.image_wrapper_view)
|
||||||
photoView = findViewById(R.id.photo_view)
|
photoView = findViewById(R.id.photo_view)
|
||||||
gifView = findViewById(R.id.gif_view)
|
gifView = findViewById(R.id.gif_view)
|
||||||
|
|
||||||
photoView.setOnPhotoTapListener{ view, x, y ->
|
photoView.setOnPhotoTapListener { view, x, y ->
|
||||||
toggleFullscreen()
|
toggleFullscreen()
|
||||||
}
|
}
|
||||||
photoView.setOnOutsidePhotoTapListener{
|
photoView.setOnOutsidePhotoTapListener {
|
||||||
toggleFullscreen()
|
toggleFullscreen()
|
||||||
}
|
}
|
||||||
gifView.setOnClickListener{
|
gifView.setOnClickListener {
|
||||||
toggleFullscreen()
|
toggleFullscreen()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,29 +116,33 @@ class FullScreenImageActivity : AppCompatActivity() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun toggleFullscreen(){
|
private fun toggleFullscreen() {
|
||||||
showFullscreen = !showFullscreen;
|
showFullscreen = !showFullscreen
|
||||||
if (showFullscreen){
|
if (showFullscreen) {
|
||||||
hideSystemUI()
|
hideSystemUI()
|
||||||
supportActionBar?.hide()
|
supportActionBar?.hide()
|
||||||
} else{
|
} else {
|
||||||
showSystemUI()
|
showSystemUI()
|
||||||
supportActionBar?.show()
|
supportActionBar?.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun hideSystemUI() {
|
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_STABLE
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
or View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSystemUI() {
|
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_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -22,7 +22,6 @@ package com.nextcloud.talk.activities
|
|||||||
|
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.util.Log
|
|
||||||
import android.view.Menu
|
import android.view.Menu
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -33,7 +32,6 @@ import autodagger.AutoInjector
|
|||||||
import com.google.android.exoplayer2.MediaItem
|
import com.google.android.exoplayer2.MediaItem
|
||||||
import com.google.android.exoplayer2.Player
|
import com.google.android.exoplayer2.Player
|
||||||
import com.google.android.exoplayer2.SimpleExoPlayer
|
import com.google.android.exoplayer2.SimpleExoPlayer
|
||||||
import com.google.android.exoplayer2.ui.PlayerControlView
|
|
||||||
import com.google.android.exoplayer2.ui.StyledPlayerView
|
import com.google.android.exoplayer2.ui.StyledPlayerView
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
@ -54,9 +52,11 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return if (item.itemId == R.id.share) {
|
return if (item.itemId == R.id.share) {
|
||||||
val shareUri = FileProvider.getUriForFile(this,
|
val shareUri = FileProvider.getUriForFile(
|
||||||
BuildConfig.APPLICATION_ID,
|
this,
|
||||||
File(path))
|
BuildConfig.APPLICATION_ID,
|
||||||
|
File(path)
|
||||||
|
)
|
||||||
|
|
||||||
val shareIntent: Intent = Intent().apply {
|
val shareIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
@ -82,11 +82,11 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
|
|||||||
|
|
||||||
setContentView(R.layout.activity_full_screen_media)
|
setContentView(R.layout.activity_full_screen_media)
|
||||||
setSupportActionBar(findViewById(R.id.mediaview_toolbar))
|
setSupportActionBar(findViewById(R.id.mediaview_toolbar))
|
||||||
supportActionBar?.setDisplayShowTitleEnabled(false);
|
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||||
|
|
||||||
playerView = findViewById(R.id.player_view)
|
playerView = findViewById(R.id.player_view)
|
||||||
|
|
||||||
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
|
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON)
|
||||||
|
|
||||||
playerView.showController()
|
playerView.showController()
|
||||||
if (isAudioOnly) {
|
if (isAudioOnly) {
|
||||||
@ -121,7 +121,7 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
|
|||||||
|
|
||||||
private fun initializePlayer() {
|
private fun initializePlayer() {
|
||||||
player = SimpleExoPlayer.Builder(applicationContext).build()
|
player = SimpleExoPlayer.Builder(applicationContext).build()
|
||||||
playerView.player = player;
|
playerView.player = player
|
||||||
player.playWhenReady = true
|
player.playWhenReady = true
|
||||||
player.addListener(this)
|
player.addListener(this)
|
||||||
}
|
}
|
||||||
@ -131,17 +131,21 @@ class FullScreenMediaActivity : AppCompatActivity(), Player.EventListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun hideSystemUI() {
|
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_STABLE
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
or View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
or View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_FULLSCREEN)
|
or View.SYSTEM_UI_FLAG_FULLSCREEN
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showSystemUI() {
|
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_HIDE_NAVIGATION
|
||||||
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)
|
or View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -34,7 +34,6 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||||||
import io.noties.markwon.Markwon
|
import io.noties.markwon.Markwon
|
||||||
import java.io.File
|
import java.io.File
|
||||||
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class FullScreenTextViewerActivity : AppCompatActivity() {
|
class FullScreenTextViewerActivity : AppCompatActivity() {
|
||||||
|
|
||||||
@ -48,9 +47,11 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
override fun onOptionsItemSelected(item: MenuItem): Boolean {
|
||||||
return if (item.itemId == R.id.share) {
|
return if (item.itemId == R.id.share) {
|
||||||
val shareUri = FileProvider.getUriForFile(this,
|
val shareUri = FileProvider.getUriForFile(
|
||||||
BuildConfig.APPLICATION_ID,
|
this,
|
||||||
File(path))
|
BuildConfig.APPLICATION_ID,
|
||||||
|
File(path)
|
||||||
|
)
|
||||||
|
|
||||||
val shareIntent: Intent = Intent().apply {
|
val shareIntent: Intent = Intent().apply {
|
||||||
action = Intent.ACTION_SEND
|
action = Intent.ACTION_SEND
|
||||||
@ -71,8 +72,7 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
|
|||||||
|
|
||||||
setContentView(R.layout.activity_full_screen_text)
|
setContentView(R.layout.activity_full_screen_text)
|
||||||
setSupportActionBar(findViewById(R.id.textview_toolbar))
|
setSupportActionBar(findViewById(R.id.textview_toolbar))
|
||||||
supportActionBar?.setDisplayShowTitleEnabled(false);
|
supportActionBar?.setDisplayShowTitleEnabled(false)
|
||||||
|
|
||||||
textView = findViewById(R.id.text_view)
|
textView = findViewById(R.id.text_view)
|
||||||
|
|
||||||
val fileName = intent.getStringExtra("FILE_NAME")
|
val fileName = intent.getStringExtra("FILE_NAME")
|
||||||
@ -81,13 +81,12 @@ class FullScreenTextViewerActivity : AppCompatActivity() {
|
|||||||
var text = readFile(path)
|
var text = readFile(path)
|
||||||
|
|
||||||
if (isMarkdown) {
|
if (isMarkdown) {
|
||||||
val markwon = Markwon.create(applicationContext);
|
val markwon = Markwon.create(applicationContext)
|
||||||
markwon.setMarkdown(textView, text);
|
markwon.setMarkdown(textView, text)
|
||||||
} else {
|
} else {
|
||||||
textView.text = text
|
textView.text = text
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun readFile(fileName: String) = File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
|
private fun readFile(fileName: String) = File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -60,10 +60,12 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
|
||||||
requestWindowFeature(Window.FEATURE_NO_TITLE)
|
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_KEEP_SCREEN_ON or
|
||||||
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED 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
|
window.decorView.systemUiVisibility = systemUiVisibility
|
||||||
|
|
||||||
setContentView(R.layout.activity_magic_call)
|
setContentView(R.layout.activity_magic_call)
|
||||||
@ -74,13 +76,17 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
|
|
||||||
if (!router!!.hasRootController()) {
|
if (!router!!.hasRootController()) {
|
||||||
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
|
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())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
router!!.setRoot(RouterTransaction.with(CallController(intent.extras))
|
router!!.setRoot(
|
||||||
|
RouterTransaction.with(CallController(intent.extras))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -89,9 +95,11 @@ class MagicCallActivity : BaseActivity() {
|
|||||||
|
|
||||||
chatController = ChatController(extras)
|
chatController = ChatController(extras)
|
||||||
chatRouter = Conductor.attachRouter(this, chatContainer, savedInstanceState)
|
chatRouter = Conductor.attachRouter(this, chatContainer, savedInstanceState)
|
||||||
chatRouter!!.setRoot(RouterTransaction.with(chatController)
|
chatRouter!!.setRoot(
|
||||||
|
RouterTransaction.with(chatController)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun showChat() {
|
fun showChat() {
|
||||||
|
@ -79,23 +79,31 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
|
|
||||||
@BindView(R.id.appBar)
|
@BindView(R.id.appBar)
|
||||||
lateinit var appBar: AppBarLayout
|
lateinit var appBar: AppBarLayout
|
||||||
|
|
||||||
@BindView(R.id.toolbar)
|
@BindView(R.id.toolbar)
|
||||||
lateinit var toolbar: MaterialToolbar
|
lateinit var toolbar: MaterialToolbar
|
||||||
|
|
||||||
@BindView(R.id.home_toolbar)
|
@BindView(R.id.home_toolbar)
|
||||||
lateinit var searchCardView: MaterialCardView
|
lateinit var searchCardView: MaterialCardView
|
||||||
|
|
||||||
@BindView(R.id.search_text)
|
@BindView(R.id.search_text)
|
||||||
lateinit var searchInputText: MaterialTextView
|
lateinit var searchInputText: MaterialTextView
|
||||||
|
|
||||||
@BindView(R.id.switch_account_button)
|
@BindView(R.id.switch_account_button)
|
||||||
lateinit var settingsButton: MaterialButton
|
lateinit var settingsButton: MaterialButton
|
||||||
|
|
||||||
@BindView(R.id.controller_container)
|
@BindView(R.id.controller_container)
|
||||||
lateinit var container: ViewGroup
|
lateinit var container: ViewGroup
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var userUtils: UserUtils
|
lateinit var userUtils: UserUtils
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var dataStore: ReactiveEntityStore<Persistable>
|
lateinit var dataStore: ReactiveEntityStore<Persistable>
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource
|
lateinit var sqlCipherDatabaseSource: SqlCipherDatabaseSource
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
|
|
||||||
@ -124,39 +132,53 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
|
|
||||||
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
||||||
if (!router!!.hasRootController()) {
|
if (!router!!.hasRootController()) {
|
||||||
router!!.setRoot(RouterTransaction.with(ConversationsListController())
|
router!!.setRoot(
|
||||||
|
RouterTransaction.with(ConversationsListController())
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
onNewIntent(intent)
|
onNewIntent(intent)
|
||||||
} else if (!router!!.hasRootController()) {
|
} else if (!router!!.hasRootController()) {
|
||||||
if (hasDb) {
|
if (hasDb) {
|
||||||
if (userUtils.anyUserExists()) {
|
if (userUtils.anyUserExists()) {
|
||||||
router!!.setRoot(RouterTransaction.with(ConversationsListController())
|
router!!.setRoot(
|
||||||
|
RouterTransaction.with(ConversationsListController())
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
|
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
|
||||||
router!!.pushController(RouterTransaction.with(
|
router!!.pushController(
|
||||||
WebViewLoginController(resources.getString(R.string.weblogin_url), false))
|
RouterTransaction.with(
|
||||||
|
WebViewLoginController(resources.getString(R.string.weblogin_url), false)
|
||||||
|
)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
|
router!!.setRoot(
|
||||||
|
RouterTransaction.with(ServerSelectionController())
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
|
if (!TextUtils.isEmpty(resources.getString(R.string.weblogin_url))) {
|
||||||
router!!.pushController(RouterTransaction.with(
|
router!!.pushController(
|
||||||
WebViewLoginController(resources.getString(R.string.weblogin_url), false))
|
RouterTransaction.with(
|
||||||
|
WebViewLoginController(resources.getString(R.string.weblogin_url), false)
|
||||||
|
)
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
router!!.setRoot(RouterTransaction.with(ServerSelectionController())
|
router!!.setRoot(
|
||||||
|
RouterTransaction.with(ServerSelectionController())
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -193,8 +215,10 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
if (userUtils.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
|
if (userUtils.currentUser?.baseUrl?.endsWith(baseUrl) == true) {
|
||||||
startConversation(user)
|
startConversation(user)
|
||||||
} else {
|
} else {
|
||||||
Snackbar.make(container, R.string.nc_phone_book_integration_account_not_found, Snackbar
|
Snackbar.make(
|
||||||
.LENGTH_LONG).show()
|
container, R.string.nc_phone_book_integration_account_not_found,
|
||||||
|
Snackbar.LENGTH_LONG
|
||||||
|
).show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -206,52 +230,67 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
val currentUser = userUtils.currentUser ?: return
|
val currentUser = userUtils.currentUser ?: return
|
||||||
|
|
||||||
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
val credentials = ApiUtils.getCredentials(currentUser.username, currentUser.token)
|
||||||
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(currentUser.baseUrl, roomType,
|
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
|
||||||
userId, null)
|
currentUser.baseUrl, roomType,
|
||||||
ncApi.createRoom(credentials,
|
userId, null
|
||||||
retrofitBucket.url, retrofitBucket.queryMap)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
ncApi.createRoom(
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
credentials,
|
||||||
.subscribe(object : Observer<RoomOverall> {
|
retrofitBucket.url, retrofitBucket.queryMap
|
||||||
override fun onSubscribe(d: Disposable) {}
|
)
|
||||||
override fun onNext(roomOverall: RoomOverall) {
|
.subscribeOn(Schedulers.io())
|
||||||
val conversationIntent = Intent(context, MagicCallActivity::class.java)
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
val bundle = Bundle()
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
bundle.putParcelable(KEY_USER_ENTITY, currentUser)
|
override fun onSubscribe(d: Disposable) {}
|
||||||
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs.data.token)
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
bundle.putString(KEY_ROOM_ID, roomOverall.ocs.data.roomId)
|
val conversationIntent = Intent(context, MagicCallActivity::class.java)
|
||||||
if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
|
val bundle = Bundle()
|
||||||
ncApi.getRoom(credentials,
|
bundle.putParcelable(KEY_USER_ENTITY, currentUser)
|
||||||
ApiUtils.getRoom(currentUser.baseUrl,
|
bundle.putString(KEY_ROOM_TOKEN, roomOverall.ocs.data.token)
|
||||||
roomOverall.ocs.data.token))
|
bundle.putString(KEY_ROOM_ID, roomOverall.ocs.data.roomId)
|
||||||
.subscribeOn(Schedulers.io())
|
if (currentUser.hasSpreedFeatureCapability("chat-v2")) {
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
ncApi.getRoom(
|
||||||
.subscribe(object : Observer<RoomOverall> {
|
credentials,
|
||||||
override fun onSubscribe(d: Disposable) {}
|
ApiUtils.getRoom(
|
||||||
override fun onNext(roomOverall: RoomOverall) {
|
currentUser.baseUrl,
|
||||||
bundle.putParcelable(KEY_ACTIVE_CONVERSATION,
|
roomOverall.ocs.data.token
|
||||||
Parcels.wrap(roomOverall.ocs.data))
|
)
|
||||||
remapChatController(router!!, currentUser.id,
|
)
|
||||||
roomOverall.ocs.data.token, bundle, true)
|
.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
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {}
|
override fun onError(e: Throwable) {}
|
||||||
override fun onComplete() {}
|
override fun onComplete() {}
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
conversationIntent.putExtras(bundle)
|
conversationIntent.putExtras(bundle)
|
||||||
startActivity(conversationIntent)
|
startActivity(conversationIntent)
|
||||||
Handler().postDelayed({
|
Handler().postDelayed(
|
||||||
|
{
|
||||||
if (!isDestroyed) {
|
if (!isDestroyed) {
|
||||||
router!!.popCurrentController()
|
router!!.popCurrentController()
|
||||||
}
|
}
|
||||||
}, 100)
|
},
|
||||||
}
|
100
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {}
|
override fun onError(e: Throwable) {}
|
||||||
override fun onComplete() {}
|
override fun onComplete() {}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@RequiresApi(api = Build.VERSION_CODES.M)
|
@RequiresApi(api = Build.VERSION_CODES.M)
|
||||||
@ -260,16 +299,17 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
|
if (keyguardManager.isKeyguardSecure && appPreferences.isScreenLocked) {
|
||||||
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
|
if (!SecurityUtils.checkIfWeAreAuthenticated(appPreferences.screenLockTimeout)) {
|
||||||
if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) {
|
if (router != null && router!!.getControllerWithTag(LockedController.TAG) == null) {
|
||||||
router!!.pushController(RouterTransaction.with(LockedController())
|
router!!.pushController(
|
||||||
|
RouterTransaction.with(LockedController())
|
||||||
.pushChangeHandler(VerticalChangeHandler())
|
.pushChangeHandler(VerticalChangeHandler())
|
||||||
.popChangeHandler(VerticalChangeHandler())
|
.popChangeHandler(VerticalChangeHandler())
|
||||||
.tag(LockedController.TAG))
|
.tag(LockedController.TAG)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
override fun onNewIntent(intent: Intent) {
|
override fun onNewIntent(intent: Intent) {
|
||||||
super.onNewIntent(intent)
|
super.onNewIntent(intent)
|
||||||
|
|
||||||
@ -277,12 +317,16 @@ class MainActivity : BaseActivity(), ActionBarProvider {
|
|||||||
|
|
||||||
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
if (intent.hasExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL)) {
|
||||||
if (intent.getBooleanExtra(BundleKeys.KEY_FROM_NOTIFICATION_START_CALL, false)) {
|
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())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()))
|
.popChangeHandler(HorizontalChangeHandler())
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
ConductorRemapping.remapChatController(router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
|
ConductorRemapping.remapChatController(
|
||||||
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false)
|
router!!, intent.getLongExtra(BundleKeys.KEY_INTERNAL_USER_ID, -1),
|
||||||
|
intent.getStringExtra(BundleKeys.KEY_ROOM_TOKEN), intent.extras!!, false
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,6 @@ import autodagger.AutoInjector
|
|||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.CircleCropTransformation
|
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
import com.facebook.drawee.view.SimpleDraweeView
|
||||||
import com.nextcloud.talk.R
|
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.TextMatchers
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import com.stfalcon.chatkit.messages.MessageHolders
|
import com.stfalcon.chatkit.messages.MessageHolders
|
||||||
import com.stfalcon.chatkit.utils.DateFormatter
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
@ -104,8 +102,8 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
|
|
||||||
init {
|
init {
|
||||||
ButterKnife.bind(
|
ButterKnife.bind(
|
||||||
this,
|
this,
|
||||||
itemView
|
itemView
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -131,13 +129,13 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
messageUserAvatarView?.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
messageUserAvatarView?.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
val drawable = TextDrawable.builder()
|
||||||
.beginConfig()
|
.beginConfig()
|
||||||
.bold()
|
.bold()
|
||||||
.endConfig()
|
.endConfig()
|
||||||
.buildRound(
|
.buildRound(
|
||||||
">",
|
">",
|
||||||
context!!.resources.getColor(R.color.black)
|
context!!.resources.getColor(R.color.black)
|
||||||
)
|
)
|
||||||
messageUserAvatarView!!.visibility = View.VISIBLE
|
messageUserAvatarView!!.visibility = View.VISIBLE
|
||||||
messageUserAvatarView?.setImageDrawable(drawable)
|
messageUserAvatarView?.setImageDrawable(drawable)
|
||||||
}
|
}
|
||||||
@ -165,9 +163,9 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
}
|
}
|
||||||
|
|
||||||
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
val bubbleDrawable = DisplayUtils.getMessageSelector(
|
||||||
bgBubbleColor,
|
bgBubbleColor,
|
||||||
resources.getColor(R.color.transparent),
|
resources.getColor(R.color.transparent),
|
||||||
bgBubbleColor, bubbleResource
|
bgBubbleColor, bubbleResource
|
||||||
)
|
)
|
||||||
ViewCompat.setBackground(bubble, bubbleDrawable)
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
|
|
||||||
@ -187,23 +185,23 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
if (individualHashMap["type"] == "user" || individualHashMap["type"] == "guest" || individualHashMap["type"] == "call") {
|
if (individualHashMap["type"] == "user" || individualHashMap["type"] == "guest" || individualHashMap["type"] == "call") {
|
||||||
if (individualHashMap["id"] == message.activeUser!!.userId) {
|
if (individualHashMap["id"] == message.activeUser!!.userId) {
|
||||||
messageString = DisplayUtils.searchAndReplaceWithMentionSpan(
|
messageString = DisplayUtils.searchAndReplaceWithMentionSpan(
|
||||||
messageText!!.context,
|
messageText!!.context,
|
||||||
messageString,
|
messageString,
|
||||||
individualHashMap["id"]!!,
|
individualHashMap["id"]!!,
|
||||||
individualHashMap["name"]!!,
|
individualHashMap["name"]!!,
|
||||||
individualHashMap["type"]!!,
|
individualHashMap["type"]!!,
|
||||||
message.activeUser!!,
|
message.activeUser!!,
|
||||||
R.xml.chip_you
|
R.xml.chip_you
|
||||||
)
|
)
|
||||||
} else {
|
} else {
|
||||||
messageString = DisplayUtils.searchAndReplaceWithMentionSpan(
|
messageString = DisplayUtils.searchAndReplaceWithMentionSpan(
|
||||||
messageText!!.context,
|
messageText!!.context,
|
||||||
messageString,
|
messageString,
|
||||||
individualHashMap["id"]!!,
|
individualHashMap["id"]!!,
|
||||||
individualHashMap["name"]!!,
|
individualHashMap["name"]!!,
|
||||||
individualHashMap["type"]!!,
|
individualHashMap["type"]!!,
|
||||||
message.activeUser!!,
|
message.activeUser!!,
|
||||||
R.xml.chip_others
|
R.xml.chip_others
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else if (individualHashMap["type"] == "file") {
|
} else if (individualHashMap["type"] == "file") {
|
||||||
@ -231,18 +229,21 @@ class MagicIncomingTextMessageViewHolder(incomingView: View) : MessageHolders
|
|||||||
parentChatMessage.imageUrl?.let {
|
parentChatMessage.imageUrl?.let {
|
||||||
quotedMessagePreview?.visibility = View.VISIBLE
|
quotedMessagePreview?.visibility = View.VISIBLE
|
||||||
quotedMessagePreview?.load(it) {
|
quotedMessagePreview?.load(it) {
|
||||||
addHeader("Authorization", ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token))
|
addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: run {
|
} ?: run {
|
||||||
quotedMessagePreview?.visibility = View.GONE
|
quotedMessagePreview?.visibility = View.GONE
|
||||||
}
|
}
|
||||||
quotedUserName?.text = parentChatMessage.actorDisplayName
|
quotedUserName?.text = parentChatMessage.actorDisplayName
|
||||||
?: context!!.getText(R.string.nc_nick_guest)
|
?: context!!.getText(R.string.nc_nick_guest)
|
||||||
quotedMessage?.text = parentChatMessage.text
|
quotedMessage?.text = parentChatMessage.text
|
||||||
|
|
||||||
quotedUserName?.setTextColor(context!!.resources.getColor(R.color.textColorMaxContrast))
|
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)
|
quoteColoredView?.setBackgroundResource(R.color.colorPrimary)
|
||||||
} else {
|
} else {
|
||||||
quoteColoredView?.setBackgroundResource(R.color.textColorMaxContrast)
|
quoteColoredView?.setBackgroundResource(R.color.textColorMaxContrast)
|
||||||
|
@ -36,7 +36,6 @@ import autodagger.AutoInjector
|
|||||||
import butterknife.BindView
|
import butterknife.BindView
|
||||||
import butterknife.ButterKnife
|
import butterknife.ButterKnife
|
||||||
import coil.load
|
import coil.load
|
||||||
import coil.transform.CircleCropTransformation
|
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
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.DisplayUtils.searchAndReplaceWithMentionSpan
|
||||||
import com.nextcloud.talk.utils.TextMatchers
|
import com.nextcloud.talk.utils.TextMatchers
|
||||||
import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
|
import com.stfalcon.chatkit.messages.MessageHolders.OutcomingTextMessageViewHolder
|
||||||
import com.stfalcon.chatkit.utils.DateFormatter
|
import java.util.HashMap
|
||||||
import java.util.*
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
@ -57,6 +55,7 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
|
|||||||
@JvmField
|
@JvmField
|
||||||
@BindView(R.id.messageText)
|
@BindView(R.id.messageText)
|
||||||
var messageText: EmojiTextView? = null
|
var messageText: EmojiTextView? = null
|
||||||
|
|
||||||
@JvmField
|
@JvmField
|
||||||
@BindView(R.id.messageTime)
|
@BindView(R.id.messageTime)
|
||||||
var messageTimeView: TextView? = null
|
var messageTimeView: TextView? = null
|
||||||
@ -104,20 +103,26 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
|
|||||||
for (key in messageParameters.keys) {
|
for (key in messageParameters.keys) {
|
||||||
val individualHashMap: HashMap<String, String>? = message.messageParameters[key]
|
val individualHashMap: HashMap<String, String>? = message.messageParameters[key]
|
||||||
if (individualHashMap != null) {
|
if (individualHashMap != null) {
|
||||||
if (individualHashMap["type"] == "user" || (individualHashMap["type"]
|
if (individualHashMap["type"] == "user" || (
|
||||||
== "guest") || individualHashMap["type"] == "call") {
|
individualHashMap["type"] == "guest"
|
||||||
messageString = searchAndReplaceWithMentionSpan(messageText!!.context,
|
) || individualHashMap["type"] == "call"
|
||||||
messageString,
|
) {
|
||||||
individualHashMap["id"]!!,
|
messageString = searchAndReplaceWithMentionSpan(
|
||||||
individualHashMap["name"]!!,
|
messageText!!.context,
|
||||||
individualHashMap["type"]!!,
|
messageString,
|
||||||
message.activeUser,
|
individualHashMap["id"]!!,
|
||||||
R.xml.chip_others)
|
individualHashMap["name"]!!,
|
||||||
|
individualHashMap["type"]!!,
|
||||||
|
message.activeUser,
|
||||||
|
R.xml.chip_others
|
||||||
|
)
|
||||||
} else if (individualHashMap["type"] == "file") {
|
} else if (individualHashMap["type"] == "file") {
|
||||||
realView.setOnClickListener(View.OnClickListener { v: View? ->
|
realView.setOnClickListener(
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
|
View.OnClickListener { v: View? ->
|
||||||
context!!.startActivity(browserIntent)
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(individualHashMap["link"]))
|
||||||
})
|
context!!.startActivity(browserIntent)
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -135,17 +140,19 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
|
|||||||
}
|
}
|
||||||
if (message.isGrouped) {
|
if (message.isGrouped) {
|
||||||
val bubbleDrawable = getMessageSelector(
|
val bubbleDrawable = getMessageSelector(
|
||||||
bgBubbleColor,
|
bgBubbleColor,
|
||||||
resources.getColor(R.color.transparent),
|
resources.getColor(R.color.transparent),
|
||||||
bgBubbleColor,
|
bgBubbleColor,
|
||||||
R.drawable.shape_grouped_outcoming_message)
|
R.drawable.shape_grouped_outcoming_message
|
||||||
|
)
|
||||||
ViewCompat.setBackground(bubble, bubbleDrawable)
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
} else {
|
} else {
|
||||||
val bubbleDrawable = getMessageSelector(
|
val bubbleDrawable = getMessageSelector(
|
||||||
bgBubbleColor,
|
bgBubbleColor,
|
||||||
resources.getColor(R.color.transparent),
|
resources.getColor(R.color.transparent),
|
||||||
bgBubbleColor,
|
bgBubbleColor,
|
||||||
R.drawable.shape_outcoming_message)
|
R.drawable.shape_outcoming_message
|
||||||
|
)
|
||||||
ViewCompat.setBackground(bubble, bubbleDrawable)
|
ViewCompat.setBackground(bubble, bubbleDrawable)
|
||||||
}
|
}
|
||||||
messageText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
|
messageText!!.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize)
|
||||||
@ -160,13 +167,16 @@ class MagicOutcomingTextMessageViewHolder(itemView: View) : OutcomingTextMessage
|
|||||||
parentChatMessage.imageUrl?.let {
|
parentChatMessage.imageUrl?.let {
|
||||||
quotedMessagePreview?.visibility = View.VISIBLE
|
quotedMessagePreview?.visibility = View.VISIBLE
|
||||||
quotedMessagePreview?.load(it) {
|
quotedMessagePreview?.load(it) {
|
||||||
addHeader("Authorization", ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token))
|
addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(message.activeUser.username, message.activeUser.token)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
} ?: run {
|
} ?: run {
|
||||||
quotedMessagePreview?.visibility = View.GONE
|
quotedMessagePreview?.visibility = View.GONE
|
||||||
}
|
}
|
||||||
quotedUserName?.text = parentChatMessage.actorDisplayName
|
quotedUserName?.text = parentChatMessage.actorDisplayName
|
||||||
?: context!!.getText(R.string.nc_nick_guest)
|
?: context!!.getText(R.string.nc_nick_guest)
|
||||||
quotedMessage?.text = parentChatMessage.text
|
quotedMessage?.text = parentChatMessage.text
|
||||||
quotedMessage?.setTextColor(context!!.resources.getColor(R.color.nc_outcoming_text_default))
|
quotedMessage?.setTextColor(context!!.resources.getColor(R.color.nc_outcoming_text_default))
|
||||||
quotedUserName?.setTextColor(context!!.resources.getColor(R.color.nc_grey))
|
quotedUserName?.setTextColor(context!!.resources.getColor(R.color.nc_grey))
|
||||||
|
@ -90,6 +90,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var appPreferences: AppPreferences
|
lateinit var appPreferences: AppPreferences
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var okHttpClient: OkHttpClient
|
lateinit var okHttpClient: OkHttpClient
|
||||||
//endregion
|
//endregion
|
||||||
@ -105,8 +106,10 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
|
WebRtcAudioManager.setBlacklistDeviceForOpenSLESUsage(true)
|
||||||
}
|
}
|
||||||
|
|
||||||
PeerConnectionFactory.initialize(PeerConnectionFactory.InitializationOptions.builder(this)
|
PeerConnectionFactory.initialize(
|
||||||
.createInitializationOptions())
|
PeerConnectionFactory.InitializationOptions.builder(this)
|
||||||
|
.createInitializationOptions()
|
||||||
|
)
|
||||||
} catch (e: UnsatisfiedLinkError) {
|
} catch (e: UnsatisfiedLinkError) {
|
||||||
Log.w(TAG, e)
|
Log.w(TAG, e)
|
||||||
}
|
}
|
||||||
@ -120,8 +123,8 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
|
|
||||||
val securityKeyManager = SecurityKeyManager.getInstance()
|
val securityKeyManager = SecurityKeyManager.getInstance()
|
||||||
val securityKeyConfig = SecurityKeyManagerConfig.Builder()
|
val securityKeyConfig = SecurityKeyManagerConfig.Builder()
|
||||||
.setEnableDebugLogging(BuildConfig.DEBUG)
|
.setEnableDebugLogging(BuildConfig.DEBUG)
|
||||||
.build()
|
.build()
|
||||||
securityKeyManager.init(this, securityKeyConfig)
|
securityKeyManager.init(this, securityKeyConfig)
|
||||||
|
|
||||||
initializeWebRtc()
|
initializeWebRtc()
|
||||||
@ -136,13 +139,15 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
|
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
|
||||||
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
|
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
|
||||||
.setMainDiskCacheConfig(DiskCacheConfig.newBuilder(this)
|
.setMainDiskCacheConfig(
|
||||||
.setMaxCacheSize(0)
|
DiskCacheConfig.newBuilder(this)
|
||||||
.setMaxCacheSizeOnLowDiskSpace(0)
|
.setMaxCacheSize(0)
|
||||||
.setMaxCacheSizeOnVeryLowDiskSpace(0)
|
.setMaxCacheSizeOnLowDiskSpace(0)
|
||||||
.build())
|
.setMaxCacheSizeOnVeryLowDiskSpace(0)
|
||||||
.build()
|
.build()
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
Fresco.initialize(this, imagePipelineConfig)
|
Fresco.initialize(this, imagePipelineConfig)
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
||||||
@ -152,8 +157,10 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
|
|
||||||
val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
|
val pushRegistrationWork = OneTimeWorkRequest.Builder(PushRegistrationWorker::class.java).build()
|
||||||
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
val accountRemovalWork = OneTimeWorkRequest.Builder(AccountRemovalWorker::class.java).build()
|
||||||
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(CapabilitiesWorker::class.java,
|
val periodicCapabilitiesUpdateWork = PeriodicWorkRequest.Builder(
|
||||||
12, TimeUnit.HOURS).build()
|
CapabilitiesWorker::class.java,
|
||||||
|
12, TimeUnit.HOURS
|
||||||
|
).build()
|
||||||
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
|
val capabilitiesUpdateWork = OneTimeWorkRequest.Builder(CapabilitiesWorker::class.java).build()
|
||||||
val signalingSettingsWork = OneTimeWorkRequest.Builder(SignalingSettingsWorker::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(accountRemovalWork)
|
||||||
WorkManager.getInstance().enqueue(capabilitiesUpdateWork)
|
WorkManager.getInstance().enqueue(capabilitiesUpdateWork)
|
||||||
WorkManager.getInstance().enqueue(signalingSettingsWork)
|
WorkManager.getInstance().enqueue(signalingSettingsWork)
|
||||||
WorkManager.getInstance().enqueueUniquePeriodicWork("DailyCapabilitiesUpdateWork", ExistingPeriodicWorkPolicy.REPLACE, periodicCapabilitiesUpdateWork)
|
WorkManager.getInstance().enqueueUniquePeriodicWork(
|
||||||
|
"DailyCapabilitiesUpdateWork",
|
||||||
|
ExistingPeriodicWorkPolicy.REPLACE,
|
||||||
|
periodicCapabilitiesUpdateWork
|
||||||
|
)
|
||||||
|
|
||||||
val config = BundledEmojiCompatConfig(this)
|
val config = BundledEmojiCompatConfig(this)
|
||||||
config.setReplaceAll(true)
|
config.setReplaceAll(true)
|
||||||
@ -176,17 +187,16 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
}
|
}
|
||||||
//endregion
|
//endregion
|
||||||
|
|
||||||
|
|
||||||
//region Protected methods
|
//region Protected methods
|
||||||
protected fun buildComponent() {
|
protected fun buildComponent() {
|
||||||
componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
|
componentApplication = DaggerNextcloudTalkApplicationComponent.builder()
|
||||||
.busModule(BusModule())
|
.busModule(BusModule())
|
||||||
.contextModule(ContextModule(applicationContext))
|
.contextModule(ContextModule(applicationContext))
|
||||||
.databaseModule(DatabaseModule())
|
.databaseModule(DatabaseModule())
|
||||||
.restModule(RestModule(applicationContext))
|
.restModule(RestModule(applicationContext))
|
||||||
.userModule(UserModule())
|
.userModule(UserModule())
|
||||||
.arbitraryStorageModule(ArbitraryStorageModule())
|
.arbitraryStorageModule(ArbitraryStorageModule())
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun attachBaseContext(base: Context) {
|
override fun attachBaseContext(base: Context) {
|
||||||
@ -196,19 +206,20 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
|
|
||||||
private fun buildDefaultImageLoader(): ImageLoader {
|
private fun buildDefaultImageLoader(): ImageLoader {
|
||||||
return ImageLoader.Builder(applicationContext)
|
return ImageLoader.Builder(applicationContext)
|
||||||
.availableMemoryPercentage(0.5) // Use 50% of the application's available memory.
|
.availableMemoryPercentage(0.5) // Use 50% of the application's available memory.
|
||||||
.crossfade(true) // Show a short crossfade when loading images from network or disk into an ImageView.
|
.crossfade(true) // Show a short crossfade when loading images from network or disk into an ImageView.
|
||||||
.componentRegistry {
|
.componentRegistry {
|
||||||
if (SDK_INT >= P) {
|
if (SDK_INT >= P) {
|
||||||
add(ImageDecoderDecoder(applicationContext))
|
add(ImageDecoderDecoder(applicationContext))
|
||||||
} else {
|
} else {
|
||||||
add(GifDecoder())
|
add(GifDecoder())
|
||||||
}
|
|
||||||
add(SvgDecoder(applicationContext))
|
|
||||||
}
|
}
|
||||||
.okHttpClient(okHttpClient)
|
add(SvgDecoder(applicationContext))
|
||||||
.build()
|
}
|
||||||
|
.okHttpClient(okHttpClient)
|
||||||
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
private val TAG = NextcloudTalkApplication::class.java.simpleName
|
||||||
//region Singleton
|
//region Singleton
|
||||||
|
@ -44,10 +44,6 @@ import android.widget.ImageView;
|
|||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
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.RouterTransaction;
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler;
|
||||||
import com.bluelinelabs.logansquare.LoganSquare;
|
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.database.UserEntity;
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation;
|
import com.nextcloud.talk.models.json.conversations.Conversation;
|
||||||
import com.nextcloud.talk.models.json.conversations.RoomOverall;
|
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.Participant;
|
||||||
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
|
import com.nextcloud.talk.models.json.participants.ParticipantsOverall;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
import com.nextcloud.talk.utils.ApiUtils;
|
||||||
@ -94,6 +89,9 @@ import java.util.List;
|
|||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import androidx.annotation.NonNull;
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.constraintlayout.widget.ConstraintLayout;
|
||||||
import autodagger.AutoInjector;
|
import autodagger.AutoInjector;
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.OnClick;
|
import butterknife.OnClick;
|
||||||
@ -206,13 +204,13 @@ public class CallNotificationController extends BaseController {
|
|||||||
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
|
originalBundle.putString(BundleKeys.INSTANCE.getKEY_CONVERSATION_NAME(), currentConversation.getDisplayName());
|
||||||
|
|
||||||
getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
|
getRouter().replaceTopController(RouterTransaction.with(new CallController(originalBundle))
|
||||||
.popChangeHandler(new HorizontalChangeHandler())
|
.popChangeHandler(new HorizontalChangeHandler())
|
||||||
.pushChangeHandler(new HorizontalChangeHandler()));
|
.pushChangeHandler(new HorizontalChangeHandler()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkIfAnyParticipantsRemainInRoom() {
|
private void checkIfAnyParticipantsRemainInRoom() {
|
||||||
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(userBeingCalled.getBaseUrl(),
|
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForCall(userBeingCalled.getBaseUrl(),
|
||||||
currentConversation.getToken()))
|
currentConversation.getToken()))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.takeWhile(observable -> !leavingScreen)
|
.takeWhile(observable -> !leavingScreen)
|
||||||
.subscribe(new Observer<ParticipantsOverall>() {
|
.subscribe(new Observer<ParticipantsOverall>() {
|
||||||
@ -261,7 +259,7 @@ public class CallNotificationController extends BaseController {
|
|||||||
|
|
||||||
private void handleFromNotification() {
|
private void handleFromNotification() {
|
||||||
boolean isConversationApiV3 = userBeingCalled.hasSpreedFeatureCapability("conversation-v3");
|
boolean isConversationApiV3 = userBeingCalled.hasSpreedFeatureCapability("conversation-v3");
|
||||||
if(isConversationApiV3) {
|
if (isConversationApiV3) {
|
||||||
ncApi.getRoom(credentials, ApiUtils.getRoomV3(userBeingCalled.getBaseUrl(), roomId))
|
ncApi.getRoom(credentials, ApiUtils.getRoomV3(userBeingCalled.getBaseUrl(), roomId))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.retry(3)
|
.retry(3)
|
||||||
@ -279,12 +277,12 @@ public class CallNotificationController extends BaseController {
|
|||||||
|
|
||||||
boolean hasCallFlags = userBeingCalled.hasSpreedFeatureCapability("conversation-call-flags");
|
boolean hasCallFlags = userBeingCalled.hasSpreedFeatureCapability("conversation-call-flags");
|
||||||
if (hasCallFlags) {
|
if (hasCallFlags) {
|
||||||
if (isInCallWithVideo(currentConversation.callFlag)){
|
if (isInCallWithVideo(currentConversation.callFlag)) {
|
||||||
incomingCallVoiceOrVideoTextView.setText(String.format(getResources().getString(R.string.nc_call_video),
|
incomingCallVoiceOrVideoTextView.setText(String.format(getResources().getString(R.string.nc_call_video),
|
||||||
getResources().getString(R.string.nc_app_name)));
|
getResources().getString(R.string.nc_app_name)));
|
||||||
} else {
|
} else {
|
||||||
incomingCallVoiceOrVideoTextView.setText(String.format(getResources().getString(R.string.nc_call_voice),
|
incomingCallVoiceOrVideoTextView.setText(String.format(getResources().getString(R.string.nc_call_voice),
|
||||||
getResources().getString(R.string.nc_app_name)));
|
getResources().getString(R.string.nc_app_name)));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -412,7 +410,7 @@ public class CallNotificationController extends BaseController {
|
|||||||
|
|
||||||
ImageRequest imageRequest =
|
ImageRequest imageRequest =
|
||||||
DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
|
DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(userBeingCalled.getBaseUrl(),
|
||||||
currentConversation.getName(), R.dimen.avatar_size_very_big), null);
|
currentConversation.getName(), R.dimen.avatar_size_very_big), null);
|
||||||
|
|
||||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
||||||
DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
|
DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(imageRequest, null);
|
||||||
@ -422,11 +420,11 @@ public class CallNotificationController extends BaseController {
|
|||||||
protected void onNewResultImpl(@Nullable Bitmap bitmap) {
|
protected void onNewResultImpl(@Nullable Bitmap bitmap) {
|
||||||
if (avatarImageView != null) {
|
if (avatarImageView != null) {
|
||||||
avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
|
avatarImageView.getHierarchy().setImage(new BitmapDrawable(bitmap), 100,
|
||||||
true);
|
true);
|
||||||
|
|
||||||
if (getResources() != null) {
|
if (getResources() != null) {
|
||||||
incomingTextRelativeLayout.setBackground(getResources().getDrawable(R.drawable
|
incomingTextRelativeLayout.setBackground(getResources().getDrawable(R.drawable
|
||||||
.incoming_gradient));
|
.incoming_gradient));
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 || AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) &&
|
if ((AvatarStatusCodeHolder.getInstance().getStatusCode() == 200 || AvatarStatusCodeHolder.getInstance().getStatusCode() == 0) &&
|
||||||
@ -512,7 +510,7 @@ public class CallNotificationController extends BaseController {
|
|||||||
if (TextUtils.isEmpty(callRingtonePreferenceString)) {
|
if (TextUtils.isEmpty(callRingtonePreferenceString)) {
|
||||||
// play default sound
|
// play default sound
|
||||||
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
|
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
|
||||||
"/raw/librem_by_feandesign_call");
|
"/raw/librem_by_feandesign_call");
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
RingtoneSettings ringtoneSettings = LoganSquare.parse(callRingtonePreferenceString, RingtoneSettings.class);
|
RingtoneSettings ringtoneSettings = LoganSquare.parse(callRingtonePreferenceString, RingtoneSettings.class);
|
||||||
@ -520,7 +518,7 @@ public class CallNotificationController extends BaseController {
|
|||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
Log.e(TAG, "Failed to parse ringtone settings");
|
Log.e(TAG, "Failed to parse ringtone settings");
|
||||||
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
|
ringtoneUri = Uri.parse("android.resource://" + getApplicationContext().getPackageName() +
|
||||||
"/raw/librem_by_feandesign_call");
|
"/raw/librem_by_feandesign_call");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -531,7 +529,7 @@ public class CallNotificationController extends BaseController {
|
|||||||
|
|
||||||
mediaPlayer.setLooping(true);
|
mediaPlayer.setLooping(true);
|
||||||
AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(AudioAttributes
|
AudioAttributes audioAttributes = new AudioAttributes.Builder().setContentType(AudioAttributes
|
||||||
.CONTENT_TYPE_SONIFICATION).setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build();
|
.CONTENT_TYPE_SONIFICATION).setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).build();
|
||||||
mediaPlayer.setAudioAttributes(audioAttributes);
|
mediaPlayer.setAudioAttributes(audioAttributes);
|
||||||
|
|
||||||
mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
|
mediaPlayer.setOnPreparedListener(mp -> mediaPlayer.start());
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -85,50 +85,69 @@ import io.reactivex.schedulers.Schedulers
|
|||||||
import org.greenrobot.eventbus.EventBus
|
import org.greenrobot.eventbus.EventBus
|
||||||
import org.greenrobot.eventbus.Subscribe
|
import org.greenrobot.eventbus.Subscribe
|
||||||
import org.greenrobot.eventbus.ThreadMode
|
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 javax.inject.Inject
|
||||||
import kotlin.collections.ArrayList
|
|
||||||
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleAdapter.OnItemClickListener {
|
class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleAdapter.OnItemClickListener {
|
||||||
|
|
||||||
@BindView(R.id.notification_settings)
|
@BindView(R.id.notification_settings)
|
||||||
lateinit var notificationsPreferenceScreen: MaterialPreferenceScreen
|
lateinit var notificationsPreferenceScreen: MaterialPreferenceScreen
|
||||||
|
|
||||||
@BindView(R.id.progressBar)
|
@BindView(R.id.progressBar)
|
||||||
lateinit var progressBar: ProgressBar
|
lateinit var progressBar: ProgressBar
|
||||||
|
|
||||||
@BindView(R.id.conversation_info_message_notifications)
|
@BindView(R.id.conversation_info_message_notifications)
|
||||||
lateinit var messageNotificationLevel: MaterialChoicePreference
|
lateinit var messageNotificationLevel: MaterialChoicePreference
|
||||||
|
|
||||||
@BindView(R.id.webinar_settings)
|
@BindView(R.id.webinar_settings)
|
||||||
lateinit var conversationInfoWebinar: MaterialPreferenceScreen
|
lateinit var conversationInfoWebinar: MaterialPreferenceScreen
|
||||||
|
|
||||||
@BindView(R.id.conversation_info_lobby)
|
@BindView(R.id.conversation_info_lobby)
|
||||||
lateinit var conversationInfoLobby: MaterialSwitchPreference
|
lateinit var conversationInfoLobby: MaterialSwitchPreference
|
||||||
|
|
||||||
@BindView(R.id.conversation_info_name)
|
@BindView(R.id.conversation_info_name)
|
||||||
lateinit var nameCategoryView: MaterialPreferenceCategory
|
lateinit var nameCategoryView: MaterialPreferenceCategory
|
||||||
|
|
||||||
@BindView(R.id.start_time_preferences)
|
@BindView(R.id.start_time_preferences)
|
||||||
lateinit var startTimeView: MaterialStandardPreference
|
lateinit var startTimeView: MaterialStandardPreference
|
||||||
|
|
||||||
@BindView(R.id.avatar_image)
|
@BindView(R.id.avatar_image)
|
||||||
lateinit var conversationAvatarImageView: SimpleDraweeView
|
lateinit var conversationAvatarImageView: SimpleDraweeView
|
||||||
|
|
||||||
@BindView(R.id.display_name_text)
|
@BindView(R.id.display_name_text)
|
||||||
lateinit var conversationDisplayName: EmojiTextView
|
lateinit var conversationDisplayName: EmojiTextView
|
||||||
|
|
||||||
@BindView(R.id.participants_list_category)
|
@BindView(R.id.participants_list_category)
|
||||||
lateinit var participantsListCategory: MaterialPreferenceCategory
|
lateinit var participantsListCategory: MaterialPreferenceCategory
|
||||||
|
|
||||||
@BindView(R.id.addParticipantsAction)
|
@BindView(R.id.addParticipantsAction)
|
||||||
lateinit var addParticipantsAction: MaterialStandardPreference;
|
lateinit var addParticipantsAction: MaterialStandardPreference
|
||||||
|
|
||||||
@BindView(R.id.recycler_view)
|
@BindView(R.id.recycler_view)
|
||||||
lateinit var recyclerView: RecyclerView
|
lateinit var recyclerView: RecyclerView
|
||||||
|
|
||||||
@BindView(R.id.deleteConversationAction)
|
@BindView(R.id.deleteConversationAction)
|
||||||
lateinit var deleteConversationAction: MaterialStandardPreference
|
lateinit var deleteConversationAction: MaterialStandardPreference
|
||||||
|
|
||||||
@BindView(R.id.leaveConversationAction)
|
@BindView(R.id.leaveConversationAction)
|
||||||
lateinit var leaveConversationAction: MaterialStandardPreference
|
lateinit var leaveConversationAction: MaterialStandardPreference
|
||||||
|
|
||||||
@BindView(R.id.ownOptions)
|
@BindView(R.id.ownOptions)
|
||||||
lateinit var ownOptionsCategory: MaterialPreferenceCategory
|
lateinit var ownOptionsCategory: MaterialPreferenceCategory
|
||||||
|
|
||||||
@BindView(R.id.muteCalls)
|
@BindView(R.id.muteCalls)
|
||||||
lateinit var muteCalls: MaterialSwitchPreference
|
lateinit var muteCalls: MaterialSwitchPreference
|
||||||
|
|
||||||
@set:Inject
|
@set:Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
|
|
||||||
@set:Inject
|
@set:Inject
|
||||||
lateinit var context: Context
|
lateinit var context: Context
|
||||||
|
|
||||||
@set:Inject
|
@set:Inject
|
||||||
lateinit var eventBus: EventBus
|
lateinit var eventBus: EventBus
|
||||||
|
|
||||||
@ -164,7 +183,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
NextcloudTalkApplication.sharedApplication?.componentApplication?.inject(this)
|
||||||
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
|
conversationUser = args.getParcelable(BundleKeys.KEY_USER_ENTITY)
|
||||||
conversationToken = args.getString(BundleKeys.KEY_ROOM_TOKEN)
|
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)
|
credentials = ApiUtils.getCredentials(conversationUser!!.username, conversationUser.token)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -207,14 +226,19 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun setupWebinaryView() {
|
private fun setupWebinaryView() {
|
||||||
if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") && (conversation!!.type
|
if (conversationUser!!.hasSpreedFeatureCapability("webinary-lobby") &&
|
||||||
== Conversation.ConversationType.ROOM_GROUP_CALL || conversation!!.type ==
|
(
|
||||||
Conversation.ConversationType.ROOM_PUBLIC_CALL) && conversation!!.canModerate(conversationUser)) {
|
conversation!!.type == Conversation.ConversationType.ROOM_GROUP_CALL ||
|
||||||
|
conversation!!.type == Conversation.ConversationType.ROOM_PUBLIC_CALL
|
||||||
|
) &&
|
||||||
|
conversation!!.canModerate(conversationUser)
|
||||||
|
) {
|
||||||
conversationInfoWebinar.visibility = View.VISIBLE
|
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)
|
(conversationInfoLobby.findViewById<View>(R.id.mp_checkable) as SwitchCompat)
|
||||||
.isChecked = isLobbyOpenToModeratorsOnly
|
.isChecked = isLobbyOpenToModeratorsOnly
|
||||||
|
|
||||||
reconfigureLobbyTimerView()
|
reconfigureLobbyTimerView()
|
||||||
|
|
||||||
@ -225,12 +249,17 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * 1000
|
currentTimeCalendar.timeInMillis = conversation!!.lobbyTimer * 1000
|
||||||
}
|
}
|
||||||
|
|
||||||
dateTimePicker(minDateTime = Calendar.getInstance(), requireFutureDateTime =
|
dateTimePicker(
|
||||||
true, currentDateTime = currentTimeCalendar, dateTimeCallback = { _,
|
minDateTime = Calendar.getInstance(),
|
||||||
dateTime ->
|
requireFutureDateTime =
|
||||||
reconfigureLobbyTimerView(dateTime)
|
true,
|
||||||
submitLobbyChanges()
|
currentDateTime = currentTimeCalendar,
|
||||||
})
|
dateTimeCallback = { _,
|
||||||
|
dateTime ->
|
||||||
|
reconfigureLobbyTimerView(dateTime)
|
||||||
|
submitLobbyChanges()
|
||||||
|
}
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,7 +282,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
|
|
||||||
conversation!!.lobbyState = if (isChecked) Conversation.LobbyState
|
conversation!!.lobbyState = if (isChecked) Conversation.LobbyState
|
||||||
.LOBBY_STATE_MODERATORS_ONLY else Conversation.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS
|
.LOBBY_STATE_MODERATORS_ONLY else Conversation.LobbyState.LOBBY_STATE_ALL_PARTICIPANTS
|
||||||
|
|
||||||
if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != java.lang.Long.MIN_VALUE && conversation!!.lobbyTimer != 0L) {
|
if (conversation!!.lobbyTimer != null && conversation!!.lobbyTimer != java.lang.Long.MIN_VALUE && conversation!!.lobbyTimer != 0L) {
|
||||||
startTimeView.setSummary(DateUtils.getLocalDateStringFromTimestampForLobby(conversation!!.lobbyTimer))
|
startTimeView.setSummary(DateUtils.getLocalDateStringFromTimestampForLobby(conversation!!.lobbyTimer))
|
||||||
@ -269,27 +298,34 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun submitLobbyChanges() {
|
fun submitLobbyChanges() {
|
||||||
val state = if ((conversationInfoLobby.findViewById<View>(R.id
|
val state = if (
|
||||||
.mp_checkable) as SwitchCompat).isChecked) 1 else 0
|
(
|
||||||
ncApi.setLobbyForConversation(ApiUtils.getCredentials(conversationUser!!.username,
|
conversationInfoLobby.findViewById<View>(
|
||||||
conversationUser.token), ApiUtils.getUrlForLobbyForConversation
|
R.id.mp_checkable
|
||||||
(conversationUser.baseUrl, conversation!!.token), state, conversation!!.lobbyTimer)
|
) as SwitchCompat
|
||||||
.subscribeOn(Schedulers.io())
|
).isChecked
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
) 1 else 0
|
||||||
.subscribe(object : Observer<GenericOverall> {
|
ncApi.setLobbyForConversation(
|
||||||
override fun onComplete() {
|
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> {
|
||||||
|
override fun onComplete() {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(t: GenericOverall) {
|
override fun onNext(t: GenericOverall) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
}
|
}
|
||||||
|
})
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun showLovelyDialog(dialogId: Int, savedInstanceState: Bundle) {
|
private fun showLovelyDialog(dialogId: Int, savedInstanceState: Bundle) {
|
||||||
@ -313,17 +349,21 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
private fun showDeleteConversationDialog(savedInstanceState: Bundle?) {
|
private fun showDeleteConversationDialog(savedInstanceState: Bundle?) {
|
||||||
if (activity != null) {
|
if (activity != null) {
|
||||||
LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL)
|
LovelyStandardDialog(activity, LovelyStandardDialog.ButtonLayout.HORIZONTAL)
|
||||||
.setTopColorRes(R.color.nc_darkRed)
|
.setTopColorRes(R.color.nc_darkRed)
|
||||||
.setIcon(DisplayUtils.getTintedDrawable(context!!.resources,
|
.setIcon(
|
||||||
R.drawable.ic_delete_black_24dp, R.color.bg_default))
|
DisplayUtils.getTintedDrawable(
|
||||||
.setPositiveButtonColor(context!!.resources.getColor(R.color.nc_darkRed))
|
context!!.resources,
|
||||||
.setTitle(R.string.nc_delete_call)
|
R.drawable.ic_delete_black_24dp, R.color.bg_default
|
||||||
.setMessage(conversation!!.deleteWarningMessage)
|
)
|
||||||
.setPositiveButton(R.string.nc_delete) { deleteConversation() }
|
)
|
||||||
.setNegativeButton(R.string.nc_cancel, null)
|
.setPositiveButtonColor(context!!.resources.getColor(R.color.nc_darkRed))
|
||||||
.setInstanceStateHandler(ID_DELETE_CONVERSATION_DIALOG, saveStateHandler!!)
|
.setTitle(R.string.nc_delete_call)
|
||||||
.setSavedInstanceState(savedInstanceState)
|
.setMessage(conversation!!.deleteWarningMessage)
|
||||||
.show()
|
.setPositiveButton(R.string.nc_delete) { deleteConversation() }
|
||||||
|
.setNegativeButton(R.string.nc_cancel, null)
|
||||||
|
.setInstanceStateHandler(ID_DELETE_CONVERSATION_DIALOG, saveStateHandler!!)
|
||||||
|
.setSavedInstanceState(savedInstanceState)
|
||||||
|
.show()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,8 +375,8 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
override fun onRestoreViewState(view: View, savedViewState: Bundle) {
|
||||||
super.onRestoreViewState(view, savedViewState)
|
super.onRestoreViewState(view, savedViewState)
|
||||||
if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
|
if (LovelySaveStateHandler.wasDialogOnScreen(savedViewState)) {
|
||||||
//Dialog won't be restarted automatically, so we need to call this method.
|
// Dialog won't be restarted automatically, so we need to call this method.
|
||||||
//Each dialog knows how to restore its state
|
// Each dialog knows how to restore its state
|
||||||
showLovelyDialog(LovelySaveStateHandler.getSavedDialogId(savedViewState), savedViewState)
|
showLovelyDialog(LovelySaveStateHandler.getSavedDialogId(savedViewState), savedViewState)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -397,27 +437,28 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getListOfParticipants() {
|
private fun getListOfParticipants() {
|
||||||
ncApi.getPeersForCall(credentials, ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken))
|
ncApi.getPeersForCall(
|
||||||
.subscribeOn(Schedulers.io())
|
credentials,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
ApiUtils.getUrlForParticipants(conversationUser!!.baseUrl, conversationToken)
|
||||||
.subscribe(object : Observer<ParticipantsOverall> {
|
)
|
||||||
override fun onSubscribe(d: Disposable) {
|
.subscribeOn(Schedulers.io())
|
||||||
participantsDisposable = d
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
}
|
.subscribe(object : Observer<ParticipantsOverall> {
|
||||||
|
override fun onSubscribe(d: Disposable) {
|
||||||
|
participantsDisposable = d
|
||||||
|
}
|
||||||
|
|
||||||
override fun onNext(participantsOverall: ParticipantsOverall) {
|
override fun onNext(participantsOverall: ParticipantsOverall) {
|
||||||
handleParticipants(participantsOverall.ocs.data)
|
handleParticipants(participantsOverall.ocs.data)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onComplete() {
|
|
||||||
participantsDisposable!!.dispose()
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
participantsDisposable!!.dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.addParticipantsAction)
|
@OnClick(R.id.addParticipantsAction)
|
||||||
@ -430,21 +471,33 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
existingParticipantsId.add(userItem.model.userId)
|
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.putStringArrayList(BundleKeys.KEY_EXISTING_PARTICIPANTS, existingParticipantsId)
|
||||||
bundle.putString(BundleKeys.KEY_TOKEN, conversation!!.token)
|
bundle.putString(BundleKeys.KEY_TOKEN, conversation!!.token)
|
||||||
|
|
||||||
getRouter().pushController((RouterTransaction.with(ContactsController(bundle))
|
getRouter().pushController(
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
(
|
||||||
.popChangeHandler(HorizontalChangeHandler())))
|
RouterTransaction.with(
|
||||||
|
ContactsController(bundle)
|
||||||
|
)
|
||||||
|
.pushChangeHandler(
|
||||||
|
HorizontalChangeHandler()
|
||||||
|
)
|
||||||
|
.popChangeHandler(
|
||||||
|
HorizontalChangeHandler()
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@OnClick(R.id.leaveConversationAction)
|
@OnClick(R.id.leaveConversationAction)
|
||||||
internal fun leaveConversation() {
|
internal fun leaveConversation() {
|
||||||
workerData?.let {
|
workerData?.let {
|
||||||
WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
|
WorkManager.getInstance().enqueue(
|
||||||
(LeaveConversationWorker::class
|
OneTimeWorkRequest.Builder(
|
||||||
.java).setInputData(it).build()
|
LeaveConversationWorker::class
|
||||||
|
.java
|
||||||
|
).setInputData(it).build()
|
||||||
)
|
)
|
||||||
popTwoLastControllers()
|
popTwoLastControllers()
|
||||||
}
|
}
|
||||||
@ -452,8 +505,11 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
|
|
||||||
private fun deleteConversation() {
|
private fun deleteConversation() {
|
||||||
workerData?.let {
|
workerData?.let {
|
||||||
WorkManager.getInstance().enqueue(OneTimeWorkRequest.Builder
|
WorkManager.getInstance().enqueue(
|
||||||
(DeleteConversationWorker::class.java).setInputData(it).build())
|
OneTimeWorkRequest.Builder(
|
||||||
|
DeleteConversationWorker::class.java
|
||||||
|
).setInputData(it).build()
|
||||||
|
)
|
||||||
popTwoLastControllers()
|
popTwoLastControllers()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -471,69 +527,67 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
|
|
||||||
private fun fetchRoomInfo() {
|
private fun fetchRoomInfo() {
|
||||||
ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser!!.baseUrl, conversationToken))
|
ncApi.getRoom(credentials, ApiUtils.getRoom(conversationUser!!.baseUrl, conversationToken))
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(object : Observer<RoomOverall> {
|
.subscribe(object : Observer<RoomOverall> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
roomDisposable = d
|
roomDisposable = d
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onNext(roomOverall: RoomOverall) {
|
||||||
|
conversation = roomOverall.ocs.data
|
||||||
|
|
||||||
|
val conversationCopy = conversation
|
||||||
|
|
||||||
|
if (conversationCopy!!.canModerate(conversationUser)) {
|
||||||
|
addParticipantsAction.visibility = View.VISIBLE
|
||||||
|
} else {
|
||||||
|
addParticipantsAction.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(roomOverall: RoomOverall) {
|
if (isAttached && (!isBeingDestroyed || !isDestroyed)) {
|
||||||
conversation = roomOverall.ocs.data
|
ownOptionsCategory.visibility = View.VISIBLE
|
||||||
|
|
||||||
val conversationCopy = conversation
|
setupWebinaryView()
|
||||||
|
|
||||||
if (conversationCopy!!.canModerate(conversationUser)) {
|
if (!conversation!!.canLeave(conversationUser)) {
|
||||||
addParticipantsAction.visibility = View.VISIBLE
|
leaveConversationAction.visibility = View.GONE
|
||||||
} else {
|
} else {
|
||||||
addParticipantsAction.visibility = View.GONE
|
leaveConversationAction.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isAttached && (!isBeingDestroyed || !isDestroyed)) {
|
if (!conversation!!.canModerate(conversationUser)) {
|
||||||
ownOptionsCategory.visibility = View.VISIBLE
|
deleteConversationAction.visibility = View.GONE
|
||||||
|
} else {
|
||||||
setupWebinaryView()
|
deleteConversationAction.visibility = View.VISIBLE
|
||||||
|
|
||||||
if (!conversation!!.canLeave(conversationUser)) {
|
|
||||||
leaveConversationAction.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
leaveConversationAction.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!conversation!!.canModerate(conversationUser)) {
|
|
||||||
deleteConversationAction.visibility = View.GONE
|
|
||||||
} else {
|
|
||||||
deleteConversationAction.visibility = View.VISIBLE
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Conversation.ConversationType.ROOM_SYSTEM == conversation!!.type) {
|
|
||||||
muteCalls.visibility = View.GONE
|
|
||||||
}
|
|
||||||
|
|
||||||
getListOfParticipants()
|
|
||||||
|
|
||||||
progressBar.visibility = View.GONE
|
|
||||||
|
|
||||||
nameCategoryView.visibility = View.VISIBLE
|
|
||||||
|
|
||||||
conversationDisplayName.text = conversation!!.displayName
|
|
||||||
|
|
||||||
|
|
||||||
loadConversationAvatar()
|
|
||||||
adjustNotificationLevelUI()
|
|
||||||
|
|
||||||
notificationsPreferenceScreen.visibility = View.VISIBLE
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
if (Conversation.ConversationType.ROOM_SYSTEM == conversation!!.type) {
|
||||||
|
muteCalls.visibility = View.GONE
|
||||||
|
}
|
||||||
|
|
||||||
}
|
getListOfParticipants()
|
||||||
|
|
||||||
override fun onComplete() {
|
progressBar.visibility = View.GONE
|
||||||
roomDisposable!!.dispose()
|
|
||||||
|
nameCategoryView.visibility = View.VISIBLE
|
||||||
|
|
||||||
|
conversationDisplayName.text = conversation!!.displayName
|
||||||
|
|
||||||
|
loadConversationAvatar()
|
||||||
|
adjustNotificationLevelUI()
|
||||||
|
|
||||||
|
notificationsPreferenceScreen.visibility = View.VISIBLE
|
||||||
}
|
}
|
||||||
})
|
}
|
||||||
|
|
||||||
|
override fun onError(e: Throwable) {
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun onComplete() {
|
||||||
|
roomDisposable!!.dispose()
|
||||||
|
}
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun adjustNotificationLevelUI() {
|
private fun adjustNotificationLevelUI() {
|
||||||
@ -543,12 +597,13 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
messageNotificationLevel.alpha = 1.0f
|
messageNotificationLevel.alpha = 1.0f
|
||||||
|
|
||||||
if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) {
|
if (conversation!!.notificationLevel != Conversation.NotificationLevel.DEFAULT) {
|
||||||
val stringValue: String = when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
|
val stringValue: String =
|
||||||
1 -> "always"
|
when (EnumNotificationLevelConverter().convertToInt(conversation!!.notificationLevel)) {
|
||||||
2 -> "mention"
|
1 -> "always"
|
||||||
3 -> "never"
|
2 -> "mention"
|
||||||
else -> "mention"
|
3 -> "never"
|
||||||
}
|
else -> "mention"
|
||||||
|
}
|
||||||
|
|
||||||
messageNotificationLevel.value = stringValue
|
messageNotificationLevel.value = stringValue
|
||||||
} else {
|
} else {
|
||||||
@ -577,22 +632,38 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
|
|
||||||
private fun loadConversationAvatar() {
|
private fun loadConversationAvatar() {
|
||||||
when (conversation!!.type) {
|
when (conversation!!.type) {
|
||||||
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty
|
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (
|
||||||
(conversation!!.name)) {
|
!TextUtils.isEmpty(conversation!!.name)
|
||||||
|
) {
|
||||||
val draweeController = Fresco.newDraweeControllerBuilder()
|
val draweeController = Fresco.newDraweeControllerBuilder()
|
||||||
.setOldController(conversationAvatarImageView.controller)
|
.setOldController(conversationAvatarImageView.controller)
|
||||||
.setAutoPlayAnimations(true)
|
.setAutoPlayAnimations(true)
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(ApiUtils.getUrlForAvatarWithName(conversationUser!!.baseUrl,
|
.setImageRequest(
|
||||||
conversation!!.name, R.dimen.avatar_size_big), conversationUser))
|
DisplayUtils.getImageRequestForUrl(
|
||||||
.build()
|
ApiUtils.getUrlForAvatarWithName(
|
||||||
|
conversationUser!!.baseUrl,
|
||||||
|
conversation!!.name, R.dimen.avatar_size_big
|
||||||
|
),
|
||||||
|
conversationUser
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
conversationAvatarImageView.controller = draweeController
|
conversationAvatarImageView.controller = draweeController
|
||||||
}
|
}
|
||||||
Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
|
Conversation.ConversationType.ROOM_GROUP_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||||
.getRoundedBitmapDrawableFromVectorDrawableResource(resources,
|
DisplayUtils
|
||||||
R.drawable.ic_people_group_white_24px))
|
.getRoundedBitmapDrawableFromVectorDrawableResource(
|
||||||
Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(DisplayUtils
|
resources,
|
||||||
.getRoundedBitmapDrawableFromVectorDrawableResource(resources,
|
R.drawable.ic_people_group_white_24px
|
||||||
R.drawable.ic_link_white_24px))
|
)
|
||||||
|
)
|
||||||
|
Conversation.ConversationType.ROOM_PUBLIC_CALL -> conversationAvatarImageView.hierarchy.setPlaceholderImage(
|
||||||
|
DisplayUtils
|
||||||
|
.getRoundedBitmapDrawableFromVectorDrawableResource(
|
||||||
|
resources,
|
||||||
|
R.drawable.ic_link_white_24px
|
||||||
|
)
|
||||||
|
)
|
||||||
Conversation.ConversationType.ROOM_SYSTEM -> {
|
Conversation.ConversationType.ROOM_SYSTEM -> {
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
val layers = arrayOfNulls<Drawable>(2)
|
||||||
layers[0] = context.getDrawable(R.drawable.ic_launcher_background)
|
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 userItem = adapter?.getItem(position) as UserItem
|
||||||
val participant = userItem.model
|
val participant = userItem.model
|
||||||
|
|
||||||
|
|
||||||
if (participant.userId != conversationUser!!.userId) {
|
if (participant.userId != conversationUser!!.userId) {
|
||||||
var items = mutableListOf(
|
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_promote)),
|
||||||
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
|
BasicListItemWithImage(R.drawable.ic_pencil_grey600_24dp, context.getString(R.string.nc_demote)),
|
||||||
BasicListItemWithImage(R.drawable.ic_delete_grey600_24dp,
|
BasicListItemWithImage(
|
||||||
context.getString(R.string.nc_remove_participant))
|
R.drawable.ic_delete_grey600_24dp,
|
||||||
|
context.getString(R.string.nc_remove_participant)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
if (!conversation!!.canModerate(conversationUser)) {
|
if (!conversation!!.canModerate(conversationUser)) {
|
||||||
@ -629,7 +701,6 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (items.isNotEmpty()) {
|
if (items.isNotEmpty()) {
|
||||||
MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
|
MaterialDialog(activity!!, BottomSheet(WRAP_CONTENT)).show {
|
||||||
cornerRadius(res = R.dimen.corner_radius)
|
cornerRadius(res = R.dimen.corner_radius)
|
||||||
@ -639,38 +710,62 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
|
|
||||||
if (index == 0) {
|
if (index == 0) {
|
||||||
if (participant.type == Participant.ParticipantType.MODERATOR) {
|
if (participant.type == Participant.ParticipantType.MODERATOR) {
|
||||||
ncApi.demoteModeratorToUser(credentials, ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), participant.userId)
|
ncApi.demoteModeratorToUser(
|
||||||
.subscribeOn(Schedulers.io())
|
credentials,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token),
|
||||||
.subscribe {
|
participant.userId
|
||||||
getListOfParticipants()
|
)
|
||||||
}
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
getListOfParticipants()
|
||||||
|
}
|
||||||
} else if (participant.type == Participant.ParticipantType.USER) {
|
} else if (participant.type == Participant.ParticipantType.USER) {
|
||||||
ncApi.promoteUserToModerator(credentials, ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token), participant.userId)
|
ncApi.promoteUserToModerator(
|
||||||
.subscribeOn(Schedulers.io())
|
credentials,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
ApiUtils.getUrlForModerators(conversationUser.baseUrl, conversation!!.token),
|
||||||
.subscribe {
|
participant.userId
|
||||||
getListOfParticipants()
|
)
|
||||||
}
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
getListOfParticipants()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if (index == 1) {
|
} else if (index == 1) {
|
||||||
if (participant.type == Participant.ParticipantType.GUEST ||
|
if (participant.type == Participant.ParticipantType.GUEST ||
|
||||||
participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK) {
|
participant.type == Participant.ParticipantType.USER_FOLLOWING_LINK
|
||||||
ncApi.removeParticipantFromConversation(credentials, ApiUtils.getUrlForRemovingParticipantFromConversation(conversationUser.baseUrl, conversation!!.token, true), participant.sessionId)
|
) {
|
||||||
.subscribeOn(Schedulers.io())
|
ncApi.removeParticipantFromConversation(
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
credentials,
|
||||||
.subscribe {
|
ApiUtils.getUrlForRemovingParticipantFromConversation(
|
||||||
getListOfParticipants()
|
conversationUser.baseUrl,
|
||||||
}
|
conversation!!.token,
|
||||||
|
true
|
||||||
|
),
|
||||||
|
participant.sessionId
|
||||||
|
)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
getListOfParticipants()
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
ncApi.removeParticipantFromConversation(credentials, ApiUtils.getUrlForRemovingParticipantFromConversation(conversationUser.baseUrl, conversation!!.token, false), participant.userId)
|
ncApi.removeParticipantFromConversation(
|
||||||
.subscribeOn(Schedulers.io())
|
credentials,
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
ApiUtils.getUrlForRemovingParticipantFromConversation(
|
||||||
.subscribe {
|
conversationUser.baseUrl,
|
||||||
getListOfParticipants()
|
conversation!!.token,
|
||||||
// get participants again
|
false
|
||||||
}
|
),
|
||||||
|
participant.userId
|
||||||
|
)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.subscribe {
|
||||||
|
getListOfParticipants()
|
||||||
|
// get participants again
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -678,7 +773,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
@ -709,7 +804,7 @@ class ConversationInfoController(args: Bundle) : BaseController(args), FlexibleA
|
|||||||
}
|
}
|
||||||
|
|
||||||
return left.model.displayName.toLowerCase(Locale.ROOT).compareTo(
|
return left.model.displayName.toLowerCase(Locale.ROOT).compareTo(
|
||||||
right.model.displayName.toLowerCase(Locale.ROOT)
|
right.model.displayName.toLowerCase(Locale.ROOT)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,5 +53,4 @@ abstract class ButterKnifeController : Controller {
|
|||||||
unbinder!!.unbind()
|
unbinder!!.unbind()
|
||||||
unbinder = null
|
unbinder = null
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -29,8 +29,9 @@ interface ListItemWithImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
data class BasicListItemWithImage(
|
data class BasicListItemWithImage(
|
||||||
@DrawableRes val iconRes: Int,
|
@DrawableRes val iconRes: Int,
|
||||||
override val title: String) : ListItemWithImage {
|
override val title: String
|
||||||
|
) : ListItemWithImage {
|
||||||
|
|
||||||
override fun populateIcon(imageView: ImageView) {
|
override fun populateIcon(imageView: ImageView) {
|
||||||
imageView.setImageResource(iconRes)
|
imageView.setImageResource(iconRes)
|
||||||
|
@ -23,7 +23,6 @@ package com.nextcloud.talk.controllers.bottomsheet.items
|
|||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.ViewGroup
|
import android.view.ViewGroup
|
||||||
import android.widget.ImageView
|
import android.widget.ImageView
|
||||||
import android.widget.TextView
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.afollestad.materialdialogs.MaterialDialog
|
import com.afollestad.materialdialogs.MaterialDialog
|
||||||
import com.afollestad.materialdialogs.WhichButton
|
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.list.getItemSelector
|
||||||
import com.afollestad.materialdialogs.utils.MDUtil.inflate
|
import com.afollestad.materialdialogs.utils.MDUtil.inflate
|
||||||
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
|
import com.afollestad.materialdialogs.utils.MDUtil.maybeSetTextColor
|
||||||
import com.google.android.material.textview.MaterialTextView
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
|
||||||
private const val KEY_ACTIVATED_INDEX = "activated_index"
|
private const val KEY_ACTIVATED_INDEX = "activated_index"
|
||||||
|
|
||||||
internal class ListItemViewHolder(
|
internal class ListItemViewHolder(
|
||||||
itemView: View,
|
itemView: View,
|
||||||
private val adapter: ListIconDialogAdapter<*>) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
private val adapter: ListIconDialogAdapter<*>
|
||||||
|
) : RecyclerView.ViewHolder(itemView), View.OnClickListener {
|
||||||
init {
|
init {
|
||||||
itemView.setOnClickListener(this)
|
itemView.setOnClickListener(this)
|
||||||
}
|
}
|
||||||
@ -53,11 +52,12 @@ internal class ListItemViewHolder(
|
|||||||
}
|
}
|
||||||
|
|
||||||
internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
||||||
private var dialog: MaterialDialog,
|
private var dialog: MaterialDialog,
|
||||||
private var items: List<IT>,
|
private var items: List<IT>,
|
||||||
disabledItems: IntArray?,
|
disabledItems: IntArray?,
|
||||||
private var waitForPositiveButton: Boolean,
|
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)
|
private var disabledIndices: IntArray = disabledItems ?: IntArray(0)
|
||||||
|
|
||||||
@ -81,12 +81,13 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun onCreateViewHolder(
|
override fun onCreateViewHolder(
|
||||||
parent: ViewGroup,
|
parent: ViewGroup,
|
||||||
viewType: Int): ListItemViewHolder {
|
viewType: Int
|
||||||
|
): ListItemViewHolder {
|
||||||
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
|
val listItemView: View = parent.inflate(dialog.windowContext, R.layout.menu_item_sheet)
|
||||||
val viewHolder = ListItemViewHolder(
|
val viewHolder = ListItemViewHolder(
|
||||||
itemView = listItemView,
|
itemView = listItemView,
|
||||||
adapter = this
|
adapter = this
|
||||||
)
|
)
|
||||||
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
|
viewHolder.titleView.maybeSetTextColor(dialog.windowContext, R.attr.md_color_content)
|
||||||
return viewHolder
|
return viewHolder
|
||||||
@ -95,8 +96,9 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
|||||||
override fun getItemCount() = items.size
|
override fun getItemCount() = items.size
|
||||||
|
|
||||||
override fun onBindViewHolder(
|
override fun onBindViewHolder(
|
||||||
holder: ListItemViewHolder,
|
holder: ListItemViewHolder,
|
||||||
position: Int) {
|
position: Int
|
||||||
|
) {
|
||||||
holder.itemView.isEnabled = !disabledIndices.contains(position)
|
holder.itemView.isEnabled = !disabledIndices.contains(position)
|
||||||
val currentItem = items[position]
|
val currentItem = items[position]
|
||||||
|
|
||||||
@ -121,8 +123,9 @@ internal class ListIconDialogAdapter<IT : ListItemWithImage>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
override fun replaceItems(
|
override fun replaceItems(
|
||||||
items: List<IT>,
|
items: List<IT>,
|
||||||
listener: ListItemListener<IT>) {
|
listener: ListItemListener<IT>
|
||||||
|
) {
|
||||||
this.items = items
|
this.items = items
|
||||||
if (listener != null) {
|
if (listener != null) {
|
||||||
this.selection = listener
|
this.selection = listener
|
||||||
|
@ -28,37 +28,40 @@ import com.afollestad.materialdialogs.list.customListAdapter
|
|||||||
import com.afollestad.materialdialogs.list.getListAdapter
|
import com.afollestad.materialdialogs.list.getListAdapter
|
||||||
|
|
||||||
typealias ListItemListener<IT> =
|
typealias ListItemListener<IT> =
|
||||||
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
|
((dialog: MaterialDialog, index: Int, item: IT) -> Unit)?
|
||||||
|
|
||||||
@CheckResult fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
|
@CheckResult
|
||||||
items: List<IT>,
|
fun <IT : ListItemWithImage> MaterialDialog.listItemsWithImage(
|
||||||
disabledIndices: IntArray? = null,
|
items: List<IT>,
|
||||||
waitForPositiveButton: Boolean = true,
|
disabledIndices: IntArray? = null,
|
||||||
selection: ListItemListener<IT> = null): MaterialDialog {
|
waitForPositiveButton: Boolean = true,
|
||||||
|
selection: ListItemListener<IT> = null
|
||||||
|
): MaterialDialog {
|
||||||
|
|
||||||
if (getListAdapter() != null) {
|
if (getListAdapter() != null) {
|
||||||
return updateListItemsWithImage(
|
return updateListItemsWithImage(
|
||||||
items = items,
|
items = items,
|
||||||
disabledIndices = disabledIndices
|
disabledIndices = disabledIndices
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
val layoutManager = LinearLayoutManager(windowContext)
|
val layoutManager = LinearLayoutManager(windowContext)
|
||||||
return customListAdapter(
|
return customListAdapter(
|
||||||
adapter = ListIconDialogAdapter(
|
adapter = ListIconDialogAdapter(
|
||||||
dialog = this,
|
dialog = this,
|
||||||
items = items,
|
items = items,
|
||||||
disabledItems = disabledIndices,
|
disabledItems = disabledIndices,
|
||||||
waitForPositiveButton = waitForPositiveButton,
|
waitForPositiveButton = waitForPositiveButton,
|
||||||
selection = selection
|
selection = selection
|
||||||
),
|
),
|
||||||
layoutManager = layoutManager
|
layoutManager = layoutManager
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun MaterialDialog.updateListItemsWithImage(
|
fun MaterialDialog.updateListItemsWithImage(
|
||||||
items: List<ListItemWithImage>,
|
items: List<ListItemWithImage>,
|
||||||
disabledIndices: IntArray? = null): MaterialDialog {
|
disabledIndices: IntArray? = null
|
||||||
|
): MaterialDialog {
|
||||||
val adapter = getListAdapter()
|
val adapter = getListAdapter()
|
||||||
check(adapter != null) {
|
check(adapter != null) {
|
||||||
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."
|
"updateGridItems(...) can't be used before you've created a bottom sheet grid dialog."
|
||||||
|
@ -20,6 +20,4 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.events
|
package com.nextcloud.talk.events
|
||||||
|
|
||||||
class CallNotificationClick {
|
class CallNotificationClick
|
||||||
|
|
||||||
}
|
|
||||||
|
@ -33,7 +33,11 @@ import android.provider.ContactsContract
|
|||||||
import android.util.Log
|
import android.util.Log
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.os.ConfigurationCompat
|
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 autodagger.AutoInjector
|
||||||
import com.bluelinelabs.conductor.Controller
|
import com.bluelinelabs.conductor.Controller
|
||||||
import com.google.gson.Gson
|
import com.google.gson.Gson
|
||||||
@ -54,10 +58,9 @@ import okhttp3.MediaType
|
|||||||
import okhttp3.RequestBody
|
import okhttp3.RequestBody
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class ContactAddressBookWorker(val context: Context, workerParameters: WorkerParameters) :
|
class ContactAddressBookWorker(val context: Context, workerParameters: WorkerParameters) :
|
||||||
Worker(context, workerParameters) {
|
Worker(context, workerParameters) {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
@ -85,7 +88,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
val deleteAll = inputData.getBoolean(DELETE_ALL, false)
|
val deleteAll = inputData.getBoolean(DELETE_ALL, false)
|
||||||
if(deleteAll){
|
if (deleteAll) {
|
||||||
deleteAllLinkedAccounts()
|
deleteAllLinkedAccounts()
|
||||||
return Result.success()
|
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)
|
AccountManager.get(context).addAccountExplicitly(Account(accountName, accountType), "", null)
|
||||||
} else {
|
} else {
|
||||||
Log.d(TAG, "Account already exists")
|
Log.d(TAG, "Account already exists")
|
||||||
@ -107,7 +110,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
|
|
||||||
val deviceContactsWithNumbers = collectContactsWithPhoneNumbersFromDevice()
|
val deviceContactsWithNumbers = collectContactsWithPhoneNumbersFromDevice()
|
||||||
|
|
||||||
if(deviceContactsWithNumbers.isNotEmpty()){
|
if (deviceContactsWithNumbers.isNotEmpty()) {
|
||||||
val currentLocale = ConfigurationCompat.getLocales(context.resources.configuration)[0].country
|
val currentLocale = ConfigurationCompat.getLocales(context.resources.configuration)[0].country
|
||||||
|
|
||||||
val map = mutableMapOf<String, Any>()
|
val map = mutableMapOf<String, Any>()
|
||||||
@ -117,28 +120,29 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
val json = Gson().toJson(map)
|
val json = Gson().toJson(map)
|
||||||
|
|
||||||
ncApi.searchContactsByPhoneNumber(
|
ncApi.searchContactsByPhoneNumber(
|
||||||
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
||||||
ApiUtils.getUrlForSearchByNumber(currentUser.baseUrl),
|
ApiUtils.getUrlForSearchByNumber(currentUser.baseUrl),
|
||||||
RequestBody.create(MediaType.parse("application/json"), json))
|
RequestBody.create(MediaType.parse("application/json"), json)
|
||||||
.subscribeOn(Schedulers.io())
|
)
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe(object : Observer<ContactsByNumberOverall> {
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
override fun onComplete() {
|
.subscribe(object : Observer<ContactsByNumberOverall> {
|
||||||
}
|
override fun onComplete() {
|
||||||
|
}
|
||||||
|
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(foundContacts: ContactsByNumberOverall) {
|
override fun onNext(foundContacts: ContactsByNumberOverall) {
|
||||||
val contactsWithAssociatedPhoneNumbers = foundContacts.ocs.map
|
val contactsWithAssociatedPhoneNumbers = foundContacts.ocs.map
|
||||||
deleteLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
deleteLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
||||||
createLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
createLinkedAccounts(contactsWithAssociatedPhoneNumbers)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Log.e(javaClass.simpleName, "Failed to searchContactsByPhoneNumber", e)
|
Log.e(javaClass.simpleName, "Failed to searchContactsByPhoneNumber", e)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// store timestamp
|
// store timestamp
|
||||||
@ -151,11 +155,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
val deviceContactsWithNumbers: MutableMap<String, List<String>> = mutableMapOf()
|
val deviceContactsWithNumbers: MutableMap<String, List<String>> = mutableMapOf()
|
||||||
|
|
||||||
val contactCursor = context.contentResolver.query(
|
val contactCursor = context.contentResolver.query(
|
||||||
ContactsContract.Contacts.CONTENT_URI,
|
ContactsContract.Contacts.CONTENT_URI,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
if (contactCursor != null) {
|
if (contactCursor != null) {
|
||||||
@ -163,7 +167,8 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
contactCursor.moveToFirst()
|
contactCursor.moveToFirst()
|
||||||
for (i in 0 until contactCursor.count) {
|
for (i in 0 until contactCursor.count) {
|
||||||
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
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)
|
deviceContactsWithNumbers[lookup] = getPhoneNumbersFromDeviceContact(id)
|
||||||
contactCursor.moveToNext()
|
contactCursor.moveToNext()
|
||||||
}
|
}
|
||||||
@ -178,39 +183,50 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
Log.d(TAG, "deleteLinkedAccount")
|
Log.d(TAG, "deleteLinkedAccount")
|
||||||
fun deleteLinkedAccount(id: String) {
|
fun deleteLinkedAccount(id: String) {
|
||||||
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
||||||
.buildUpon()
|
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
|
||||||
.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)
|
|
||||||
Log.d(TAG, "deleted $count linked accounts for id $id")
|
|
||||||
}
|
|
||||||
|
|
||||||
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
|
||||||
.build()
|
.build()
|
||||||
|
val count = context.contentResolver.delete(
|
||||||
|
rawContactUri,
|
||||||
|
ContactsContract.RawContacts.CONTACT_ID + " " + "LIKE \"" + id + "\"",
|
||||||
|
null
|
||||||
|
)
|
||||||
|
Log.d(TAG, "deleted $count linked accounts for id $id")
|
||||||
|
}
|
||||||
|
|
||||||
|
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
||||||
|
.buildUpon()
|
||||||
|
.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"
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
val rawContactsCursor = context.contentResolver.query(
|
val rawContactsCursor = context.contentResolver.query(
|
||||||
rawContactUri,
|
rawContactUri,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
if (rawContactsCursor != null) {
|
if (rawContactsCursor != null) {
|
||||||
if (rawContactsCursor.count > 0) {
|
if (rawContactsCursor.count > 0) {
|
||||||
while (rawContactsCursor.moveToNext()) {
|
while (rawContactsCursor.moveToNext()) {
|
||||||
val lookupKey = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.LOOKUP_KEY))
|
val lookupKey =
|
||||||
val contactId = rawContactsCursor.getString(rawContactsCursor.getColumnIndex(ContactsContract.Data.CONTACT_ID))
|
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)
|
deleteLinkedAccount(contactId)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,25 +238,29 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createLinkedAccounts(contactsWithAssociatedPhoneNumbers: Map<String, String>?) {
|
private fun createLinkedAccounts(contactsWithAssociatedPhoneNumbers: Map<String, String>?) {
|
||||||
fun hasLinkedAccount(id: String) : Boolean {
|
fun hasLinkedAccount(id: String): Boolean {
|
||||||
var hasLinkedAccount = false
|
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 params = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
||||||
|
|
||||||
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
val rawContactUri = ContactsContract.Data.CONTENT_URI
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
.appendQueryParameter(ContactsContract.Data.MIMETYPE, "vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat")
|
.appendQueryParameter(
|
||||||
.build()
|
ContactsContract.Data.MIMETYPE,
|
||||||
|
"vnd.android.cursor.item/vnd.com.nextcloud.talk2.chat"
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
val rawContactsCursor = context.contentResolver.query(
|
val rawContactsCursor = context.contentResolver.query(
|
||||||
rawContactUri,
|
rawContactUri,
|
||||||
null,
|
null,
|
||||||
where,
|
where,
|
||||||
params,
|
params,
|
||||||
null
|
null
|
||||||
)
|
)
|
||||||
|
|
||||||
if (rawContactsCursor != null) {
|
if (rawContactsCursor != null) {
|
||||||
@ -259,18 +279,19 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
val lookupUri = Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, lookupKey)
|
||||||
val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
|
val lookupContactUri = ContactsContract.Contacts.lookupContact(context.contentResolver, lookupUri)
|
||||||
val contactCursor = context.contentResolver.query(
|
val contactCursor = context.contentResolver.query(
|
||||||
lookupContactUri,
|
lookupContactUri,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null,
|
null,
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
|
|
||||||
if (contactCursor != null) {
|
if (contactCursor != null) {
|
||||||
if (contactCursor.count > 0) {
|
if (contactCursor.count > 0) {
|
||||||
contactCursor.moveToFirst()
|
contactCursor.moveToFirst()
|
||||||
|
|
||||||
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
val id = contactCursor.getString(contactCursor.getColumnIndex(ContactsContract.Contacts._ID))
|
||||||
if(hasLinkedAccount(id)){
|
if (hasLinkedAccount(id)) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -285,34 +306,60 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
|
val rawContactsUri = ContactsContract.RawContacts.CONTENT_URI.buildUpon().build()
|
||||||
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
|
val dataUri = ContactsContract.Data.CONTENT_URI.buildUpon().build()
|
||||||
|
|
||||||
ops.add(ContentProviderOperation
|
ops.add(
|
||||||
|
ContentProviderOperation
|
||||||
.newInsert(rawContactsUri)
|
.newInsert(rawContactsUri)
|
||||||
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
.withValue(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
.withValue(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
.withValue(ContactsContract.RawContacts.AGGREGATION_MODE,
|
.withValue(
|
||||||
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT)
|
ContactsContract.RawContacts.AGGREGATION_MODE,
|
||||||
|
ContactsContract.RawContacts.AGGREGATION_MODE_DEFAULT
|
||||||
|
)
|
||||||
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
|
.withValue(ContactsContract.RawContacts.SYNC2, cloudId)
|
||||||
.build())
|
.build()
|
||||||
ops.add(ContentProviderOperation
|
)
|
||||||
|
ops.add(
|
||||||
|
ContentProviderOperation
|
||||||
.newInsert(dataUri)
|
.newInsert(dataUri)
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
.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])
|
.withValue(ContactsContract.CommonDataKinds.Phone.NUMBER, numbers[0])
|
||||||
.build())
|
.build()
|
||||||
ops.add(ContentProviderOperation
|
)
|
||||||
|
ops.add(
|
||||||
|
ContentProviderOperation
|
||||||
.newInsert(dataUri)
|
.newInsert(dataUri)
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
.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)
|
.withValue(ContactsContract.CommonDataKinds.StructuredName.DISPLAY_NAME, displayName)
|
||||||
.build())
|
.build()
|
||||||
ops.add(ContentProviderOperation
|
)
|
||||||
|
ops.add(
|
||||||
|
ContentProviderOperation
|
||||||
.newInsert(dataUri)
|
.newInsert(dataUri)
|
||||||
.withValueBackReference(ContactsContract.Data.RAW_CONTACT_ID, 0)
|
.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.DATA1, cloudId)
|
||||||
.withValue(ContactsContract.Data.DATA2, String.format(context.resources.getString(R
|
.withValue(
|
||||||
.string.nc_phone_book_integration_chat_via), accountName))
|
ContactsContract.Data.DATA2,
|
||||||
.build())
|
String.format(
|
||||||
|
context.resources.getString(
|
||||||
|
R.string.nc_phone_book_integration_chat_via
|
||||||
|
),
|
||||||
|
accountName
|
||||||
|
)
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
)
|
||||||
|
|
||||||
try {
|
try {
|
||||||
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
context.contentResolver.applyBatch(ContactsContract.AUTHORITY, ops)
|
||||||
@ -322,8 +369,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
Log.e(javaClass.simpleName, "", e)
|
Log.e(javaClass.simpleName, "", e)
|
||||||
}
|
}
|
||||||
|
|
||||||
Log.d(TAG, "added new entry for contact $displayName (cloudId: $cloudId | lookupKey: $lookupKey" +
|
Log.d(
|
||||||
" | id: $id)")
|
TAG,
|
||||||
|
"added new entry for contact $displayName (cloudId: $cloudId | lookupKey: $lookupKey" +
|
||||||
|
" | id: $id)"
|
||||||
|
)
|
||||||
}
|
}
|
||||||
contactCursor.close()
|
contactCursor.close()
|
||||||
}
|
}
|
||||||
@ -341,18 +391,21 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun getDisplayNameFromDeviceContact(id: String?): String? {
|
private fun getDisplayNameFromDeviceContact(id: String?): String? {
|
||||||
var displayName:String? = null
|
var displayName: String? = null
|
||||||
val whereName = ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
|
val whereName =
|
||||||
|
ContactsContract.Data.MIMETYPE + " = ? AND " + ContactsContract.CommonDataKinds.StructuredName.CONTACT_ID + " = ?"
|
||||||
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
val whereNameParams = arrayOf(ContactsContract.CommonDataKinds.StructuredName.CONTENT_ITEM_TYPE, id)
|
||||||
val nameCursor = context.contentResolver.query(
|
val nameCursor = context.contentResolver.query(
|
||||||
ContactsContract.Data.CONTENT_URI,
|
ContactsContract.Data.CONTENT_URI,
|
||||||
null,
|
null,
|
||||||
whereName,
|
whereName,
|
||||||
whereNameParams,
|
whereNameParams,
|
||||||
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME)
|
ContactsContract.CommonDataKinds.StructuredName.GIVEN_NAME
|
||||||
|
)
|
||||||
if (nameCursor != null) {
|
if (nameCursor != null) {
|
||||||
while (nameCursor.moveToNext()) {
|
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()
|
nameCursor.close()
|
||||||
}
|
}
|
||||||
@ -362,11 +415,12 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
private fun getPhoneNumbersFromDeviceContact(id: String?): MutableList<String> {
|
private fun getPhoneNumbersFromDeviceContact(id: String?): MutableList<String> {
|
||||||
val numbers = mutableListOf<String>()
|
val numbers = mutableListOf<String>()
|
||||||
val phonesNumbersCursor = context.contentResolver.query(
|
val phonesNumbersCursor = context.contentResolver.query(
|
||||||
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
|
||||||
null,
|
null,
|
||||||
ContactsContract.Data.CONTACT_ID + " = " + id,
|
ContactsContract.Data.CONTACT_ID + " = " + id,
|
||||||
null,
|
null,
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
|
|
||||||
if (phonesNumbersCursor != null) {
|
if (phonesNumbersCursor != null) {
|
||||||
while (phonesNumbersCursor.moveToNext()) {
|
while (phonesNumbersCursor.moveToNext()) {
|
||||||
@ -374,7 +428,7 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
}
|
}
|
||||||
phonesNumbersCursor.close()
|
phonesNumbersCursor.close()
|
||||||
}
|
}
|
||||||
if(numbers.size > 0){
|
if (numbers.size > 0) {
|
||||||
Log.d(TAG, "Found ${numbers.size} phone numbers for contact with id $id")
|
Log.d(TAG, "Found ${numbers.size} phone numbers for contact with id $id")
|
||||||
}
|
}
|
||||||
return numbers
|
return numbers
|
||||||
@ -382,11 +436,11 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
|
|
||||||
fun deleteAllLinkedAccounts() {
|
fun deleteAllLinkedAccounts() {
|
||||||
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
val rawContactUri = ContactsContract.RawContacts.CONTENT_URI
|
||||||
.buildUpon()
|
.buildUpon()
|
||||||
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
.appendQueryParameter(ContactsContract.CALLER_IS_SYNCADAPTER, "true")
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_NAME, accountName)
|
||||||
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
.appendQueryParameter(ContactsContract.RawContacts.ACCOUNT_TYPE, accountType)
|
||||||
.build()
|
.build()
|
||||||
context.contentResolver.delete(rawContactUri, null, null)
|
context.contentResolver.delete(rawContactUri, null, null)
|
||||||
Log.d(TAG, "deleted all linked accounts")
|
Log.d(TAG, "deleted all linked accounts")
|
||||||
}
|
}
|
||||||
@ -398,42 +452,63 @@ class ContactAddressBookWorker(val context: Context, workerParameters: WorkerPar
|
|||||||
const val DELETE_ALL = "DELETE_ALL"
|
const val DELETE_ALL = "DELETE_ALL"
|
||||||
|
|
||||||
fun run(context: Context) {
|
fun run(context: Context) {
|
||||||
if (ContextCompat.checkSelfPermission(context,
|
if (ContextCompat.checkSelfPermission(
|
||||||
Manifest.permission.WRITE_CONTACTS) == PackageManager.PERMISSION_GRANTED &&
|
context,
|
||||||
ContextCompat.checkSelfPermission(context,
|
Manifest.permission.WRITE_CONTACTS
|
||||||
Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
|
) == PackageManager.PERMISSION_GRANTED &&
|
||||||
|
ContextCompat.checkSelfPermission(
|
||||||
|
context,
|
||||||
|
Manifest.permission.READ_CONTACTS
|
||||||
|
) == PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
WorkManager
|
WorkManager
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
.enqueue(
|
||||||
.setInputData(Data.Builder().putBoolean(KEY_FORCE, false).build())
|
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
||||||
.build())
|
.setInputData(Data.Builder().putBoolean(KEY_FORCE, false).build())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun checkPermission(controller: Controller, context: Context): Boolean {
|
fun checkPermission(controller: Controller, context: Context): Boolean {
|
||||||
if (ContextCompat.checkSelfPermission(context,
|
if (ContextCompat.checkSelfPermission(
|
||||||
Manifest.permission.WRITE_CONTACTS) != PackageManager.PERMISSION_GRANTED ||
|
context,
|
||||||
ContextCompat.checkSelfPermission(context,
|
Manifest.permission.WRITE_CONTACTS
|
||||||
Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) {
|
) != PackageManager.PERMISSION_GRANTED ||
|
||||||
controller.requestPermissions(arrayOf(Manifest.permission.WRITE_CONTACTS,
|
ContextCompat.checkSelfPermission(
|
||||||
Manifest.permission.READ_CONTACTS), REQUEST_PERMISSION)
|
context,
|
||||||
|
Manifest.permission.READ_CONTACTS
|
||||||
|
) != PackageManager.PERMISSION_GRANTED
|
||||||
|
) {
|
||||||
|
controller.requestPermissions(
|
||||||
|
arrayOf(
|
||||||
|
Manifest.permission.WRITE_CONTACTS,
|
||||||
|
Manifest.permission.READ_CONTACTS
|
||||||
|
),
|
||||||
|
REQUEST_PERMISSION
|
||||||
|
)
|
||||||
return false
|
return false
|
||||||
} else {
|
} else {
|
||||||
WorkManager
|
WorkManager
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
.enqueue(
|
||||||
.setInputData(Data.Builder().putBoolean(KEY_FORCE, true).build())
|
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
||||||
.build())
|
.setInputData(Data.Builder().putBoolean(KEY_FORCE, true).build())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun deleteAll() {
|
fun deleteAll() {
|
||||||
WorkManager
|
WorkManager
|
||||||
.getInstance()
|
.getInstance()
|
||||||
.enqueue(OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
.enqueue(
|
||||||
.setInputData(Data.Builder().putBoolean(DELETE_ALL, true).build())
|
OneTimeWorkRequest.Builder(ContactAddressBookWorker::class.java)
|
||||||
.build())
|
.setInputData(Data.Builder().putBoolean(DELETE_ALL, true).build())
|
||||||
|
.build()
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,13 +33,16 @@ import com.nextcloud.talk.utils.ApiUtils
|
|||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
import okhttp3.ResponseBody
|
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
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerParameters) :
|
class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerParameters) :
|
||||||
Worker(context, workerParameters) {
|
Worker(context, workerParameters) {
|
||||||
|
|
||||||
private var totalFileSize: Int = -1
|
private var totalFileSize: Int = -1
|
||||||
|
|
||||||
@ -86,8 +89,9 @@ class DownloadFileToCacheWorker(val context: Context, workerParameters: WorkerPa
|
|||||||
|
|
||||||
private fun downloadFile(currentUser: UserEntity, url: String, fileName: String): Result {
|
private fun downloadFile(currentUser: UserEntity, url: String, fileName: String): Result {
|
||||||
val downloadCall = ncApi.downloadFile(
|
val downloadCall = ncApi.downloadFile(
|
||||||
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
||||||
url)
|
url
|
||||||
|
)
|
||||||
|
|
||||||
return executeDownload(downloadCall.execute().body(), fileName)
|
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 KEY_FILE_SIZE = "KEY_FILE_SIZE"
|
||||||
const val PROGRESS = "PROGRESS"
|
const val PROGRESS = "PROGRESS"
|
||||||
const val SUCCESS = "SUCCESS"
|
const val SUCCESS = "SUCCESS"
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,11 @@ package com.nextcloud.talk.jobs
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
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 autodagger.AutoInjector
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
@ -46,13 +50,12 @@ import retrofit2.Response
|
|||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerParameters) :
|
class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerParameters) :
|
||||||
Worker(context, workerParameters) {
|
Worker(context, workerParameters) {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
lateinit var ncApi: NcApi
|
lateinit var ncApi: NcApi
|
||||||
@ -107,31 +110,37 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
|||||||
return requestBody
|
return requestBody
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun uploadFile(currentUser: UserEntity, ncTargetpath: String?, filename: String, roomToken: String?,
|
private fun uploadFile(
|
||||||
requestBody: RequestBody?, sourcefileUri: Uri) {
|
currentUser: UserEntity,
|
||||||
|
ncTargetpath: String?,
|
||||||
|
filename: String,
|
||||||
|
roomToken: String?,
|
||||||
|
requestBody: RequestBody?,
|
||||||
|
sourcefileUri: Uri
|
||||||
|
) {
|
||||||
ncApi.uploadFile(
|
ncApi.uploadFile(
|
||||||
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
ApiUtils.getCredentials(currentUser.username, currentUser.token),
|
||||||
ApiUtils.getUrlForFileUpload(currentUser.baseUrl, currentUser.userId, ncTargetpath, filename),
|
ApiUtils.getUrlForFileUpload(currentUser.baseUrl, currentUser.userId, ncTargetpath, filename),
|
||||||
requestBody
|
requestBody
|
||||||
)
|
)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(object : Observer<Response<GenericOverall>> {
|
.subscribe(object : Observer<Response<GenericOverall>> {
|
||||||
override fun onSubscribe(d: Disposable) {
|
override fun onSubscribe(d: Disposable) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onNext(t: Response<GenericOverall>) {
|
override fun onNext(t: Response<GenericOverall>) {
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onError(e: Throwable) {
|
override fun onError(e: Throwable) {
|
||||||
Log.e(TAG, "failed to upload file $filename")
|
Log.e(TAG, "failed to upload file $filename")
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onComplete() {
|
override fun onComplete() {
|
||||||
shareFile(roomToken, currentUser, ncTargetpath, filename)
|
shareFile(roomToken, currentUser, ncTargetpath, filename)
|
||||||
copyFileToCache(sourcefileUri, filename)
|
copyFileToCache(sourcefileUri, filename)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun copyFileToCache(sourceFileUri: Uri, filename: String) {
|
private fun copyFileToCache(sourceFileUri: Uri, filename: String) {
|
||||||
@ -151,13 +160,13 @@ class UploadAndShareFilesWorker(val context: Context, workerParameters: WorkerPa
|
|||||||
paths.add("$ncTargetpath/$filename")
|
paths.add("$ncTargetpath/$filename")
|
||||||
|
|
||||||
val data = Data.Builder()
|
val data = Data.Builder()
|
||||||
.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
|
.putLong(KEY_INTERNAL_USER_ID, currentUser.id)
|
||||||
.putString(KEY_ROOM_TOKEN, roomToken)
|
.putString(KEY_ROOM_TOKEN, roomToken)
|
||||||
.putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
|
.putStringArray(KEY_FILE_PATHS, paths.toTypedArray())
|
||||||
.build()
|
.build()
|
||||||
val shareWorker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
val shareWorker = OneTimeWorkRequest.Builder(ShareOperationWorker::class.java)
|
||||||
.setInputData(data)
|
.setInputData(data)
|
||||||
.build()
|
.build()
|
||||||
WorkManager.getInstance().enqueue(shareWorker)
|
WorkManager.getInstance().enqueue(shareWorker)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -25,7 +25,7 @@ package com.nextcloud.talk.models.json.chat
|
|||||||
class ChatUtils {
|
class ChatUtils {
|
||||||
companion object {
|
companion object {
|
||||||
fun getParsedMessage(message: String?, messageParameters: HashMap<String?, HashMap<String?, String?>>?):
|
fun getParsedMessage(message: String?, messageParameters: HashMap<String?, HashMap<String?, String?>>?):
|
||||||
String? {
|
String? {
|
||||||
var resultMessage = message
|
var resultMessage = message
|
||||||
if (messageParameters != null && messageParameters.size > 0) {
|
if (messageParameters != null && messageParameters.size > 0) {
|
||||||
for (key in messageParameters.keys) {
|
for (key in messageParameters.keys) {
|
||||||
@ -46,4 +46,3 @@ class ChatUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,11 +22,28 @@ package com.nextcloud.talk.models.json.converters
|
|||||||
|
|
||||||
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
|
import com.bluelinelabs.logansquare.typeconverters.StringBasedTypeConverter
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
|
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.CALL_ENDED
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage.SystemMessageType.*
|
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_created - {actor} created the conversation
|
||||||
conversation_renamed - {actor} renamed the conversation from "foo" to "bar"
|
conversation_renamed - {actor} renamed the conversation from "foo" to "bar"
|
||||||
call_joined - {actor} joined the call
|
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
|
user_removed - {actor} removed {user} from the conversation
|
||||||
moderator_promoted - {actor} promoted {user} to moderator
|
moderator_promoted - {actor} promoted {user} to moderator
|
||||||
moderator_demoted - {actor} demoted {user} from moderator
|
moderator_demoted - {actor} demoted {user} from moderator
|
||||||
|
|
||||||
*/
|
*/
|
||||||
class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() {
|
class EnumSystemMessageTypeConverter : StringBasedTypeConverter<ChatMessage.SystemMessageType>() {
|
||||||
override fun getFromString(string: String): ChatMessage.SystemMessageType {
|
override fun getFromString(string: String): ChatMessage.SystemMessageType {
|
||||||
|
@ -20,12 +20,10 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.receivers
|
package com.nextcloud.talk.receivers
|
||||||
|
|
||||||
import android.app.NotificationChannelGroup
|
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.BroadcastReceiver
|
import android.content.BroadcastReceiver
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageInfo
|
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
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.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.database.user.UserUtils
|
import com.nextcloud.talk.utils.database.user.UserUtils
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
|
|
||||||
import javax.inject.Inject
|
import javax.inject.Inject
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
@ -50,16 +47,20 @@ class PackageReplacedReceiver : BroadcastReceiver() {
|
|||||||
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
NextcloudTalkApplication.sharedApplication!!.componentApplication.inject(this)
|
||||||
|
|
||||||
if (intent != null && intent.action != null &&
|
if (intent != null && intent.action != null &&
|
||||||
intent.action == "android.intent.action.MY_PACKAGE_REPLACED") {
|
intent.action == "android.intent.action.MY_PACKAGE_REPLACED"
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
val packageInfo = context.packageManager.getPackageInfo(context.packageName, 0)
|
||||||
if (packageInfo.versionCode > 43 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (packageInfo.versionCode > 43 && Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
val notificationManager = context.getSystemService(Context
|
val notificationManager = context.getSystemService(
|
||||||
.NOTIFICATION_SERVICE) as NotificationManager
|
Context
|
||||||
|
.NOTIFICATION_SERVICE
|
||||||
|
) as NotificationManager
|
||||||
|
|
||||||
if (!appPreferences.isNotificationChannelUpgradedToV2) {
|
if (!appPreferences.isNotificationChannelUpgradedToV2) {
|
||||||
for (notificationChannelGroup in notificationManager
|
for (
|
||||||
.notificationChannelGroups) {
|
notificationChannelGroup in notificationManager.notificationChannelGroups
|
||||||
|
) {
|
||||||
notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id)
|
notificationManager.deleteNotificationChannelGroup(notificationChannelGroup.id)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -80,7 +81,6 @@ class PackageReplacedReceiver : BroadcastReceiver() {
|
|||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
Log.e(TAG, "Failed to fetch package info")
|
Log.e(TAG, "Failed to fetch package info")
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,7 +32,6 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.components.filebrowser.controllers.BrowserController
|
import com.nextcloud.talk.components.filebrowser.controllers.BrowserController
|
||||||
import com.nextcloud.talk.controllers.ChatController
|
import com.nextcloud.talk.controllers.ChatController
|
||||||
|
|
||||||
|
|
||||||
class AttachmentDialog(val activity: Activity, var chatController: ChatController) : BottomSheetDialog(activity) {
|
class AttachmentDialog(val activity: Activity, var chatController: ChatController) : BottomSheetDialog(activity) {
|
||||||
|
|
||||||
@BindView(R.id.txt_attach_file_from_local)
|
@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
|
var serverName = chatController.conversationUser?.serverName
|
||||||
attachFromCloud?.text = chatController.resources?.let {
|
attachFromCloud?.text = chatController.resources?.let {
|
||||||
if(serverName.isNullOrEmpty()){
|
if (serverName.isNullOrEmpty()) {
|
||||||
serverName = it.getString(R.string.nc_server_product_name)
|
serverName = it.getString(R.string.nc_server_product_name)
|
||||||
}
|
}
|
||||||
String.format(it.getString(R.string.nc_upload_from_cloud), serverName)
|
String.format(it.getString(R.string.nc_upload_from_cloud), serverName)
|
||||||
|
@ -30,12 +30,13 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.controllers.ProfileController
|
import com.nextcloud.talk.controllers.ProfileController
|
||||||
import com.nextcloud.talk.models.json.userprofile.Scope
|
import com.nextcloud.talk.models.json.userprofile.Scope
|
||||||
|
|
||||||
|
class ScopeDialog(
|
||||||
class ScopeDialog(con: Context,
|
con: Context,
|
||||||
private val userInfoAdapter: ProfileController.UserInfoAdapter,
|
private val userInfoAdapter: ProfileController.UserInfoAdapter,
|
||||||
private val field: ProfileController.Field,
|
private val field: ProfileController.Field,
|
||||||
private val position: Int) :
|
private val position: Int
|
||||||
BottomSheetDialog(con) {
|
) :
|
||||||
|
BottomSheetDialog(con) {
|
||||||
override fun onCreate(savedInstanceState: Bundle?) {
|
override fun onCreate(savedInstanceState: Bundle?) {
|
||||||
super.onCreate(savedInstanceState)
|
super.onCreate(savedInstanceState)
|
||||||
val view = layoutInflater.inflate(R.layout.dialog_scope, null)
|
val view = layoutInflater.inflate(R.layout.dialog_scope, null)
|
||||||
|
@ -32,7 +32,8 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.models.ImportAccount
|
import com.nextcloud.talk.models.ImportAccount
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
import com.nextcloud.talk.models.database.UserEntity
|
||||||
import java.util.*
|
import java.util.ArrayList
|
||||||
|
import java.util.Arrays
|
||||||
|
|
||||||
object AccountUtils {
|
object AccountUtils {
|
||||||
|
|
||||||
@ -60,14 +61,15 @@ object AccountUtils {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (internalUserEntity.username == importAccount.username && (internalUserEntity
|
if (internalUserEntity.username == importAccount.username &&
|
||||||
.baseUrl == "http://" + importAccount.baseUrl ||
|
(
|
||||||
internalUserEntity.baseUrl == "https://" + importAccount
|
internalUserEntity.baseUrl == "http://" + importAccount.baseUrl ||
|
||||||
.baseUrl)) {
|
internalUserEntity.baseUrl == "https://" + importAccount.baseUrl
|
||||||
|
)
|
||||||
|
) {
|
||||||
accountFound = true
|
accountFound = true
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
accountFound = true
|
accountFound = true
|
||||||
@ -88,8 +90,12 @@ object AccountUtils {
|
|||||||
val packageManager = context.packageManager
|
val packageManager = context.packageManager
|
||||||
var appName = ""
|
var appName = ""
|
||||||
try {
|
try {
|
||||||
appName = packageManager.getApplicationLabel(packageManager.getApplicationInfo(packageName,
|
appName = packageManager.getApplicationLabel(
|
||||||
PackageManager.GET_META_DATA)) as String
|
packageManager.getApplicationInfo(
|
||||||
|
packageName,
|
||||||
|
PackageManager.GET_META_DATA
|
||||||
|
)
|
||||||
|
) as String
|
||||||
} catch (e: PackageManager.NameNotFoundException) {
|
} catch (e: PackageManager.NameNotFoundException) {
|
||||||
Log.e(TAG, "Failed to get app name based on package")
|
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)
|
val packageInfo = pm.getPackageInfo(context.getString(R.string.nc_import_accounts_from), 0)
|
||||||
if (packageInfo.versionCode >= 30060151) {
|
if (packageInfo.versionCode >= 30060151) {
|
||||||
val ownSignatures = pm.getPackageInfo(context.packageName, PackageManager.GET_SIGNATURES).signatures
|
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)) {
|
if (Arrays.equals(ownSignatures, filesAppSignatures)) {
|
||||||
val accMgr = AccountManager.get(context)
|
val accMgr = AccountManager.get(context)
|
||||||
@ -118,7 +127,7 @@ object AccountUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (appNotFoundException: PackageManager.NameNotFoundException) {
|
} catch (appNotFoundException: PackageManager.NameNotFoundException) {
|
||||||
|
// ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
return false
|
return false
|
||||||
@ -146,4 +155,3 @@ object AccountUtils {
|
|||||||
return ImportAccount(username, password, urlString)
|
return ImportAccount(username, password, urlString)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,13 @@ import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
|||||||
import com.nextcloud.talk.controllers.ChatController
|
import com.nextcloud.talk.controllers.ChatController
|
||||||
|
|
||||||
object ConductorRemapping {
|
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"
|
val tag = "$internalUserId@$roomTokenOrId"
|
||||||
if (router.getControllerWithTag(tag) != null) {
|
if (router.getControllerWithTag(tag) != null) {
|
||||||
val backstack = router.backstack
|
val backstack = router.backstack
|
||||||
@ -44,13 +50,17 @@ object ConductorRemapping {
|
|||||||
router.setBackstack(backstack, HorizontalChangeHandler())
|
router.setBackstack(backstack, HorizontalChangeHandler())
|
||||||
} else {
|
} else {
|
||||||
if (!replaceTop) {
|
if (!replaceTop) {
|
||||||
router.pushController(RouterTransaction.with(ChatController(bundle))
|
router.pushController(
|
||||||
|
RouterTransaction.with(ChatController(bundle))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()).tag(tag))
|
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
router.replaceTopController(RouterTransaction.with(ChatController(bundle))
|
router.replaceTopController(
|
||||||
|
RouterTransaction.with(ChatController(bundle))
|
||||||
.pushChangeHandler(HorizontalChangeHandler())
|
.pushChangeHandler(HorizontalChangeHandler())
|
||||||
.popChangeHandler(HorizontalChangeHandler()).tag(tag))
|
.popChangeHandler(HorizontalChangeHandler()).tag(tag)
|
||||||
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,9 @@
|
|||||||
package com.nextcloud.talk.utils
|
package com.nextcloud.talk.utils
|
||||||
|
|
||||||
import java.text.DateFormat
|
import java.text.DateFormat
|
||||||
import java.util.*
|
import java.util.Calendar
|
||||||
|
import java.util.Date
|
||||||
|
import java.util.Locale
|
||||||
|
|
||||||
object DateUtils {
|
object DateUtils {
|
||||||
fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
|
fun getLocalDateTimeStringFromTimestamp(timestamp: Long): String {
|
||||||
@ -30,14 +31,16 @@ object DateUtils {
|
|||||||
val tz = cal.timeZone
|
val tz = cal.timeZone
|
||||||
|
|
||||||
/* date formatter in local timezone */
|
/* date formatter in local timezone */
|
||||||
val format = DateFormat.getDateTimeInstance(DateFormat.DEFAULT, DateFormat.SHORT, Locale
|
val format = DateFormat.getDateTimeInstance(
|
||||||
.getDefault())
|
DateFormat.DEFAULT, DateFormat.SHORT,
|
||||||
|
Locale.getDefault()
|
||||||
|
)
|
||||||
format.timeZone = tz
|
format.timeZone = tz
|
||||||
|
|
||||||
return format.format(Date(timestamp))
|
return format.format(Date(timestamp))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getLocalDateStringFromTimestampForLobby(timestamp: Long): String {
|
fun getLocalDateStringFromTimestampForLobby(timestamp: Long): String {
|
||||||
return getLocalDateTimeStringFromTimestamp(timestamp * 1000);
|
return getLocalDateTimeStringFromTimestamp(timestamp * 1000)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -21,12 +21,10 @@
|
|||||||
package com.nextcloud.talk.utils
|
package com.nextcloud.talk.utils
|
||||||
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
|
|
||||||
import java.util.HashMap
|
import java.util.HashMap
|
||||||
|
|
||||||
object DrawableUtils {
|
object DrawableUtils {
|
||||||
|
|
||||||
|
|
||||||
fun getDrawableResourceIdForMimeType(mimetype: String): Int {
|
fun getDrawableResourceIdForMimeType(mimetype: String): Int {
|
||||||
var localMimetype = mimetype
|
var localMimetype = mimetype
|
||||||
val drawableMap = HashMap<String, Int>()
|
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.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"] = 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.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.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-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-fontobject"] = R.drawable.ic_mimetype_image
|
||||||
drawableMap["application/vnd.ms-powerpoint"] = R.drawable.ic_mimetype_x_office_presentation
|
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.addin.macroEnabled.12"] =
|
||||||
drawableMap["application/vnd.ms-powerpoint.presentation.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
|
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.presentation.macroEnabled.12"] =
|
||||||
drawableMap["application/vnd.ms-powerpoint.template.macroEnabled.12"] = R.drawable.ic_mimetype_x_office_presentation
|
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.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.drawing"] = R.drawable.ic_mimetype_x_office_document
|
||||||
drawableMap["application/vnd.ms-visio.stencil.macroEnabled.12"] = 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-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.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"] = 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"] = 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"] = 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-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-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.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.presentation"] =
|
||||||
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.slideshow"] = R.drawable.ic_mimetype_x_office_presentation
|
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.presentationml.slideshow"] =
|
||||||
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.sheet"] = R.drawable.ic_mimetype_x_office_spreadsheet
|
R.drawable.ic_mimetype_x_office_presentation
|
||||||
drawableMap["application/vnd.openxmlformats-officedocument.spreadsheetml.template"] = R.drawable.ic_mimetype_x_office_spreadsheet
|
drawableMap["application/vnd.openxmlformats-officedocument.presentationml.template"] =
|
||||||
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.document"] = R.drawable.ic_mimetype_x_office_document
|
R.drawable.ic_mimetype_x_office_presentation
|
||||||
drawableMap["application/vnd.openxmlformats-officedocument.wordprocessingml.template"] = R.drawable.ic_mimetype_x_office_document
|
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.visio"] = R.drawable.ic_mimetype_x_office_document
|
||||||
drawableMap["application/vnd.wordperfect"] = 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
|
drawableMap["application/x-7z-compressed"] = R.drawable.ic_mimetype_package_x_generic
|
||||||
|
@ -29,7 +29,7 @@ import com.nextcloud.talk.BuildConfig
|
|||||||
import java.io.FileNotFoundException
|
import java.io.FileNotFoundException
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.text.SimpleDateFormat
|
import java.text.SimpleDateFormat
|
||||||
import java.util.*
|
import java.util.Date
|
||||||
|
|
||||||
object LoggingUtils {
|
object LoggingUtils {
|
||||||
fun writeLogEntryToFile(context: Context, logEntry: String) {
|
fun writeLogEntryToFile(context: Context, logEntry: String) {
|
||||||
@ -38,8 +38,10 @@ object LoggingUtils {
|
|||||||
val logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n"
|
val logEntryWithDateTime = dateFormat.format(date) + ": " + logEntry + "\n"
|
||||||
|
|
||||||
try {
|
try {
|
||||||
val outputStream = context.openFileOutput("nc_log.txt",
|
val outputStream = context.openFileOutput(
|
||||||
Context.MODE_PRIVATE or Context.MODE_APPEND)
|
"nc_log.txt",
|
||||||
|
Context.MODE_PRIVATE or Context.MODE_APPEND
|
||||||
|
)
|
||||||
outputStream.write(logEntryWithDateTime.toByteArray())
|
outputStream.write(logEntryWithDateTime.toByteArray())
|
||||||
outputStream.flush()
|
outputStream.flush()
|
||||||
outputStream.close()
|
outputStream.close()
|
||||||
@ -48,13 +50,12 @@ object LoggingUtils {
|
|||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun sendMailWithAttachment(context: Context) {
|
fun sendMailWithAttachment(context: Context) {
|
||||||
val logFile = context.getFileStreamPath("nc_log.txt")
|
val logFile = context.getFileStreamPath("nc_log.txt")
|
||||||
val emailIntent = Intent(Intent.ACTION_SEND)
|
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_EMAIL, arrayOf(mailto))
|
||||||
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs")
|
emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Talk logs")
|
||||||
emailIntent.type = "text/plain"
|
emailIntent.type = "text/plain"
|
||||||
|
@ -33,7 +33,7 @@ import android.service.notification.StatusBarNotification
|
|||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.models.database.UserEntity
|
import com.nextcloud.talk.models.database.UserEntity
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import java.util.*
|
import java.util.Objects
|
||||||
|
|
||||||
object NotificationUtils {
|
object NotificationUtils {
|
||||||
val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
|
val NOTIFICATION_CHANNEL_CALLS = "NOTIFICATION_CHANNEL_CALLS"
|
||||||
@ -47,25 +47,50 @@ object NotificationUtils {
|
|||||||
return longArrayOf(0L, 400L, 800L, 600L, 800L, 800L, 800L, 1000L)
|
return longArrayOf(0L, 400L, 800L, 600L, 800L, 800L, 800L, 1000L)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getNotificationChannelId(channelName: String,
|
fun getNotificationChannelId(
|
||||||
channelDescription: String, enableLights: Boolean,
|
channelName: String,
|
||||||
importance: Int, sound: Uri, audioAttributes: AudioAttributes, vibrationPattern: LongArray?, bypassDnd: Boolean): String {
|
channelDescription: String,
|
||||||
return Objects.hash(channelName, channelDescription, enableLights, importance, sound, audioAttributes, vibrationPattern, bypassDnd).toString()
|
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)
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
fun createNotificationChannel(context: Context,
|
fun createNotificationChannel(
|
||||||
channelId: String, channelName: String,
|
context: Context,
|
||||||
channelDescription: String, enableLights: Boolean,
|
channelId: String,
|
||||||
importance: Int, sound: Uri, audioAttributes: AudioAttributes,
|
channelName: String,
|
||||||
vibrationPattern: LongArray?, bypassDnd: Boolean = false) {
|
channelDescription: String,
|
||||||
|
enableLights: Boolean,
|
||||||
|
importance: Int,
|
||||||
|
sound: Uri,
|
||||||
|
audioAttributes: AudioAttributes,
|
||||||
|
vibrationPattern: LongArray?,
|
||||||
|
bypassDnd: Boolean = false
|
||||||
|
) {
|
||||||
|
|
||||||
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(channelId) == null) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && notificationManager.getNotificationChannel(channelId) == null) {
|
||||||
|
|
||||||
val channel = NotificationChannel(channelId, channelName,
|
val channel = NotificationChannel(
|
||||||
importance)
|
channelId, channelName,
|
||||||
|
importance
|
||||||
|
)
|
||||||
|
|
||||||
channel.description = channelDescription
|
channel.description = channelDescription
|
||||||
channel.enableLights(enableLights)
|
channel.enableLights(enableLights)
|
||||||
@ -84,8 +109,11 @@ object NotificationUtils {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@TargetApi(Build.VERSION_CODES.O)
|
@TargetApi(Build.VERSION_CODES.O)
|
||||||
fun createNotificationChannelGroup(context: Context,
|
fun createNotificationChannelGroup(
|
||||||
groupId: String, groupName: CharSequence) {
|
context: Context,
|
||||||
|
groupId: String,
|
||||||
|
groupName: CharSequence
|
||||||
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (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
|
||||||
|
|
||||||
@ -113,12 +141,12 @@ object NotificationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelExistingNotificationWithId(context: Context?, conversationUser: UserEntity, notificationId: Long) {
|
fun cancelExistingNotificationWithId(context: Context?, conversationUser: UserEntity, notificationId: Long) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
|
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
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
@ -128,7 +156,10 @@ object NotificationUtils {
|
|||||||
notification = statusBarNotification.notification
|
notification = statusBarNotification.notification
|
||||||
|
|
||||||
if (notification != null && !notification.extras.isEmpty) {
|
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)
|
notificationManager.cancel(statusBarNotification.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -136,11 +167,14 @@ object NotificationUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun findNotificationForRoom(context: Context?,
|
fun findNotificationForRoom(
|
||||||
conversationUser: UserEntity,
|
context: Context?,
|
||||||
roomTokenOrId: String): StatusBarNotification? {
|
conversationUser: UserEntity,
|
||||||
|
roomTokenOrId: String
|
||||||
|
): StatusBarNotification? {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
|
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
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
@ -150,7 +184,10 @@ object NotificationUtils {
|
|||||||
notification = statusBarNotification.notification
|
notification = statusBarNotification.notification
|
||||||
|
|
||||||
if (notification != null && !notification.extras.isEmpty) {
|
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
|
return statusBarNotification
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,10 +197,14 @@ object NotificationUtils {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
fun cancelExistingNotificationsForRoom(context: Context?, conversationUser: UserEntity,
|
fun cancelExistingNotificationsForRoom(
|
||||||
roomTokenOrId: String) {
|
context: Context?,
|
||||||
|
conversationUser: UserEntity,
|
||||||
|
roomTokenOrId: String
|
||||||
|
) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && conversationUser.id != -1L &&
|
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
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
||||||
|
|
||||||
@ -173,7 +214,11 @@ object NotificationUtils {
|
|||||||
notification = statusBarNotification.notification
|
notification = statusBarNotification.notification
|
||||||
|
|
||||||
if (notification != null && !notification.extras.isEmpty) {
|
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)
|
notificationManager.cancel(statusBarNotification.id)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,6 @@ import android.database.Cursor
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.provider.OpenableColumns
|
import android.provider.OpenableColumns
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
|
|
||||||
|
|
||||||
object UriUtils {
|
object UriUtils {
|
||||||
|
|
||||||
@ -51,5 +50,4 @@ object UriUtils {
|
|||||||
}
|
}
|
||||||
return filename
|
return filename
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -21,8 +21,8 @@
|
|||||||
package com.nextcloud.talk.utils.bundle
|
package com.nextcloud.talk.utils.bundle
|
||||||
|
|
||||||
object BundleKeys {
|
object BundleKeys {
|
||||||
val KEY_SELECTED_USERS = "KEY_SELECTED_USERS";
|
val KEY_SELECTED_USERS = "KEY_SELECTED_USERS"
|
||||||
val KEY_SELECTED_GROUPS = "KEY_SELECTED_GROUPS";
|
val KEY_SELECTED_GROUPS = "KEY_SELECTED_GROUPS"
|
||||||
val KEY_USERNAME = "KEY_USERNAME"
|
val KEY_USERNAME = "KEY_USERNAME"
|
||||||
val KEY_TOKEN = "KEY_TOKEN"
|
val KEY_TOKEN = "KEY_TOKEN"
|
||||||
val KEY_BASE_URL = "KEY_BASE_URL"
|
val KEY_BASE_URL = "KEY_BASE_URL"
|
||||||
|
@ -13,11 +13,17 @@ import java.io.IOException
|
|||||||
import java.net.InetAddress
|
import java.net.InetAddress
|
||||||
import java.net.Socket
|
import java.net.Socket
|
||||||
import java.security.GeneralSecurityException
|
import java.security.GeneralSecurityException
|
||||||
import java.util.*
|
import java.util.LinkedList
|
||||||
import javax.net.ssl.*
|
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?,
|
class SSLSocketFactoryCompat(
|
||||||
trustManager: X509TrustManager) : SSLSocketFactory() {
|
keyManager: KeyManager?,
|
||||||
|
trustManager: X509TrustManager
|
||||||
|
) : SSLSocketFactory() {
|
||||||
|
|
||||||
private var delegate: SSLSocketFactory
|
private var delegate: SSLSocketFactory
|
||||||
|
|
||||||
@ -50,24 +56,24 @@ class SSLSocketFactoryCompat(keyManager: KeyManager?,
|
|||||||
|
|
||||||
/* set up reasonable cipher suites */
|
/* set up reasonable cipher suites */
|
||||||
val knownCiphers = arrayOf<String>(
|
val knownCiphers = arrayOf<String>(
|
||||||
// TLS 1.2
|
// TLS 1.2
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
// maximum interoperability
|
// maximum interoperability
|
||||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
|
"SSL_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||||
// additionally
|
// additionally
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||||
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA"
|
||||||
)
|
)
|
||||||
val availableCiphers = socket.supportedCipherSuites
|
val availableCiphers = socket.supportedCipherSuites
|
||||||
|
|
||||||
@ -89,31 +95,31 @@ class SSLSocketFactoryCompat(keyManager: KeyManager?,
|
|||||||
} catch (e: IOException) {
|
} catch (e: IOException) {
|
||||||
// Exception is to be ignored
|
// Exception is to be ignored
|
||||||
} finally {
|
} finally {
|
||||||
socket?.close() // doesn't implement Closeable on all supported Android versions
|
socket?.close() // doesn't implement Closeable on all supported Android versions
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
init {
|
init {
|
||||||
try {
|
try {
|
||||||
val sslContext = SSLContext.getInstance("TLS")
|
val sslContext = SSLContext.getInstance("TLS")
|
||||||
sslContext.init(
|
sslContext.init(
|
||||||
if (keyManager != null) arrayOf(keyManager) else null,
|
if (keyManager != null) arrayOf(keyManager) else null,
|
||||||
arrayOf(trustManager),
|
arrayOf(trustManager),
|
||||||
null)
|
null
|
||||||
|
)
|
||||||
delegate = sslContext.socketFactory
|
delegate = sslContext.socketFactory
|
||||||
} catch (e: GeneralSecurityException) {
|
} catch (e: GeneralSecurityException) {
|
||||||
throw IllegalStateException() // system has no TLS
|
throw IllegalStateException() // system has no TLS
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun getDefaultCipherSuites(): Array<String>? = cipherSuites
|
override fun getDefaultCipherSuites(): Array<String>? = cipherSuites
|
||||||
?: delegate.defaultCipherSuites
|
?: delegate.defaultCipherSuites
|
||||||
|
|
||||||
override fun getSupportedCipherSuites(): Array<String>? = cipherSuites
|
override fun getSupportedCipherSuites(): Array<String>? = cipherSuites
|
||||||
?: delegate.supportedCipherSuites
|
?: delegate.supportedCipherSuites
|
||||||
|
|
||||||
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket {
|
override fun createSocket(s: Socket, host: String, port: Int, autoClose: Boolean): Socket {
|
||||||
val ssl = delegate.createSocket(s, host, port, autoClose)
|
val ssl = delegate.createSocket(s, host, port, autoClose)
|
||||||
@ -150,10 +156,8 @@ class SSLSocketFactoryCompat(keyManager: KeyManager?,
|
|||||||
return ssl
|
return ssl
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun upgradeTLS(ssl: SSLSocket) {
|
private fun upgradeTLS(ssl: SSLSocket) {
|
||||||
protocols?.let { ssl.enabledProtocols = it }
|
protocols?.let { ssl.enabledProtocols = it }
|
||||||
cipherSuites?.let { ssl.enabledCipherSuites = it }
|
cipherSuites?.let { ssl.enabledCipherSuites = it }
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user