mirror of
https://github.com/nextcloud/talk-android
synced 2025-07-20 19:25:01 +01:00
Replace Fresco with Coil
Fresco is replaced with Coil everywhere to make it possible to set 'minSdkVersion' to 23. But Coil is not used directly to avoid splintering the dependency everywhere in the code. Coil is wrapped by extension functions for 'ImageView'. Some shared functionality is moved from 'DisplayUtils' into the 'ImageViewExtensions'. The exisiting initialization of Coil has also be changed. The usage of the self initialized OKHttp client is removed. If this one is added the caching of the http client is used by Coil additionally to memory and disk cache. Resolves: #2227, #2376 Signed-off-by: Tim Krüger <t@timkrueger.me>
This commit is contained in:
parent
537f375f86
commit
49da463971
@ -245,15 +245,8 @@ dependencies {
|
|||||||
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
implementation 'org.apache.commons:commons-lang3:3.12.0'
|
||||||
implementation 'com.github.wooplr:Spotlight:1.3'
|
implementation 'com.github.wooplr:Spotlight:1.3'
|
||||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||||
implementation('com.github.nextcloud-deps:ChatKit:0.3.0-1', {
|
implementation 'com.github.nextcloud-deps:ChatKit:0.3.1'
|
||||||
exclude group: 'com.facebook.fresco'
|
|
||||||
})
|
|
||||||
|
|
||||||
implementation 'com.github.nextcloud-deps.fresco:fresco:v111'
|
|
||||||
implementation 'com.github.nextcloud-deps.fresco:animated-webp:v111'
|
|
||||||
implementation 'com.github.nextcloud-deps.fresco:webpsupport:v111'
|
|
||||||
implementation 'com.github.nextcloud-deps.fresco:animated-gif:v111'
|
|
||||||
implementation 'com.github.nextcloud-deps.fresco:imagepipeline-okhttp3:v111'
|
|
||||||
implementation 'joda-time:joda-time:2.12.2'
|
implementation 'joda-time:joda-time:2.12.2'
|
||||||
implementation "io.coil-kt:coil:${coilKtVersion}"
|
implementation "io.coil-kt:coil:${coilKtVersion}"
|
||||||
implementation "io.coil-kt:coil-gif:${coilKtVersion}"
|
implementation "io.coil-kt:coil-gif:${coilKtVersion}"
|
||||||
|
@ -149,7 +149,6 @@ import androidx.annotation.NonNull;
|
|||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.annotation.RequiresApi;
|
import androidx.annotation.RequiresApi;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.content.res.AppCompatResources;
|
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.drawable.DrawableCompat;
|
import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
import autodagger.AutoInjector;
|
import autodagger.AutoInjector;
|
||||||
@ -540,20 +539,16 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
private void updateAudioOutputButton(WebRtcAudioManager.AudioDevice activeAudioDevice) {
|
private void updateAudioOutputButton(WebRtcAudioManager.AudioDevice activeAudioDevice) {
|
||||||
switch (activeAudioDevice) {
|
switch (activeAudioDevice) {
|
||||||
case BLUETOOTH:
|
case BLUETOOTH:
|
||||||
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
binding.audioOutputButton.setImageResource ( R.drawable.ic_baseline_bluetooth_audio_24);
|
||||||
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_bluetooth_audio_24));
|
|
||||||
break;
|
break;
|
||||||
case SPEAKER_PHONE:
|
case SPEAKER_PHONE:
|
||||||
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
binding.audioOutputButton.setImageResource(R.drawable.ic_volume_up_white_24dp);
|
||||||
AppCompatResources.getDrawable(context, R.drawable.ic_volume_up_white_24dp));
|
|
||||||
break;
|
break;
|
||||||
case EARPIECE:
|
case EARPIECE:
|
||||||
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
binding.audioOutputButton.setImageResource(R.drawable.ic_baseline_phone_in_talk_24);
|
||||||
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_phone_in_talk_24));
|
|
||||||
break;
|
break;
|
||||||
case WIRED_HEADSET:
|
case WIRED_HEADSET:
|
||||||
binding.audioOutputButton.getHierarchy().setPlaceholderImage(
|
binding.audioOutputButton.setImageResource(R.drawable.ic_baseline_headset_mic_24);
|
||||||
AppCompatResources.getDrawable(context, R.drawable.ic_baseline_headset_mic_24));
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Log.e(TAG, "Icon for audio output not available");
|
Log.e(TAG, "Icon for audio output not available");
|
||||||
@ -795,7 +790,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
onCameraClick();
|
onCameraClick();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
|
binding.cameraButton.setImageResource(R.drawable.ic_videocam_off_white_24px);
|
||||||
binding.cameraButton.setAlpha(0.7f);
|
binding.cameraButton.setAlpha(0.7f);
|
||||||
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
@ -806,7 +801,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
onMicrophoneClick();
|
onMicrophoneClick();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isConnectionEstablished()) {
|
if (!isConnectionEstablished()) {
|
||||||
@ -917,7 +912,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
|
|
||||||
if (!canPublishAudioStream) {
|
if (!canPublishAudioStream) {
|
||||||
microphoneOn = false;
|
microphoneOn = false;
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px);
|
||||||
toggleMedia(false, false);
|
toggleMedia(false, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,12 +956,12 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
microphoneOn = !microphoneOn;
|
microphoneOn = !microphoneOn;
|
||||||
|
|
||||||
if (microphoneOn) {
|
if (microphoneOn) {
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_white_24px);
|
||||||
updatePictureInPictureActions(R.drawable.ic_mic_white_24px,
|
updatePictureInPictureActions(R.drawable.ic_mic_white_24px,
|
||||||
getResources().getString(R.string.nc_pip_microphone_mute),
|
getResources().getString(R.string.nc_pip_microphone_mute),
|
||||||
MICROPHONE_PIP_REQUEST_MUTE);
|
MICROPHONE_PIP_REQUEST_MUTE);
|
||||||
} else {
|
} else {
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px);
|
||||||
updatePictureInPictureActions(R.drawable.ic_mic_off_white_24px,
|
updatePictureInPictureActions(R.drawable.ic_mic_off_white_24px,
|
||||||
getResources().getString(R.string.nc_pip_microphone_unmute),
|
getResources().getString(R.string.nc_pip_microphone_unmute),
|
||||||
MICROPHONE_PIP_REQUEST_UNMUTE);
|
MICROPHONE_PIP_REQUEST_UNMUTE);
|
||||||
@ -974,7 +969,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
|
|
||||||
toggleMedia(microphoneOn, false);
|
toggleMedia(microphoneOn, false);
|
||||||
} else {
|
} else {
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_white_24px);
|
||||||
pulseAnimation.start();
|
pulseAnimation.start();
|
||||||
toggleMedia(true, false);
|
toggleMedia(true, false);
|
||||||
}
|
}
|
||||||
@ -997,7 +992,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
|
|
||||||
if (!canPublishVideoStream) {
|
if (!canPublishVideoStream) {
|
||||||
videoOn = false;
|
videoOn = false;
|
||||||
binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
|
binding.cameraButton.setImageResource(R.drawable.ic_videocam_off_white_24px);
|
||||||
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1006,12 +1001,12 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
videoOn = !videoOn;
|
videoOn = !videoOn;
|
||||||
|
|
||||||
if (videoOn) {
|
if (videoOn) {
|
||||||
binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_white_24px);
|
binding.cameraButton.setImageResource(R.drawable.ic_videocam_white_24px);
|
||||||
if (cameraEnumerator.getDeviceNames().length > 1) {
|
if (cameraEnumerator.getDeviceNames().length > 1) {
|
||||||
binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
|
binding.switchSelfVideoButton.setVisibility(View.VISIBLE);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
binding.cameraButton.getHierarchy().setPlaceholderImage(R.drawable.ic_videocam_off_white_24px);
|
binding.cameraButton.setImageResource(R.drawable.ic_videocam_off_white_24px);
|
||||||
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
binding.switchSelfVideoButton.setVisibility(View.GONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2675,7 +2670,7 @@ public class CallActivity extends CallBaseActivity {
|
|||||||
v.onTouchEvent(event);
|
v.onTouchEvent(event);
|
||||||
if (event.getAction() == MotionEvent.ACTION_UP && isPushToTalkActive) {
|
if (event.getAction() == MotionEvent.ACTION_UP && isPushToTalkActive) {
|
||||||
isPushToTalkActive = false;
|
isPushToTalkActive = false;
|
||||||
binding.microphoneButton.getHierarchy().setPlaceholderImage(R.drawable.ic_mic_off_white_24px);
|
binding.microphoneButton.setImageResource(R.drawable.ic_mic_off_white_24px);
|
||||||
pulseAnimation.stop();
|
pulseAnimation.stop();
|
||||||
toggleMedia(false, false);
|
toggleMedia(false, false);
|
||||||
animateCallControls(false, 5000);
|
animateCallControls(false, 5000);
|
||||||
|
@ -28,8 +28,6 @@ import android.app.PendingIntent
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.res.Configuration
|
import android.content.res.Configuration
|
||||||
import android.graphics.Bitmap
|
|
||||||
import android.graphics.drawable.BitmapDrawable
|
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
@ -41,24 +39,18 @@ import android.view.View
|
|||||||
import androidx.annotation.RequiresApi
|
import androidx.annotation.RequiresApi
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
|
||||||
import com.facebook.common.references.CloseableReference
|
|
||||||
import com.facebook.datasource.DataSource
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.CallNotificationActivityBinding
|
import com.nextcloud.talk.databinding.CallNotificationActivityBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
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.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
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.DoNotDisturbUtils.shouldPlaySound
|
import com.nextcloud.talk.utils.DoNotDisturbUtils.shouldPlaySound
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri
|
import com.nextcloud.talk.utils.NotificationUtils.getCallRingtoneUri
|
||||||
@ -75,6 +67,7 @@ import io.reactivex.Observer
|
|||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import kotlinx.android.synthetic.main.call_item.*
|
||||||
import okhttp3.Cache
|
import okhttp3.Cache
|
||||||
import org.parceler.Parcels
|
import org.parceler.Parcels
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
@ -356,7 +349,7 @@ class CallNotificationActivity : CallBaseActivity() {
|
|||||||
private fun setUpAfterConversationIsKnown() {
|
private fun setUpAfterConversationIsKnown() {
|
||||||
binding!!.conversationNameTextView.text = currentConversation!!.displayName
|
binding!!.conversationNameTextView.text = currentConversation!!.displayName
|
||||||
if (currentConversation!!.type === Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
if (currentConversation!!.type === Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||||
setAvatarForOneToOneCall()
|
avatarImageView.loadAvatar(userBeingCalled!!, currentConversation!!.name!!)
|
||||||
} else {
|
} else {
|
||||||
binding!!.avatarImageView.setImageResource(R.drawable.ic_circular_group)
|
binding!!.avatarImageView.setImageResource(R.drawable.ic_circular_group)
|
||||||
}
|
}
|
||||||
@ -364,34 +357,6 @@ class CallNotificationActivity : CallBaseActivity() {
|
|||||||
showAnswerControls()
|
showAnswerControls()
|
||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("MagicNumber")
|
|
||||||
private fun setAvatarForOneToOneCall() {
|
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
userBeingCalled!!.baseUrl,
|
|
||||||
currentConversation!!.name,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val imagePipeline = Fresco.getImagePipeline()
|
|
||||||
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
|
|
||||||
dataSource.subscribe(
|
|
||||||
object : BaseBitmapDataSubscriber() {
|
|
||||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
||||||
binding!!.avatarImageView.hierarchy.setImage(
|
|
||||||
BitmapDrawable(resources, bitmap), 100f,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage?>>) {
|
|
||||||
Log.e(TAG, "failed to load avatar")
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UiThreadImmediateExecutorService.getInstance()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun endMediaNotifications() {
|
private fun endMediaNotifications() {
|
||||||
if (mediaPlayer != null) {
|
if (mediaPlayer != null) {
|
||||||
if (mediaPlayer!!.isPlaying) {
|
if (mediaPlayer!!.isPlaying) {
|
||||||
|
@ -12,12 +12,9 @@ import android.widget.ProgressBar;
|
|||||||
import android.widget.RelativeLayout;
|
import android.widget.RelativeLayout;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.activities.CallActivity;
|
import com.nextcloud.talk.activities.CallActivity;
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
|
|
||||||
import org.webrtc.MediaStream;
|
import org.webrtc.MediaStream;
|
||||||
import org.webrtc.MediaStreamTrack;
|
import org.webrtc.MediaStreamTrack;
|
||||||
@ -109,7 +106,7 @@ public class ParticipantsAdapter extends BaseAdapter {
|
|||||||
convertView.setLayoutParams(layoutParams);
|
convertView.setLayoutParams(layoutParams);
|
||||||
|
|
||||||
TextView nickTextView = convertView.findViewById(R.id.peer_nick_text_view);
|
TextView nickTextView = convertView.findViewById(R.id.peer_nick_text_view);
|
||||||
SimpleDraweeView imageView = convertView.findViewById(R.id.avatarImageView);
|
ImageView imageView = convertView.findViewById(R.id.avatarImageView);
|
||||||
|
|
||||||
MediaStream mediaStream = participantDisplayItem.getMediaStream();
|
MediaStream mediaStream = participantDisplayItem.getMediaStream();
|
||||||
if (hasVideoStream(participantDisplayItem, mediaStream)) {
|
if (hasVideoStream(participantDisplayItem, mediaStream)) {
|
||||||
@ -128,13 +125,7 @@ public class ParticipantsAdapter extends BaseAdapter {
|
|||||||
nickTextView.setVisibility(View.VISIBLE);
|
nickTextView.setVisibility(View.VISIBLE);
|
||||||
nickTextView.setText(participantDisplayItem.getNick());
|
nickTextView.setText(participantDisplayItem.getNick());
|
||||||
}
|
}
|
||||||
|
ImageViewExtensionsKt.loadAvatarWithUrl(imageView,null, participantDisplayItem.getUrlForAvatar());
|
||||||
imageView.setController(null);
|
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(imageView.getController())
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(participantDisplayItem.getUrlForAvatar()))
|
|
||||||
.build();
|
|
||||||
imageView.setController(draweeController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ImageView audioOffView = convertView.findViewById(R.id.remote_audio_off);
|
ImageView audioOffView = convertView.findViewById(R.id.remote_audio_off);
|
||||||
|
@ -34,7 +34,7 @@ class ReactionsAdapter(
|
|||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReactionsViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ReactionsViewHolder {
|
||||||
val itemBinding = ReactionItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
val itemBinding = ReactionItemBinding.inflate(LayoutInflater.from(parent.context), parent, false)
|
||||||
return ReactionsViewHolder(itemBinding, user?.baseUrl)
|
return ReactionsViewHolder(itemBinding, user)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onBindViewHolder(holder: ReactionsViewHolder, position: Int) {
|
override fun onBindViewHolder(holder: ReactionsViewHolder, position: Int) {
|
||||||
|
@ -22,18 +22,17 @@ package com.nextcloud.talk.adapters
|
|||||||
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ReactionItemBinding
|
import com.nextcloud.talk.databinding.ReactionItemBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadGuestAvatar
|
||||||
import com.nextcloud.talk.models.json.reactions.ReactionVoter
|
import com.nextcloud.talk.models.json.reactions.ReactionVoter
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
|
|
||||||
class ReactionsViewHolder(
|
class ReactionsViewHolder(
|
||||||
private val binding: ReactionItemBinding,
|
private val binding: ReactionItemBinding,
|
||||||
private val baseUrl: String?
|
private val user: User?
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
fun bind(reactionItem: ReactionItem, clickListener: ReactionItemClickListener) {
|
fun bind(reactionItem: ReactionItem, clickListener: ReactionItemClickListener) {
|
||||||
@ -41,7 +40,7 @@ class ReactionsViewHolder(
|
|||||||
binding.reaction.text = reactionItem.reaction
|
binding.reaction.text = reactionItem.reaction
|
||||||
binding.name.text = reactionItem.reactionVoter.actorDisplayName
|
binding.name.text = reactionItem.reactionVoter.actorDisplayName
|
||||||
|
|
||||||
if (baseUrl != null && baseUrl.isNotEmpty()) {
|
if (user != null && user.baseUrl?.isNotEmpty() == true) {
|
||||||
loadAvatar(reactionItem)
|
loadAvatar(reactionItem)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -52,35 +51,13 @@ class ReactionsViewHolder(
|
|||||||
if (!TextUtils.isEmpty(reactionItem.reactionVoter.actorDisplayName)) {
|
if (!TextUtils.isEmpty(reactionItem.reactionVoter.actorDisplayName)) {
|
||||||
displayName = reactionItem.reactionVoter.actorDisplayName!!
|
displayName = reactionItem.reactionVoter.actorDisplayName!!
|
||||||
}
|
}
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
binding.avatar.loadGuestAvatar(user!!.baseUrl!!, displayName!!, false)
|
||||||
.setOldController(binding.avatar.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForGuestAvatar(
|
|
||||||
baseUrl,
|
|
||||||
displayName,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
binding.avatar.controller = draweeController
|
|
||||||
} else if (reactionItem.reactionVoter.actorType == ReactionVoter.ReactionActorType.USERS) {
|
} else if (reactionItem.reactionVoter.actorType == ReactionVoter.ReactionActorType.USERS) {
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
binding.avatar.loadAvatar(
|
||||||
.setOldController(binding.avatar.controller)
|
user!!,
|
||||||
.setAutoPlayAnimations(true)
|
reactionItem.reactionVoter.actorId!!,
|
||||||
.setImageRequest(
|
false
|
||||||
DisplayUtils.getImageRequestForUrl(
|
)
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
baseUrl,
|
|
||||||
reactionItem.reactionVoter.actorId,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
binding.avatar.controller = draweeController
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,15 +27,12 @@ import android.net.Uri;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.databinding.AccountItemBinding;
|
import com.nextcloud.talk.databinding.AccountItemBinding;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.models.json.participants.Participant;
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -108,7 +105,6 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position, List payloads) {
|
public void bindViewHolder(FlexibleAdapter adapter, UserItemViewHolder holder, int position, List payloads) {
|
||||||
holder.binding.userIcon.setController(null);
|
|
||||||
|
|
||||||
if (adapter.hasFilter()) {
|
if (adapter.hasFilter()) {
|
||||||
FlexibleUtils.highlightText(
|
FlexibleUtils.highlightText(
|
||||||
@ -129,24 +125,10 @@ public class AdvancedUserItem extends AbstractFlexibleItem<AdvancedUserItem.User
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.binding.userIcon.getHierarchy().setPlaceholderImage(R.drawable.account_circle_48dp);
|
|
||||||
holder.binding.userIcon.getHierarchy().setFailureImage(R.drawable.account_circle_48dp);
|
|
||||||
|
|
||||||
if (user != null && user.getBaseUrl() != null &&
|
if (user != null && user.getBaseUrl() != null &&
|
||||||
user.getBaseUrl().startsWith("http://") ||
|
user.getBaseUrl().startsWith("http://") ||
|
||||||
user.getBaseUrl().startsWith("https://")) {
|
user.getBaseUrl().startsWith("https://")) {
|
||||||
|
ImageViewExtensionsKt.loadAvatar(holder.binding.userIcon, user, participant.getCalculatedActorId(), true);
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(holder.binding.userIcon.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.getBaseUrl(),
|
|
||||||
participant.getCalculatedActorId(),
|
|
||||||
true)))
|
|
||||||
.build();
|
|
||||||
holder.binding.userIcon.setController(draweeController);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,16 +29,13 @@ import android.os.Build;
|
|||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.databinding.RvItemContactBinding;
|
import com.nextcloud.talk.databinding.RvItemContactBinding;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.models.json.participants.Participant;
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
@ -110,7 +107,6 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
|
|||||||
@SuppressLint("SetTextI18n")
|
@SuppressLint("SetTextI18n")
|
||||||
@Override
|
@Override
|
||||||
public void bindViewHolder(FlexibleAdapter adapter, ContactItemViewHolder holder, int position, List payloads) {
|
public void bindViewHolder(FlexibleAdapter adapter, ContactItemViewHolder holder, int position, List payloads) {
|
||||||
holder.binding.avatarDraweeView.setController(null);
|
|
||||||
|
|
||||||
if (participant.getSelected()) {
|
if (participant.getSelected()) {
|
||||||
viewThemeUtils.platform.colorImageView(holder.binding.checkedImageView);
|
viewThemeUtils.platform.colorImageView(holder.binding.checkedImageView);
|
||||||
@ -121,18 +117,18 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
|
|||||||
|
|
||||||
if (!isOnline) {
|
if (!isOnline) {
|
||||||
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
||||||
holder.binding.nameText.getContext().getResources(),
|
holder.binding.nameText.getContext().getResources(),
|
||||||
R.color.medium_emphasis_text,
|
R.color.medium_emphasis_text,
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
holder.binding.avatarDraweeView.setAlpha(0.38f);
|
holder.binding.avatarView.setAlpha(0.38f);
|
||||||
} else {
|
} else {
|
||||||
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
||||||
holder.binding.nameText.getContext().getResources(),
|
holder.binding.nameText.getContext().getResources(),
|
||||||
R.color.high_emphasis_text,
|
R.color.high_emphasis_text,
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
holder.binding.avatarDraweeView.setAlpha(1.0f);
|
holder.binding.avatarView.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.binding.nameText.setText(participant.getDisplayName());
|
holder.binding.nameText.setText(participant.getDisplayName());
|
||||||
@ -179,38 +175,29 @@ public class ContactItem extends AbstractFlexibleItem<ContactItem.ContactItemVie
|
|||||||
.getResources().getString(R.string.nc_guest);
|
.getResources().getString(R.string.nc_guest);
|
||||||
}
|
}
|
||||||
|
|
||||||
setUserStyleAvatar(holder,
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, user, displayName, true);
|
||||||
ApiUtils.getUrlForGuestAvatar(user.getBaseUrl(), displayName, false));
|
|
||||||
} else if (participant.getCalculatedActorType() == Participant.ActorType.USERS ||
|
} else if (participant.getCalculatedActorType() == Participant.ActorType.USERS ||
|
||||||
PARTICIPANT_SOURCE_USERS.equals(participant.getSource())) {
|
PARTICIPANT_SOURCE_USERS.equals(participant.getSource())) {
|
||||||
setUserStyleAvatar(holder,
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, user, participant.getCalculatedActorId(), true);
|
||||||
ApiUtils.getUrlForAvatar(user.getBaseUrl(),
|
|
||||||
participant.getCalculatedActorId(),
|
|
||||||
false));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setUserStyleAvatar(ContactItemViewHolder holder, String avatarUrl) {
|
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(holder.binding.avatarDraweeView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarUrl))
|
|
||||||
.build();
|
|
||||||
holder.binding.avatarDraweeView.setController(draweeController);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void setGenericAvatar(
|
private void setGenericAvatar(
|
||||||
ContactItemViewHolder holder,
|
ContactItemViewHolder holder,
|
||||||
int roundPlaceholderDrawable,
|
int roundPlaceholderDrawable,
|
||||||
int fallbackImageResource) {
|
int fallbackImageResource) {
|
||||||
|
Object avatar;
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
|
avatar = viewThemeUtils.talk.themePlaceholderAvatar(
|
||||||
DisplayUtils.getRoundedDrawable(
|
holder.binding.avatarView,
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
|
roundPlaceholderDrawable
|
||||||
roundPlaceholderDrawable)));
|
);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
holder.binding.avatarDraweeView.setImageResource(fallbackImageResource);
|
avatar = fallbackImageResource;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, avatar);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -29,27 +29,26 @@ import android.annotation.SuppressLint
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.res.ColorStateList
|
import android.content.res.ColorStateList
|
||||||
import android.graphics.Typeface
|
import android.graphics.Typeface
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.text.format.DateUtils
|
import android.text.format.DateUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
import androidx.core.content.res.ResourcesCompat
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder
|
import com.nextcloud.talk.adapters.items.ConversationItem.ConversationItemViewHolder
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding
|
import com.nextcloud.talk.databinding.RvItemConversationWithLastMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadGroupCallAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadPublicCallAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadSystemAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
import com.nextcloud.talk.models.json.conversations.Conversation.ConversationType
|
||||||
import com.nextcloud.talk.ui.StatusDrawable
|
import com.nextcloud.talk.ui.StatusDrawable
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew.hasSpreedFeatureCapability
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
@ -113,7 +112,6 @@ class ConversationItem(
|
|||||||
payloads: List<Any>
|
payloads: List<Any>
|
||||||
) {
|
) {
|
||||||
val appContext = sharedApplication!!.applicationContext
|
val appContext = sharedApplication!!.applicationContext
|
||||||
holder.binding.dialogAvatar.controller = null
|
|
||||||
holder.binding.dialogName.setTextColor(
|
holder.binding.dialogName.setTextColor(
|
||||||
ResourcesCompat.getColor(
|
ResourcesCompat.getColor(
|
||||||
context.resources,
|
context.resources,
|
||||||
@ -130,40 +128,7 @@ class ConversationItem(
|
|||||||
holder.binding.dialogName.text = model.displayName
|
holder.binding.dialogName.text = model.displayName
|
||||||
}
|
}
|
||||||
if (model.unreadMessages > 0) {
|
if (model.unreadMessages > 0) {
|
||||||
holder.binding.dialogName.setTypeface(holder.binding.dialogName.typeface, Typeface.BOLD)
|
showUnreadMessages(holder)
|
||||||
holder.binding.dialogLastMessage.setTypeface(holder.binding.dialogLastMessage.typeface, Typeface.BOLD)
|
|
||||||
holder.binding.dialogUnreadBubble.visibility = View.VISIBLE
|
|
||||||
if (model.unreadMessages < 1000) {
|
|
||||||
holder.binding.dialogUnreadBubble.text = model.unreadMessages.toLong().toString()
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages)
|
|
||||||
}
|
|
||||||
val lightBubbleFillColor = ColorStateList.valueOf(
|
|
||||||
ContextCompat.getColor(
|
|
||||||
context,
|
|
||||||
R.color.conversation_unread_bubble
|
|
||||||
)
|
|
||||||
)
|
|
||||||
val lightBubbleTextColor = ContextCompat.getColor(
|
|
||||||
context,
|
|
||||||
R.color.conversation_unread_bubble_text
|
|
||||||
)
|
|
||||||
if (model.type === ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
|
||||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
|
||||||
} else if (model.unreadMention) {
|
|
||||||
if (hasSpreedFeatureCapability(user, "direct-mention-flag")) {
|
|
||||||
if (model.unreadMentionDirect!!) {
|
|
||||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
|
||||||
} else {
|
|
||||||
viewThemeUtils.material.colorChipOutlined(holder.binding.dialogUnreadBubble, 6.0f)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogUnreadBubble.chipBackgroundColor = lightBubbleFillColor
|
|
||||||
holder.binding.dialogUnreadBubble.setTextColor(lightBubbleTextColor)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
holder.binding.dialogName.setTypeface(null, Typeface.NORMAL)
|
holder.binding.dialogName.setTypeface(null, Typeface.NORMAL)
|
||||||
holder.binding.dialogDate.setTypeface(null, Typeface.NORMAL)
|
holder.binding.dialogDate.setTypeface(null, Typeface.NORMAL)
|
||||||
@ -175,13 +140,13 @@ class ConversationItem(
|
|||||||
} else {
|
} else {
|
||||||
holder.binding.favoriteConversationImageView.visibility = View.GONE
|
holder.binding.favoriteConversationImageView.visibility = View.GONE
|
||||||
}
|
}
|
||||||
if (model != null && ConversationType.ROOM_SYSTEM !== model.type) {
|
if (ConversationType.ROOM_SYSTEM !== model.type) {
|
||||||
val size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, appContext)
|
val size = DisplayUtils.convertDpToPixel(STATUS_SIZE_IN_DP, appContext)
|
||||||
holder.binding.userStatusImage.visibility = View.VISIBLE
|
holder.binding.userStatusImage.visibility = View.VISIBLE
|
||||||
holder.binding.userStatusImage.setImageDrawable(
|
holder.binding.userStatusImage.setImageDrawable(
|
||||||
StatusDrawable(
|
StatusDrawable(
|
||||||
model.status,
|
model.status,
|
||||||
model.status,
|
model.statusIcon,
|
||||||
size,
|
size,
|
||||||
context.resources.getColor(R.color.bg_default),
|
context.resources.getColor(R.color.bg_default),
|
||||||
appContext
|
appContext
|
||||||
@ -190,10 +155,77 @@ class ConversationItem(
|
|||||||
} else {
|
} else {
|
||||||
holder.binding.userStatusImage.visibility = View.GONE
|
holder.binding.userStatusImage.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
setLastMessage(holder, appContext)
|
||||||
|
showAvatar(holder)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showAvatar(holder: ConversationItemViewHolder) {
|
||||||
|
holder.binding.dialogAvatar.visibility = View.VISIBLE
|
||||||
|
var shouldLoadAvatar = shouldLoadAvatar(holder)
|
||||||
|
if (ConversationType.ROOM_SYSTEM == model.type) {
|
||||||
|
holder.binding.dialogAvatar.loadSystemAvatar()
|
||||||
|
shouldLoadAvatar = false
|
||||||
|
}
|
||||||
|
if (shouldLoadAvatar) {
|
||||||
|
when (model.type) {
|
||||||
|
ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(model.name)) {
|
||||||
|
holder.binding.dialogAvatar.loadAvatar(user, model.name!!)
|
||||||
|
} else {
|
||||||
|
holder.binding.dialogAvatar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
ConversationType.ROOM_GROUP_CALL ->
|
||||||
|
holder.binding.dialogAvatar.loadGroupCallAvatar(viewThemeUtils)
|
||||||
|
ConversationType.ROOM_PUBLIC_CALL ->
|
||||||
|
holder.binding.dialogAvatar.loadPublicCallAvatar(viewThemeUtils)
|
||||||
|
else -> holder.binding.dialogAvatar.visibility = View.GONE
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun shouldLoadAvatar(
|
||||||
|
holder: ConversationItemViewHolder
|
||||||
|
): Boolean {
|
||||||
|
var objectType: String?
|
||||||
|
var returnValue = true
|
||||||
|
if (!TextUtils.isEmpty(model.objectType.also { objectType = it })) {
|
||||||
|
when (objectType) {
|
||||||
|
"share:password" -> {
|
||||||
|
holder.binding.dialogAvatar.setImageDrawable(
|
||||||
|
ContextCompat.getDrawable(
|
||||||
|
context,
|
||||||
|
R.drawable.ic_circular_lock
|
||||||
|
)
|
||||||
|
)
|
||||||
|
returnValue = false
|
||||||
|
}
|
||||||
|
"file" -> {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
holder.binding.dialogAvatar.loadAvatar(
|
||||||
|
viewThemeUtils.talk.themePlaceholderAvatar(
|
||||||
|
holder.binding.dialogAvatar,
|
||||||
|
R.drawable.ic_avatar_document
|
||||||
|
)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
holder.binding.dialogAvatar.loadAvatar(
|
||||||
|
R.drawable.ic_circular_document
|
||||||
|
)
|
||||||
|
}
|
||||||
|
returnValue = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return returnValue
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun setLastMessage(
|
||||||
|
holder: ConversationItemViewHolder,
|
||||||
|
appContext: Context
|
||||||
|
) {
|
||||||
if (model.lastMessage != null) {
|
if (model.lastMessage != null) {
|
||||||
holder.binding.dialogDate.visibility = View.VISIBLE
|
holder.binding.dialogDate.visibility = View.VISIBLE
|
||||||
holder.binding.dialogDate.text = DateUtils.getRelativeTimeSpanString(
|
holder.binding.dialogDate.text = DateUtils.getRelativeTimeSpanString(
|
||||||
model.lastActivity * 1000L,
|
model.lastActivity * MILLIES,
|
||||||
System.currentTimeMillis(),
|
System.currentTimeMillis(),
|
||||||
0,
|
0,
|
||||||
DateUtils.FORMAT_ABBREV_RELATIVE
|
DateUtils.FORMAT_ABBREV_RELATIVE
|
||||||
@ -204,30 +236,13 @@ class ConversationItem(
|
|||||||
holder.binding.dialogLastMessage.text = model.lastMessage!!.text
|
holder.binding.dialogLastMessage.text = model.lastMessage!!.text
|
||||||
} else {
|
} else {
|
||||||
model.lastMessage!!.activeUser = user
|
model.lastMessage!!.activeUser = user
|
||||||
val text: String
|
|
||||||
if (model.lastMessage!!.getCalculateMessageType() === ChatMessage.MessageType.REGULAR_TEXT_MESSAGE) {
|
val text = if (model.lastMessage!!.getCalculateMessageType() === ChatMessage.MessageType
|
||||||
if (model.lastMessage!!.actorId == user.userId) {
|
.REGULAR_TEXT_MESSAGE
|
||||||
text = String.format(
|
) {
|
||||||
appContext.getString(R.string.nc_formatted_message_you),
|
calculateRegularLastMessageText(appContext)
|
||||||
model.lastMessage!!.lastMessageDisplayText
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
val authorDisplayName =
|
|
||||||
if (!TextUtils.isEmpty(model.lastMessage!!.actorDisplayName)) {
|
|
||||||
model.lastMessage!!.actorDisplayName
|
|
||||||
} else if ("guests" == model.lastMessage!!.actorType) {
|
|
||||||
appContext.getString(R.string.nc_guest)
|
|
||||||
} else {
|
|
||||||
""
|
|
||||||
}
|
|
||||||
text = String.format(
|
|
||||||
appContext.getString(R.string.nc_formatted_message),
|
|
||||||
authorDisplayName,
|
|
||||||
model.lastMessage!!.lastMessageDisplayText
|
|
||||||
)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
text = model.lastMessage!!.lastMessageDisplayText
|
model.lastMessage!!.lastMessageDisplayText
|
||||||
}
|
}
|
||||||
holder.binding.dialogLastMessage.text = text
|
holder.binding.dialogLastMessage.text = text
|
||||||
}
|
}
|
||||||
@ -235,105 +250,68 @@ class ConversationItem(
|
|||||||
holder.binding.dialogDate.visibility = View.GONE
|
holder.binding.dialogDate.visibility = View.GONE
|
||||||
holder.binding.dialogLastMessage.setText(R.string.nc_no_messages_yet)
|
holder.binding.dialogLastMessage.setText(R.string.nc_no_messages_yet)
|
||||||
}
|
}
|
||||||
holder.binding.dialogAvatar.visibility = View.VISIBLE
|
}
|
||||||
var shouldLoadAvatar = true
|
|
||||||
var objectType: String?
|
private fun calculateRegularLastMessageText(appContext: Context): String {
|
||||||
if (!TextUtils.isEmpty(model.objectType.also { objectType = it })) {
|
return if (model.lastMessage!!.actorId == user.userId) {
|
||||||
when (objectType) {
|
String.format(
|
||||||
"share:password" -> {
|
appContext.getString(R.string.nc_formatted_message_you),
|
||||||
shouldLoadAvatar = false
|
model.lastMessage!!.lastMessageDisplayText
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
)
|
||||||
ContextCompat.getDrawable(
|
} else {
|
||||||
context,
|
val authorDisplayName =
|
||||||
R.drawable.ic_circular_lock
|
if (!TextUtils.isEmpty(model.lastMessage!!.actorDisplayName)) {
|
||||||
)
|
model.lastMessage!!.actorDisplayName
|
||||||
|
} else if ("guests" == model.lastMessage!!.actorType) {
|
||||||
|
appContext.getString(R.string.nc_guest)
|
||||||
|
} else {
|
||||||
|
""
|
||||||
|
}
|
||||||
|
String.format(
|
||||||
|
appContext.getString(R.string.nc_formatted_message),
|
||||||
|
authorDisplayName,
|
||||||
|
model.lastMessage!!.lastMessageDisplayText
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun showUnreadMessages(holder: ConversationItemViewHolder) {
|
||||||
|
holder.binding.dialogName.setTypeface(holder.binding.dialogName.typeface, Typeface.BOLD)
|
||||||
|
holder.binding.dialogLastMessage.setTypeface(holder.binding.dialogLastMessage.typeface, Typeface.BOLD)
|
||||||
|
holder.binding.dialogUnreadBubble.visibility = View.VISIBLE
|
||||||
|
if (model.unreadMessages < UNREAD_MESSAGES_TRESHOLD) {
|
||||||
|
holder.binding.dialogUnreadBubble.text = model.unreadMessages.toLong().toString()
|
||||||
|
} else {
|
||||||
|
holder.binding.dialogUnreadBubble.setText(R.string.tooManyUnreadMessages)
|
||||||
|
}
|
||||||
|
val lightBubbleFillColor = ColorStateList.valueOf(
|
||||||
|
ContextCompat.getColor(
|
||||||
|
context,
|
||||||
|
R.color.conversation_unread_bubble
|
||||||
|
)
|
||||||
|
)
|
||||||
|
val lightBubbleTextColor = ContextCompat.getColor(
|
||||||
|
context,
|
||||||
|
R.color.conversation_unread_bubble_text
|
||||||
|
)
|
||||||
|
if (model.type === ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL) {
|
||||||
|
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||||
|
} else if (model.unreadMention) {
|
||||||
|
if (hasSpreedFeatureCapability(user, "direct-mention-flag")) {
|
||||||
|
if (model.unreadMentionDirect!!) {
|
||||||
|
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||||
|
} else {
|
||||||
|
viewThemeUtils.material.colorChipOutlined(
|
||||||
|
holder.binding.dialogUnreadBubble,
|
||||||
|
UNREAD_BUBBLE_STROKE_WIDTH
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
"file" -> {
|
|
||||||
shouldLoadAvatar = false
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
|
||||||
holder.binding.dialogAvatar,
|
|
||||||
R.drawable.ic_avatar_document
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_document)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else -> {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (ConversationType.ROOM_SYSTEM == model.type) {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
holder.binding.dialogAvatar.hierarchy.setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(layerDrawable)
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
holder.binding.dialogAvatar.hierarchy.setPlaceholderImage(R.mipmap.ic_launcher)
|
viewThemeUtils.material.colorChipBackground(holder.binding.dialogUnreadBubble)
|
||||||
}
|
|
||||||
shouldLoadAvatar = false
|
|
||||||
}
|
|
||||||
if (shouldLoadAvatar) {
|
|
||||||
when (model.type) {
|
|
||||||
ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(model.name)) {
|
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(holder.binding.dialogAvatar.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
model.name,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
user
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
holder.binding.dialogAvatar.controller = draweeController
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogAvatar.visibility = View.GONE
|
|
||||||
}
|
|
||||||
ConversationType.ROOM_GROUP_CALL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
|
||||||
holder.binding.dialogAvatar,
|
|
||||||
R.drawable.ic_avatar_group
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_group)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
ConversationType.ROOM_PUBLIC_CALL -> if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(
|
|
||||||
holder.binding.dialogAvatar,
|
|
||||||
R.drawable.ic_avatar_link
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
holder.binding.dialogAvatar.setImageDrawable(
|
|
||||||
ContextCompat.getDrawable(context, R.drawable.ic_circular_link)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
else -> holder.binding.dialogAvatar.visibility = View.GONE
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
holder.binding.dialogUnreadBubble.chipBackgroundColor = lightBubbleFillColor
|
||||||
|
holder.binding.dialogUnreadBubble.setTextColor(lightBubbleTextColor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -363,6 +341,9 @@ class ConversationItem(
|
|||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val VIEW_TYPE = R.layout.rv_item_conversation_with_last_message
|
const val VIEW_TYPE = R.layout.rv_item_conversation_with_last_message
|
||||||
|
private const val MILLIES = 1000L
|
||||||
private const val STATUS_SIZE_IN_DP = 9f
|
private const val STATUS_SIZE_IN_DP = 9f
|
||||||
|
private const val UNREAD_BUBBLE_STROKE_WIDTH = 6.0f
|
||||||
|
private const val UNREAD_MESSAGES_TRESHOLD = 1000
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -29,15 +29,13 @@ import android.content.Context;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.models.json.mention.Mention;
|
import com.nextcloud.talk.models.json.mention.Mention;
|
||||||
import com.nextcloud.talk.models.json.status.StatusType;
|
import com.nextcloud.talk.models.json.status.StatusType;
|
||||||
import com.nextcloud.talk.ui.StatusDrawable;
|
import com.nextcloud.talk.ui.StatusDrawable;
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
import com.nextcloud.talk.utils.DisplayUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -151,34 +149,22 @@ public class MentionAutocompleteItem extends AbstractFlexibleItem<ParticipantIte
|
|||||||
|
|
||||||
if (SOURCE_CALLS.equals(source)) {
|
if (SOURCE_CALLS.equals(source)) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
|
ImageViewExtensionsKt.loadAvatar(
|
||||||
DisplayUtils.getRoundedDrawable(
|
holder.binding.avatarView,
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
|
viewThemeUtils.talk.themePlaceholderAvatar(
|
||||||
R.drawable.ic_avatar_group)));
|
holder.binding.avatarView,
|
||||||
|
R.drawable.ic_avatar_group
|
||||||
|
)
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, R.drawable.ic_circular_group);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
String avatarId = objectId;
|
String avatarId = objectId;
|
||||||
String avatarUrl = ApiUtils.getUrlForAvatar(currentUser.getBaseUrl(),
|
|
||||||
avatarId, true);
|
|
||||||
|
|
||||||
if (SOURCE_GUESTS.equals(source)) {
|
if (SOURCE_GUESTS.equals(source)) {
|
||||||
avatarId = displayName;
|
avatarId = displayName;
|
||||||
avatarUrl = ApiUtils.getUrlForGuestAvatar(
|
|
||||||
currentUser.getBaseUrl(),
|
|
||||||
avatarId,
|
|
||||||
false);
|
|
||||||
}
|
}
|
||||||
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, currentUser, avatarId, true);
|
||||||
holder.binding.avatarDraweeView.setController(null);
|
|
||||||
|
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(holder.binding.avatarDraweeView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarUrl))
|
|
||||||
.build();
|
|
||||||
holder.binding.avatarDraweeView.setController(draweeController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
drawStatus(holder);
|
drawStatus(holder);
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* Nextcloud Talk application
|
* Nextcloud Talk application
|
||||||
*
|
*
|
||||||
* @author Álvaro Brey
|
* @author Álvaro Brey
|
||||||
|
* @author Tim Krüger
|
||||||
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2022 Álvaro Brey
|
* Copyright (C) 2022 Álvaro Brey
|
||||||
* Copyright (C) 2022 Nextcloud GmbH
|
* Copyright (C) 2022 Nextcloud GmbH
|
||||||
*
|
*
|
||||||
@ -27,9 +29,9 @@ import androidx.recyclerview.widget.RecyclerView
|
|||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.RvItemSearchMessageBinding
|
import com.nextcloud.talk.databinding.RvItemSearchMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadThumbnail
|
||||||
import com.nextcloud.talk.models.domain.SearchMessageEntry
|
import com.nextcloud.talk.models.domain.SearchMessageEntry
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
import eu.davidea.flexibleadapter.items.AbstractFlexibleItem
|
||||||
import eu.davidea.flexibleadapter.items.IFilterable
|
import eu.davidea.flexibleadapter.items.IFilterable
|
||||||
@ -72,7 +74,7 @@ data class MessageResultItem constructor(
|
|||||||
) {
|
) {
|
||||||
holder.binding.conversationTitle.text = messageEntry.title
|
holder.binding.conversationTitle.text = messageEntry.title
|
||||||
bindMessageExcerpt(holder)
|
bindMessageExcerpt(holder)
|
||||||
loadImage(holder)
|
messageEntry.thumbnailURL?.let { holder.binding.thumbnail.loadThumbnail(it, currentUser) }
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun bindMessageExcerpt(holder: ViewHolder) {
|
private fun bindMessageExcerpt(holder: ViewHolder) {
|
||||||
@ -83,17 +85,6 @@ data class MessageResultItem constructor(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadImage(holder: ViewHolder) {
|
|
||||||
DisplayUtils.loadAvatarPlaceholder(holder.binding.thumbnail)
|
|
||||||
if (messageEntry.thumbnailURL != null) {
|
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
|
||||||
messageEntry.thumbnailURL,
|
|
||||||
currentUser
|
|
||||||
)
|
|
||||||
DisplayUtils.loadImage(holder.binding.thumbnail, imageRequest)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun filter(constraint: String?): Boolean = true
|
override fun filter(constraint: String?): Boolean = true
|
||||||
|
|
||||||
override fun getItemViewType(): Int {
|
override fun getItemViewType(): Int {
|
||||||
|
@ -27,23 +27,20 @@ package com.nextcloud.talk.adapters.items;
|
|||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.res.Resources;
|
import android.content.res.Resources;
|
||||||
import android.os.Build;
|
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.databinding.RvItemConversationInfoParticipantBinding;
|
import com.nextcloud.talk.databinding.RvItemConversationInfoParticipantBinding;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
|
import com.nextcloud.talk.models.json.converters.EnumParticipantTypeConverter;
|
||||||
import com.nextcloud.talk.models.json.participants.Participant;
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
import com.nextcloud.talk.models.json.participants.Participant.InCallFlags;
|
import com.nextcloud.talk.models.json.participants.Participant.InCallFlags;
|
||||||
import com.nextcloud.talk.models.json.status.StatusType;
|
import com.nextcloud.talk.models.json.status.StatusType;
|
||||||
import com.nextcloud.talk.ui.StatusDrawable;
|
import com.nextcloud.talk.ui.StatusDrawable;
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||||
import com.nextcloud.talk.utils.ApiUtils;
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils;
|
import com.nextcloud.talk.utils.DisplayUtils;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -111,24 +108,22 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
|
|||||||
@Override
|
@Override
|
||||||
public void bindViewHolder(FlexibleAdapter adapter, ParticipantItemViewHolder holder, int position, List payloads) {
|
public void bindViewHolder(FlexibleAdapter adapter, ParticipantItemViewHolder holder, int position, List payloads) {
|
||||||
|
|
||||||
holder.binding.avatarDraweeView.setController(null);
|
|
||||||
|
|
||||||
drawStatus(holder);
|
drawStatus(holder);
|
||||||
|
|
||||||
if (!isOnline) {
|
if (!isOnline) {
|
||||||
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
||||||
holder.binding.nameText.getContext().getResources(),
|
holder.binding.nameText.getContext().getResources(),
|
||||||
R.color.medium_emphasis_text,
|
R.color.medium_emphasis_text,
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
holder.binding.avatarDraweeView.setAlpha(0.38f);
|
holder.binding.avatarView.setAlpha(0.38f);
|
||||||
} else {
|
} else {
|
||||||
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
holder.binding.nameText.setTextColor(ResourcesCompat.getColor(
|
||||||
holder.binding.nameText.getContext().getResources(),
|
holder.binding.nameText.getContext().getResources(),
|
||||||
R.color.high_emphasis_text,
|
R.color.high_emphasis_text,
|
||||||
null)
|
null)
|
||||||
);
|
);
|
||||||
holder.binding.avatarDraweeView.setAlpha(1.0f);
|
holder.binding.avatarView.setAlpha(1.0f);
|
||||||
}
|
}
|
||||||
|
|
||||||
holder.binding.nameText.setText(participant.getDisplayName());
|
holder.binding.nameText.setText(participant.getDisplayName());
|
||||||
@ -152,23 +147,9 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
|
|||||||
"groups".equals(participant.getSource()) ||
|
"groups".equals(participant.getSource()) ||
|
||||||
participant.getCalculatedActorType() == Participant.ActorType.CIRCLES ||
|
participant.getCalculatedActorType() == Participant.ActorType.CIRCLES ||
|
||||||
"circles".equals(participant.getSource())) {
|
"circles".equals(participant.getSource())) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
ImageViewExtensionsKt.loadGroupCallAvatar(holder.binding.avatarView, viewThemeUtils);
|
||||||
holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
|
|
||||||
R.drawable.ic_avatar_group)));
|
|
||||||
} else {
|
|
||||||
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_group);
|
|
||||||
}
|
|
||||||
} else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) {
|
} else if (participant.getCalculatedActorType() == Participant.ActorType.EMAILS) {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
ImageViewExtensionsKt.loadMailAvatar(holder.binding.avatarView, viewThemeUtils);
|
||||||
holder.binding.avatarDraweeView.getHierarchy().setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(holder.binding.avatarDraweeView,
|
|
||||||
R.drawable.ic_avatar_mail)));
|
|
||||||
} else {
|
|
||||||
holder.binding.avatarDraweeView.setImageResource(R.drawable.ic_circular_mail);
|
|
||||||
}
|
|
||||||
} else if (participant.getCalculatedActorType() == Participant.ActorType.GUESTS ||
|
} else if (participant.getCalculatedActorType() == Participant.ActorType.GUESTS ||
|
||||||
participant.getType() == Participant.ParticipantType.GUEST ||
|
participant.getType() == Participant.ParticipantType.GUEST ||
|
||||||
participant.getType() == Participant.ParticipantType.GUEST_MODERATOR) {
|
participant.getType() == Participant.ParticipantType.GUEST_MODERATOR) {
|
||||||
@ -180,25 +161,11 @@ public class ParticipantItem extends AbstractFlexibleItem<ParticipantItem.Partic
|
|||||||
displayName = participant.getDisplayName();
|
displayName = participant.getDisplayName();
|
||||||
}
|
}
|
||||||
|
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
ImageViewExtensionsKt.loadGuestAvatar(holder.binding.avatarView, user, displayName, false);
|
||||||
.setOldController(holder.binding.avatarDraweeView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForGuestAvatar(user.getBaseUrl(),
|
|
||||||
displayName, false)))
|
|
||||||
.build();
|
|
||||||
holder.binding.avatarDraweeView.setController(draweeController);
|
|
||||||
|
|
||||||
} else if (participant.getCalculatedActorType() == Participant.ActorType.USERS ||
|
} else if (participant.getCalculatedActorType() == Participant.ActorType.USERS ||
|
||||||
participant.getSource().equals("users")) {
|
participant.getSource().equals("users")) {
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
ImageViewExtensionsKt.loadAvatar(holder.binding.avatarView, user, participant.getCalculatedActorId(), true);
|
||||||
.setOldController(holder.binding.avatarDraweeView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(user.getBaseUrl(),
|
|
||||||
participant.getCalculatedActorId(), false)))
|
|
||||||
.build();
|
|
||||||
holder.binding.avatarDraweeView.setController(draweeController);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
|
Resources resources = NextcloudTalkApplication.Companion.getSharedApplication().getResources();
|
||||||
|
@ -24,25 +24,21 @@ package com.nextcloud.talk.adapters.messages
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingLinkPreviewMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomIncomingLinkPreviewMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadBotsAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -143,26 +139,9 @@ class IncomingLinkPreviewMessageViewHolder(incomingView: View, payload: Any) : M
|
|||||||
if (message.actorType == "guests") {
|
if (message.actorType == "guests") {
|
||||||
// do nothing, avatar is set
|
// do nothing, avatar is set
|
||||||
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
binding.messageUserAvatar.loadChangelogBotAvatar()
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
} else {
|
|
||||||
binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher)
|
|
||||||
}
|
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
binding.messageUserAvatar.loadBotsAvatar()
|
||||||
.beginConfig()
|
|
||||||
.bold()
|
|
||||||
.endConfig()
|
|
||||||
.buildRound(
|
|
||||||
">",
|
|
||||||
ResourcesCompat.getColor(context.resources, R.color.black, null)
|
|
||||||
)
|
|
||||||
binding.messageUserAvatar.visibility = View.VISIBLE
|
|
||||||
binding.messageUserAvatar.setImageDrawable(drawable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,8 +29,6 @@ package com.nextcloud.talk.adapters.messages
|
|||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
@ -40,18 +38,17 @@ import android.view.View
|
|||||||
import android.webkit.WebView
|
import android.webkit.WebView
|
||||||
import android.webkit.WebViewClient
|
import android.webkit.WebViewClient
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.content.res.AppCompatResources
|
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadBotsAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.UriUtils
|
import com.nextcloud.talk.utils.UriUtils
|
||||||
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
|
||||||
@ -136,22 +133,9 @@ class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : Mess
|
|||||||
if (message.actorType == "guests") {
|
if (message.actorType == "guests") {
|
||||||
// do nothing, avatar is set
|
// do nothing, avatar is set
|
||||||
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
binding.messageUserAvatar.loadChangelogBotAvatar()
|
||||||
layers[0] = AppCompatResources.getDrawable(context!!, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = AppCompatResources.getDrawable(context!!, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
binding.messageUserAvatar.loadBotsAvatar()
|
||||||
.beginConfig()
|
|
||||||
.bold()
|
|
||||||
.endConfig()
|
|
||||||
.buildRound(
|
|
||||||
">",
|
|
||||||
context!!.resources.getColor(R.color.black)
|
|
||||||
)
|
|
||||||
binding.messageUserAvatar.visibility = View.VISIBLE
|
|
||||||
binding.messageUserAvatar.setImageDrawable(drawable)
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (message.isOneToOneConversation) {
|
if (message.isOneToOneConversation) {
|
||||||
|
@ -22,27 +22,23 @@ package com.nextcloud.talk.adapters.messages
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingPollMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomIncomingPollMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadBotsAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.polls.ui.PollMainDialogFragment
|
import com.nextcloud.talk.polls.ui.PollMainDialogFragment
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
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 javax.inject.Inject
|
import javax.inject.Inject
|
||||||
@ -170,26 +166,9 @@ class IncomingPollMessageViewHolder(incomingView: View, payload: Any) : MessageH
|
|||||||
if (message.actorType == "guests") {
|
if (message.actorType == "guests") {
|
||||||
// do nothing, avatar is set
|
// do nothing, avatar is set
|
||||||
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
binding.messageUserAvatar.loadChangelogBotAvatar()
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
} else {
|
|
||||||
binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher)
|
|
||||||
}
|
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
binding.messageUserAvatar.loadBotsAvatar()
|
||||||
.beginConfig()
|
|
||||||
.bold()
|
|
||||||
.endConfig()
|
|
||||||
.buildRound(
|
|
||||||
">",
|
|
||||||
ResourcesCompat.getColor(context.resources, R.color.black, null)
|
|
||||||
)
|
|
||||||
binding.messageUserAvatar.visibility = View.VISIBLE
|
|
||||||
binding.messageUserAvatar.setImageDrawable(drawable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
*
|
*
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
* @author Tim Krüger
|
* @author Tim Krüger
|
||||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
* Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -23,9 +23,9 @@
|
|||||||
package com.nextcloud.talk.adapters.messages;
|
package com.nextcloud.talk.adapters.messages;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView;
|
|
||||||
import com.google.android.material.card.MaterialCardView;
|
import com.google.android.material.card.MaterialCardView;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingPreviewMessageBinding;
|
import com.nextcloud.talk.databinding.ItemCustomIncomingPreviewMessageBinding;
|
||||||
@ -74,7 +74,7 @@ public class IncomingPreviewMessageViewHolder extends PreviewMessageViewHolder {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleDraweeView getPreviewContactPhoto() {
|
public ImageView getPreviewContactPhoto() {
|
||||||
return binding.contactPhoto;
|
return binding.contactPhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,24 +26,21 @@ package com.nextcloud.talk.adapters.messages
|
|||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
|
||||||
import android.text.Spannable
|
import android.text.Spannable
|
||||||
import android.text.SpannableString
|
import android.text.SpannableString
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.TypedValue
|
import android.util.TypedValue
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import coil.load
|
import coil.load
|
||||||
import com.amulyakhare.textdrawable.TextDrawable
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadBotsAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
@ -179,28 +176,9 @@ class IncomingTextMessageViewHolder(itemView: View, payload: Any) : MessageHolde
|
|||||||
if (message.actorType == "guests") {
|
if (message.actorType == "guests") {
|
||||||
// do nothing, avatar is set
|
// do nothing, avatar is set
|
||||||
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
if (context != null) {
|
binding.messageUserAvatar.loadChangelogBotAvatar()
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
} else {
|
|
||||||
binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
binding.messageUserAvatar.loadBotsAvatar()
|
||||||
.beginConfig()
|
|
||||||
.bold()
|
|
||||||
.endConfig()
|
|
||||||
.buildRound(
|
|
||||||
">",
|
|
||||||
ResourcesCompat.getColor(context!!.resources, R.color.black, null)
|
|
||||||
)
|
|
||||||
binding.messageUserAvatar.visibility = View.VISIBLE
|
|
||||||
binding.messageUserAvatar.setImageDrawable(drawable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,9 +28,6 @@ package com.nextcloud.talk.adapters.messages
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
@ -46,10 +43,10 @@ import com.nextcloud.talk.R
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.databinding.ItemCustomIncomingVoiceMessageBinding
|
import com.nextcloud.talk.databinding.ItemCustomIncomingVoiceMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
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 java.util.concurrent.ExecutionException
|
import java.util.concurrent.ExecutionException
|
||||||
@ -245,15 +242,7 @@ class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : Message
|
|||||||
if (message.actorType == "guests") {
|
if (message.actorType == "guests") {
|
||||||
// do nothing, avatar is set
|
// do nothing, avatar is set
|
||||||
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
} else if (message.actorType == "bots" && message.actorId == "changelog") {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
binding.messageUserAvatar.loadChangelogBotAvatar()
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.messageUserAvatar.setImageDrawable(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
} else {
|
|
||||||
binding.messageUserAvatar.setImageResource(R.mipmap.ic_launcher)
|
|
||||||
}
|
|
||||||
} else if (message.actorType == "bots") {
|
} else if (message.actorType == "bots") {
|
||||||
val drawable = TextDrawable.builder()
|
val drawable = TextDrawable.builder()
|
||||||
.beginConfig()
|
.beginConfig()
|
||||||
|
@ -25,14 +25,12 @@ import android.content.Intent
|
|||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
import coil.load
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.nextcloud.talk.api.NcApi
|
import com.nextcloud.talk.api.NcApi
|
||||||
import com.nextcloud.talk.databinding.ReferenceInsideMessageBinding
|
import com.nextcloud.talk.databinding.ReferenceInsideMessageBinding
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.models.json.opengraph.OpenGraphOverall
|
import com.nextcloud.talk.models.json.opengraph.OpenGraphOverall
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import io.reactivex.Observer
|
import io.reactivex.Observer
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
@ -92,12 +90,7 @@ class LinkPreview {
|
|||||||
val referenceThumbUrl = reference.openGraphObject?.thumb
|
val referenceThumbUrl = reference.openGraphObject?.thumb
|
||||||
if (!referenceThumbUrl.isNullOrEmpty()) {
|
if (!referenceThumbUrl.isNullOrEmpty()) {
|
||||||
binding.referenceThumbImage.visibility = View.VISIBLE
|
binding.referenceThumbImage.visibility = View.VISIBLE
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
binding.referenceThumbImage.load(referenceThumbUrl)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(referenceThumbUrl))
|
|
||||||
.build()
|
|
||||||
binding.referenceThumbImage.controller =
|
|
||||||
draweeController
|
|
||||||
} else {
|
} else {
|
||||||
binding.referenceThumbImage.visibility = View.GONE
|
binding.referenceThumbImage.visibility = View.GONE
|
||||||
}
|
}
|
||||||
|
@ -23,9 +23,9 @@
|
|||||||
package com.nextcloud.talk.adapters.messages;
|
package com.nextcloud.talk.adapters.messages;
|
||||||
|
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.ProgressBar;
|
import android.widget.ProgressBar;
|
||||||
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView;
|
|
||||||
import com.google.android.material.card.MaterialCardView;
|
import com.google.android.material.card.MaterialCardView;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.databinding.ItemCustomOutcomingPreviewMessageBinding;
|
import com.nextcloud.talk.databinding.ItemCustomOutcomingPreviewMessageBinding;
|
||||||
@ -75,7 +75,7 @@ public class OutcomingPreviewMessageViewHolder extends PreviewMessageViewHolder
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public SimpleDraweeView getPreviewContactPhoto() {
|
public ImageView getPreviewContactPhoto() {
|
||||||
return binding.contactPhoto;
|
return binding.contactPhoto;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @author Marcel Hibbe
|
* @author Marcel Hibbe
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
* @author Tim Krüger
|
* @author Tim Krüger
|
||||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
* Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
@ -30,7 +30,6 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.PorterDuff
|
import android.graphics.PorterDuff
|
||||||
import android.graphics.drawable.Drawable
|
import android.graphics.drawable.Drawable
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Handler
|
import android.os.Handler
|
||||||
import android.util.Base64
|
import android.util.Base64
|
||||||
@ -38,13 +37,13 @@ import android.util.Log
|
|||||||
import android.view.Gravity
|
import android.view.Gravity
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.PopupMenu
|
import android.widget.PopupMenu
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import androidx.appcompat.view.ContextThemeWrapper
|
import androidx.appcompat.view.ContextThemeWrapper
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.emoji.widget.EmojiTextView
|
import androidx.emoji.widget.EmojiTextView
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.google.android.material.card.MaterialCardView
|
import com.google.android.material.card.MaterialCardView
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
@ -53,6 +52,7 @@ import com.nextcloud.talk.components.filebrowser.models.BrowserFile
|
|||||||
import com.nextcloud.talk.components.filebrowser.webdav.ReadFilesystemOperation
|
import com.nextcloud.talk.components.filebrowser.webdav.ReadFilesystemOperation
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
|
import com.nextcloud.talk.databinding.ReactionsInsideMessageBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadChangelogBotAvatar
|
||||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||||
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
@ -92,6 +92,8 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
lateinit var commonMessageInterface: CommonMessageInterface
|
lateinit var commonMessageInterface: CommonMessageInterface
|
||||||
var previewMessageInterface: PreviewMessageInterface? = null
|
var previewMessageInterface: PreviewMessageInterface? = null
|
||||||
|
|
||||||
|
private var placeholder: Drawable? = null
|
||||||
|
|
||||||
init {
|
init {
|
||||||
sharedApplication!!.componentApplication.inject(this)
|
sharedApplication!!.componentApplication.inject(this)
|
||||||
}
|
}
|
||||||
@ -118,13 +120,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ACTOR_TYPE_BOTS == message.actorType && ACTOR_ID_CHANGELOG == message.actorId) {
|
if (ACTOR_TYPE_BOTS == message.actorType && ACTOR_ID_CHANGELOG == message.actorId) {
|
||||||
if (context != null) {
|
userAvatar.loadChangelogBotAvatar()
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
|
||||||
layers[0] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context!!, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
userAvatar.hierarchy.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -150,11 +146,10 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
}
|
}
|
||||||
if (message.selectedIndividualHashMap!!.containsKey(KEY_CONTACT_PHOTO)) {
|
if (message.selectedIndividualHashMap!!.containsKey(KEY_CONTACT_PHOTO)) {
|
||||||
image = previewContactPhoto
|
image = previewContactPhoto
|
||||||
val drawable = getDrawableFromContactDetails(
|
placeholder = getDrawableFromContactDetails(
|
||||||
context,
|
context,
|
||||||
message.selectedIndividualHashMap!![KEY_CONTACT_PHOTO]
|
message.selectedIndividualHashMap!![KEY_CONTACT_PHOTO]
|
||||||
)
|
)
|
||||||
image.hierarchy.setPlaceholderImage(drawable)
|
|
||||||
} else if (message.selectedIndividualHashMap!!.containsKey(KEY_MIMETYPE)) {
|
} else if (message.selectedIndividualHashMap!!.containsKey(KEY_MIMETYPE)) {
|
||||||
val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE]
|
val mimetype = message.selectedIndividualHashMap!![KEY_MIMETYPE]
|
||||||
val drawableResourceId = getDrawableResourceIdForMimeType(mimetype)
|
val drawableResourceId = getDrawableResourceIdForMimeType(mimetype)
|
||||||
@ -170,7 +165,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
PorterDuff.Mode.SRC_ATOP
|
PorterDuff.Mode.SRC_ATOP
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
image.hierarchy.setPlaceholderImage(drawable)
|
placeholder = drawable
|
||||||
} else {
|
} else {
|
||||||
fetchFileInformation(
|
fetchFileInformation(
|
||||||
"/" + message.selectedIndividualHashMap!![KEY_PATH],
|
"/" + message.selectedIndividualHashMap!![KEY_PATH],
|
||||||
@ -208,13 +203,13 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
DisplayUtils.setClickableString("Tenor", "https://tenor.com", messageText)
|
DisplayUtils.setClickableString("Tenor", "https://tenor.com", messageText)
|
||||||
} else {
|
} else {
|
||||||
if (message.messageType == ChatMessage.MessageType.SINGLE_LINK_IMAGE_MESSAGE.name) {
|
if (message.messageType == ChatMessage.MessageType.SINGLE_LINK_IMAGE_MESSAGE.name) {
|
||||||
(clickView as SimpleDraweeView?)?.setOnClickListener {
|
clickView!!.setOnClickListener {
|
||||||
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(message.imageUrl))
|
val browserIntent = Intent(Intent.ACTION_VIEW, Uri.parse(message.imageUrl))
|
||||||
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
browserIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
context!!.startActivity(browserIntent)
|
context!!.startActivity(browserIntent)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
(clickView as SimpleDraweeView?)?.setOnClickListener(null)
|
clickView!!.setOnClickListener(null)
|
||||||
}
|
}
|
||||||
messageText.text = ""
|
messageText.text = ""
|
||||||
}
|
}
|
||||||
@ -238,6 +233,10 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
commonMessageInterface.onClickReaction(chatMessage, emoji)
|
commonMessageInterface.onClickReaction(chatMessage, emoji)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun getPayloadForImageLoader(message: ChatMessage?): Any? {
|
||||||
|
return placeholder
|
||||||
|
}
|
||||||
|
|
||||||
private fun getDrawableFromContactDetails(context: Context?, base64: String?): Drawable? {
|
private fun getDrawableFromContactDetails(context: Context?, base64: String?): Drawable? {
|
||||||
var drawable: Drawable? = null
|
var drawable: Drawable? = null
|
||||||
if (base64 != "") {
|
if (base64 != "") {
|
||||||
@ -300,8 +299,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
if (browserFileList.isNotEmpty()) {
|
if (browserFileList.isNotEmpty()) {
|
||||||
Handler(context!!.mainLooper).post {
|
Handler(context!!.mainLooper).post {
|
||||||
val resourceId = getDrawableResourceIdForMimeType(browserFileList[0].mimeType)
|
val resourceId = getDrawableResourceIdForMimeType(browserFileList[0].mimeType)
|
||||||
val drawable = ContextCompat.getDrawable(context!!, resourceId)
|
placeholder = ContextCompat.getDrawable(context!!, resourceId)
|
||||||
image.hierarchy.setPlaceholderImage(drawable)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -324,7 +322,7 @@ abstract class PreviewMessageViewHolder(itemView: View?, payload: Any?) :
|
|||||||
abstract val messageText: EmojiTextView
|
abstract val messageText: EmojiTextView
|
||||||
abstract val previewContainer: View
|
abstract val previewContainer: View
|
||||||
abstract val previewContactContainer: MaterialCardView
|
abstract val previewContactContainer: MaterialCardView
|
||||||
abstract val previewContactPhoto: SimpleDraweeView
|
abstract val previewContactPhoto: ImageView
|
||||||
abstract val previewContactName: EmojiTextView
|
abstract val previewContactName: EmojiTextView
|
||||||
abstract val previewContactProgressBar: ProgressBar?
|
abstract val previewContactProgressBar: ProgressBar?
|
||||||
|
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
* @author Marcel Hibbe
|
* @author Marcel Hibbe
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
|
* @author Tim Krüger
|
||||||
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2022 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017 Mario Danic <mario@lovelyhq.com>
|
||||||
@ -46,9 +48,7 @@ import coil.decode.GifDecoder
|
|||||||
import coil.decode.ImageDecoderDecoder
|
import coil.decode.ImageDecoderDecoder
|
||||||
import coil.decode.SvgDecoder
|
import coil.decode.SvgDecoder
|
||||||
import coil.memory.MemoryCache
|
import coil.memory.MemoryCache
|
||||||
import com.facebook.cache.disk.DiskCacheConfig
|
import coil.util.DebugLogger
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.core.ImagePipelineConfig
|
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.components.filebrowser.webdav.DavUtils
|
import com.nextcloud.talk.components.filebrowser.webdav.DavUtils
|
||||||
import com.nextcloud.talk.dagger.modules.BusModule
|
import com.nextcloud.talk.dagger.modules.BusModule
|
||||||
@ -66,7 +66,6 @@ import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
|||||||
import com.nextcloud.talk.utils.DeviceUtils
|
import com.nextcloud.talk.utils.DeviceUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
import com.nextcloud.talk.utils.DisplayUtils
|
||||||
import com.nextcloud.talk.utils.NotificationUtils
|
import com.nextcloud.talk.utils.NotificationUtils
|
||||||
import com.nextcloud.talk.utils.OkHttpNetworkFetcherWithCache
|
|
||||||
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
|
import com.nextcloud.talk.utils.database.arbitrarystorage.ArbitraryStorageModule
|
||||||
import com.nextcloud.talk.utils.database.user.UserModule
|
import com.nextcloud.talk.utils.database.user.UserModule
|
||||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||||
@ -174,18 +173,6 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
setAppTheme(appPreferences.theme)
|
setAppTheme(appPreferences.theme)
|
||||||
super.onCreate()
|
super.onCreate()
|
||||||
|
|
||||||
val imagePipelineConfig = ImagePipelineConfig.newBuilder(this)
|
|
||||||
.setNetworkFetcher(OkHttpNetworkFetcherWithCache(okHttpClient))
|
|
||||||
.setMainDiskCacheConfig(
|
|
||||||
DiskCacheConfig.newBuilder(this)
|
|
||||||
.setMaxCacheSize(0)
|
|
||||||
.setMaxCacheSizeOnLowDiskSpace(0)
|
|
||||||
.setMaxCacheSizeOnVeryLowDiskSpace(0)
|
|
||||||
.build()
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
Fresco.initialize(this, imagePipelineConfig)
|
|
||||||
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
Security.insertProviderAt(Conscrypt.newProvider(), 1)
|
||||||
|
|
||||||
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
|
ClosedInterfaceImpl().providerInstallerInstallIfNeededAsync()
|
||||||
@ -240,7 +227,7 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun buildDefaultImageLoader(): ImageLoader {
|
private fun buildDefaultImageLoader(): ImageLoader {
|
||||||
return ImageLoader.Builder(applicationContext)
|
val imageLoaderBuilder = ImageLoader.Builder(applicationContext)
|
||||||
.memoryCache {
|
.memoryCache {
|
||||||
// Use 50% of the application's available memory.
|
// Use 50% of the application's available memory.
|
||||||
MemoryCache.Builder(applicationContext).maxSizePercent(FIFTY_PERCENT).build()
|
MemoryCache.Builder(applicationContext).maxSizePercent(FIFTY_PERCENT).build()
|
||||||
@ -254,8 +241,12 @@ class NextcloudTalkApplication : MultiDexApplication(), LifecycleObserver {
|
|||||||
}
|
}
|
||||||
add(SvgDecoder.Factory())
|
add(SvgDecoder.Factory())
|
||||||
}
|
}
|
||||||
.okHttpClient(okHttpClient)
|
|
||||||
.build()
|
if (BuildConfig.DEBUG) {
|
||||||
|
imageLoaderBuilder.logger(DebugLogger())
|
||||||
|
}
|
||||||
|
|
||||||
|
return imageLoaderBuilder.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -27,7 +27,7 @@ import android.text.Editable;
|
|||||||
import android.text.Spanned;
|
import android.text.Spanned;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
|
||||||
import com.facebook.widget.text.span.BetterImageSpan;
|
import third.parties.fresco.BetterImageSpan;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.models.json.mention.Mention;
|
import com.nextcloud.talk.models.json.mention.Mention;
|
||||||
|
@ -5,7 +5,7 @@
|
|||||||
* @author Marcel Hibbe
|
* @author Marcel Hibbe
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
* @author Tim Krüger
|
* @author Tim Krüger
|
||||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
* Copyright (C) 2021-2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
* Copyright (C) 2021-2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||||
@ -37,8 +37,9 @@ import android.content.pm.PackageManager
|
|||||||
import android.content.res.AssetFileDescriptor
|
import android.content.res.AssetFileDescriptor
|
||||||
import android.content.res.Resources
|
import android.content.res.Resources
|
||||||
import android.database.Cursor
|
import android.database.Cursor
|
||||||
import android.graphics.Bitmap
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.graphics.drawable.ColorDrawable
|
import android.graphics.drawable.ColorDrawable
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
import android.media.MediaPlayer
|
import android.media.MediaPlayer
|
||||||
import android.media.MediaRecorder
|
import android.media.MediaRecorder
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
@ -78,7 +79,7 @@ import androidx.appcompat.view.ContextThemeWrapper
|
|||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
import androidx.core.content.PermissionChecker
|
import androidx.core.content.PermissionChecker
|
||||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
import androidx.core.graphics.drawable.toBitmap
|
||||||
import androidx.core.widget.doAfterTextChanged
|
import androidx.core.widget.doAfterTextChanged
|
||||||
import androidx.emoji.text.EmojiCompat
|
import androidx.emoji.text.EmojiCompat
|
||||||
import androidx.emoji.widget.EmojiTextView
|
import androidx.emoji.widget.EmojiTextView
|
||||||
@ -90,15 +91,13 @@ import androidx.work.OneTimeWorkRequest
|
|||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
|
import coil.imageLoader
|
||||||
import coil.load
|
import coil.load
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.target.Target
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
|
||||||
import com.facebook.common.references.CloseableReference
|
|
||||||
import com.facebook.datasource.DataSource
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage
|
|
||||||
import com.google.android.flexbox.FlexboxLayout
|
import com.google.android.flexbox.FlexboxLayout
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
@ -134,6 +133,7 @@ import com.nextcloud.talk.data.user.model.User
|
|||||||
import com.nextcloud.talk.databinding.ControllerChatBinding
|
import com.nextcloud.talk.databinding.ControllerChatBinding
|
||||||
import com.nextcloud.talk.events.UserMentionClickEvent
|
import com.nextcloud.talk.events.UserMentionClickEvent
|
||||||
import com.nextcloud.talk.events.WebSocketCommunicationEvent
|
import com.nextcloud.talk.events.WebSocketCommunicationEvent
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatarOrImagePreview
|
||||||
import com.nextcloud.talk.jobs.DownloadFileToCacheWorker
|
import com.nextcloud.talk.jobs.DownloadFileToCacheWorker
|
||||||
import com.nextcloud.talk.jobs.ShareOperationWorker
|
import com.nextcloud.talk.jobs.ShareOperationWorker
|
||||||
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
|
import com.nextcloud.talk.jobs.UploadAndShareFilesWorker
|
||||||
@ -165,7 +165,6 @@ import com.nextcloud.talk.utils.ConductorRemapping
|
|||||||
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
||||||
import com.nextcloud.talk.utils.ContactUtils
|
import com.nextcloud.talk.utils.ContactUtils
|
||||||
import com.nextcloud.talk.utils.DateUtils
|
import com.nextcloud.talk.utils.DateUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.FileUtils
|
import com.nextcloud.talk.utils.FileUtils
|
||||||
import com.nextcloud.talk.utils.ImageEmojiEditText
|
import com.nextcloud.talk.utils.ImageEmojiEditText
|
||||||
import com.nextcloud.talk.utils.MagicCharPolicy
|
import com.nextcloud.talk.utils.MagicCharPolicy
|
||||||
@ -462,42 +461,48 @@ class ChatController(args: Bundle) :
|
|||||||
|
|
||||||
private fun loadAvatarForStatusBar() {
|
private fun loadAvatarForStatusBar() {
|
||||||
if (isOneToOneConversation() && activity != null) {
|
if (isOneToOneConversation() && activity != null) {
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
val url = ApiUtils.getUrlForAvatar(
|
||||||
conversationUser?.baseUrl,
|
conversationUser!!.baseUrl,
|
||||||
currentConversation?.name,
|
currentConversation!!.name,
|
||||||
true
|
true
|
||||||
),
|
|
||||||
conversationUser!!
|
|
||||||
)
|
)
|
||||||
|
val target = object : Target {
|
||||||
|
|
||||||
val imagePipeline = Fresco.getImagePipeline()
|
private fun setIcon(drawable: Drawable?) {
|
||||||
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
|
|
||||||
|
|
||||||
dataSource.subscribe(
|
actionBar?.let {
|
||||||
object : BaseBitmapDataSubscriber() {
|
val avatarSize = (it.height / TOOLBAR_AVATAR_RATIO).roundToInt()
|
||||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
||||||
if (actionBar != null && bitmap != null && resources != null) {
|
|
||||||
val avatarSize = (actionBar?.height!! / TOOLBAR_AVATAR_RATIO).roundToInt()
|
|
||||||
if (avatarSize > 0) {
|
|
||||||
val bitmapResized = Bitmap.createScaledBitmap(bitmap, avatarSize, avatarSize, false)
|
|
||||||
|
|
||||||
val roundedBitmapDrawable =
|
if (drawable != null && avatarSize > 0) {
|
||||||
RoundedBitmapDrawableFactory.create(resources!!, bitmapResized)
|
val bitmap = drawable.toBitmap(avatarSize, avatarSize)
|
||||||
roundedBitmapDrawable.isCircular = true
|
it.setIcon(BitmapDrawable(resources, bitmap))
|
||||||
roundedBitmapDrawable.setAntiAlias(true)
|
} else {
|
||||||
actionBar?.setIcon(roundedBitmapDrawable)
|
Log.d(TAG, "loadAvatarForStatusBar avatarSize <= 0")
|
||||||
} else {
|
|
||||||
Log.d(TAG, "loadAvatarForStatusBar avatarSize <= 0")
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage>>) {
|
override fun onStart(placeholder: Drawable?) {
|
||||||
// unused atm
|
this.setIcon(placeholder)
|
||||||
}
|
}
|
||||||
},
|
|
||||||
UiThreadImmediateExecutorService.getInstance()
|
override fun onSuccess(result: Drawable) {
|
||||||
|
this.setIcon(result)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val credentials = ApiUtils.getCredentials(conversationUser.username, conversationUser.token)
|
||||||
|
|
||||||
|
context.imageLoader.enqueue(
|
||||||
|
ImageRequest.Builder(context)
|
||||||
|
.data(url)
|
||||||
|
.addHeader("Authorization", credentials)
|
||||||
|
.placeholder(R.drawable.ic_user)
|
||||||
|
.transformations(CircleCropTransformation())
|
||||||
|
.crossfade(true)
|
||||||
|
.target(target)
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -617,14 +622,8 @@ class ChatController(args: Bundle) :
|
|||||||
adapter = TalkMessagesListAdapter(
|
adapter = TalkMessagesListAdapter(
|
||||||
senderId,
|
senderId,
|
||||||
messageHolders,
|
messageHolders,
|
||||||
ImageLoader { imageView, url, payload ->
|
ImageLoader { imageView, url, _ ->
|
||||||
val draweeController = Fresco.newDraweeControllerBuilder()
|
imageView.loadAvatarOrImagePreview(url!!, conversationUser, placeholder = payload as? Drawable)
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(url, conversationUser))
|
|
||||||
.setControllerListener(DisplayUtils.getImageControllerListener(imageView))
|
|
||||||
.setOldController(imageView.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.build()
|
|
||||||
imageView.controller = draweeController
|
|
||||||
},
|
},
|
||||||
this
|
this
|
||||||
)
|
)
|
||||||
|
@ -28,9 +28,6 @@ package com.nextcloud.talk.controllers
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.graphics.drawable.Drawable
|
|
||||||
import android.graphics.drawable.LayerDrawable
|
|
||||||
import android.os.Build
|
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.os.Parcelable
|
import android.os.Parcelable
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
@ -42,7 +39,6 @@ import android.view.View.VISIBLE
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.SwitchCompat
|
import androidx.appcompat.widget.SwitchCompat
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.work.Data
|
import androidx.work.Data
|
||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
@ -53,7 +49,6 @@ import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
|||||||
import com.afollestad.materialdialogs.datetime.dateTimePicker
|
import com.afollestad.materialdialogs.datetime.dateTimePicker
|
||||||
import com.bluelinelabs.conductor.RouterTransaction
|
import com.bluelinelabs.conductor.RouterTransaction
|
||||||
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.HorizontalChangeHandler
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.adapters.items.ParticipantItem
|
import com.nextcloud.talk.adapters.items.ParticipantItem
|
||||||
@ -67,6 +62,10 @@ import com.nextcloud.talk.conversation.info.GuestAccessHelper
|
|||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.ControllerConversationInfoBinding
|
import com.nextcloud.talk.databinding.ControllerConversationInfoBinding
|
||||||
import com.nextcloud.talk.events.EventStatus
|
import com.nextcloud.talk.events.EventStatus
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadSystemAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadGroupCallAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadPublicCallAvatar
|
||||||
import com.nextcloud.talk.jobs.DeleteConversationWorker
|
import com.nextcloud.talk.jobs.DeleteConversationWorker
|
||||||
import com.nextcloud.talk.jobs.LeaveConversationWorker
|
import com.nextcloud.talk.jobs.LeaveConversationWorker
|
||||||
import com.nextcloud.talk.models.json.conversations.Conversation
|
import com.nextcloud.talk.models.json.conversations.Conversation
|
||||||
@ -83,7 +82,6 @@ import com.nextcloud.talk.shareditems.activities.SharedItemsActivity
|
|||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DateConstants
|
import com.nextcloud.talk.utils.DateConstants
|
||||||
import com.nextcloud.talk.utils.DateUtils
|
import com.nextcloud.talk.utils.DateUtils
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||||
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
import com.nextcloud.talk.utils.database.user.CapabilitiesUtilNew
|
||||||
import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
|
import com.nextcloud.talk.utils.preferences.preferencestorage.DatabaseStorageModule
|
||||||
@ -778,54 +776,16 @@ class ConversationInfoController(args: Bundle) :
|
|||||||
private fun loadConversationAvatar() {
|
private fun loadConversationAvatar() {
|
||||||
when (conversation!!.type) {
|
when (conversation!!.type) {
|
||||||
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) {
|
Conversation.ConversationType.ROOM_TYPE_ONE_TO_ONE_CALL -> if (!TextUtils.isEmpty(conversation!!.name)) {
|
||||||
val draweeController = Fresco.newDraweeControllerBuilder()
|
conversation!!.name?.let { binding.avatarImage.loadAvatar(conversationUser!!, it) }
|
||||||
.setOldController(binding.avatarImage.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
conversationUser!!.baseUrl,
|
|
||||||
conversation!!.name,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
conversationUser
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
binding.avatarImage.controller = draweeController
|
|
||||||
}
|
}
|
||||||
Conversation.ConversationType.ROOM_GROUP_CALL -> {
|
Conversation.ConversationType.ROOM_GROUP_CALL -> {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
binding.avatarImage.loadGroupCallAvatar(viewThemeUtils)
|
||||||
binding.avatarImage.hierarchy.setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_group)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
binding.avatarImage.hierarchy.setPlaceholderImage(
|
|
||||||
R.drawable.ic_circular_group
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Conversation.ConversationType.ROOM_PUBLIC_CALL -> {
|
Conversation.ConversationType.ROOM_PUBLIC_CALL -> {
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
binding.avatarImage.loadPublicCallAvatar(viewThemeUtils)
|
||||||
binding.avatarImage.hierarchy.setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(
|
|
||||||
viewThemeUtils.talk.themePlaceholderAvatar(binding.avatarImage, R.drawable.ic_avatar_link)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
} else {
|
|
||||||
binding.avatarImage.hierarchy.setPlaceholderImage(
|
|
||||||
R.drawable.ic_circular_link
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
Conversation.ConversationType.ROOM_SYSTEM -> {
|
Conversation.ConversationType.ROOM_SYSTEM -> {
|
||||||
val layers = arrayOfNulls<Drawable>(2)
|
binding.avatarImage.loadSystemAvatar()
|
||||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
|
||||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
|
||||||
val layerDrawable = LayerDrawable(layers)
|
|
||||||
binding.avatarImage.hierarchy.setPlaceholderImage(DisplayUtils.getRoundedDrawable(layerDrawable))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
|
@ -31,7 +31,7 @@ import android.app.SearchManager
|
|||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Bitmap
|
import android.graphics.drawable.Drawable
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
@ -49,8 +49,6 @@ import android.view.inputmethod.InputMethodManager
|
|||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.appcompat.app.AlertDialog
|
import androidx.appcompat.app.AlertDialog
|
||||||
import androidx.appcompat.widget.SearchView
|
import androidx.appcompat.widget.SearchView
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import androidx.core.graphics.drawable.RoundedBitmapDrawableFactory
|
|
||||||
import androidx.core.view.MenuItemCompat
|
import androidx.core.view.MenuItemCompat
|
||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
@ -58,15 +56,13 @@ import androidx.work.Data
|
|||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
|
import coil.imageLoader
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.target.Target
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
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.conductor.changehandler.VerticalChangeHandler
|
import com.bluelinelabs.conductor.changehandler.VerticalChangeHandler
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService
|
|
||||||
import com.facebook.common.references.CloseableReference
|
|
||||||
import com.facebook.datasource.DataSource
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage
|
|
||||||
import com.google.android.material.button.MaterialButton
|
import com.google.android.material.button.MaterialButton
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
@ -104,7 +100,6 @@ import com.nextcloud.talk.users.UserManager
|
|||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
import com.nextcloud.talk.utils.ClosedInterfaceImpl
|
||||||
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
import com.nextcloud.talk.utils.ConductorRemapping.remapChatController
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.FileUtils
|
import com.nextcloud.talk.utils.FileUtils
|
||||||
import com.nextcloud.talk.utils.Mimetype
|
import com.nextcloud.talk.utils.Mimetype
|
||||||
import com.nextcloud.talk.utils.ParticipantPermissions
|
import com.nextcloud.talk.utils.ParticipantPermissions
|
||||||
@ -211,78 +206,56 @@ class ConversationsListController(bundle: Bundle) :
|
|||||||
prepareViews()
|
prepareViews()
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadUserAvatar(button: MaterialButton) {
|
private fun loadUserAvatar(
|
||||||
if (activity != null) {
|
target: Target
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
) {
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
currentUser!!.baseUrl,
|
|
||||||
currentUser!!.userId,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
currentUser
|
|
||||||
)
|
|
||||||
val imagePipeline = Fresco.getImagePipeline()
|
|
||||||
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
|
|
||||||
dataSource.subscribe(
|
|
||||||
object : BaseBitmapDataSubscriber() {
|
|
||||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
||||||
if (bitmap != null && resources != null) {
|
|
||||||
val roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
|
|
||||||
resources!!,
|
|
||||||
bitmap
|
|
||||||
)
|
|
||||||
roundedBitmapDrawable.isCircular = true
|
|
||||||
roundedBitmapDrawable.setAntiAlias(true)
|
|
||||||
button.icon = roundedBitmapDrawable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage?>>) {
|
if (activity != null) {
|
||||||
if (resources != null) {
|
val url = ApiUtils.getUrlForAvatar(
|
||||||
button.icon = ResourcesCompat.getDrawable(resources!!, R.drawable.ic_user, null)
|
currentUser!!.baseUrl,
|
||||||
}
|
currentUser!!.userId,
|
||||||
}
|
true
|
||||||
},
|
)
|
||||||
UiThreadImmediateExecutorService.getInstance()
|
|
||||||
|
val credentials = ApiUtils.getCredentials(currentUser!!.username, currentUser!!.token)
|
||||||
|
|
||||||
|
context.imageLoader.enqueue(
|
||||||
|
ImageRequest.Builder(context)
|
||||||
|
.data(url)
|
||||||
|
.addHeader("Authorization", credentials)
|
||||||
|
.placeholder(R.drawable.ic_user)
|
||||||
|
.transformations(CircleCropTransformation())
|
||||||
|
.crossfade(true)
|
||||||
|
.target(target)
|
||||||
|
.build()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun loadUserAvatar(menuItem: MenuItem) {
|
private fun loadUserAvatar(button: MaterialButton) {
|
||||||
if (activity != null) {
|
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
currentUser!!.baseUrl,
|
|
||||||
currentUser!!.userId,
|
|
||||||
true
|
|
||||||
),
|
|
||||||
currentUser
|
|
||||||
)
|
|
||||||
val imagePipeline = Fresco.getImagePipeline()
|
|
||||||
val dataSource = imagePipeline.fetchDecodedImage(imageRequest, null)
|
|
||||||
dataSource.subscribe(
|
|
||||||
object : BaseBitmapDataSubscriber() {
|
|
||||||
override fun onNewResultImpl(bitmap: Bitmap?) {
|
|
||||||
if (bitmap != null && resources != null) {
|
|
||||||
val roundedBitmapDrawable = RoundedBitmapDrawableFactory.create(
|
|
||||||
resources!!,
|
|
||||||
bitmap
|
|
||||||
)
|
|
||||||
roundedBitmapDrawable.isCircular = true
|
|
||||||
roundedBitmapDrawable.setAntiAlias(true)
|
|
||||||
menuItem.icon = roundedBitmapDrawable
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun onFailureImpl(dataSource: DataSource<CloseableReference<CloseableImage?>>) {
|
val target = object : Target {
|
||||||
if (resources != null) {
|
override fun onStart(placeholder: Drawable?) {
|
||||||
menuItem.icon = ResourcesCompat.getDrawable(resources!!, R.drawable.ic_user, null)
|
button.icon = placeholder
|
||||||
}
|
}
|
||||||
}
|
override fun onSuccess(result: Drawable) {
|
||||||
},
|
button.icon = result
|
||||||
UiThreadImmediateExecutorService.getInstance()
|
}
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
loadUserAvatar(target)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun loadUserAvatar(menuItem: MenuItem) {
|
||||||
|
val target = object : Target {
|
||||||
|
override fun onStart(placeholder: Drawable?) {
|
||||||
|
menuItem.icon = placeholder
|
||||||
|
}
|
||||||
|
override fun onSuccess(result: Drawable) {
|
||||||
|
menuItem.icon = result
|
||||||
|
}
|
||||||
|
}
|
||||||
|
loadUserAvatar(target)
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun onAttach(view: View) {
|
override fun onAttach(view: View) {
|
||||||
|
@ -0,0 +1,283 @@
|
|||||||
|
/*
|
||||||
|
* Nextcloud Talk application
|
||||||
|
*
|
||||||
|
* @author Tim Krüger
|
||||||
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
|
* Copyright (C) 2022 Nextcloud GmbH
|
||||||
|
*
|
||||||
|
* This program is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
@file:Suppress("TooManyFunctions")
|
||||||
|
|
||||||
|
package com.nextcloud.talk.extensions
|
||||||
|
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.graphics.drawable.LayerDrawable
|
||||||
|
import android.os.Build
|
||||||
|
import android.util.Log
|
||||||
|
import android.widget.ImageView
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import androidx.core.content.res.ResourcesCompat
|
||||||
|
import coil.annotation.ExperimentalCoilApi
|
||||||
|
import coil.imageLoader
|
||||||
|
import coil.load
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.request.SuccessResult
|
||||||
|
import coil.result
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
|
import coil.transform.RoundedCornersTransformation
|
||||||
|
import com.amulyakhare.textdrawable.TextDrawable
|
||||||
|
import com.nextcloud.talk.R
|
||||||
|
import com.nextcloud.talk.data.user.model.User
|
||||||
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
|
|
||||||
|
private const val ROUNDING_PIXEL = 16f
|
||||||
|
private const val TAG = "ImageViewExtensions"
|
||||||
|
|
||||||
|
fun ImageView.loadAvatar(
|
||||||
|
user: User,
|
||||||
|
avatar: String,
|
||||||
|
requestBigSize: Boolean = true
|
||||||
|
): io.reactivex.disposables
|
||||||
|
.Disposable {
|
||||||
|
|
||||||
|
val imageRequestUri = ApiUtils.getUrlForAvatar(
|
||||||
|
user.baseUrl,
|
||||||
|
avatar,
|
||||||
|
requestBigSize
|
||||||
|
)
|
||||||
|
|
||||||
|
return loadAvatarInternal(user, imageRequestUri, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.replaceAvatar(
|
||||||
|
user: User,
|
||||||
|
avatar: String,
|
||||||
|
requestBigSize: Boolean = true
|
||||||
|
): io.reactivex.disposables
|
||||||
|
.Disposable {
|
||||||
|
|
||||||
|
val imageRequestUri = ApiUtils.getUrlForAvatar(
|
||||||
|
user.baseUrl,
|
||||||
|
avatar,
|
||||||
|
requestBigSize
|
||||||
|
)
|
||||||
|
|
||||||
|
return loadAvatarInternal(user, imageRequestUri, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
@OptIn(ExperimentalCoilApi::class)
|
||||||
|
private fun ImageView.loadAvatarInternal(
|
||||||
|
user: User?,
|
||||||
|
url: String,
|
||||||
|
replace: Boolean
|
||||||
|
): io.reactivex.disposables
|
||||||
|
.Disposable {
|
||||||
|
|
||||||
|
if (replace && this.result is SuccessResult) {
|
||||||
|
val result = this.result as SuccessResult
|
||||||
|
val memoryCacheKey = result.memoryCacheKey
|
||||||
|
val memoryCache = context.imageLoader.memoryCache
|
||||||
|
memoryCacheKey?.let { memoryCache?.remove(it) }
|
||||||
|
|
||||||
|
val diskCacheKey = result.diskCacheKey
|
||||||
|
val diskCache = context.imageLoader.diskCache
|
||||||
|
diskCacheKey?.let { diskCache?.remove(it) }
|
||||||
|
}
|
||||||
|
|
||||||
|
return DisposableWrapper(
|
||||||
|
load(url) {
|
||||||
|
user?.let {
|
||||||
|
addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(user.username, user.token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
transformations(CircleCropTransformation())
|
||||||
|
placeholder(R.drawable.account_circle_96dp)
|
||||||
|
listener(onError = { _, result ->
|
||||||
|
Log.w(TAG, "Can't load avatar with URL: $url", result.throwable)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated("Use function loadAvatar", level = DeprecationLevel.WARNING)
|
||||||
|
fun ImageView.loadAvatarWithUrl(user: User? = null, url: String): io.reactivex.disposables.Disposable {
|
||||||
|
return loadAvatarInternal(user, url, false)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadThumbnail(url: String, user: User): io.reactivex.disposables.Disposable {
|
||||||
|
val requestBuilder = ImageRequest.Builder(context)
|
||||||
|
.data(url)
|
||||||
|
.crossfade(true)
|
||||||
|
.target(this)
|
||||||
|
.transformations(CircleCropTransformation())
|
||||||
|
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val layers = arrayOfNulls<Drawable>(2)
|
||||||
|
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
||||||
|
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
||||||
|
requestBuilder.placeholder(LayerDrawable(layers))
|
||||||
|
} else {
|
||||||
|
requestBuilder.placeholder(R.mipmap.ic_launcher)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (url.startsWith(user.baseUrl!!) &&
|
||||||
|
(url.contains("index.php/core/preview?fileId=") || url.contains("/avatar/"))
|
||||||
|
) {
|
||||||
|
requestBuilder.addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(user.username, user.token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DisposableWrapper(context.imageLoader.enqueue(requestBuilder.build()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadImage(url: String, user: User, placeholder: Drawable? = null): io.reactivex.disposables.Disposable {
|
||||||
|
|
||||||
|
val requestBuilder = ImageRequest.Builder(context)
|
||||||
|
.data(url)
|
||||||
|
.crossfade(true)
|
||||||
|
.target(this)
|
||||||
|
.placeholder(placeholder)
|
||||||
|
.error(placeholder)
|
||||||
|
.transformations(RoundedCornersTransformation(ROUNDING_PIXEL, ROUNDING_PIXEL, ROUNDING_PIXEL, ROUNDING_PIXEL))
|
||||||
|
|
||||||
|
if (url.startsWith(user.baseUrl!!) &&
|
||||||
|
(url.contains("index.php/core/preview?fileId=") || url.contains("/avatar/"))
|
||||||
|
) {
|
||||||
|
requestBuilder.addHeader(
|
||||||
|
"Authorization",
|
||||||
|
ApiUtils.getCredentials(user.username, user.token)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
return DisposableWrapper(context.imageLoader.enqueue(requestBuilder.build()))
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadAvatarOrImagePreview(url: String, user: User, placeholder: Drawable? = null): io.reactivex
|
||||||
|
.disposables.Disposable {
|
||||||
|
return if (url.contains("/avatar/")) {
|
||||||
|
loadAvatarInternal(user, url, false)
|
||||||
|
} else {
|
||||||
|
loadImage(url, user, placeholder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadAvatar(any: Any?): io.reactivex.disposables.Disposable {
|
||||||
|
return DisposableWrapper(
|
||||||
|
load(any) {
|
||||||
|
transformations(CircleCropTransformation())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadSystemAvatar(): io.reactivex.disposables.Disposable {
|
||||||
|
val data: Any = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val layers = arrayOfNulls<Drawable>(2)
|
||||||
|
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background)
|
||||||
|
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground)
|
||||||
|
val layerDrawable = LayerDrawable(layers)
|
||||||
|
layerDrawable
|
||||||
|
} else {
|
||||||
|
R.mipmap.ic_launcher
|
||||||
|
}
|
||||||
|
|
||||||
|
return DisposableWrapper(
|
||||||
|
load(data) {
|
||||||
|
transformations(CircleCropTransformation())
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadChangelogBotAvatar(): io.reactivex.disposables.Disposable {
|
||||||
|
return loadSystemAvatar()
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadBotsAvatar(): io.reactivex.disposables.Disposable {
|
||||||
|
return loadAvatar(
|
||||||
|
TextDrawable.builder()
|
||||||
|
.beginConfig()
|
||||||
|
.bold()
|
||||||
|
.endConfig()
|
||||||
|
.buildRound(
|
||||||
|
">",
|
||||||
|
ResourcesCompat.getColor(context.resources, R.color.black, null)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadGroupCallAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable {
|
||||||
|
|
||||||
|
val data: Any = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.ic_avatar_group) as Any
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_circular_group
|
||||||
|
}
|
||||||
|
return loadAvatar(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadPublicCallAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable {
|
||||||
|
val data: Any = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.ic_avatar_link) as Any
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_circular_link
|
||||||
|
}
|
||||||
|
return loadAvatar(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadMailAvatar(viewThemeUtils: ViewThemeUtils): io.reactivex.disposables.Disposable {
|
||||||
|
val data: Any = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
viewThemeUtils.talk.themePlaceholderAvatar(this, R.drawable.ic_avatar_mail) as Any
|
||||||
|
} else {
|
||||||
|
R.drawable.ic_circular_mail
|
||||||
|
}
|
||||||
|
return loadAvatar(data)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadGuestAvatar(user: User, name: String, big: Boolean): io.reactivex.disposables.Disposable {
|
||||||
|
return loadGuestAvatar(user.baseUrl!!, name, big)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun ImageView.loadGuestAvatar(baseUrl: String, name: String, big: Boolean): io.reactivex.disposables.Disposable {
|
||||||
|
val imageRequestUri = ApiUtils.getUrlForGuestAvatar(
|
||||||
|
baseUrl,
|
||||||
|
name,
|
||||||
|
big
|
||||||
|
)
|
||||||
|
return DisposableWrapper(
|
||||||
|
load(imageRequestUri) {
|
||||||
|
transformations(CircleCropTransformation())
|
||||||
|
listener(onError = { _, result ->
|
||||||
|
Log.w(TAG, "Can't load guest avatar with URL: $imageRequestUri", result.throwable)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private class DisposableWrapper(private val disposable: coil.request.Disposable) : io.reactivex.disposables
|
||||||
|
.Disposable {
|
||||||
|
|
||||||
|
override fun dispose() {
|
||||||
|
disposable.dispose()
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun isDisposed(): Boolean {
|
||||||
|
return disposable.isDisposed
|
||||||
|
}
|
||||||
|
}
|
@ -526,7 +526,7 @@ class NotificationWorker(context: Context, workerParams: WorkerParameters) : Wor
|
|||||||
notificationUser.id,
|
notificationUser.id,
|
||||||
false
|
false
|
||||||
) else ApiUtils.getUrlForGuestAvatar(baseUrl, notificationUser.name, false)
|
) else ApiUtils.getUrlForGuestAvatar(baseUrl, notificationUser.name, false)
|
||||||
person.setIcon(loadAvatarSync(avatarUrl))
|
person.setIcon(loadAvatarSync(avatarUrl, context!!))
|
||||||
}
|
}
|
||||||
notificationBuilder.setStyle(getStyle(person.build(), style))
|
notificationBuilder.setStyle(getStyle(person.build(), style))
|
||||||
}
|
}
|
||||||
|
@ -22,16 +22,15 @@ package com.nextcloud.talk.polls.adapters
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
import android.widget.ImageView
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.PollResultVoterItemBinding
|
import com.nextcloud.talk.databinding.PollResultVoterItemBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadGuestAvatar
|
||||||
import com.nextcloud.talk.polls.model.PollDetails
|
import com.nextcloud.talk.polls.model.PollDetails
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
|
|
||||||
class PollResultVoterViewHolder(
|
class PollResultVoterViewHolder(
|
||||||
private val user: User,
|
private val user: User,
|
||||||
@ -46,45 +45,19 @@ class PollResultVoterViewHolder(
|
|||||||
binding.root.setOnClickListener { clickListener.onClick() }
|
binding.root.setOnClickListener { clickListener.onClick() }
|
||||||
|
|
||||||
binding.pollVoterName.text = item.details.actorDisplayName
|
binding.pollVoterName.text = item.details.actorDisplayName
|
||||||
binding.pollVoterAvatar.controller = getAvatarDraweeController(item.details)
|
loadAvatar(item.details, binding.pollVoterAvatar)
|
||||||
viewThemeUtils.dialog.colorDialogSupportingText(binding.pollVoterName)
|
viewThemeUtils.dialog.colorDialogSupportingText(binding.pollVoterName)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? {
|
private fun loadAvatar(pollDetail: PollDetails, avatar: ImageView) {
|
||||||
var draweeController: DraweeController? = null
|
|
||||||
if (pollDetail.actorType == "guests") {
|
if (pollDetail.actorType == "guests") {
|
||||||
var displayName = NextcloudTalkApplication.sharedApplication?.resources?.getString(R.string.nc_guest)
|
var displayName = NextcloudTalkApplication.sharedApplication?.resources?.getString(R.string.nc_guest)
|
||||||
if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) {
|
if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) {
|
||||||
displayName = pollDetail.actorDisplayName!!
|
displayName = pollDetail.actorDisplayName!!
|
||||||
}
|
}
|
||||||
draweeController = Fresco.newDraweeControllerBuilder()
|
avatar.loadGuestAvatar(user, displayName!!, false)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForGuestAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
displayName,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
user
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
} else if (pollDetail.actorType == "users") {
|
} else if (pollDetail.actorType == "users") {
|
||||||
draweeController = Fresco.newDraweeControllerBuilder()
|
avatar.loadAvatar(user, pollDetail.actorId!!, false)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
pollDetail.actorId,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
user
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
return draweeController
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
* Nextcloud Talk application
|
* Nextcloud Talk application
|
||||||
*
|
*
|
||||||
* @author Marcel Hibbe
|
* @author Marcel Hibbe
|
||||||
|
* @author Tim Krüger
|
||||||
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
* Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
*
|
*
|
||||||
* This program is free software: you can redistribute it and/or modify
|
* This program is free software: you can redistribute it and/or modify
|
||||||
@ -22,20 +24,16 @@ package com.nextcloud.talk.polls.adapters
|
|||||||
|
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.LinearLayout
|
import android.widget.LinearLayout
|
||||||
import android.widget.TextView
|
import android.widget.TextView
|
||||||
import androidx.core.content.res.ResourcesCompat
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.generic.RoundingParams
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.PollResultVotersOverviewItemBinding
|
import com.nextcloud.talk.databinding.PollResultVotersOverviewItemBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
|
import com.nextcloud.talk.extensions.loadGuestAvatar
|
||||||
import com.nextcloud.talk.polls.model.PollDetails
|
import com.nextcloud.talk.polls.model.PollDetails
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
|
|
||||||
class PollResultVotersOverviewViewHolder(
|
class PollResultVotersOverviewViewHolder(
|
||||||
private val user: User,
|
private val user: User,
|
||||||
@ -61,24 +59,14 @@ class PollResultVotersOverviewViewHolder(
|
|||||||
|
|
||||||
for (i in 0 until avatarsToDisplay) {
|
for (i in 0 until avatarsToDisplay) {
|
||||||
val pollDetails = item.detailsList[i]
|
val pollDetails = item.detailsList[i]
|
||||||
val avatar = SimpleDraweeView(binding.root.context)
|
val avatar = ImageView(binding.root.context)
|
||||||
|
|
||||||
layoutParams.marginStart = i * AVATAR_OFFSET
|
layoutParams.marginStart = i * AVATAR_OFFSET
|
||||||
avatar.layoutParams = layoutParams
|
avatar.layoutParams = layoutParams
|
||||||
|
|
||||||
avatar.translationZ = i.toFloat() * -1
|
avatar.translationZ = i.toFloat() * -1
|
||||||
|
|
||||||
val roundingParams = RoundingParams.fromCornersRadius(AVATAR_RADIUS)
|
loadAvatar(pollDetails, avatar)
|
||||||
roundingParams.roundAsCircle = true
|
|
||||||
roundingParams.borderColor = ResourcesCompat.getColor(
|
|
||||||
itemView.context.resources!!,
|
|
||||||
R.color.vote_dialog_background,
|
|
||||||
null
|
|
||||||
)
|
|
||||||
roundingParams.borderWidth = DisplayUtils.convertDpToPixel(2.0f, itemView.context)
|
|
||||||
|
|
||||||
avatar.hierarchy.roundingParams = roundingParams
|
|
||||||
avatar.controller = getAvatarDraweeController(pollDetails)
|
|
||||||
|
|
||||||
binding.votersAvatarsOverviewWrapper.addView(avatar)
|
binding.votersAvatarsOverviewWrapper.addView(avatar)
|
||||||
|
|
||||||
@ -92,47 +80,20 @@ class PollResultVotersOverviewViewHolder(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getAvatarDraweeController(pollDetail: PollDetails): DraweeController? {
|
private fun loadAvatar(pollDetail: PollDetails, avatar: ImageView) {
|
||||||
var draweeController: DraweeController? = null
|
|
||||||
if (pollDetail.actorType == "guests") {
|
if (pollDetail.actorType == "guests") {
|
||||||
var displayName = NextcloudTalkApplication.sharedApplication?.resources?.getString(R.string.nc_guest)
|
var displayName = NextcloudTalkApplication.sharedApplication?.resources?.getString(R.string.nc_guest)
|
||||||
if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) {
|
if (!TextUtils.isEmpty(pollDetail.actorDisplayName)) {
|
||||||
displayName = pollDetail.actorDisplayName!!
|
displayName = pollDetail.actorDisplayName!!
|
||||||
}
|
}
|
||||||
draweeController = Fresco.newDraweeControllerBuilder()
|
avatar.loadGuestAvatar(user, displayName!!, false)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForGuestAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
displayName,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
user
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
} else if (pollDetail.actorType == "users") {
|
} else if (pollDetail.actorType == "users") {
|
||||||
draweeController = Fresco.newDraweeControllerBuilder()
|
avatar.loadAvatar(user, pollDetail.actorId!!, false)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
pollDetail.actorId,
|
|
||||||
false
|
|
||||||
),
|
|
||||||
user
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
}
|
}
|
||||||
return draweeController
|
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
const val AVATAR_SIZE = 60
|
const val AVATAR_SIZE = 60
|
||||||
const val AVATAR_RADIUS = 5f
|
|
||||||
const val MAX_AVATARS = 10
|
const val MAX_AVATARS = 10
|
||||||
const val AVATAR_OFFSET = AVATAR_SIZE - 20
|
const val AVATAR_OFFSET = AVATAR_SIZE - 20
|
||||||
const val DOTS_OFFSET = 70
|
const val DOTS_OFFSET = 70
|
||||||
|
@ -162,7 +162,7 @@ class DirectReplyReceiver : BroadcastReceiver() {
|
|||||||
val avatarUrl = ApiUtils.getUrlForAvatar(currentUser.baseUrl, currentUser.userId, false)
|
val avatarUrl = ApiUtils.getUrlForAvatar(currentUser.baseUrl, currentUser.userId, false)
|
||||||
val me = Person.Builder()
|
val me = Person.Builder()
|
||||||
.setName(currentUser.displayName)
|
.setName(currentUser.displayName)
|
||||||
.setIcon(NotificationUtils.loadAvatarSync(avatarUrl))
|
.setIcon(NotificationUtils.loadAvatarSync(avatarUrl, context))
|
||||||
.build()
|
.build()
|
||||||
val message = NotificationCompat.MessagingStyle.Message(reply, System.currentTimeMillis(), me)
|
val message = NotificationCompat.MessagingStyle.Message(reply, System.currentTimeMillis(), me)
|
||||||
previousStyle?.addMessage(message)
|
previousStyle?.addMessage(message)
|
||||||
|
@ -22,20 +22,18 @@ package com.nextcloud.talk.remotefilebrowser.adapters
|
|||||||
|
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
|
import com.nextcloud.talk.databinding.RvItemBrowserFileBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadImage
|
||||||
import com.nextcloud.talk.remotefilebrowser.SelectionInterface
|
import com.nextcloud.talk.remotefilebrowser.SelectionInterface
|
||||||
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.utils.ApiUtils
|
||||||
import com.nextcloud.talk.utils.DateUtils.getLocalDateTimeStringFromTimestamp
|
import com.nextcloud.talk.utils.DateUtils.getLocalDateTimeStringFromTimestamp
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import com.nextcloud.talk.utils.Mimetype.FOLDER
|
import com.nextcloud.talk.utils.Mimetype.FOLDER
|
||||||
|
|
||||||
@AutoInjector(NextcloudTalkApplication::class)
|
@AutoInjector(NextcloudTalkApplication::class)
|
||||||
@ -48,7 +46,7 @@ class RemoteFileBrowserItemsListViewHolder(
|
|||||||
onItemClicked: (Int) -> Unit
|
onItemClicked: (Int) -> Unit
|
||||||
) : RemoteFileBrowserItemsViewHolder(binding, mimeTypeSelectionFilter, currentUser, selectionInterface) {
|
) : RemoteFileBrowserItemsViewHolder(binding, mimeTypeSelectionFilter, currentUser, selectionInterface) {
|
||||||
|
|
||||||
override val fileIcon: SimpleDraweeView
|
override val fileIcon: ImageView
|
||||||
get() = binding.fileIcon
|
get() = binding.fileIcon
|
||||||
|
|
||||||
private var selectable: Boolean = true
|
private var selectable: Boolean = true
|
||||||
@ -68,7 +66,6 @@ class RemoteFileBrowserItemsListViewHolder(
|
|||||||
override fun onBind(item: RemoteFileBrowserItem) {
|
override fun onBind(item: RemoteFileBrowserItem) {
|
||||||
super.onBind(item)
|
super.onBind(item)
|
||||||
|
|
||||||
binding.fileIcon.controller = null
|
|
||||||
if (!item.isAllowedToReShare || item.isEncrypted) {
|
if (!item.isAllowedToReShare || item.isEncrypted) {
|
||||||
binding.root.isEnabled = false
|
binding.root.isEnabled = false
|
||||||
binding.root.alpha = DISABLED_ALPHA
|
binding.root.alpha = DISABLED_ALPHA
|
||||||
@ -95,11 +92,7 @@ class RemoteFileBrowserItemsListViewHolder(
|
|||||||
calculateClickability(item, selectable)
|
calculateClickability(item, selectable)
|
||||||
setSelectability()
|
setSelectability()
|
||||||
|
|
||||||
binding.fileIcon
|
val placeholder = viewThemeUtils.talk.getPlaceholderImage(binding.root.context, item.mimeType)
|
||||||
.hierarchy
|
|
||||||
.setPlaceholderImage(
|
|
||||||
viewThemeUtils.talk.getPlaceholderImage(binding.root.context, item.mimeType)
|
|
||||||
)
|
|
||||||
|
|
||||||
if (item.hasPreview) {
|
if (item.hasPreview) {
|
||||||
val path = ApiUtils.getUrlForFilePreviewWithRemotePath(
|
val path = ApiUtils.getUrlForFilePreviewWithRemotePath(
|
||||||
@ -108,12 +101,10 @@ class RemoteFileBrowserItemsListViewHolder(
|
|||||||
binding.fileIcon.context.resources.getDimensionPixelSize(R.dimen.small_item_height)
|
binding.fileIcon.context.resources.getDimensionPixelSize(R.dimen.small_item_height)
|
||||||
)
|
)
|
||||||
if (path.isNotEmpty()) {
|
if (path.isNotEmpty()) {
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
binding.fileIcon.loadImage(path, currentUser, placeholder)
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(path))
|
|
||||||
.build()
|
|
||||||
binding.fileIcon.controller = draweeController
|
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
binding.fileIcon.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
binding.filenameTextView.text = item.displayName
|
binding.filenameTextView.text = item.displayName
|
||||||
|
@ -20,11 +20,9 @@
|
|||||||
|
|
||||||
package com.nextcloud.talk.remotefilebrowser.adapters
|
package com.nextcloud.talk.remotefilebrowser.adapters
|
||||||
|
|
||||||
import android.graphics.drawable.Drawable
|
import android.widget.ImageView
|
||||||
import androidx.core.content.ContextCompat
|
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.remotefilebrowser.SelectionInterface
|
import com.nextcloud.talk.remotefilebrowser.SelectionInterface
|
||||||
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
||||||
@ -37,17 +35,9 @@ abstract class RemoteFileBrowserItemsViewHolder(
|
|||||||
val selectionInterface: SelectionInterface,
|
val selectionInterface: SelectionInterface,
|
||||||
) : RecyclerView.ViewHolder(binding.root) {
|
) : RecyclerView.ViewHolder(binding.root) {
|
||||||
|
|
||||||
abstract val fileIcon: SimpleDraweeView
|
abstract val fileIcon: ImageView
|
||||||
|
|
||||||
open fun onBind(item: RemoteFileBrowserItem) {
|
open fun onBind(item: RemoteFileBrowserItem) {
|
||||||
fileIcon.hierarchy.setPlaceholderImage(staticImage(item.mimeType, fileIcon))
|
fileIcon.setImageResource(DrawableUtils.getDrawableResourceIdForMimeType(item.mimeType))
|
||||||
}
|
|
||||||
|
|
||||||
private fun staticImage(
|
|
||||||
mimeType: String?,
|
|
||||||
image: SimpleDraweeView
|
|
||||||
): Drawable {
|
|
||||||
val drawableResourceId = DrawableUtils.getDrawableResourceIdForMimeType(mimeType)
|
|
||||||
return ContextCompat.getDrawable(image.context, drawableResourceId)!!
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -23,8 +23,8 @@
|
|||||||
package com.nextcloud.talk.shareditems.adapters
|
package com.nextcloud.talk.shareditems.adapters
|
||||||
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.SharedItemGridBinding
|
import com.nextcloud.talk.databinding.SharedItemGridBinding
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
@ -35,7 +35,7 @@ class SharedItemsGridViewHolder(
|
|||||||
viewThemeUtils: ViewThemeUtils
|
viewThemeUtils: ViewThemeUtils
|
||||||
) : SharedItemsViewHolder(binding, user, viewThemeUtils) {
|
) : SharedItemsViewHolder(binding, user, viewThemeUtils) {
|
||||||
|
|
||||||
override val image: SimpleDraweeView
|
override val image: ImageView
|
||||||
get() = binding.image
|
get() = binding.image
|
||||||
override val clickTarget: View
|
override val clickTarget: View
|
||||||
get() = binding.image
|
get() = binding.image
|
||||||
|
@ -26,9 +26,10 @@ import android.content.Context
|
|||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.text.format.Formatter
|
import android.text.format.Formatter
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import androidx.core.content.ContextCompat
|
import androidx.core.content.ContextCompat
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
import coil.load
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.SharedItemListBinding
|
import com.nextcloud.talk.databinding.SharedItemListBinding
|
||||||
@ -46,7 +47,7 @@ class SharedItemsListViewHolder(
|
|||||||
viewThemeUtils: ViewThemeUtils
|
viewThemeUtils: ViewThemeUtils
|
||||||
) : SharedItemsViewHolder(binding, user, viewThemeUtils) {
|
) : SharedItemsViewHolder(binding, user, viewThemeUtils) {
|
||||||
|
|
||||||
override val image: SimpleDraweeView
|
override val image: ImageView
|
||||||
get() = binding.fileImage
|
get() = binding.fileImage
|
||||||
override val clickTarget: View
|
override val clickTarget: View
|
||||||
get() = binding.fileItem
|
get() = binding.fileItem
|
||||||
@ -75,7 +76,7 @@ class SharedItemsListViewHolder(
|
|||||||
binding.separator1.visibility = View.GONE
|
binding.separator1.visibility = View.GONE
|
||||||
binding.fileDate.text = item.dateTime
|
binding.fileDate.text = item.dateTime
|
||||||
binding.actor.text = item.actorName
|
binding.actor.text = item.actorName
|
||||||
image.hierarchy.setPlaceholderImage(R.drawable.ic_baseline_bar_chart_24)
|
image.load(R.drawable.ic_baseline_bar_chart_24)
|
||||||
image.setColorFilter(
|
image.setColorFilter(
|
||||||
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
||||||
android.graphics.PorterDuff.Mode.SRC_IN
|
android.graphics.PorterDuff.Mode.SRC_IN
|
||||||
@ -93,7 +94,7 @@ class SharedItemsListViewHolder(
|
|||||||
binding.separator1.visibility = View.GONE
|
binding.separator1.visibility = View.GONE
|
||||||
binding.fileDate.text = item.dateTime
|
binding.fileDate.text = item.dateTime
|
||||||
binding.actor.text = item.actorName
|
binding.actor.text = item.actorName
|
||||||
image.hierarchy.setPlaceholderImage(R.drawable.ic_baseline_location_on_24)
|
image.load(R.drawable.ic_baseline_location_on_24)
|
||||||
image.setColorFilter(
|
image.setColorFilter(
|
||||||
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
||||||
android.graphics.PorterDuff.Mode.SRC_IN
|
android.graphics.PorterDuff.Mode.SRC_IN
|
||||||
@ -114,7 +115,7 @@ class SharedItemsListViewHolder(
|
|||||||
binding.separator1.visibility = View.GONE
|
binding.separator1.visibility = View.GONE
|
||||||
binding.fileDate.text = item.dateTime
|
binding.fileDate.text = item.dateTime
|
||||||
binding.actor.text = item.actorName
|
binding.actor.text = item.actorName
|
||||||
image.hierarchy.setPlaceholderImage(R.drawable.ic_mimetype_file)
|
image.load(R.drawable.ic_mimetype_file)
|
||||||
image.setColorFilter(
|
image.setColorFilter(
|
||||||
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
||||||
android.graphics.PorterDuff.Mode.SRC_IN
|
android.graphics.PorterDuff.Mode.SRC_IN
|
||||||
@ -129,7 +130,7 @@ class SharedItemsListViewHolder(
|
|||||||
binding.separator1.visibility = View.GONE
|
binding.separator1.visibility = View.GONE
|
||||||
binding.fileDate.text = item.dateTime
|
binding.fileDate.text = item.dateTime
|
||||||
binding.actor.text = item.actorName
|
binding.actor.text = item.actorName
|
||||||
image.hierarchy.setPlaceholderImage(R.drawable.ic_baseline_deck_24)
|
image.load(R.drawable.ic_baseline_deck_24)
|
||||||
image.setColorFilter(
|
image.setColorFilter(
|
||||||
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
ContextCompat.getColor(image.context, R.color.high_emphasis_menu_icon),
|
||||||
android.graphics.PorterDuff.Mode.SRC_IN
|
android.graphics.PorterDuff.Mode.SRC_IN
|
||||||
|
@ -23,29 +23,20 @@
|
|||||||
package com.nextcloud.talk.shareditems.adapters
|
package com.nextcloud.talk.shareditems.adapters
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.net.Uri
|
|
||||||
import android.util.Log
|
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import androidx.recyclerview.widget.RecyclerView
|
import androidx.recyclerview.widget.RecyclerView
|
||||||
import androidx.viewbinding.ViewBinding
|
import androidx.viewbinding.ViewBinding
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.controller.BaseControllerListener
|
|
||||||
import com.facebook.drawee.controller.ControllerListener
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.facebook.imagepipeline.common.RotationOptions
|
|
||||||
import com.facebook.imagepipeline.image.ImageInfo
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequestBuilder
|
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
|
import com.nextcloud.talk.extensions.loadImage
|
||||||
import com.nextcloud.talk.shareditems.model.SharedDeckCardItem
|
import com.nextcloud.talk.shareditems.model.SharedDeckCardItem
|
||||||
import com.nextcloud.talk.shareditems.model.SharedFileItem
|
import com.nextcloud.talk.shareditems.model.SharedFileItem
|
||||||
import com.nextcloud.talk.shareditems.model.SharedItem
|
import com.nextcloud.talk.shareditems.model.SharedItem
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
|
||||||
import com.nextcloud.talk.shareditems.model.SharedLocationItem
|
import com.nextcloud.talk.shareditems.model.SharedLocationItem
|
||||||
import com.nextcloud.talk.shareditems.model.SharedOtherItem
|
import com.nextcloud.talk.shareditems.model.SharedOtherItem
|
||||||
import com.nextcloud.talk.shareditems.model.SharedPollItem
|
import com.nextcloud.talk.shareditems.model.SharedPollItem
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.utils.FileViewerUtils
|
import com.nextcloud.talk.utils.FileViewerUtils
|
||||||
|
|
||||||
abstract class SharedItemsViewHolder(
|
abstract class SharedItemsViewHolder(
|
||||||
@ -58,21 +49,21 @@ abstract class SharedItemsViewHolder(
|
|||||||
private val TAG = SharedItemsViewHolder::class.simpleName
|
private val TAG = SharedItemsViewHolder::class.simpleName
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract val image: SimpleDraweeView
|
abstract val image: ImageView
|
||||||
abstract val clickTarget: View
|
abstract val clickTarget: View
|
||||||
abstract val progressBar: ProgressBar
|
abstract val progressBar: ProgressBar
|
||||||
|
|
||||||
private val authHeader = mapOf(
|
|
||||||
Pair(
|
|
||||||
"Authorization",
|
|
||||||
ApiUtils.getCredentials(user.username, user.token)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
|
|
||||||
open fun onBind(item: SharedFileItem) {
|
open fun onBind(item: SharedFileItem) {
|
||||||
image.hierarchy.setPlaceholderImage(viewThemeUtils.talk.getPlaceholderImage(image.context, item.mimeType))
|
|
||||||
|
val placeholder = viewThemeUtils.talk.getPlaceholderImage(image.context, item.mimeType)
|
||||||
if (item.previewAvailable) {
|
if (item.previewAvailable) {
|
||||||
image.controller = configurePreview(item)
|
image.loadImage(
|
||||||
|
item.previewLink,
|
||||||
|
user,
|
||||||
|
placeholder
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
image.setImageDrawable(placeholder)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -105,28 +96,6 @@ abstract class SharedItemsViewHolder(
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun configurePreview(item: SharedFileItem): DraweeController {
|
|
||||||
val imageRequest = ImageRequestBuilder.newBuilderWithSource(Uri.parse(item.previewLink))
|
|
||||||
.setProgressiveRenderingEnabled(true)
|
|
||||||
.setRotationOptions(RotationOptions.autoRotate())
|
|
||||||
.disableDiskCache()
|
|
||||||
.setHeaders(authHeader)
|
|
||||||
.build()
|
|
||||||
|
|
||||||
val listener: ControllerListener<ImageInfo?> = object : BaseControllerListener<ImageInfo?>() {
|
|
||||||
override fun onFailure(id: String, e: Throwable) {
|
|
||||||
Log.w(TAG, "Failed to load image. A static mimetype image will be used", e)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(image.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(imageRequest)
|
|
||||||
.setControllerListener(listener)
|
|
||||||
.build()
|
|
||||||
}
|
|
||||||
|
|
||||||
open fun onBind(item: SharedPollItem, showPoll: (item: SharedItem, context: Context) -> Unit) {}
|
open fun onBind(item: SharedPollItem, showPoll: (item: SharedItem, context: Context) -> Unit) {}
|
||||||
|
|
||||||
open fun onBind(item: SharedLocationItem) {}
|
open fun onBind(item: SharedLocationItem) {}
|
||||||
|
@ -33,8 +33,6 @@ import android.view.LayoutInflater;
|
|||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
|
||||||
import com.nextcloud.talk.activities.MainActivity;
|
import com.nextcloud.talk.activities.MainActivity;
|
||||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
|
import com.nextcloud.talk.adapters.items.AdvancedUserItem;
|
||||||
@ -42,6 +40,7 @@ import com.nextcloud.talk.api.NcApi;
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.databinding.DialogChooseAccountBinding;
|
import com.nextcloud.talk.databinding.DialogChooseAccountBinding;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.models.json.participants.Participant;
|
import com.nextcloud.talk.models.json.participants.Participant;
|
||||||
import com.nextcloud.talk.models.json.status.Status;
|
import com.nextcloud.talk.models.json.status.Status;
|
||||||
import com.nextcloud.talk.models.json.status.StatusOverall;
|
import com.nextcloud.talk.models.json.status.StatusOverall;
|
||||||
@ -132,22 +131,10 @@ public class ChooseAccountDialogFragment extends DialogFragment {
|
|||||||
if (user.getBaseUrl() != null &&
|
if (user.getBaseUrl() != null &&
|
||||||
(user.getBaseUrl().startsWith("http://") || user.getBaseUrl().startsWith("https://"))) {
|
(user.getBaseUrl().startsWith("http://") || user.getBaseUrl().startsWith("https://"))) {
|
||||||
binding.currentAccount.userIcon.setVisibility(View.VISIBLE);
|
binding.currentAccount.userIcon.setVisibility(View.VISIBLE);
|
||||||
|
ImageViewExtensionsKt.loadAvatar(binding.currentAccount.userIcon, user, user.getUserId(), true);
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(binding.currentAccount.userIcon.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.getBaseUrl(),
|
|
||||||
user.getUserId(),
|
|
||||||
false)))
|
|
||||||
.build();
|
|
||||||
binding.currentAccount.userIcon.setController(draweeController);
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
binding.currentAccount.userIcon.setVisibility(View.INVISIBLE);
|
binding.currentAccount.userIcon.setVisibility(View.INVISIBLE);
|
||||||
}
|
}
|
||||||
|
|
||||||
loadCurrentStatus(user);
|
loadCurrentStatus(user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,8 +33,6 @@ import android.view.ViewGroup
|
|||||||
import androidx.fragment.app.DialogFragment
|
import androidx.fragment.app.DialogFragment
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
import autodagger.AutoInjector
|
import autodagger.AutoInjector
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController
|
|
||||||
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
import com.google.android.material.dialog.MaterialAlertDialogBuilder
|
||||||
import com.nextcloud.talk.activities.MainActivity
|
import com.nextcloud.talk.activities.MainActivity
|
||||||
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
import com.nextcloud.talk.adapters.items.AdvancedUserItem
|
||||||
@ -42,11 +40,10 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||||||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
import com.nextcloud.talk.databinding.DialogChooseAccountShareToBinding
|
import com.nextcloud.talk.databinding.DialogChooseAccountShareToBinding
|
||||||
|
import com.nextcloud.talk.extensions.loadAvatar
|
||||||
import com.nextcloud.talk.models.json.participants.Participant
|
import com.nextcloud.talk.models.json.participants.Participant
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils
|
||||||
import com.nextcloud.talk.users.UserManager
|
import com.nextcloud.talk.users.UserManager
|
||||||
import com.nextcloud.talk.utils.ApiUtils
|
|
||||||
import com.nextcloud.talk.utils.DisplayUtils
|
|
||||||
import eu.davidea.flexibleadapter.FlexibleAdapter
|
import eu.davidea.flexibleadapter.FlexibleAdapter
|
||||||
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
import eu.davidea.flexibleadapter.common.SmoothScrollLinearLayoutManager
|
||||||
import java.net.CookieManager
|
import java.net.CookieManager
|
||||||
@ -97,21 +94,7 @@ class ChooseAccountShareToDialogFragment : DialogFragment() {
|
|||||||
if (user.baseUrl != null &&
|
if (user.baseUrl != null &&
|
||||||
(user.baseUrl!!.startsWith("http://") || user.baseUrl!!.startsWith("https://"))
|
(user.baseUrl!!.startsWith("http://") || user.baseUrl!!.startsWith("https://"))
|
||||||
) {
|
) {
|
||||||
binding!!.currentAccount.userIcon.visibility = View.VISIBLE
|
binding!!.currentAccount.userIcon.loadAvatar(user, user.userId!!)
|
||||||
val draweeController: DraweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(binding!!.currentAccount.userIcon.controller)
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(
|
|
||||||
DisplayUtils.getImageRequestForUrl(
|
|
||||||
ApiUtils.getUrlForAvatar(
|
|
||||||
user.baseUrl,
|
|
||||||
user.userId,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
)
|
|
||||||
)
|
|
||||||
.build()
|
|
||||||
binding!!.currentAccount.userIcon.controller = draweeController
|
|
||||||
} else {
|
} else {
|
||||||
binding!!.currentAccount.userIcon.visibility = View.INVISIBLE
|
binding!!.currentAccount.userIcon.visibility = View.INVISIBLE
|
||||||
}
|
}
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
*
|
*
|
||||||
* @author Mario Danic
|
* @author Mario Danic
|
||||||
* @author Andy Scherzinger
|
* @author Andy Scherzinger
|
||||||
|
* @author Tim Krüger
|
||||||
|
* Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
* Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
* Copyright (C) 2017-2020 Mario Danic <mario@lovelyhq.com>
|
||||||
*
|
*
|
||||||
@ -33,11 +35,7 @@ import android.graphics.Bitmap;
|
|||||||
import android.graphics.Canvas;
|
import android.graphics.Canvas;
|
||||||
import android.graphics.Color;
|
import android.graphics.Color;
|
||||||
import android.graphics.Typeface;
|
import android.graphics.Typeface;
|
||||||
import android.graphics.drawable.Animatable;
|
|
||||||
import android.graphics.drawable.BitmapDrawable;
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
import android.graphics.drawable.LayerDrawable;
|
|
||||||
import android.graphics.drawable.VectorDrawable;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.text.Spannable;
|
import android.text.Spannable;
|
||||||
@ -51,36 +49,19 @@ import android.text.style.AbsoluteSizeSpan;
|
|||||||
import android.text.style.ClickableSpan;
|
import android.text.style.ClickableSpan;
|
||||||
import android.text.style.ForegroundColorSpan;
|
import android.text.style.ForegroundColorSpan;
|
||||||
import android.text.style.StyleSpan;
|
import android.text.style.StyleSpan;
|
||||||
import android.util.Log;
|
|
||||||
import android.util.TypedValue;
|
import android.util.TypedValue;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.view.Window;
|
import android.view.Window;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import com.facebook.common.executors.UiThreadImmediateExecutorService;
|
|
||||||
import com.facebook.common.references.CloseableReference;
|
|
||||||
import com.facebook.datasource.DataSource;
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco;
|
|
||||||
import com.facebook.drawee.controller.ControllerListener;
|
|
||||||
import com.facebook.drawee.interfaces.DraweeController;
|
|
||||||
import com.facebook.drawee.view.SimpleDraweeView;
|
|
||||||
import com.facebook.imagepipeline.common.RotationOptions;
|
|
||||||
import com.facebook.imagepipeline.core.ImagePipeline;
|
|
||||||
import com.facebook.imagepipeline.datasource.BaseBitmapDataSubscriber;
|
|
||||||
import com.facebook.imagepipeline.image.CloseableImage;
|
|
||||||
import com.facebook.imagepipeline.image.ImageInfo;
|
|
||||||
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor;
|
|
||||||
import com.facebook.imagepipeline.postprocessors.RoundPostprocessor;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequest;
|
|
||||||
import com.facebook.imagepipeline.request.ImageRequestBuilder;
|
|
||||||
import com.facebook.widget.text.span.BetterImageSpan;
|
|
||||||
import com.google.android.material.chip.ChipDrawable;
|
import com.google.android.material.chip.ChipDrawable;
|
||||||
import com.nextcloud.talk.R;
|
import com.nextcloud.talk.R;
|
||||||
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
import com.nextcloud.talk.application.NextcloudTalkApplication;
|
||||||
import com.nextcloud.talk.data.user.model.User;
|
import com.nextcloud.talk.data.user.model.User;
|
||||||
import com.nextcloud.talk.events.UserMentionClickEvent;
|
import com.nextcloud.talk.events.UserMentionClickEvent;
|
||||||
|
import com.nextcloud.talk.extensions.ImageViewExtensionsKt;
|
||||||
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
import com.nextcloud.talk.ui.theme.ViewThemeUtils;
|
||||||
import com.nextcloud.talk.utils.text.Spans;
|
import com.nextcloud.talk.utils.text.Spans;
|
||||||
|
|
||||||
@ -91,8 +72,6 @@ import java.lang.reflect.InvocationTargetException;
|
|||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.text.DateFormat;
|
import java.text.DateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
@ -109,6 +88,11 @@ import androidx.core.content.res.ResourcesCompat;
|
|||||||
import androidx.core.graphics.ColorUtils;
|
import androidx.core.graphics.ColorUtils;
|
||||||
import androidx.core.graphics.drawable.DrawableCompat;
|
import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
import androidx.emoji.text.EmojiCompat;
|
import androidx.emoji.text.EmojiCompat;
|
||||||
|
import coil.Coil;
|
||||||
|
import coil.request.ImageRequest;
|
||||||
|
import coil.target.Target;
|
||||||
|
import coil.transform.CircleCropTransformation;
|
||||||
|
import third.parties.fresco.BetterImageSpan;
|
||||||
|
|
||||||
import static com.nextcloud.talk.utils.FileSortOrder.sort_a_to_z_id;
|
import static com.nextcloud.talk.utils.FileSortOrder.sort_a_to_z_id;
|
||||||
import static com.nextcloud.talk.utils.FileSortOrder.sort_big_to_small_id;
|
import static com.nextcloud.talk.utils.FileSortOrder.sort_big_to_small_id;
|
||||||
@ -119,8 +103,6 @@ import static com.nextcloud.talk.utils.FileSortOrder.sort_z_to_a_id;
|
|||||||
|
|
||||||
public class DisplayUtils {
|
public class DisplayUtils {
|
||||||
|
|
||||||
private static final String TAG = "DisplayUtils";
|
|
||||||
|
|
||||||
private static final int INDEX_LUMINATION = 2;
|
private static final int INDEX_LUMINATION = 2;
|
||||||
private static final double MAX_LIGHTNESS = 0.92;
|
private static final double MAX_LIGHTNESS = 0.92;
|
||||||
|
|
||||||
@ -154,33 +136,6 @@ public class DisplayUtils {
|
|||||||
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
textView.setMovementMethod(LinkMovementMethod.getInstance());
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void updateViewSize(@Nullable ImageInfo imageInfo, SimpleDraweeView draweeView) {
|
|
||||||
if (imageInfo != null && draweeView.getId() != R.id.messageUserAvatar) {
|
|
||||||
int maxSize = draweeView.getContext().getResources().getDimensionPixelSize(R.dimen.maximum_file_preview_size);
|
|
||||||
draweeView.getLayoutParams().width = imageInfo.getWidth() > maxSize ? maxSize : imageInfo.getWidth();
|
|
||||||
draweeView.getLayoutParams().height = ViewGroup.LayoutParams.WRAP_CONTENT;
|
|
||||||
draweeView.setAspectRatio((float) imageInfo.getWidth() / imageInfo.getHeight());
|
|
||||||
draweeView.requestLayout();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Drawable getRoundedDrawable(Drawable drawable) {
|
|
||||||
Bitmap bitmap = getBitmap(drawable);
|
|
||||||
new RoundAsCirclePostprocessor(true).process(bitmap);
|
|
||||||
return new BitmapDrawable(bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap getRoundedBitmapFromVectorDrawableResource(Resources resources, int resource) {
|
|
||||||
VectorDrawable vectorDrawable = (VectorDrawable) ResourcesCompat.getDrawable(resources, resource, null);
|
|
||||||
Bitmap bitmap = getBitmap(vectorDrawable);
|
|
||||||
new RoundPostprocessor(true).process(bitmap);
|
|
||||||
return bitmap;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Drawable getRoundedBitmapDrawableFromVectorDrawableResource(Resources resources, int resource) {
|
|
||||||
return new BitmapDrawable(getRoundedBitmapFromVectorDrawableResource(resources, resource));
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Bitmap getBitmap(Drawable drawable) {
|
public static Bitmap getBitmap(Drawable drawable) {
|
||||||
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
|
Bitmap bitmap = Bitmap.createBitmap(drawable.getIntrinsicWidth(),
|
||||||
drawable.getIntrinsicHeight(),
|
drawable.getIntrinsicHeight(),
|
||||||
@ -191,60 +146,6 @@ public class DisplayUtils {
|
|||||||
return bitmap;
|
return bitmap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ImageRequest getImageRequestForUrl(String url) {
|
|
||||||
return getImageRequestForUrl(url, (User) null);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ImageRequest getImageRequestForUrl(String url, @Nullable User user) {
|
|
||||||
Map<String, String> headers = new HashMap<>();
|
|
||||||
if (user != null &&
|
|
||||||
url.startsWith(user.getBaseUrl()) &&
|
|
||||||
(url.contains("index.php/core/preview?fileId=") || url.contains("/avatar/"))) {
|
|
||||||
headers.put("Authorization", ApiUtils.getCredentials(user.getUsername(), user.getToken()));
|
|
||||||
}
|
|
||||||
|
|
||||||
return ImageRequestBuilder.newBuilderWithSource(Uri.parse(url))
|
|
||||||
.setProgressiveRenderingEnabled(true)
|
|
||||||
.setRotationOptions(RotationOptions.autoRotate())
|
|
||||||
.disableDiskCache()
|
|
||||||
.setHeaders(headers)
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ControllerListener getImageControllerListener(SimpleDraweeView draweeView) {
|
|
||||||
return new ControllerListener() {
|
|
||||||
@Override
|
|
||||||
public void onSubmit(String id, Object callerContext) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFinalImageSet(String id, @Nullable Object imageInfo, @Nullable Animatable animatable) {
|
|
||||||
updateViewSize((ImageInfo) imageInfo, draweeView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onIntermediateImageSet(String id, @Nullable Object imageInfo) {
|
|
||||||
updateViewSize((ImageInfo) imageInfo, draweeView);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onIntermediateImageFailed(String id, Throwable throwable) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onFailure(String id, Throwable throwable) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onRelease(String id) {
|
|
||||||
// unused atm
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
public static float convertDpToPixel(float dp, Context context) {
|
public static float convertDpToPixel(float dp, Context context) {
|
||||||
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
|
return Math.round(TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
|
||||||
context.getResources().getDisplayMetrics()) + 0.5f);
|
context.getResources().getDisplayMetrics()) + 0.5f);
|
||||||
@ -335,33 +236,37 @@ public class DisplayUtils {
|
|||||||
conversationUser.getBaseUrl(),
|
conversationUser.getBaseUrl(),
|
||||||
String.valueOf(label), true);
|
String.valueOf(label), true);
|
||||||
}
|
}
|
||||||
ImageRequest imageRequest = getImageRequestForUrl(url);
|
|
||||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
|
||||||
DataSource<CloseableReference<CloseableImage>> dataSource = imagePipeline.fetchDecodedImage(
|
|
||||||
imageRequest,
|
|
||||||
context);
|
|
||||||
|
|
||||||
dataSource.subscribe(
|
ImageRequest imageRequest = new ImageRequest.Builder(context)
|
||||||
new BaseBitmapDataSubscriber() {
|
.data(url)
|
||||||
|
.crossfade(true)
|
||||||
|
.transformations(new CircleCropTransformation())
|
||||||
|
.target(new Target() {
|
||||||
@Override
|
@Override
|
||||||
protected void onNewResultImpl(Bitmap bitmap) {
|
public void onStart(@Nullable Drawable drawable) {
|
||||||
if (bitmap != null) {
|
|
||||||
chip.setChipIcon(getRoundedDrawable(new BitmapDrawable(bitmap)));
|
|
||||||
|
|
||||||
// A hack to refresh the chip icon
|
}
|
||||||
if (emojiEditText != null) {
|
|
||||||
emojiEditText.post(() -> emojiEditText.setTextKeepState(
|
@Override
|
||||||
emojiEditText.getText(),
|
public void onError(@Nullable Drawable drawable) {
|
||||||
TextView.BufferType.SPANNABLE));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onSuccess(@NonNull Drawable drawable) {
|
||||||
|
chip.setChipIcon(drawable);
|
||||||
|
|
||||||
|
// A hack to refresh the chip icon
|
||||||
|
if (emojiEditText != null) {
|
||||||
|
emojiEditText.post(() -> emojiEditText.setTextKeepState(
|
||||||
|
emojiEditText.getText(),
|
||||||
|
TextView.BufferType.SPANNABLE));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
.build();
|
||||||
|
|
||||||
@Override
|
Coil.imageLoader(context).enqueue(imageRequest);
|
||||||
protected void onFailureImpl(DataSource<CloseableReference<CloseableImage>> dataSource) {
|
|
||||||
}
|
|
||||||
},
|
|
||||||
UiThreadImmediateExecutorService.getInstance());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return chip;
|
return chip;
|
||||||
@ -575,7 +480,7 @@ public class DisplayUtils {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadAvatarImage(User user, SimpleDraweeView avatarImageView, boolean deleteCache) {
|
public static void loadAvatarImage(User user, ImageView avatarImageView, boolean deleteCache) {
|
||||||
String avatarId;
|
String avatarId;
|
||||||
if (!TextUtils.isEmpty(user.getUserId())) {
|
if (!TextUtils.isEmpty(user.getUserId())) {
|
||||||
avatarId = user.getUserId();
|
avatarId = user.getUserId();
|
||||||
@ -583,50 +488,13 @@ public class DisplayUtils {
|
|||||||
avatarId = user.getUsername();
|
avatarId = user.getUsername();
|
||||||
}
|
}
|
||||||
|
|
||||||
String avatarString = ApiUtils.getUrlForAvatar(user.getBaseUrl(), avatarId, true);
|
|
||||||
|
|
||||||
// clear cache
|
|
||||||
if (deleteCache) {
|
if (deleteCache) {
|
||||||
Uri avatarUri = Uri.parse(avatarString);
|
ImageViewExtensionsKt.replaceAvatar(avatarImageView, user, avatarId, true);
|
||||||
|
|
||||||
ImagePipeline imagePipeline = Fresco.getImagePipeline();
|
|
||||||
imagePipeline.evictFromMemoryCache(avatarUri);
|
|
||||||
imagePipeline.evictFromDiskCache(avatarUri);
|
|
||||||
imagePipeline.evictFromCache(avatarUri);
|
|
||||||
}
|
|
||||||
|
|
||||||
DraweeController draweeController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(avatarImageView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(DisplayUtils.getImageRequestForUrl(avatarString))
|
|
||||||
.build();
|
|
||||||
avatarImageView.setController(draweeController);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void loadAvatarPlaceholder(final SimpleDraweeView targetView) {
|
|
||||||
final Context context = targetView.getContext();
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
Drawable[] layers = new Drawable[2];
|
|
||||||
layers[0] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_background);
|
|
||||||
layers[1] = ContextCompat.getDrawable(context, R.drawable.ic_launcher_foreground);
|
|
||||||
LayerDrawable layerDrawable = new LayerDrawable(layers);
|
|
||||||
|
|
||||||
targetView.getHierarchy().setPlaceholderImage(
|
|
||||||
DisplayUtils.getRoundedDrawable(layerDrawable));
|
|
||||||
} else {
|
} else {
|
||||||
targetView.getHierarchy().setPlaceholderImage(R.mipmap.ic_launcher);
|
ImageViewExtensionsKt.loadAvatar(avatarImageView, user, avatarId, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void loadImage(final SimpleDraweeView targetView, final ImageRequest imageRequest) {
|
|
||||||
final DraweeController newController = Fresco.newDraweeControllerBuilder()
|
|
||||||
.setOldController(targetView.getController())
|
|
||||||
.setAutoPlayAnimations(true)
|
|
||||||
.setImageRequest(imageRequest)
|
|
||||||
.build();
|
|
||||||
targetView.setController(newController);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static @StringRes
|
public static @StringRes
|
||||||
int getSortOrderStringId(FileSortOrder sortOrder) {
|
int getSortOrderStringId(FileSortOrder sortOrder) {
|
||||||
switch (sortOrder.getName()) {
|
switch (sortOrder.getName()) {
|
||||||
@ -649,7 +517,7 @@ public class DisplayUtils {
|
|||||||
/**
|
/**
|
||||||
* calculates the relative time string based on the given modification timestamp.
|
* calculates the relative time string based on the given modification timestamp.
|
||||||
*
|
*
|
||||||
* @param context the app's context
|
* @param context the app's context
|
||||||
* @param modificationTimestamp the UNIX timestamp of the file modification time in milliseconds.
|
* @param modificationTimestamp the UNIX timestamp of the file modification time in milliseconds.
|
||||||
* @return a relative time string
|
* @return a relative time string
|
||||||
*/
|
*/
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
package com.nextcloud.talk.utils
|
package com.nextcloud.talk.utils
|
||||||
|
|
||||||
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
import com.nextcloud.talk.remotefilebrowser.model.RemoteFileBrowserItem
|
||||||
import third_parties.daveKoeller.AlphanumComparator
|
import third.parties.daveKoeller.AlphanumComparator
|
||||||
import java.util.Collections
|
import java.util.Collections
|
||||||
|
|
||||||
class FileSortOrderByName internal constructor(name: String, ascending: Boolean) : FileSortOrder(name, ascending) {
|
class FileSortOrderByName internal constructor(name: String, ascending: Boolean) : FileSortOrder(name, ascending) {
|
||||||
@ -40,7 +40,8 @@ class FileSortOrderByName internal constructor(name: String, ascending: Boolean)
|
|||||||
* Comparator for RemoteFileBrowserItems, sorts by name.
|
* Comparator for RemoteFileBrowserItems, sorts by name.
|
||||||
*/
|
*/
|
||||||
class RemoteFileBrowserItemNameComparator(private val multiplier: Int) : Comparator<RemoteFileBrowserItem> {
|
class RemoteFileBrowserItemNameComparator(private val multiplier: Int) : Comparator<RemoteFileBrowserItem> {
|
||||||
private val alphanumComparator = AlphanumComparator<RemoteFileBrowserItem>()
|
private val alphanumComparator =
|
||||||
|
AlphanumComparator<RemoteFileBrowserItem>()
|
||||||
|
|
||||||
override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
|
override fun compare(left: RemoteFileBrowserItem, right: RemoteFileBrowserItem): Int {
|
||||||
return if (!left.isFile && !right.isFile) {
|
return if (!left.isFile && !right.isFile) {
|
||||||
|
@ -28,6 +28,7 @@ import android.net.Uri
|
|||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.util.Log
|
import android.util.Log
|
||||||
import android.view.View
|
import android.view.View
|
||||||
|
import android.widget.ImageView
|
||||||
import android.widget.ProgressBar
|
import android.widget.ProgressBar
|
||||||
import android.widget.Toast
|
import android.widget.Toast
|
||||||
import androidx.core.content.FileProvider
|
import androidx.core.content.FileProvider
|
||||||
@ -36,7 +37,6 @@ import androidx.work.Data
|
|||||||
import androidx.work.OneTimeWorkRequest
|
import androidx.work.OneTimeWorkRequest
|
||||||
import androidx.work.WorkInfo
|
import androidx.work.WorkInfo
|
||||||
import androidx.work.WorkManager
|
import androidx.work.WorkManager
|
||||||
import com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.activities.FullScreenImageActivity
|
import com.nextcloud.talk.activities.FullScreenImageActivity
|
||||||
import com.nextcloud.talk.activities.FullScreenMediaActivity
|
import com.nextcloud.talk.activities.FullScreenMediaActivity
|
||||||
@ -412,7 +412,7 @@ class FileViewerUtils(private val context: Context, private val user: User) {
|
|||||||
data class ProgressUi(
|
data class ProgressUi(
|
||||||
val progressBar: ProgressBar?,
|
val progressBar: ProgressBar?,
|
||||||
val messageText: EmojiTextView?,
|
val messageText: EmojiTextView?,
|
||||||
val previewImage: SimpleDraweeView
|
val previewImage: ImageView
|
||||||
)
|
)
|
||||||
|
|
||||||
data class FileInfo(
|
data class FileInfo(
|
||||||
|
@ -27,18 +27,19 @@ import android.app.Notification
|
|||||||
import android.app.NotificationChannel
|
import android.app.NotificationChannel
|
||||||
import android.app.NotificationManager
|
import android.app.NotificationManager
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import android.graphics.drawable.BitmapDrawable
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Build
|
import android.os.Build
|
||||||
import android.service.notification.StatusBarNotification
|
import android.service.notification.StatusBarNotification
|
||||||
import android.text.TextUtils
|
import android.text.TextUtils
|
||||||
|
import android.util.Log
|
||||||
import androidx.core.graphics.drawable.IconCompat
|
import androidx.core.graphics.drawable.IconCompat
|
||||||
|
import coil.executeBlocking
|
||||||
|
import coil.imageLoader
|
||||||
|
import coil.request.ImageRequest
|
||||||
|
import coil.transform.CircleCropTransformation
|
||||||
import com.bluelinelabs.logansquare.LoganSquare
|
import com.bluelinelabs.logansquare.LoganSquare
|
||||||
import com.facebook.common.references.CloseableReference
|
|
||||||
import com.facebook.datasource.DataSources
|
|
||||||
import com.facebook.drawee.backends.pipeline.Fresco
|
|
||||||
import com.facebook.imagepipeline.image.CloseableBitmap
|
|
||||||
import com.facebook.imagepipeline.postprocessors.RoundAsCirclePostprocessor
|
|
||||||
import com.nextcloud.talk.BuildConfig
|
import com.nextcloud.talk.BuildConfig
|
||||||
import com.nextcloud.talk.R
|
import com.nextcloud.talk.R
|
||||||
import com.nextcloud.talk.data.user.model.User
|
import com.nextcloud.talk.data.user.model.User
|
||||||
@ -50,6 +51,8 @@ import java.io.IOException
|
|||||||
@Suppress("TooManyFunctions")
|
@Suppress("TooManyFunctions")
|
||||||
object NotificationUtils {
|
object NotificationUtils {
|
||||||
|
|
||||||
|
const val TAG = "NotificationUtils"
|
||||||
|
|
||||||
enum class NotificationChannels {
|
enum class NotificationChannels {
|
||||||
NOTIFICATION_CHANNEL_MESSAGES_V4,
|
NOTIFICATION_CHANNEL_MESSAGES_V4,
|
||||||
NOTIFICATION_CHANNEL_CALLS_V4,
|
NOTIFICATION_CHANNEL_CALLS_V4,
|
||||||
@ -320,28 +323,31 @@ object NotificationUtils {
|
|||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
fun loadAvatarSync(avatarUrl: String, context: Context): IconCompat? {
|
||||||
* Load user avatar synchronously.
|
|
||||||
* Inspired by:
|
|
||||||
* https://frescolib.org/docs/using-image-pipeline.html
|
|
||||||
* https://github.com/facebook/fresco/issues/830
|
|
||||||
* https://localcoder.org/using-facebooks-fresco-to-load-a-bitmap
|
|
||||||
*/
|
|
||||||
fun loadAvatarSync(avatarUrl: String): IconCompat? {
|
|
||||||
// TODO - how to handle errors here?
|
|
||||||
var avatarIcon: IconCompat? = null
|
var avatarIcon: IconCompat? = null
|
||||||
val imageRequest = DisplayUtils.getImageRequestForUrl(avatarUrl)
|
|
||||||
val dataSource = Fresco.getImagePipeline().fetchDecodedImage(imageRequest, null)
|
val request = ImageRequest.Builder(context)
|
||||||
val closeableImageRef = DataSources.waitForFinalResult(dataSource) as CloseableReference<CloseableBitmap>?
|
.data(avatarUrl)
|
||||||
val bitmap = closeableImageRef?.get()?.underlyingBitmap
|
.transformations(CircleCropTransformation())
|
||||||
if (bitmap != null) {
|
.placeholder(R.drawable.account_circle_96dp)
|
||||||
// According to Fresco documentation a copy of the bitmap should be made before closing the references.
|
.placeholder(R.drawable.account_circle_96dp)
|
||||||
// However, it seems to work without making a copy... ;-)
|
.target(
|
||||||
RoundAsCirclePostprocessor(true).process(bitmap)
|
onSuccess = { result ->
|
||||||
avatarIcon = IconCompat.createWithBitmap(bitmap)
|
val bitmap = (result as BitmapDrawable).bitmap
|
||||||
}
|
avatarIcon = IconCompat.createWithBitmap(bitmap)
|
||||||
CloseableReference.closeSafely(closeableImageRef)
|
},
|
||||||
dataSource.close()
|
onError = { error ->
|
||||||
|
error?.let {
|
||||||
|
val bitmap = (error as BitmapDrawable).bitmap
|
||||||
|
avatarIcon = IconCompat.createWithBitmap(bitmap)
|
||||||
|
}
|
||||||
|
Log.w(TAG, "Can't load avatar for URL: $avatarUrl")
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.build()
|
||||||
|
|
||||||
|
context.imageLoader.executeBlocking(request)
|
||||||
|
|
||||||
return avatarIcon
|
return avatarIcon
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,41 +0,0 @@
|
|||||||
/*
|
|
||||||
* Nextcloud Talk application
|
|
||||||
*
|
|
||||||
* @author Mario Danic
|
|
||||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
package com.nextcloud.talk.utils;
|
|
||||||
|
|
||||||
import com.facebook.imagepipeline.backends.okhttp3.OkHttpNetworkFetcher;
|
|
||||||
import okhttp3.Call;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
|
|
||||||
import java.util.concurrent.Executor;
|
|
||||||
|
|
||||||
public class OkHttpNetworkFetcherWithCache extends OkHttpNetworkFetcher {
|
|
||||||
public OkHttpNetworkFetcherWithCache(OkHttpClient okHttpClient) {
|
|
||||||
super(okHttpClient);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OkHttpNetworkFetcherWithCache(Call.Factory callFactory, Executor cancellationExecutor) {
|
|
||||||
super(callFactory, cancellationExecutor);
|
|
||||||
}
|
|
||||||
|
|
||||||
public OkHttpNetworkFetcherWithCache(Call.Factory callFactory, Executor cancellationExecutor, boolean disableOkHttpCache) {
|
|
||||||
super(callFactory, cancellationExecutor, true);
|
|
||||||
}
|
|
||||||
}
|
|
@ -22,9 +22,10 @@ package com.nextcloud.talk.utils.text;
|
|||||||
|
|
||||||
import android.graphics.drawable.Drawable;
|
import android.graphics.drawable.Drawable;
|
||||||
|
|
||||||
import com.facebook.widget.text.span.BetterImageSpan;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
import third.parties.fresco.BetterImageSpan;
|
||||||
|
|
||||||
public class Spans {
|
public class Spans {
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package third_parties.daveKoeller;
|
package third.parties.daveKoeller;
|
||||||
|
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
138
app/src/main/java/third/parties/fresco/BetterImageSpan.kt
Normal file
138
app/src/main/java/third/parties/fresco/BetterImageSpan.kt
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2015-present, Facebook, Inc.
|
||||||
|
*
|
||||||
|
* MIT License
|
||||||
|
*
|
||||||
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in all
|
||||||
|
* copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
* SOFTWARE.
|
||||||
|
*/
|
||||||
|
package third.parties.fresco
|
||||||
|
|
||||||
|
import android.graphics.Canvas
|
||||||
|
import android.graphics.Paint
|
||||||
|
import android.graphics.Paint.FontMetricsInt
|
||||||
|
import android.graphics.Rect
|
||||||
|
import android.graphics.drawable.Drawable
|
||||||
|
import android.text.style.ReplacementSpan
|
||||||
|
import androidx.annotation.IntDef
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A better implementation of image spans that also supports centering images against the text.
|
||||||
|
*
|
||||||
|
* In order to migrate from ImageSpan, replace `new ImageSpan(drawable, alignment)` with
|
||||||
|
* `new BetterImageSpan(drawable, BetterImageSpan.normalizeAlignment(alignment))`.
|
||||||
|
*
|
||||||
|
* There are 2 main differences between BetterImageSpan and ImageSpan:
|
||||||
|
* 1. Pass in ALIGN_CENTER to center images against the text.
|
||||||
|
* 2. ALIGN_BOTTOM no longer unnecessarily increases the size of the text:
|
||||||
|
* DynamicDrawableSpan (ImageSpan's parent) adjusts sizes as if alignment was ALIGN_BASELINE
|
||||||
|
* which can lead to unnecessary whitespace.
|
||||||
|
*/
|
||||||
|
open class BetterImageSpan @JvmOverloads constructor(
|
||||||
|
val drawable: Drawable,
|
||||||
|
@param:BetterImageSpanAlignment private val mAlignment: Int = ALIGN_BASELINE
|
||||||
|
) : ReplacementSpan() {
|
||||||
|
@IntDef(*[ALIGN_BASELINE, ALIGN_BOTTOM, ALIGN_CENTER])
|
||||||
|
@Retention(AnnotationRetention.SOURCE)
|
||||||
|
annotation class BetterImageSpanAlignment
|
||||||
|
|
||||||
|
private var mWidth = 0
|
||||||
|
private var mHeight = 0
|
||||||
|
private var mBounds: Rect? = null
|
||||||
|
private val mFontMetricsInt = FontMetricsInt()
|
||||||
|
|
||||||
|
init {
|
||||||
|
updateBounds()
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the width of the image span and increases the height if font metrics are available.
|
||||||
|
*/
|
||||||
|
override fun getSize(
|
||||||
|
paint: Paint,
|
||||||
|
text: CharSequence,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
fontMetrics: FontMetricsInt?
|
||||||
|
): Int {
|
||||||
|
updateBounds()
|
||||||
|
if (fontMetrics == null) {
|
||||||
|
return mWidth
|
||||||
|
}
|
||||||
|
val offsetAbove = getOffsetAboveBaseline(fontMetrics)
|
||||||
|
val offsetBelow = mHeight + offsetAbove
|
||||||
|
if (offsetAbove < fontMetrics.ascent) {
|
||||||
|
fontMetrics.ascent = offsetAbove
|
||||||
|
}
|
||||||
|
if (offsetAbove < fontMetrics.top) {
|
||||||
|
fontMetrics.top = offsetAbove
|
||||||
|
}
|
||||||
|
if (offsetBelow > fontMetrics.descent) {
|
||||||
|
fontMetrics.descent = offsetBelow
|
||||||
|
}
|
||||||
|
if (offsetBelow > fontMetrics.bottom) {
|
||||||
|
fontMetrics.bottom = offsetBelow
|
||||||
|
}
|
||||||
|
return mWidth
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun draw(
|
||||||
|
canvas: Canvas,
|
||||||
|
text: CharSequence,
|
||||||
|
start: Int,
|
||||||
|
end: Int,
|
||||||
|
x: Float,
|
||||||
|
top: Int,
|
||||||
|
y: Int,
|
||||||
|
bottom: Int,
|
||||||
|
paint: Paint
|
||||||
|
) {
|
||||||
|
paint.getFontMetricsInt(mFontMetricsInt)
|
||||||
|
val iconTop = y + getOffsetAboveBaseline(mFontMetricsInt)
|
||||||
|
canvas.translate(x, iconTop.toFloat())
|
||||||
|
drawable.draw(canvas)
|
||||||
|
canvas.translate(-x, -iconTop.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun updateBounds() {
|
||||||
|
mBounds = drawable.bounds
|
||||||
|
mWidth = mBounds!!.width()
|
||||||
|
mHeight = mBounds!!.height()
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun getOffsetAboveBaseline(fm: FontMetricsInt): Int {
|
||||||
|
return when (mAlignment) {
|
||||||
|
ALIGN_BOTTOM -> fm.descent - mHeight
|
||||||
|
ALIGN_CENTER -> {
|
||||||
|
val textHeight = fm.descent - fm.ascent
|
||||||
|
val offset = (textHeight - mHeight) / 2
|
||||||
|
fm.ascent + offset
|
||||||
|
}
|
||||||
|
ALIGN_BASELINE -> -mHeight
|
||||||
|
else -> -mHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val ALIGN_BOTTOM = 0
|
||||||
|
const val ALIGN_BASELINE = 1
|
||||||
|
const val ALIGN_CENTER = 2
|
||||||
|
}
|
||||||
|
}
|
5
app/src/main/res/drawable/shape_oval.xml
Normal file
5
app/src/main/res/drawable/shape_oval.xml
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<shape xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:shape="oval">
|
||||||
|
<solid android:color="#000000" />
|
||||||
|
</shape>
|
@ -21,7 +21,6 @@
|
|||||||
-->
|
-->
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
@ -44,7 +43,7 @@
|
|||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_centerVertical="true">
|
android:layout_centerVertical="true">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/user_icon"
|
android:id="@+id/user_icon"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
@ -54,10 +53,7 @@
|
|||||||
android:layout_marginEnd="1dp"
|
android:layout_marginEnd="1dp"
|
||||||
android:layout_marginBottom="1dp"
|
android:layout_marginBottom="1dp"
|
||||||
android:contentDescription="@string/avatar"
|
android:contentDescription="@string/avatar"
|
||||||
android:src="@drawable/account_circle_48dp"
|
android:src="@drawable/account_circle_48dp" />
|
||||||
fresco:placeholderImage="@drawable/account_circle_48dp"
|
|
||||||
fresco:failureImage="@drawable/account_circle_48dp"
|
|
||||||
app:roundAsCircle="true"/>
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
|
@ -113,7 +113,8 @@
|
|||||||
android:transitionName="userAvatar.transitionTag"
|
android:transitionName="userAvatar.transitionTag"
|
||||||
app:cornerRadius="@dimen/button_corner_radius"
|
app:cornerRadius="@dimen/button_corner_radius"
|
||||||
app:iconSize="@dimen/avatar_size_app_bar"
|
app:iconSize="@dimen/avatar_size_app_bar"
|
||||||
tools:visibility="gone" />
|
app:iconTint="@null"
|
||||||
|
tools:icon="@drawable/ic_user" />
|
||||||
|
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
@ -2,9 +2,11 @@
|
|||||||
~ Nextcloud Talk application
|
~ Nextcloud Talk application
|
||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
|
||||||
~ @author Marcel Hibbe
|
~ @author Marcel Hibbe
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
~ Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||||
|
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
~
|
~
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
~ it under the terms of the GNU General Public License as published by
|
~ it under the terms of the GNU General Public License as published by
|
||||||
@ -69,14 +71,14 @@
|
|||||||
android:visibility="invisible"
|
android:visibility="invisible"
|
||||||
tools:visibility="visible" />
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/switchSelfVideoButton"
|
android:id="@+id/switchSelfVideoButton"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_gravity="center_horizontal|bottom"
|
android:layout_gravity="center_horizontal|bottom"
|
||||||
android:layout_marginBottom="20dp"
|
android:layout_marginBottom="20dp"
|
||||||
app:placeholderImage="@drawable/ic_switch_video_white_24px"
|
app:srcCompat="@drawable/ic_switch_video_white_24px"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/nc_call_button_content_description_switch_to_self_vide"/>
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/selfVideoViewProgressBar"
|
android:id="@+id/selfVideoViewProgressBar"
|
||||||
@ -144,6 +146,7 @@
|
|||||||
android:id="@+id/callControls"
|
android:id="@+id/callControls"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/call_controls_height"
|
android:layout_height="@dimen/call_controls_height"
|
||||||
|
android:paddingHorizontal="@dimen/call_controls_padding_horizontal"
|
||||||
android:layout_alignBottom="@id/linearWrapperLayout"
|
android:layout_alignBottom="@id/linearWrapperLayout"
|
||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:background="@android:color/transparent"
|
android:background="@android:color/transparent"
|
||||||
@ -151,94 +154,98 @@
|
|||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:weightSum="5">
|
android:weightSum="5">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/pictureInPictureButton"
|
android:id="@+id/pictureInPictureButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="20dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginHorizontal="@dimen/call_controls_margin_horizontal"
|
||||||
android:elevation="10dp"
|
android:layout_weight="1"
|
||||||
app:backgroundImage="@color/call_buttons_background"
|
android:background="@drawable/shape_oval"
|
||||||
app:placeholderImage="@drawable/ic_baseline_picture_in_picture_alt_24"
|
android:backgroundTint="@color/call_buttons_background"
|
||||||
app:roundAsCircle="true"
|
app:srcCompat="@drawable/ic_baseline_picture_in_picture_alt_24"
|
||||||
android:layout_weight="1"/>
|
android:contentDescription="@string/nc_call_button_content_description_pip" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/audioOutputButton"
|
android:id="@+id/audioOutputButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginHorizontal="@dimen/call_controls_margin_horizontal"
|
||||||
app:backgroundImage="@color/call_buttons_background"
|
android:layout_weight="1"
|
||||||
app:placeholderImage="@drawable/ic_volume_mute_white_24dp"
|
android:background="@drawable/shape_oval"
|
||||||
app:roundAsCircle="true"
|
android:backgroundTint="@color/call_buttons_background"
|
||||||
android:layout_weight="1"/>
|
app:srcCompat="@drawable/ic_volume_mute_white_24dp"
|
||||||
|
android:contentDescription="@string/nc_call_button_content_description_audio_output" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/cameraButton"
|
android:id="@+id/cameraButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginHorizontal="@dimen/call_controls_margin_horizontal"
|
||||||
|
android:layout_weight="1"
|
||||||
android:alpha="0.7"
|
android:alpha="0.7"
|
||||||
app:backgroundImage="@color/call_buttons_background"
|
android:background="@drawable/shape_oval"
|
||||||
app:placeholderImage="@drawable/ic_videocam_white_24px"
|
android:backgroundTint="@color/call_buttons_background"
|
||||||
app:roundAsCircle="true"
|
app:srcCompat="@drawable/ic_videocam_white_24px"
|
||||||
android:layout_weight="1"/>
|
android:contentDescription="@string/nc_call_button_content_description_camera" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/microphoneButton"
|
android:id="@+id/microphoneButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginEnd="10dp"
|
android:layout_marginHorizontal="@dimen/call_controls_margin_horizontal"
|
||||||
|
android:layout_weight="1"
|
||||||
android:alpha="0.7"
|
android:alpha="0.7"
|
||||||
app:backgroundImage="@color/call_buttons_background"
|
android:background="@drawable/shape_oval"
|
||||||
app:placeholderImage="@drawable/ic_mic_off_white_24px"
|
android:backgroundTint="@color/call_buttons_background"
|
||||||
app:roundAsCircle="true"
|
app:srcCompat="@drawable/ic_mic_off_white_24px"
|
||||||
android:layout_weight="1"/>
|
android:contentDescription="@string/nc_call_button_content_description_microphone" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/hangupButton"
|
android:id="@+id/hangupButton"
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginStart="10dp"
|
android:adjustViewBounds="true"
|
||||||
android:layout_marginEnd="20dp"
|
android:layout_marginHorizontal="@dimen/call_controls_margin_horizontal"
|
||||||
app:backgroundImage="@color/nc_darkRed"
|
android:layout_weight="1"
|
||||||
app:placeholderImage="@drawable/ic_call_end_white_24px"
|
android:background="@drawable/shape_oval"
|
||||||
app:roundAsCircle="true"
|
android:backgroundTint="@color/nc_darkRed"
|
||||||
android:layout_weight="1"/>
|
app:srcCompat="@drawable/ic_call_end_white_24px"
|
||||||
|
android:contentDescription="@string/nc_call_button_content_description_hangup" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@+id/pipGroupCallOverlay"
|
android:id="@+id/pipGroupCallOverlay"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:orientation="vertical"
|
|
||||||
android:background="@color/black"
|
android:background="@color/black"
|
||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
|
android:orientation="vertical"
|
||||||
android:visibility="gone">
|
android:visibility="gone">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/pipCallConversationNameTextView"
|
android:id="@+id/pipCallConversationNameTextView"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginTop="-30dp"
|
|
||||||
android:layout_marginBottom="15dp"
|
|
||||||
android:layout_marginStart="5dp"
|
android:layout_marginStart="5dp"
|
||||||
|
android:layout_marginTop="-30dp"
|
||||||
android:layout_marginEnd="5dp"
|
android:layout_marginEnd="5dp"
|
||||||
android:textAlignment="center"
|
android:layout_marginBottom="15dp"
|
||||||
android:maxLines="3"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:maxLines="3"
|
||||||
|
android:textAlignment="center"
|
||||||
android:textColor="@color/white"
|
android:textColor="@color/white"
|
||||||
android:textSize="16sp"
|
android:textSize="16sp"
|
||||||
tools:text="our group call" />
|
tools:text="our group call" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
app:backgroundImage="@drawable/ic_circular_group"
|
app:srcCompat="@drawable/ic_circular_group"
|
||||||
app:roundAsCircle="true" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
@ -31,12 +31,12 @@
|
|||||||
android:gravity="center"
|
android:gravity="center"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatarImageView"
|
android:id="@+id/avatarImageView"
|
||||||
android:layout_width="80dp"
|
android:layout_width="80dp"
|
||||||
android:layout_height="80dp"
|
android:layout_height="80dp"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar"/>
|
||||||
|
|
||||||
<org.webrtc.SurfaceViewRenderer
|
<org.webrtc.SurfaceViewRenderer
|
||||||
android:id="@+id/surface_view"
|
android:id="@+id/surface_view"
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ @author Andy Scherzinger
|
~ @author Andy Scherzinger
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
~
|
~
|
||||||
@ -36,36 +38,37 @@
|
|||||||
android:animateLayoutChanges="true"
|
android:animateLayoutChanges="true"
|
||||||
android:orientation="horizontal">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/callAnswerVoiceOnlyView"
|
android:id="@+id/callAnswerVoiceOnlyView"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_margin="24dp"
|
android:layout_margin="24dp"
|
||||||
android:visibility="gone"
|
android:background="@drawable/shape_oval"
|
||||||
app:backgroundImage="@color/nc_darkGreen"
|
android:backgroundTint="@color/nc_darkGreen"
|
||||||
app:placeholderImage="@drawable/ic_call_white_24dp"
|
android:src="@drawable/ic_call_white_24dp"
|
||||||
app:roundAsCircle="true"
|
android:contentDescription="@string/nc_call_button_content_description_answer_voice_only" />
|
||||||
tools:visibility="visible" />
|
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/hangupButton"
|
android:id="@+id/hangupButton"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_margin="24dp"
|
android:layout_margin="24dp"
|
||||||
app:backgroundImage="@color/nc_darkRed"
|
android:background="@drawable/shape_oval"
|
||||||
app:placeholderImage="@drawable/ic_call_end_white_24px"
|
android:backgroundTint="@color/nc_darkRed"
|
||||||
app:roundAsCircle="true" />
|
android:src="@drawable/ic_call_end_white_24px"
|
||||||
|
android:contentDescription="@string/nc_call_button_content_description_hangup" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageButton
|
||||||
android:id="@+id/callAnswerCameraView"
|
android:id="@+id/callAnswerCameraView"
|
||||||
android:layout_width="60dp"
|
android:layout_width="60dp"
|
||||||
android:layout_height="60dp"
|
android:layout_height="60dp"
|
||||||
android:layout_margin="24dp"
|
android:layout_margin="24dp"
|
||||||
|
android:background="@drawable/shape_oval"
|
||||||
|
android:backgroundTint="@color/nc_darkGreen"
|
||||||
|
android:src="@drawable/ic_videocam_white_24px"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:backgroundImage="@color/nc_darkGreen"
|
tools:visibility="visible"
|
||||||
app:placeholderImage="@drawable/ic_videocam_white_24px"
|
android:contentDescription="@string/nc_call_button_content_description_answer_video_call" />
|
||||||
app:roundAsCircle="true"
|
|
||||||
tools:visibility="visible" />
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
@ -111,11 +114,11 @@
|
|||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatarImageView"
|
android:id="@+id/avatarImageView"
|
||||||
android:layout_width="@dimen/avatar_size_big"
|
android:layout_width="@dimen/avatar_size_big"
|
||||||
android:layout_height="@dimen/avatar_size_big"
|
android:layout_height="@dimen/avatar_size_big"
|
||||||
android:layout_centerInParent="true"
|
android:layout_centerInParent="true"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -77,13 +77,13 @@
|
|||||||
android:layout_marginTop="@dimen/margin_between_elements"
|
android:layout_marginTop="@dimen/margin_between_elements"
|
||||||
tools:text="Jane Doe" />
|
tools:text="Jane Doe" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar_image"
|
android:id="@+id/avatar_image"
|
||||||
android:layout_width="@dimen/avatar_size_big"
|
android:layout_width="@dimen/avatar_size_big"
|
||||||
android:layout_height="@dimen/avatar_size_big"
|
android:layout_height="@dimen/avatar_size_big"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
apc:roundAsCircle="true"
|
tools:background="@color/hwSecurityRed"
|
||||||
tools:background="@color/hwSecurityRed" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
</com.yarolegovich.mp.MaterialPreferenceCategory>
|
</com.yarolegovich.mp.MaterialPreferenceCategory>
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
-->
|
-->
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
@ -31,7 +30,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar_image"
|
android:id="@+id/avatar_image"
|
||||||
android:layout_width="@dimen/avatar_size_big"
|
android:layout_width="@dimen/avatar_size_big"
|
||||||
android:layout_height="@dimen/avatar_size_big"
|
android:layout_height="@dimen/avatar_size_big"
|
||||||
@ -39,9 +38,7 @@
|
|||||||
android:layout_marginTop="@dimen/standard_margin"
|
android:layout_marginTop="@dimen/standard_margin"
|
||||||
android:src="@drawable/account_circle_96dp"
|
android:src="@drawable/account_circle_96dp"
|
||||||
android:transitionName="userAvatar.transitionTag"
|
android:transitionName="userAvatar.transitionTag"
|
||||||
app:roundAsCircle="true"
|
android:contentDescription="@string/avatar" />
|
||||||
fresco:failureImage="@drawable/account_circle_96dp"
|
|
||||||
fresco:placeholderImage="@drawable/account_circle_96dp" />
|
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/userinfo_fullName"
|
android:id="@+id/userinfo_fullName"
|
||||||
|
@ -25,7 +25,6 @@
|
|||||||
<com.yarolegovich.mp.MaterialPreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.yarolegovich.mp.MaterialPreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:apc="http://schemas.android.com/apk/res-auto"
|
xmlns:apc="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
tools:background="@color/white"
|
tools:background="@color/white"
|
||||||
android:id="@+id/settings_screen"
|
android:id="@+id/settings_screen"
|
||||||
@ -119,16 +118,14 @@
|
|||||||
|
|
||||||
</com.google.android.material.card.MaterialCardView>
|
</com.google.android.material.card.MaterialCardView>
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar_image"
|
android:id="@+id/avatar_image"
|
||||||
android:layout_width="@dimen/avatar_size_big"
|
android:layout_width="@dimen/avatar_size_big"
|
||||||
android:layout_height="@dimen/avatar_size_big"
|
android:layout_height="@dimen/avatar_size_big"
|
||||||
android:layout_centerHorizontal="true"
|
android:layout_centerHorizontal="true"
|
||||||
android:src="@drawable/account_circle_96dp"
|
android:src="@drawable/account_circle_96dp"
|
||||||
android:transitionName="userAvatar.transitionTag"
|
android:transitionName="userAvatar.transitionTag"
|
||||||
apc:roundAsCircle="true"
|
android:contentDescription="@string/avatar" />
|
||||||
fresco:failureImage="@drawable/account_circle_96dp"
|
|
||||||
fresco:placeholderImage="@drawable/account_circle_96dp" />
|
|
||||||
|
|
||||||
<com.yarolegovich.mp.MaterialStandardPreference
|
<com.yarolegovich.mp.MaterialStandardPreference
|
||||||
android:id="@+id/settings_remove_account"
|
android:id="@+id/settings_remove_account"
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
-->
|
-->
|
||||||
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
<com.google.android.material.card.MaterialCardView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="72dp"
|
android:layout_height="72dp"
|
||||||
@ -45,7 +44,7 @@
|
|||||||
android:layout_alignParentStart="true"
|
android:layout_alignParentStart="true"
|
||||||
android:layout_centerVertical="true">
|
android:layout_centerVertical="true">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/user_icon"
|
android:id="@+id/user_icon"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
@ -55,10 +54,7 @@
|
|||||||
android:layout_marginEnd="1dp"
|
android:layout_marginEnd="1dp"
|
||||||
android:layout_marginBottom="1dp"
|
android:layout_marginBottom="1dp"
|
||||||
android:contentDescription="@string/avatar"
|
android:contentDescription="@string/avatar"
|
||||||
android:src="@drawable/account_circle_48dp"
|
android:src="@drawable/account_circle_48dp" />
|
||||||
fresco:placeholderImage="@drawable/account_circle_48dp"
|
|
||||||
fresco:failureImage="@drawable/account_circle_48dp"
|
|
||||||
app:roundAsCircle="true"/>
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/ticker"
|
android:id="@+id/ticker"
|
||||||
|
@ -32,13 +32,13 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@id/bubble"
|
android:id="@id/bubble"
|
||||||
|
@ -31,13 +31,13 @@
|
|||||||
android:layout_marginEnd="@dimen/standard_margin"
|
android:layout_marginEnd="@dimen/standard_margin"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@id/bubble"
|
android:id="@id/bubble"
|
||||||
|
@ -28,13 +28,13 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@id/bubble"
|
android:id="@id/bubble"
|
||||||
|
@ -32,13 +32,13 @@
|
|||||||
android:layout_marginEnd="14dp"
|
android:layout_marginEnd="14dp"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="6dp"
|
android:layout_marginEnd="6dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@ -64,14 +64,13 @@
|
|||||||
app:layout_wrapBefore="true"
|
app:layout_wrapBefore="true"
|
||||||
tools:visibility="gone">
|
tools:visibility="gone">
|
||||||
|
|
||||||
<!-- SimpleDraweeView does not support wrap_content for layout_width or layout_height attributes! -->
|
<ImageView
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
android:id="@id/image"
|
android:id="@id/image"
|
||||||
android:layout_width="100dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="fitStart"
|
android:scaleType="fitStart"
|
||||||
app:roundedCornerRadius="6dp"
|
tools:src="@drawable/ic_call_black_24dp"
|
||||||
tools:src="@drawable/ic_call_black_24dp" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
@ -105,14 +104,13 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:adjustViewBounds="true">
|
android:adjustViewBounds="true">
|
||||||
|
|
||||||
<!-- SimpleDraweeView does not support wrap_content for layout_width or layout_height attributes! -->
|
<ImageView
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
android:id="@+id/contact_photo"
|
android:id="@+id/contact_photo"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:scaleType="fitStart"
|
android:scaleType="fitStart"
|
||||||
app:roundAsCircle="true"
|
tools:src="@drawable/ic_call_black_24dp"
|
||||||
tools:src="@drawable/ic_call_black_24dp" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/contact_progress_bar"
|
android:id="@+id/contact_progress_bar"
|
||||||
|
@ -30,13 +30,13 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@id/bubble"
|
android:id="@id/bubble"
|
||||||
|
@ -32,13 +32,13 @@
|
|||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
android:layout_marginBottom="2dp">
|
android:layout_marginBottom="2dp">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/messageUserAvatar"
|
android:id="@id/messageUserAvatar"
|
||||||
android:layout_width="24dp"
|
android:layout_width="24dp"
|
||||||
android:layout_height="24dp"
|
android:layout_height="24dp"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
<com.google.android.flexbox.FlexboxLayout
|
<com.google.android.flexbox.FlexboxLayout
|
||||||
android:id="@id/bubble"
|
android:id="@id/bubble"
|
||||||
|
@ -55,14 +55,13 @@
|
|||||||
app:layout_flexGrow="1"
|
app:layout_flexGrow="1"
|
||||||
app:layout_wrapBefore="true">
|
app:layout_wrapBefore="true">
|
||||||
|
|
||||||
<!-- SimpleDraweeView does not support wrap_content for layout_width or layout_height attributes! -->
|
<ImageView
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
android:id="@id/image"
|
android:id="@id/image"
|
||||||
android:layout_width="100dp"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="100dp"
|
android:layout_height="wrap_content"
|
||||||
android:scaleType="fitEnd"
|
android:scaleType="fitStart"
|
||||||
app:roundedCornerRadius="6dp"
|
tools:src="@drawable/ic_call_black_24dp"
|
||||||
tools:src="@drawable/ic_call_black_24dp" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
@ -95,14 +94,13 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:adjustViewBounds="true">
|
android:adjustViewBounds="true">
|
||||||
|
|
||||||
<!-- SimpleDraweeView does not support wrap_content for layout_width or layout_height attributes! -->
|
<ImageView
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
|
||||||
android:id="@+id/contact_photo"
|
android:id="@+id/contact_photo"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:scaleType="fitStart"
|
android:scaleType="fitStart"
|
||||||
app:roundAsCircle="true"
|
tools:src="@drawable/ic_call_black_24dp"
|
||||||
tools:src="@drawable/ic_call_black_24dp" />
|
tools:ignore="ContentDescription" />
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/contact_progress_bar"
|
android:id="@+id/contact_progress_bar"
|
||||||
|
@ -19,20 +19,19 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
tools:background="@color/white">
|
tools:background="@color/white">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/poll_voter_avatar"
|
android:id="@+id/poll_voter_avatar"
|
||||||
android:layout_width="32dp"
|
android:layout_width="32dp"
|
||||||
android:layout_height="32dp"
|
android:layout_height="32dp"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:layout_gravity="center"
|
android:layout_gravity="center"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/poll_voter_name"
|
android:id="@+id/poll_voter_name"
|
||||||
|
@ -19,19 +19,18 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="@dimen/item_height"
|
android:layout_height="@dimen/item_height"
|
||||||
android:background="?android:attr/selectableItemBackground">
|
android:background="?android:attr/selectableItemBackground">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar"
|
android:id="@+id/avatar"
|
||||||
android:layout_width="@dimen/avatar_size"
|
android:layout_width="@dimen/avatar_size"
|
||||||
android:layout_height="@dimen/avatar_size"
|
android:layout_height="@dimen/avatar_size"
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:layout_margin="@dimen/standard_margin"
|
android:layout_margin="@dimen/standard_margin"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar"/>
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/name"
|
android:id="@+id/name"
|
||||||
|
@ -19,7 +19,6 @@
|
|||||||
-->
|
-->
|
||||||
|
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:id="@+id/referenceWrapper"
|
android:id="@+id/referenceWrapper"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
@ -32,64 +31,64 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginEnd="8dp"
|
android:layout_marginEnd="8dp"
|
||||||
android:background="@color/low_emphasis_text"
|
android:background="@color/low_emphasis_text"
|
||||||
tools:layout_height="100dp"/>
|
tools:layout_height="100dp" />
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/referenceName"
|
android:id="@+id/referenceName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:ellipsize="end"
|
||||||
android:lineSpacingMultiplier="1.2"
|
android:lineSpacingMultiplier="1.2"
|
||||||
|
android:maxLines="2"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textIsSelectable="false"
|
android:textIsSelectable="false"
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:visibility="gone"
|
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
android:textStyle="bold"
|
android:textStyle="bold"
|
||||||
|
android:visibility="gone"
|
||||||
tools:text="Name of Website"
|
tools:text="Name of Website"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/referenceDescription"
|
android:id="@+id/referenceDescription"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/referenceName"
|
android:layout_below="@id/referenceName"
|
||||||
|
android:layout_marginStart="10dp"
|
||||||
|
android:ellipsize="end"
|
||||||
android:lineSpacingMultiplier="1.2"
|
android:lineSpacingMultiplier="1.2"
|
||||||
|
android:maxLines="2"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textIsSelectable="false"
|
android:textIsSelectable="false"
|
||||||
android:layout_marginStart="10dp"
|
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
android:ellipsize="end"
|
|
||||||
android:maxLines="2"
|
|
||||||
tools:text="Description of Website"
|
tools:text="Description of Website"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/referenceLink"
|
android:id="@+id/referenceLink"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_below="@id/referenceDescription"
|
android:layout_below="@id/referenceDescription"
|
||||||
android:lineSpacingMultiplier="1.2"
|
|
||||||
android:textAlignment="viewStart"
|
|
||||||
android:textIsSelectable="false"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
android:textColor="@color/medium_emphasis_text"
|
|
||||||
android:singleLine="true"
|
|
||||||
android:lines="1"
|
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
|
android:lineSpacingMultiplier="1.2"
|
||||||
|
android:lines="1"
|
||||||
|
android:singleLine="true"
|
||||||
|
android:textAlignment="viewStart"
|
||||||
|
android:textColor="@color/medium_emphasis_text"
|
||||||
|
android:textIsSelectable="false"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
tools:text="http://nextcloud.com"
|
tools:text="http://nextcloud.com"
|
||||||
tools:visibility="visible"/>
|
tools:visibility="visible" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/referenceThumbImage"
|
android:id="@+id/referenceThumbImage"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="120dp"
|
android:layout_height="120dp"
|
||||||
android:scaleType="fitEnd"
|
|
||||||
android:layout_below="@id/referenceLink"
|
android:layout_below="@id/referenceLink"
|
||||||
android:layout_marginTop="5dp"
|
|
||||||
android:layout_marginStart="10dp"
|
android:layout_marginStart="10dp"
|
||||||
|
android:layout_marginTop="5dp"
|
||||||
|
android:scaleType="fitEnd"
|
||||||
android:visibility="gone"
|
android:visibility="gone"
|
||||||
app:roundedCornerRadius="6dp"
|
tools:visibility="visible"
|
||||||
tools:visibility="visible"/>
|
tools:ignore="ContentDescription" />
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
@ -93,13 +93,12 @@
|
|||||||
android:textSize="@dimen/two_line_primary_text_size"
|
android:textSize="@dimen/two_line_primary_text_size"
|
||||||
tools:text="filename.md" />
|
tools:text="filename.md" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/file_icon"
|
android:id="@+id/file_icon"
|
||||||
android:layout_width="40dp"
|
android:layout_width="40dp"
|
||||||
android:layout_height="40dp"
|
android:layout_height="40dp"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="@dimen/standard_margin"
|
android:layout_marginEnd="@dimen/standard_margin"
|
||||||
app:actualImageScaleType="fitCenter"
|
tools:ignore="ContentDescription" />
|
||||||
app:placeholderImageScaleType="fitCenter" />
|
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -48,19 +48,19 @@
|
|||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_toStartOf="@id/checkedImageView"
|
android:layout_toStartOf="@id/checkedImageView"
|
||||||
android:layout_toEndOf="@id/avatar_drawee_view"
|
android:layout_toEndOf="@id/avatar_view"
|
||||||
android:ellipsize="end"
|
android:ellipsize="end"
|
||||||
android:lines="1"
|
android:lines="1"
|
||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textAppearance="@style/ListItem"
|
android:textAppearance="@style/ListItem"
|
||||||
tools:text="Jane Doe" />
|
tools:text="Jane Doe" />
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar_drawee_view"
|
android:id="@+id/avatar_view"
|
||||||
android:layout_width="@dimen/avatar_size"
|
android:layout_width="@dimen/avatar_size"
|
||||||
android:layout_height="@dimen/avatar_size"
|
android:layout_height="@dimen/avatar_size"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="@dimen/standard_margin"
|
android:layout_marginEnd="@dimen/standard_margin"
|
||||||
app:roundAsCircle="true" />
|
android:contentDescription="@string/avatar" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -29,7 +29,7 @@
|
|||||||
android:orientation="vertical">
|
android:orientation="vertical">
|
||||||
|
|
||||||
<com.elyeproj.loaderviewlibrary.LoaderTextView
|
<com.elyeproj.loaderviewlibrary.LoaderTextView
|
||||||
android:id="@+id/simple_drawee_view"
|
android:id="@+id/loader_text_view"
|
||||||
android:layout_width="@dimen/avatar_size"
|
android:layout_width="@dimen/avatar_size"
|
||||||
android:layout_height="@dimen/avatar_size"
|
android:layout_height="@dimen/avatar_size"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
@ -42,7 +42,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_toEndOf="@id/simple_drawee_view"
|
android:layout_toEndOf="@id/loader_text_view"
|
||||||
app:custom_color="@color/nc_shimmer_default_color" />
|
app:custom_color="@color/nc_shimmer_default_color" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
@ -26,15 +26,14 @@
|
|||||||
android:layout_marginBottom="@dimen/standard_half_margin"
|
android:layout_marginBottom="@dimen/standard_half_margin"
|
||||||
android:layout_marginTop="@dimen/standard_margin">
|
android:layout_marginTop="@dimen/standard_margin">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/avatar_drawee_view"
|
android:id="@+id/avatar_view"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:layout_marginStart="@dimen/standard_margin"
|
android:layout_marginStart="@dimen/standard_margin"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:roundAsCircle="true" />
|
|
||||||
|
|
||||||
<com.vanniktech.emoji.EmojiEditText
|
<com.vanniktech.emoji.EmojiEditText
|
||||||
android:id="@+id/participant_status_emoji"
|
android:id="@+id/participant_status_emoji"
|
||||||
@ -54,8 +53,8 @@
|
|||||||
android:layout_height="18dp"
|
android:layout_height="18dp"
|
||||||
android:layout_gravity="bottom|end"
|
android:layout_gravity="bottom|end"
|
||||||
android:contentDescription="@string/nc_account_chooser_active_user"
|
android:contentDescription="@string/nc_account_chooser_active_user"
|
||||||
app:layout_constraintBottom_toBottomOf="@+id/avatar_drawee_view"
|
app:layout_constraintBottom_toBottomOf="@+id/avatar_view"
|
||||||
app:layout_constraintEnd_toEndOf="@+id/avatar_drawee_view"
|
app:layout_constraintEnd_toEndOf="@+id/avatar_view"
|
||||||
tools:src="@drawable/emoji_one_category_smileysandpeople"/>
|
tools:src="@drawable/emoji_one_category_smileysandpeople"/>
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
@ -68,8 +67,8 @@
|
|||||||
android:textAlignment="viewStart"
|
android:textAlignment="viewStart"
|
||||||
android:textAppearance="?android:attr/textAppearanceListItem"
|
android:textAppearance="?android:attr/textAppearanceListItem"
|
||||||
android:textColor="@color/conversation_item_header"
|
android:textColor="@color/conversation_item_header"
|
||||||
app:layout_constraintStart_toEndOf="@id/avatar_drawee_view"
|
app:layout_constraintStart_toEndOf="@id/avatar_view"
|
||||||
app:layout_constraintTop_toTopOf="@+id/avatar_drawee_view"
|
app:layout_constraintTop_toTopOf="@+id/avatar_view"
|
||||||
tools:text="Jane Doe" />
|
tools:text="Jane Doe" />
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ @author Andy Scherzinger
|
~ @author Andy Scherzinger
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
~
|
~
|
||||||
@ -38,12 +40,11 @@
|
|||||||
android:layout_centerVertical="true"
|
android:layout_centerVertical="true"
|
||||||
android:layout_marginEnd="@dimen/double_margin_between_elements">
|
android:layout_marginEnd="@dimen/double_margin_between_elements">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@id/dialogAvatar"
|
android:id="@id/dialogAvatar"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:contentDescription="@null"
|
android:contentDescription="@null" />
|
||||||
app:roundAsCircle="true" />
|
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/favoriteConversationImageView"
|
android:id="@+id/favoriteConversationImageView"
|
||||||
|
@ -41,8 +41,7 @@
|
|||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:roundAsCircle="true" />
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ @author Andy Scherzinger
|
~ @author Andy Scherzinger
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
~
|
~
|
||||||
@ -35,14 +37,13 @@
|
|||||||
android:layout_margin="@dimen/double_margin_between_elements"
|
android:layout_margin="@dimen/double_margin_between_elements"
|
||||||
tools:background="@color/white">
|
tools:background="@color/white">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/thumbnail"
|
android:id="@+id/thumbnail"
|
||||||
android:layout_width="@dimen/small_item_height"
|
android:layout_width="@dimen/small_item_height"
|
||||||
android:layout_height="@dimen/small_item_height"
|
android:layout_height="@dimen/small_item_height"
|
||||||
android:importantForAccessibility="no"
|
android:importantForAccessibility="no"
|
||||||
app:layout_constraintStart_toStartOf="parent"
|
app:layout_constraintStart_toStartOf="parent"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent" />
|
||||||
app:roundAsCircle="true" />
|
|
||||||
|
|
||||||
<androidx.emoji.widget.EmojiTextView
|
<androidx.emoji.widget.EmojiTextView
|
||||||
android:id="@+id/conversation_title"
|
android:id="@+id/conversation_title"
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content">
|
||||||
|
|
||||||
@ -40,14 +40,12 @@
|
|||||||
app:layout_flexGrow="1"
|
app:layout_flexGrow="1"
|
||||||
app:layout_wrapBefore="true">
|
app:layout_wrapBefore="true">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
android:id="@+id/image"
|
android:id="@+id/image"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
app:placeholderImageScaleType="fitCenter"
|
tools:ignore="ContentDescription" />
|
||||||
fresco:actualImageScaleType="centerCrop"
|
|
||||||
fresco:roundedCornerRadius="4dp" />
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
|
@ -39,17 +39,14 @@
|
|||||||
app:layout_flexGrow="1"
|
app:layout_flexGrow="1"
|
||||||
app:layout_wrapBefore="true">
|
app:layout_wrapBefore="true">
|
||||||
|
|
||||||
<com.facebook.drawee.view.SimpleDraweeView
|
<ImageView
|
||||||
xmlns:fresco="http://schemas.android.com/apk/res-auto"
|
|
||||||
android:id="@+id/file_image"
|
android:id="@+id/file_image"
|
||||||
android:layout_width="@dimen/mediatab_file_icon_size"
|
android:layout_width="@dimen/mediatab_file_icon_size"
|
||||||
android:layout_height="@dimen/mediatab_file_icon_size"
|
android:layout_height="@dimen/mediatab_file_icon_size"
|
||||||
android:padding="4dp"
|
android:padding="4dp"
|
||||||
app:layout_constraintTop_toTopOf="parent"
|
app:layout_constraintTop_toTopOf="parent"
|
||||||
app:placeholderImageScaleType="fitCenter"
|
tools:src="@drawable/ic_call_black_24dp"
|
||||||
fresco:actualImageScaleType="centerCrop"
|
tools:ignore="ContentDescription" />
|
||||||
fresco:roundedCornerRadius="4dp"
|
|
||||||
tools:src="@drawable/ic_call_black_24dp"/>
|
|
||||||
|
|
||||||
<ProgressBar
|
<ProgressBar
|
||||||
android:id="@+id/progress_bar"
|
android:id="@+id/progress_bar"
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
~ Nextcloud Talk application
|
~ Nextcloud Talk application
|
||||||
~
|
~
|
||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2019 Mario Danic <mario@lovelyhq.com>
|
||||||
~
|
~
|
||||||
~ This program is free software: you can redistribute it and/or modify
|
~ This program is free software: you can redistribute it and/or modify
|
||||||
@ -67,6 +69,8 @@
|
|||||||
<dimen name="call_self_video_short_side_length">80dp</dimen>
|
<dimen name="call_self_video_short_side_length">80dp</dimen>
|
||||||
<dimen name="call_grid_item_min_height">180dp</dimen>
|
<dimen name="call_grid_item_min_height">180dp</dimen>
|
||||||
<dimen name="call_controls_height">110dp</dimen>
|
<dimen name="call_controls_height">110dp</dimen>
|
||||||
|
<dimen name="call_controls_padding_horizontal">10dp</dimen>
|
||||||
|
<dimen name="call_controls_margin_horizontal">10dp</dimen>
|
||||||
<dimen name="call_participant_progress_bar_size">48dp</dimen>
|
<dimen name="call_participant_progress_bar_size">48dp</dimen>
|
||||||
<dimen name="call_self_participant_progress_bar_size">48dp</dimen>
|
<dimen name="call_self_participant_progress_bar_size">48dp</dimen>
|
||||||
<dimen name="zero">0dp</dimen>
|
<dimen name="zero">0dp</dimen>
|
||||||
|
@ -4,6 +4,8 @@
|
|||||||
~ @author Mario Danic
|
~ @author Mario Danic
|
||||||
~ @author Andy Scherzinger
|
~ @author Andy Scherzinger
|
||||||
~ @author Marcel Hibbe
|
~ @author Marcel Hibbe
|
||||||
|
~ @author Tim Krüger
|
||||||
|
~ Copyright (C) 2022 Tim Krüger <t@timkrueger.me>
|
||||||
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
~ Copyright (C) 2022 Marcel Hibbe <dev@mhibbe.de>
|
||||||
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
~ Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||||
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
~ Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||||
@ -211,6 +213,14 @@
|
|||||||
<string name="nc_call_state_with_phone">%1$s with phone</string>
|
<string name="nc_call_state_with_phone">%1$s with phone</string>
|
||||||
<string name="nc_call_state_with_video">%1$s with video</string>
|
<string name="nc_call_state_with_video">%1$s with video</string>
|
||||||
<string name="nc_missed_call">You missed a call from %s</string>
|
<string name="nc_missed_call">You missed a call from %s</string>
|
||||||
|
<string name="nc_call_button_content_description_pip">Open picture in picture mode</string>
|
||||||
|
<string name="nc_call_button_content_description_audio_output">Change audio output</string>
|
||||||
|
<string name="nc_call_button_content_description_camera">Toggle camera</string>
|
||||||
|
<string name="nc_call_button_content_description_microphone">Toggle microphone</string>
|
||||||
|
<string name="nc_call_button_content_description_hangup">Hangup</string>
|
||||||
|
<string name="nc_call_button_content_description_answer_voice_only">Answer as voice call only</string>
|
||||||
|
<string name="nc_call_button_content_description_answer_video_call">Answer as video call</string>
|
||||||
|
<string name="nc_call_button_content_description_switch_to_self_vide">Switch to self video</string>
|
||||||
|
|
||||||
<!-- Picture in Picture -->
|
<!-- Picture in Picture -->
|
||||||
<string name="nc_pip_microphone_mute">Mute microphone</string>
|
<string name="nc_pip_microphone_mute">Mute microphone</string>
|
||||||
|
Loading…
Reference in New Issue
Block a user