Search in sources :

Example 76 with Conversation

use of eu.siacs.conversations.entities.Conversation in project Conversations by siacs.

the class ConversationAdapter method onBindViewHolder.

@Override
public void onBindViewHolder(@NonNull ConversationViewHolder viewHolder, int position) {
    Conversation conversation = conversations.get(position);
    if (conversation == null) {
        return;
    }
    CharSequence name = conversation.getName();
    if (name instanceof Jid) {
        viewHolder.binding.conversationName.setText(IrregularUnicodeDetector.style(activity, (Jid) name));
    } else {
        viewHolder.binding.conversationName.setText(EmojiWrapper.transform(name));
    }
    if (conversation == ConversationFragment.getConversation(activity)) {
        viewHolder.binding.frame.setBackgroundColor(StyledAttributes.getColor(activity, R.attr.color_background_tertiary));
    } else {
        viewHolder.binding.frame.setBackgroundColor(StyledAttributes.getColor(activity, R.attr.color_background_primary));
    }
    Message message = conversation.getLatestMessage();
    final int unreadCount = conversation.unreadCount();
    final boolean isRead = conversation.isRead();
    final Conversation.Draft draft = isRead ? conversation.getDraft() : null;
    if (unreadCount > 0) {
        viewHolder.binding.unreadCount.setVisibility(View.VISIBLE);
        viewHolder.binding.unreadCount.setUnreadCount(unreadCount);
    } else {
        viewHolder.binding.unreadCount.setVisibility(View.GONE);
    }
    if (isRead) {
        viewHolder.binding.conversationName.setTypeface(null, Typeface.NORMAL);
    } else {
        viewHolder.binding.conversationName.setTypeface(null, Typeface.BOLD);
    }
    if (draft != null) {
        viewHolder.binding.conversationLastmsgImg.setVisibility(View.GONE);
        viewHolder.binding.conversationLastmsg.setText(EmojiWrapper.transform(draft.getMessage()));
        viewHolder.binding.senderName.setText(R.string.draft);
        viewHolder.binding.senderName.setVisibility(View.VISIBLE);
        viewHolder.binding.conversationLastmsg.setTypeface(null, Typeface.NORMAL);
        viewHolder.binding.senderName.setTypeface(null, Typeface.ITALIC);
    } else {
        final boolean fileAvailable = !message.isDeleted();
        final boolean showPreviewText;
        if (fileAvailable && (message.isFileOrImage() || message.treatAsDownloadable() || message.isGeoUri())) {
            final int imageResource;
            if (message.isGeoUri()) {
                imageResource = activity.getThemeResource(R.attr.ic_attach_location, R.drawable.ic_attach_location);
                showPreviewText = false;
            } else {
                // TODO move this into static MediaPreview method and use same icons as in MediaAdapter
                final String mime = message.getMimeType();
                switch(mime == null ? "" : mime.split("/")[0]) {
                    case "image":
                        imageResource = activity.getThemeResource(R.attr.ic_attach_photo, R.drawable.ic_attach_photo);
                        showPreviewText = false;
                        break;
                    case "video":
                        imageResource = activity.getThemeResource(R.attr.ic_attach_videocam, R.drawable.ic_attach_videocam);
                        showPreviewText = false;
                        break;
                    case "audio":
                        imageResource = activity.getThemeResource(R.attr.ic_attach_record, R.drawable.ic_attach_record);
                        showPreviewText = false;
                        break;
                    default:
                        imageResource = activity.getThemeResource(R.attr.ic_attach_document, R.drawable.ic_attach_document);
                        showPreviewText = true;
                        break;
                }
            }
            viewHolder.binding.conversationLastmsgImg.setImageResource(imageResource);
            viewHolder.binding.conversationLastmsgImg.setVisibility(View.VISIBLE);
        } else {
            viewHolder.binding.conversationLastmsgImg.setVisibility(View.GONE);
            showPreviewText = true;
        }
        final Pair<CharSequence, Boolean> preview = UIHelper.getMessagePreview(activity, message, viewHolder.binding.conversationLastmsg.getCurrentTextColor());
        if (showPreviewText) {
            viewHolder.binding.conversationLastmsg.setText(EmojiWrapper.transform(UIHelper.shorten(preview.first)));
        } else {
            viewHolder.binding.conversationLastmsgImg.setContentDescription(preview.first);
        }
        viewHolder.binding.conversationLastmsg.setVisibility(showPreviewText ? View.VISIBLE : View.GONE);
        if (preview.second) {
            if (isRead) {
                viewHolder.binding.conversationLastmsg.setTypeface(null, Typeface.ITALIC);
                viewHolder.binding.senderName.setTypeface(null, Typeface.NORMAL);
            } else {
                viewHolder.binding.conversationLastmsg.setTypeface(null, Typeface.BOLD_ITALIC);
                viewHolder.binding.senderName.setTypeface(null, Typeface.BOLD);
            }
        } else {
            if (isRead) {
                viewHolder.binding.conversationLastmsg.setTypeface(null, Typeface.NORMAL);
                viewHolder.binding.senderName.setTypeface(null, Typeface.NORMAL);
            } else {
                viewHolder.binding.conversationLastmsg.setTypeface(null, Typeface.BOLD);
                viewHolder.binding.senderName.setTypeface(null, Typeface.BOLD);
            }
        }
        if (message.getStatus() == Message.STATUS_RECEIVED) {
            if (conversation.getMode() == Conversation.MODE_MULTI) {
                viewHolder.binding.senderName.setVisibility(View.VISIBLE);
                viewHolder.binding.senderName.setText(UIHelper.getMessageDisplayName(message).split("\\s+")[0] + ':');
            } else {
                viewHolder.binding.senderName.setVisibility(View.GONE);
            }
        } else if (message.getType() != Message.TYPE_STATUS) {
            viewHolder.binding.senderName.setVisibility(View.VISIBLE);
            viewHolder.binding.senderName.setText(activity.getString(R.string.me) + ':');
        } else {
            viewHolder.binding.senderName.setVisibility(View.GONE);
        }
    }
    final Optional<OngoingRtpSession> ongoingCall;
    if (conversation.getMode() == Conversational.MODE_MULTI) {
        ongoingCall = Optional.absent();
    } else {
        ongoingCall = activity.xmppConnectionService.getJingleConnectionManager().getOngoingRtpConnection(conversation.getContact());
    }
    if (ongoingCall.isPresent()) {
        viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
        final int ic_ongoing_call = activity.getThemeResource(R.attr.ic_ongoing_call_hint, R.drawable.ic_phone_in_talk_black_18dp);
        viewHolder.binding.notificationStatus.setImageResource(ic_ongoing_call);
    } else {
        final long muted_till = conversation.getLongAttribute(Conversation.ATTRIBUTE_MUTED_TILL, 0);
        if (muted_till == Long.MAX_VALUE) {
            viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
            int ic_notifications_off = activity.getThemeResource(R.attr.icon_notifications_off, R.drawable.ic_notifications_off_black_24dp);
            viewHolder.binding.notificationStatus.setImageResource(ic_notifications_off);
        } else if (muted_till >= System.currentTimeMillis()) {
            viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
            int ic_notifications_paused = activity.getThemeResource(R.attr.icon_notifications_paused, R.drawable.ic_notifications_paused_black_24dp);
            viewHolder.binding.notificationStatus.setImageResource(ic_notifications_paused);
        } else if (conversation.alwaysNotify()) {
            viewHolder.binding.notificationStatus.setVisibility(View.GONE);
        } else {
            viewHolder.binding.notificationStatus.setVisibility(View.VISIBLE);
            int ic_notifications_none = activity.getThemeResource(R.attr.icon_notifications_none, R.drawable.ic_notifications_none_black_24dp);
            viewHolder.binding.notificationStatus.setImageResource(ic_notifications_none);
        }
    }
    long timestamp;
    if (draft != null) {
        timestamp = draft.getTimestamp();
    } else {
        timestamp = conversation.getLatestMessage().getTimeSent();
    }
    viewHolder.binding.pinnedOnTop.setVisibility(conversation.getBooleanAttribute(Conversation.ATTRIBUTE_PINNED_ON_TOP, false) ? View.VISIBLE : View.GONE);
    viewHolder.binding.conversationLastupdate.setText(UIHelper.readableTimeDifference(activity, timestamp));
    AvatarWorkerTask.loadAvatar(conversation, viewHolder.binding.conversationImage, R.dimen.avatar_on_conversation_overview);
    viewHolder.itemView.setOnClickListener(v -> listener.onConversationClick(v, conversation));
}
Also used : Jid(eu.siacs.conversations.xmpp.Jid) Message(eu.siacs.conversations.entities.Message) Conversation(eu.siacs.conversations.entities.Conversation) OngoingRtpSession(eu.siacs.conversations.xmpp.jingle.OngoingRtpSession)

Example 77 with Conversation

use of eu.siacs.conversations.entities.Conversation in project Conversations by siacs.

the class AxolotlService method trustedOrPreviouslyResponded.

public boolean trustedOrPreviouslyResponded(Jid jid) {
    final Contact contact = account.getRoster().getContact(jid);
    if (contact.showInRoster() || contact.isSelf()) {
        return true;
    }
    final Conversation conversation = mXmppConnectionService.find(account, jid);
    return conversation != null && conversation.sentMessagesCount() > 0;
}
Also used : Conversation(eu.siacs.conversations.entities.Conversation) Contact(eu.siacs.conversations.entities.Contact)

Example 78 with Conversation

use of eu.siacs.conversations.entities.Conversation in project Conversations by siacs.

the class DatabaseBackend method findConversation.

public Conversation findConversation(final Account account, final Jid contactJid) {
    SQLiteDatabase db = this.getReadableDatabase();
    String[] selectionArgs = { account.getUuid(), contactJid.asBareJid().toString() + "/%", contactJid.asBareJid().toString() };
    Cursor cursor = db.query(Conversation.TABLENAME, null, Conversation.ACCOUNT + "=? AND (" + Conversation.CONTACTJID + " like ? OR " + Conversation.CONTACTJID + "=?)", selectionArgs, null, null, null);
    if (cursor.getCount() == 0) {
        cursor.close();
        return null;
    }
    cursor.moveToFirst();
    Conversation conversation = Conversation.fromCursor(cursor);
    cursor.close();
    if (conversation.getJid() instanceof InvalidJid) {
        return null;
    }
    return conversation;
}
Also used : SQLiteDatabase(android.database.sqlite.SQLiteDatabase) Conversation(eu.siacs.conversations.entities.Conversation) Cursor(android.database.Cursor) InvalidJid(eu.siacs.conversations.xmpp.InvalidJid)

Example 79 with Conversation

use of eu.siacs.conversations.entities.Conversation in project Conversations by siacs.

the class PresenceParser method parseContactPresence.

private void parseContactPresence(final PresencePacket packet, final Account account) {
    final PresenceGenerator mPresenceGenerator = mXmppConnectionService.getPresenceGenerator();
    final Jid from = packet.getFrom();
    if (from == null || from.equals(account.getJid())) {
        return;
    }
    final String type = packet.getAttribute("type");
    final Contact contact = account.getRoster().getContact(from);
    if (type == null) {
        final String resource = from.isBareJid() ? "" : from.getResource();
        Avatar avatar = Avatar.parsePresence(packet.findChild("x", "vcard-temp:x:update"));
        if (avatar != null && (!contact.isSelf() || account.getAvatar() == null)) {
            avatar.owner = from.asBareJid();
            if (mXmppConnectionService.getFileBackend().isAvatarCached(avatar)) {
                if (avatar.owner.equals(account.getJid().asBareJid())) {
                    account.setAvatar(avatar.getFilename());
                    mXmppConnectionService.databaseBackend.updateAccount(account);
                    mXmppConnectionService.getAvatarService().clear(account);
                    mXmppConnectionService.updateConversationUi();
                    mXmppConnectionService.updateAccountUi();
                } else {
                    contact.setAvatar(avatar);
                    mXmppConnectionService.syncRoster(account);
                    mXmppConnectionService.getAvatarService().clear(contact);
                    mXmppConnectionService.updateConversationUi();
                    mXmppConnectionService.updateRosterUi();
                }
            } else if (mXmppConnectionService.isDataSaverDisabled()) {
                mXmppConnectionService.fetchAvatar(account, avatar);
            }
        }
        if (mXmppConnectionService.isMuc(account, from)) {
            return;
        }
        int sizeBefore = contact.getPresences().size();
        final String show = packet.findChildContent("show");
        final Element caps = packet.findChild("c", "http://jabber.org/protocol/caps");
        final String message = packet.findChildContent("status");
        final Presence presence = Presence.parse(show, caps, message);
        contact.updatePresence(resource, presence);
        if (presence.hasCaps()) {
            mXmppConnectionService.fetchCaps(account, from, presence);
        }
        final Element idle = packet.findChild("idle", Namespace.IDLE);
        if (idle != null) {
            try {
                final String since = idle.getAttribute("since");
                contact.setLastseen(AbstractParser.parseTimestamp(since));
                contact.flagInactive();
            } catch (Throwable throwable) {
                if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) {
                    contact.flagActive();
                }
            }
        } else {
            if (contact.setLastseen(AbstractParser.parseTimestamp(packet))) {
                contact.flagActive();
            }
        }
        PgpEngine pgp = mXmppConnectionService.getPgpEngine();
        Element x = packet.findChild("x", "jabber:x:signed");
        if (pgp != null && x != null) {
            final String status = packet.findChildContent("status");
            final long keyId = pgp.fetchKeyId(account, status, x.getContent());
            if (keyId != 0 && contact.setPgpKeyId(keyId)) {
                Log.d(Config.LOGTAG, account.getJid().asBareJid() + ": found OpenPGP key id for " + contact.getJid() + " " + OpenPgpUtils.convertKeyIdToHex(keyId));
                mXmppConnectionService.syncRoster(account);
            }
        }
        boolean online = sizeBefore < contact.getPresences().size();
        mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, online);
    } else if (type.equals("unavailable")) {
        if (contact.setLastseen(AbstractParser.parseTimestamp(packet, 0L, true))) {
            contact.flagInactive();
        }
        if (from.isBareJid()) {
            contact.clearPresences();
        } else {
            contact.removePresence(from.getResource());
        }
        if (contact.getShownStatus() == Presence.Status.OFFLINE) {
            contact.flagInactive();
        }
        mXmppConnectionService.onContactStatusChanged.onContactStatusChanged(contact, false);
    } else if (type.equals("subscribe")) {
        if (contact.setPresenceName(packet.findChildContent("nick", Namespace.NICK))) {
            mXmppConnectionService.syncRoster(account);
            mXmppConnectionService.getAvatarService().clear(contact);
        }
        if (contact.getOption(Contact.Options.PREEMPTIVE_GRANT)) {
            mXmppConnectionService.sendPresencePacket(account, mPresenceGenerator.sendPresenceUpdatesTo(contact));
        } else {
            contact.setOption(Contact.Options.PENDING_SUBSCRIPTION_REQUEST);
            final Conversation conversation = mXmppConnectionService.findOrCreateConversation(account, contact.getJid().asBareJid(), false, false);
            final String statusMessage = packet.findChildContent("status");
            if (statusMessage != null && !statusMessage.isEmpty() && conversation.countMessages() == 0) {
                conversation.add(new Message(conversation, statusMessage, Message.ENCRYPTION_NONE, Message.STATUS_RECEIVED));
            }
        }
    }
    mXmppConnectionService.updateRosterUi();
}
Also used : PresenceGenerator(eu.siacs.conversations.generator.PresenceGenerator) InvalidJid(eu.siacs.conversations.xmpp.InvalidJid) Jid(eu.siacs.conversations.xmpp.Jid) Message(eu.siacs.conversations.entities.Message) Element(eu.siacs.conversations.xml.Element) PgpEngine(eu.siacs.conversations.crypto.PgpEngine) Conversation(eu.siacs.conversations.entities.Conversation) Avatar(eu.siacs.conversations.xmpp.pep.Avatar) Contact(eu.siacs.conversations.entities.Contact) Presence(eu.siacs.conversations.entities.Presence)

Example 80 with Conversation

use of eu.siacs.conversations.entities.Conversation in project Conversations by siacs.

the class MessageGenerator method preparePacket.

private MessagePacket preparePacket(Message message) {
    Conversation conversation = (Conversation) message.getConversation();
    Account account = conversation.getAccount();
    MessagePacket packet = new MessagePacket();
    final boolean isWithSelf = conversation.getContact().isSelf();
    if (conversation.getMode() == Conversation.MODE_SINGLE) {
        packet.setTo(message.getCounterpart());
        packet.setType(MessagePacket.TYPE_CHAT);
        if (!isWithSelf) {
            packet.addChild("request", "urn:xmpp:receipts");
        }
    } else if (message.isPrivateMessage()) {
        packet.setTo(message.getCounterpart());
        packet.setType(MessagePacket.TYPE_CHAT);
        packet.addChild("x", "http://jabber.org/protocol/muc#user");
        packet.addChild("request", "urn:xmpp:receipts");
    } else {
        packet.setTo(message.getCounterpart().asBareJid());
        packet.setType(MessagePacket.TYPE_GROUPCHAT);
    }
    if (conversation.isSingleOrPrivateAndNonAnonymous() && !message.isPrivateMessage()) {
        packet.addChild("markable", "urn:xmpp:chat-markers:0");
    }
    packet.setFrom(account.getJid());
    packet.setId(message.getUuid());
    if (conversation.getMode() == Conversational.MODE_SINGLE || message.isPrivateMessage() || !conversation.getMucOptions().stableId()) {
        packet.addChild("origin-id", Namespace.STANZA_IDS).setAttribute("id", message.getUuid());
    }
    if (message.edited()) {
        packet.addChild("replace", "urn:xmpp:message-correct:0").setAttribute("id", message.getEditedIdWireFormat());
    }
    return packet;
}
Also used : MessagePacket(eu.siacs.conversations.xmpp.stanzas.MessagePacket) Account(eu.siacs.conversations.entities.Account) Conversation(eu.siacs.conversations.entities.Conversation)

Aggregations

Conversation (eu.siacs.conversations.entities.Conversation)110 Account (eu.siacs.conversations.entities.Account)27 Message (eu.siacs.conversations.entities.Message)24 Jid (eu.siacs.conversations.xmpp.Jid)22 Contact (eu.siacs.conversations.entities.Contact)17 MucOptions (eu.siacs.conversations.entities.MucOptions)10 Intent (android.content.Intent)9 Element (eu.siacs.conversations.xml.Element)9 PendingIntent (android.app.PendingIntent)8 XmppAxolotlMessage (eu.siacs.conversations.crypto.axolotl.XmppAxolotlMessage)8 MessagePacket (eu.siacs.conversations.xmpp.stanzas.MessagePacket)8 Uri (android.net.Uri)7 Conversational (eu.siacs.conversations.entities.Conversational)7 InvalidJidException (eu.siacs.conversations.xmpp.jid.InvalidJidException)7 SuppressLint (android.annotation.SuppressLint)6 SpannableString (android.text.SpannableString)6 XmppConnection (eu.siacs.conversations.xmpp.XmppConnection)6 Jid (eu.siacs.conversations.xmpp.jid.Jid)6 ArrayList (java.util.ArrayList)6 Fragment (android.app.Fragment)4