mirror of
https://github.com/nextcloud/talk-android.git
synced 2024-11-26 23:25:20 +03:00
Show profile action on avatar click
For every click on a avatar in a group chat it will be tried to receive a hover card from the Nextcloud server. The endpoint returns multiple actions. Those actions will be filtered for the app ids 'spreed', 'email' and 'profile'. Other will be ignored. The received filtered actions will be shown in a bottom sheet. Resolves: #1644 Signed-off-by: Tim Krüger <t@timkrueger.me>
This commit is contained in:
parent
036cf7c590
commit
9accac3325
15 changed files with 627 additions and 15 deletions
|
@ -4,6 +4,8 @@
|
|||
* @author Mario Danic
|
||||
* @author Marcel Hibbe
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
|
@ -48,6 +50,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.databinding.ItemCustomIncomingLocationMessageBinding
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
|
@ -56,8 +59,8 @@ import java.net.URLEncoder
|
|||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class IncomingLocationMessageViewHolder(incomingView: View) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(incomingView) {
|
||||
class IncomingLocationMessageViewHolder(incomingView: View, payload: Any) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(incomingView, payload) {
|
||||
private val binding: ItemCustomIncomingLocationMessageBinding =
|
||||
ItemCustomIncomingLocationMessageBinding.bind(itemView)
|
||||
|
||||
|
@ -102,6 +105,9 @@ class IncomingLocationMessageViewHolder(incomingView: View) : MessageHolders
|
|||
val author: String = message.actorDisplayName
|
||||
if (!TextUtils.isEmpty(author)) {
|
||||
binding.messageAuthor.text = author
|
||||
binding.messageUserAvatar.setOnClickListener {
|
||||
(payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
|
||||
}
|
||||
} else {
|
||||
binding.messageAuthor.setText(R.string.nc_nick_guest)
|
||||
}
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
@ -31,8 +33,8 @@ import androidx.emoji.widget.EmojiTextView;
|
|||
public class IncomingPreviewMessageViewHolder extends MagicPreviewMessageViewHolder {
|
||||
private final ItemCustomIncomingPreviewMessageBinding binding;
|
||||
|
||||
public IncomingPreviewMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
public IncomingPreviewMessageViewHolder(View itemView, Object payload) {
|
||||
super(itemView, payload);
|
||||
binding = ItemCustomIncomingPreviewMessageBinding.bind(itemView);
|
||||
}
|
||||
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* @author Mario Danic
|
||||
* @author Marcel Hibbe
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
|
@ -46,6 +48,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.databinding.ItemCustomIncomingVoiceMessageBinding
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
import com.nextcloud.talk.utils.preferences.AppPreferences
|
||||
|
@ -54,8 +57,8 @@ import java.util.concurrent.ExecutionException
|
|||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class IncomingVoiceMessageViewHolder(incomingView: View) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(incomingView) {
|
||||
class IncomingVoiceMessageViewHolder(incomingView: View, payload: Any) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(incomingView, payload) {
|
||||
|
||||
private val binding: ItemCustomIncomingVoiceMessageBinding =
|
||||
ItemCustomIncomingVoiceMessageBinding.bind(itemView)
|
||||
|
@ -192,6 +195,9 @@ class IncomingVoiceMessageViewHolder(incomingView: View) : MessageHolders
|
|||
val author: String = message.actorDisplayName
|
||||
if (!TextUtils.isEmpty(author)) {
|
||||
binding.messageAuthor.text = author
|
||||
binding.messageUserAvatar.setOnClickListener {
|
||||
(payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
|
||||
}
|
||||
} else {
|
||||
binding.messageAuthor.setText(R.string.nc_nick_guest)
|
||||
}
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
*
|
||||
* @author Mario Danic
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
*
|
||||
|
@ -44,6 +46,7 @@ import com.nextcloud.talk.application.NextcloudTalkApplication
|
|||
import com.nextcloud.talk.application.NextcloudTalkApplication.Companion.sharedApplication
|
||||
import com.nextcloud.talk.databinding.ItemCustomIncomingTextMessageBinding
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.DisplayUtils
|
||||
|
@ -53,8 +56,8 @@ import com.stfalcon.chatkit.messages.MessageHolders
|
|||
import javax.inject.Inject
|
||||
|
||||
@AutoInjector(NextcloudTalkApplication::class)
|
||||
class MagicIncomingTextMessageViewHolder(itemView: View) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(itemView) {
|
||||
class MagicIncomingTextMessageViewHolder(itemView: View, payload: Any) : MessageHolders
|
||||
.IncomingTextMessageViewHolder<ChatMessage>(itemView, payload) {
|
||||
|
||||
private val binding: ItemCustomIncomingTextMessageBinding = ItemCustomIncomingTextMessageBinding.bind(itemView)
|
||||
|
||||
|
@ -72,6 +75,9 @@ class MagicIncomingTextMessageViewHolder(itemView: View) : MessageHolders
|
|||
val author: String = message.actorDisplayName
|
||||
if (!TextUtils.isEmpty(author)) {
|
||||
binding.messageAuthor.text = author
|
||||
binding.messageUserAvatar.setOnClickListener {
|
||||
(payload as? ProfileBottomSheet)?.showFor(message.actorId, itemView.context)
|
||||
}
|
||||
} else {
|
||||
binding.messageAuthor.setText(R.string.nc_nick_guest)
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@
|
|||
* @author Mario Danic
|
||||
* @author Marcel Hibbe
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
* Copyright (C) 2021 Marcel Hibbe <dev@mhibbe.de>
|
||||
* Copyright (C) 2017-2018 Mario Danic <mario@lovelyhq.com>
|
||||
|
@ -54,6 +56,7 @@ import com.nextcloud.talk.jobs.DownloadFileToCacheWorker;
|
|||
import com.nextcloud.talk.models.database.CapabilitiesUtil;
|
||||
import com.nextcloud.talk.models.database.UserEntity;
|
||||
import com.nextcloud.talk.models.json.chat.ChatMessage;
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet;
|
||||
import com.nextcloud.talk.utils.AccountUtils;
|
||||
import com.nextcloud.talk.utils.DisplayUtils;
|
||||
import com.nextcloud.talk.utils.DrawableUtils;
|
||||
|
@ -110,8 +113,8 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
|
|||
|
||||
View clickView;
|
||||
|
||||
public MagicPreviewMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
public MagicPreviewMessageViewHolder(View itemView, Object payload) {
|
||||
super(itemView, payload);
|
||||
NextcloudTalkApplication.Companion.getSharedApplication().getComponentApplication().inject(this);
|
||||
}
|
||||
|
||||
|
@ -128,6 +131,11 @@ public abstract class MagicPreviewMessageViewHolder extends MessageHolders.Incom
|
|||
}
|
||||
} else {
|
||||
userAvatar.setVisibility(View.VISIBLE);
|
||||
userAvatar.setOnClickListener(v -> {
|
||||
if (payload instanceof ProfileBottomSheet){
|
||||
((ProfileBottomSheet) payload).showFor(message.actorId, v.getContext());
|
||||
}
|
||||
});
|
||||
|
||||
if (ACTOR_TYPE_BOTS.equals(message.actorType) && ACTOR_ID_CHANGELOG.equals(message.actorId)) {
|
||||
if (context != null) {
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Andy Scherzinger
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
* Copyright (C) 2021 Andy Scherzinger <info@andy-scherzinger.de>
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
|
@ -32,7 +34,7 @@ public class OutcomingPreviewMessageViewHolder extends MagicPreviewMessageViewHo
|
|||
private final ItemCustomOutcomingPreviewMessageBinding binding;
|
||||
|
||||
public OutcomingPreviewMessageViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
super(itemView, null);
|
||||
binding = ItemCustomOutcomingPreviewMessageBinding.bind(itemView);
|
||||
}
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ import com.nextcloud.talk.models.json.conversations.RoomOverall;
|
|||
import com.nextcloud.talk.models.json.conversations.RoomsOverall;
|
||||
import com.nextcloud.talk.models.json.generic.GenericOverall;
|
||||
import com.nextcloud.talk.models.json.generic.Status;
|
||||
import com.nextcloud.talk.models.json.hovercard.HoverCardOverall;
|
||||
import com.nextcloud.talk.models.json.mention.MentionOverall;
|
||||
import com.nextcloud.talk.models.json.notifications.NotificationOverall;
|
||||
import com.nextcloud.talk.models.json.participants.AddParticipantOverall;
|
||||
|
@ -425,4 +426,7 @@ public interface NcApi {
|
|||
@POST
|
||||
Observable<GenericOverall> notificationCalls(@Header("Authorization") String authorization, @Url String url,
|
||||
@Field("level") Integer level);
|
||||
|
||||
@GET
|
||||
Observable<HoverCardOverall> hoverCard(@Header("Authorization") String authorization, @Url String url);
|
||||
}
|
||||
|
|
|
@ -132,6 +132,7 @@ import com.nextcloud.talk.models.json.conversations.RoomsOverall
|
|||
import com.nextcloud.talk.models.json.generic.GenericOverall
|
||||
import com.nextcloud.talk.models.json.mention.Mention
|
||||
import com.nextcloud.talk.presenters.MentionAutocompletePresenter
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet
|
||||
import com.nextcloud.talk.ui.dialog.AttachmentDialog
|
||||
import com.nextcloud.talk.ui.recyclerview.MessageSwipeActions
|
||||
import com.nextcloud.talk.ui.recyclerview.MessageSwipeCallback
|
||||
|
@ -427,9 +428,12 @@ class ChatController(args: Bundle) :
|
|||
adapterWasNull = true
|
||||
|
||||
val messageHolders = MessageHolders()
|
||||
val profileBottomSheet = ProfileBottomSheet(ncApi!!, conversationUser!!, router)
|
||||
|
||||
messageHolders.setIncomingTextConfig(
|
||||
MagicIncomingTextMessageViewHolder::class.java,
|
||||
R.layout.item_custom_incoming_text_message
|
||||
R.layout.item_custom_incoming_text_message,
|
||||
profileBottomSheet
|
||||
)
|
||||
messageHolders.setOutcomingTextConfig(
|
||||
MagicOutcomingTextMessageViewHolder::class.java,
|
||||
|
@ -438,7 +442,8 @@ class ChatController(args: Bundle) :
|
|||
|
||||
messageHolders.setIncomingImageConfig(
|
||||
IncomingPreviewMessageViewHolder::class.java,
|
||||
R.layout.item_custom_incoming_preview_message
|
||||
R.layout.item_custom_incoming_preview_message,
|
||||
profileBottomSheet
|
||||
)
|
||||
|
||||
messageHolders.setOutcomingImageConfig(
|
||||
|
@ -460,14 +465,17 @@ class ChatController(args: Bundle) :
|
|||
MagicUnreadNoticeMessageViewHolder::class.java,
|
||||
R.layout.item_date_header,
|
||||
MagicUnreadNoticeMessageViewHolder::class.java,
|
||||
R.layout.item_date_header, this
|
||||
R.layout.item_date_header,
|
||||
this
|
||||
)
|
||||
|
||||
messageHolders.registerContentType(
|
||||
CONTENT_TYPE_LOCATION,
|
||||
IncomingLocationMessageViewHolder::class.java,
|
||||
profileBottomSheet,
|
||||
R.layout.item_custom_incoming_location_message,
|
||||
OutcomingLocationMessageViewHolder::class.java,
|
||||
null,
|
||||
R.layout.item_custom_outcoming_location_message,
|
||||
this
|
||||
)
|
||||
|
@ -475,8 +483,10 @@ class ChatController(args: Bundle) :
|
|||
messageHolders.registerContentType(
|
||||
CONTENT_TYPE_VOICE_MESSAGE,
|
||||
IncomingVoiceMessageViewHolder::class.java,
|
||||
profileBottomSheet,
|
||||
R.layout.item_custom_incoming_voice_message,
|
||||
OutcomingVoiceMessageViewHolder::class.java,
|
||||
null,
|
||||
R.layout.item_custom_outcoming_voice_message,
|
||||
this
|
||||
)
|
||||
|
@ -2178,7 +2188,7 @@ class ChatController(args: Bundle) :
|
|||
bundle.putBoolean(BundleKeys.KEY_FORWARD_MSG_FLAG, true)
|
||||
bundle.putString(BundleKeys.KEY_FORWARD_MSG_TEXT, message?.text)
|
||||
bundle.putString(BundleKeys.KEY_FORWARD_HIDE_SOURCE_ROOM, roomId)
|
||||
getRouter().pushController(
|
||||
router.pushController(
|
||||
RouterTransaction.with(ConversationsListController(bundle))
|
||||
.pushChangeHandler(HorizontalChangeHandler())
|
||||
.popChangeHandler(HorizontalChangeHandler())
|
||||
|
|
|
@ -0,0 +1,96 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
*
|
||||
* 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.models.json.hovercard;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
@Parcel
|
||||
@JsonObject
|
||||
public class HoverCard {
|
||||
|
||||
@JsonField(name = "userId")
|
||||
public String userId;
|
||||
|
||||
@JsonField(name = "displayName")
|
||||
public String displayName;
|
||||
|
||||
@JsonField(name = "actions")
|
||||
public List<HoverCardAction> actions;
|
||||
|
||||
|
||||
public String getUserId() {
|
||||
return this.userId;
|
||||
}
|
||||
|
||||
public void setUserId(String userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
|
||||
public String getDisplayName() {
|
||||
return displayName;
|
||||
}
|
||||
|
||||
public void setDisplayName(String displayName) {
|
||||
this.displayName = displayName;
|
||||
}
|
||||
|
||||
public List<HoverCardAction> getActions() {
|
||||
return actions;
|
||||
}
|
||||
|
||||
public void setActions(List<HoverCardAction> actions) {
|
||||
this.actions = actions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
HoverCard hoverCard = (HoverCard) o;
|
||||
return Objects.equals(userId, hoverCard.userId) &&
|
||||
Objects.equals(displayName, hoverCard.displayName) &&
|
||||
Objects.equals(actions, hoverCard.actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(userId, displayName, actions);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HoverCard{" +
|
||||
"userId='" + userId + '\'' +
|
||||
", displayName='" + displayName + '\'' +
|
||||
", actions=" + actions +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,107 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
*
|
||||
* 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.models.json.hovercard;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import org.parceler.Parcel;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@Parcel
|
||||
@JsonObject
|
||||
public class HoverCardAction {
|
||||
|
||||
@JsonField(name = "title")
|
||||
public String title;
|
||||
|
||||
@JsonField(name = "icon")
|
||||
public String icon;
|
||||
|
||||
@JsonField(name = "hyperlink")
|
||||
public String hyperlink;
|
||||
|
||||
@JsonField(name = "appId")
|
||||
public String appId;
|
||||
|
||||
public String getTitle() {
|
||||
return this.title;
|
||||
}
|
||||
|
||||
public void setTitle(String title) {
|
||||
this.title = title;
|
||||
}
|
||||
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(String icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
public String getAppId() {
|
||||
return appId;
|
||||
}
|
||||
|
||||
public void setAppId(String appId) {
|
||||
this.appId = appId;
|
||||
}
|
||||
|
||||
public String getHyperlink() {
|
||||
return hyperlink;
|
||||
}
|
||||
|
||||
public void setHyperlink(String hyperlink) {
|
||||
this.hyperlink = hyperlink;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
HoverCardAction that = (HoverCardAction) o;
|
||||
return Objects.equals(title, that.title) &&
|
||||
Objects.equals(icon, that.icon) &&
|
||||
Objects.equals(hyperlink, that.hyperlink) &&
|
||||
Objects.equals(appId, that.appId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(title, icon, hyperlink, appId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HoverCardAction{" +
|
||||
"title='" + title + '\'' +
|
||||
", icon='" + icon + '\'' +
|
||||
", hyper='" + hyperlink + '\'' +
|
||||
", appId='" + appId + '\'' +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
*
|
||||
* 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.models.json.hovercard;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
import com.nextcloud.talk.models.json.generic.GenericOCS;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@JsonObject
|
||||
public class HoverCardOCS extends GenericOCS {
|
||||
@JsonField(name = "data")
|
||||
public HoverCard data;
|
||||
|
||||
public HoverCard getData() {
|
||||
return this.data;
|
||||
}
|
||||
|
||||
public void setData(HoverCard data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
if (!super.equals(o)) {
|
||||
return false;
|
||||
}
|
||||
HoverCardOCS that = (HoverCardOCS) o;
|
||||
return Objects.equals(data, that.data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(super.hashCode(), data);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HoverCardOCS{" +
|
||||
"data=" + data +
|
||||
'}';
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
*
|
||||
* 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.models.json.hovercard;
|
||||
|
||||
import com.bluelinelabs.logansquare.annotation.JsonField;
|
||||
import com.bluelinelabs.logansquare.annotation.JsonObject;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
@JsonObject
|
||||
public class HoverCardOverall {
|
||||
@JsonField(name = "ocs")
|
||||
public HoverCardOCS ocs;
|
||||
|
||||
public HoverCardOCS getOcs() {
|
||||
return this.ocs;
|
||||
}
|
||||
|
||||
public void setOcs(HoverCardOCS ocs) {
|
||||
this.ocs = ocs;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
HoverCardOverall that = (HoverCardOverall) o;
|
||||
return Objects.equals(ocs, that.ocs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hash(ocs);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "HoverCardOverall{" +
|
||||
"ocs=" + ocs +
|
||||
'}';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
*
|
||||
* Nextcloud Talk application
|
||||
*
|
||||
* @author Tim Krüger
|
||||
* Copyright (C) 2021 Tim Krüger <t@timkrueger.me>
|
||||
*
|
||||
* 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.ui.bottom.sheet
|
||||
|
||||
import android.content.Context
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Bundle
|
||||
import android.util.Log
|
||||
import com.afollestad.materialdialogs.LayoutMode
|
||||
import com.afollestad.materialdialogs.MaterialDialog
|
||||
import com.afollestad.materialdialogs.bottomsheets.BottomSheet
|
||||
import com.bluelinelabs.conductor.Router
|
||||
import com.nextcloud.talk.R
|
||||
import com.nextcloud.talk.api.NcApi
|
||||
import com.nextcloud.talk.controllers.bottomsheet.items.BasicListItemWithImage
|
||||
import com.nextcloud.talk.controllers.bottomsheet.items.listItemsWithImage
|
||||
import com.nextcloud.talk.models.database.UserEntity
|
||||
import com.nextcloud.talk.models.json.conversations.RoomOverall
|
||||
import com.nextcloud.talk.models.json.hovercard.HoverCardAction
|
||||
import com.nextcloud.talk.models.json.hovercard.HoverCardOverall
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet.AllowedAppIds.EMAIL
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet.AllowedAppIds.PROFILE
|
||||
import com.nextcloud.talk.ui.bottom.sheet.ProfileBottomSheet.AllowedAppIds.SPREED
|
||||
import com.nextcloud.talk.utils.ApiUtils
|
||||
import com.nextcloud.talk.utils.ConductorRemapping
|
||||
import com.nextcloud.talk.utils.bundle.BundleKeys
|
||||
import io.reactivex.Observer
|
||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||
import io.reactivex.disposables.Disposable
|
||||
import io.reactivex.schedulers.Schedulers
|
||||
import org.parceler.Parcels
|
||||
|
||||
private const val TAG = "ProfileBottomSheet"
|
||||
|
||||
class ProfileBottomSheet(val ncApi: NcApi, val userEntity: UserEntity, val router: Router) {
|
||||
|
||||
private val allowedAppIds = listOf(SPREED.stringValue, PROFILE.stringValue, EMAIL.stringValue)
|
||||
|
||||
fun showFor(user: String, context: Context) {
|
||||
|
||||
ncApi.hoverCard(
|
||||
ApiUtils.getCredentials(userEntity.username, userEntity.token),
|
||||
ApiUtils.getUrlForHoverCard(userEntity.baseUrl, user)
|
||||
).subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : io.reactivex.Observer<HoverCardOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
}
|
||||
|
||||
override fun onNext(hoverCardOverall: HoverCardOverall) {
|
||||
bottomSheet(hoverCardOverall.ocs.data.actions, hoverCardOverall.ocs.data.displayName, user, context)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, "Failed to get hover card for user $user", e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun bottomSheet(actions: List<HoverCardAction>, displayName: String, userId: String, context: Context) {
|
||||
|
||||
val filteredActions = actions.filter { allowedAppIds.contains(it.appId) }
|
||||
val items = filteredActions.map { configureActionListItem(it) }
|
||||
|
||||
MaterialDialog(context, BottomSheet(LayoutMode.WRAP_CONTENT)).show {
|
||||
cornerRadius(res = R.dimen.corner_radius)
|
||||
|
||||
title(text = displayName)
|
||||
listItemsWithImage(items = items) { _, index, _ ->
|
||||
|
||||
val action = filteredActions[index]
|
||||
|
||||
when (AllowedAppIds.createFor(action)) {
|
||||
PROFILE -> openProfile(action.hyperlink, context)
|
||||
EMAIL -> composeEmail(action.title, context)
|
||||
SPREED -> talkTo(userId)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private fun configureActionListItem(action: HoverCardAction): BasicListItemWithImage {
|
||||
|
||||
val drawable = when (AllowedAppIds.createFor(action)) {
|
||||
PROFILE -> R.drawable.ic_user
|
||||
EMAIL -> R.drawable.ic_email
|
||||
SPREED -> R.drawable.ic_talk
|
||||
}
|
||||
|
||||
return BasicListItemWithImage(
|
||||
drawable,
|
||||
action.title
|
||||
)
|
||||
}
|
||||
|
||||
private fun talkTo(userId: String) {
|
||||
|
||||
val apiVersion =
|
||||
ApiUtils.getConversationApiVersion(userEntity, intArrayOf(ApiUtils.APIv4, 1))
|
||||
val retrofitBucket = ApiUtils.getRetrofitBucketForCreateRoom(
|
||||
apiVersion,
|
||||
userEntity.baseUrl,
|
||||
"1",
|
||||
null,
|
||||
userId,
|
||||
null
|
||||
)
|
||||
val credentials = ApiUtils.getCredentials(userEntity.username, userEntity.token)
|
||||
ncApi!!.createRoom(
|
||||
credentials,
|
||||
retrofitBucket.getUrl(), retrofitBucket.getQueryMap()
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<RoomOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(roomOverall: RoomOverall) {
|
||||
val bundle = Bundle()
|
||||
bundle.putParcelable(BundleKeys.KEY_USER_ENTITY, userEntity)
|
||||
bundle.putString(BundleKeys.KEY_ROOM_TOKEN, roomOverall.getOcs().getData().getToken())
|
||||
bundle.putString(BundleKeys.KEY_ROOM_ID, roomOverall.getOcs().getData().getRoomId())
|
||||
|
||||
// FIXME once APIv2+ is used only, the createRoom already returns all the data
|
||||
ncApi!!.getRoom(
|
||||
credentials,
|
||||
ApiUtils.getUrlForRoom(
|
||||
apiVersion, userEntity.baseUrl,
|
||||
roomOverall.getOcs().getData().getToken()
|
||||
)
|
||||
)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(object : Observer<RoomOverall> {
|
||||
override fun onSubscribe(d: Disposable) {
|
||||
// unused atm
|
||||
}
|
||||
|
||||
override fun onNext(roomOverall: RoomOverall) {
|
||||
bundle.putParcelable(
|
||||
BundleKeys.KEY_ACTIVE_CONVERSATION,
|
||||
Parcels.wrap(roomOverall.getOcs().getData())
|
||||
)
|
||||
ConductorRemapping.remapChatController(
|
||||
router, userEntity.id,
|
||||
roomOverall.getOcs().getData().getToken(), bundle, true
|
||||
)
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, e.message, e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
override fun onError(e: Throwable) {
|
||||
Log.e(TAG, e.message, e)
|
||||
}
|
||||
|
||||
override fun onComplete() {
|
||||
// unused atm
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
private fun composeEmail(address: String, context: Context) {
|
||||
val addresses = arrayListOf(address)
|
||||
val intent = Intent(Intent.ACTION_SENDTO).apply {
|
||||
data = Uri.parse("mailto:") // only email apps should handle this
|
||||
putExtra(Intent.EXTRA_EMAIL, addresses)
|
||||
}
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
private fun openProfile(hyperlink: String, context: Context) {
|
||||
val webpage: Uri = Uri.parse(hyperlink)
|
||||
val intent = Intent(Intent.ACTION_VIEW, webpage)
|
||||
context.startActivity(intent)
|
||||
}
|
||||
|
||||
enum class AllowedAppIds(val stringValue: String) {
|
||||
SPREED("spreed"),
|
||||
PROFILE("profile"),
|
||||
EMAIL("email");
|
||||
|
||||
companion object {
|
||||
fun createFor(action: HoverCardAction): AllowedAppIds = valueOf(action.appId.uppercase())
|
||||
}
|
||||
}
|
||||
}
|
|
@ -400,4 +400,7 @@ public class ApiUtils {
|
|||
public static String getUrlToSendLocation(int version, String baseUrl, String roomToken) {
|
||||
return getUrlForChat(version, baseUrl, roomToken) + "/share";
|
||||
}
|
||||
|
||||
public static String getUrlForHoverCard(String baseUrl, String userId) { return baseUrl + ocsApiVersion +
|
||||
"/hovercard/v1/" + userId; }
|
||||
}
|
||||
|
|
12
app/src/main/res/drawable/ic_talk.xml
Normal file
12
app/src/main/res/drawable/ic_talk.xml
Normal file
|
@ -0,0 +1,12 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<vector android:autoMirrored="true"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="16"
|
||||
android:viewportWidth="16"
|
||||
android:width="24dp"
|
||||
xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path
|
||||
android:fillColor="#757575"
|
||||
android:pathData="m7.9992,0.999a6.9993,6.9994 0,0 0,-6.9992 6.9996,6.9993 6.9994,0 0,0 6.9992,6.9994 6.9993,6.9994 0,0 0,3.6308 -1.024c0.8602,0.3418 2.7871,1.356 3.2457,0.9179 0.4792,-0.4577 -0.5626,-2.6116 -0.8124,-3.412a6.9993,6.9994 0,0 0,0.935 -3.4814,6.9993 6.9994,0 0,0 -6.9991,-6.9993zM8,3.6601a4.34,4.3401 0,0 1,4.34 4.3401,4.34 4.3401,0 0,1 -4.34,4.3398 4.34,4.3401 0,0 1,-4.34 -4.3398,4.34 4.3401,0 0,1 4.34,-4.3401z"
|
||||
android:strokeWidth=".14" />
|
||||
</vector>
|
Loading…
Reference in a new issue