aboutsummaryrefslogtreecommitdiffstats
path: root/src/main/java/eu/siacs/conversations/ui
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/java/eu/siacs/conversations/ui')
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationActivity.java8
-rw-r--r--src/main/java/eu/siacs/conversations/ui/ConversationFragment.java81
-rw-r--r--src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java64
-rw-r--r--src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java5
-rw-r--r--src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java38
5 files changed, 155 insertions, 41 deletions
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
index 37be65a9..d71958d2 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationActivity.java
@@ -860,7 +860,7 @@ public class ConversationActivity extends XmppActivity
MenuItem pgp = popup.getMenu().findItem(R.id.encryption_choice_pgp);
MenuItem axolotl = popup.getMenu().findItem(R.id.encryption_choice_axolotl);
pgp.setVisible(!Config.HIDE_PGP_IN_UI && !Config.X509_VERIFICATION);
- none.setVisible(!Config.FORCE_E2E_ENCRYPTION);
+ none.setVisible(!Config.FORCE_E2E_ENCRYPTION || conversation.getMode() == Conversation.MODE_MULTI);
otr.setVisible(!Config.X509_VERIFICATION);
if (conversation.getMode() == Conversation.MODE_MULTI) {
otr.setVisible(false);
@@ -1577,4 +1577,10 @@ public class ConversationActivity extends XmppActivity
public boolean highlightSelectedConversations() {
return !isConversationsOverviewHideable() || this.conversationWasSelectedByKeyboard;
}
+
+ public void setMessagesLoaded() {
+ if (mConversationFragment != null) {
+ mConversationFragment.setMessagesLoaded();
+ }
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
index 169c5bbe..ea3d7e71 100644
--- a/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
+++ b/src/main/java/eu/siacs/conversations/ui/ConversationFragment.java
@@ -8,6 +8,7 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
+import android.content.IntentSender;
import android.content.IntentSender.SendIntentException;
import android.os.Bundle;
import android.support.annotation.Nullable;
@@ -23,6 +24,8 @@ import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.view.inputmethod.EditorInfo;
import android.view.inputmethod.InputMethodManager;
+import android.widget.AbsListView;
+import android.widget.AbsListView.OnScrollListener;
import android.widget.AdapterView;
import android.widget.AdapterView.AdapterContextMenuInfo;
import android.widget.ImageButton;
@@ -41,6 +44,8 @@ import net.java.otr4j.session.SessionStatus;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.NoSuchElementException;
+import java.util.concurrent.ConcurrentLinkedQueue;
import de.thedevstack.conversationsplus.ConversationsPlusPreferences;
import eu.siacs.conversations.Config;
@@ -52,6 +57,7 @@ import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.DownloadableFile;
import eu.siacs.conversations.entities.Message;
import eu.siacs.conversations.entities.MucOptions;
+import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.entities.Transferable;
import eu.siacs.conversations.entities.TransferablePlaceholder;
@@ -237,6 +243,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
private ConversationActivity activity;
private Message selectedMessage;
+ public void setMessagesLoaded() {
+ this.messagesLoaded = true;
+ }
+
private void sendMessage() {
final String body = mEditMessage.getText().toString();
if (body.length() == 0 || this.conversation == null) {
@@ -887,82 +897,82 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
enum SendButtonAction {TEXT, TAKE_PHOTO, SEND_LOCATION, RECORD_VOICE, CANCEL, CHOOSE_PICTURE}
- private int getSendButtonImageResource(SendButtonAction action, int status) {
+ private int getSendButtonImageResource(SendButtonAction action, Presence.Status status) {
switch (action) {
case TEXT:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_text_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_text_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_text_dnd;
default:
return R.drawable.ic_send_text_offline;
}
case TAKE_PHOTO:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_photo_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_photo_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_photo_dnd;
default:
return R.drawable.ic_send_photo_offline;
}
case RECORD_VOICE:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_voice_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_voice_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_voice_dnd;
default:
return R.drawable.ic_send_voice_offline;
}
case SEND_LOCATION:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_location_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_location_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_location_dnd;
default:
return R.drawable.ic_send_location_offline;
}
case CANCEL:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_cancel_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_cancel_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_cancel_dnd;
default:
return R.drawable.ic_send_cancel_offline;
}
case CHOOSE_PICTURE:
switch (status) {
- case Presences.CHAT:
- case Presences.ONLINE:
+ case CHAT:
+ case ONLINE:
return R.drawable.ic_send_picture_online;
- case Presences.AWAY:
+ case AWAY:
return R.drawable.ic_send_picture_away;
- case Presences.XA:
- case Presences.DND:
+ case XA:
+ case DND:
return R.drawable.ic_send_picture_dnd;
default:
return R.drawable.ic_send_picture_offline;
@@ -974,7 +984,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public void updateSendButton() {
final Conversation c = this.conversation;
final SendButtonAction action;
- final int status;
+ final Presence.Status status;
final boolean empty = this.mEditMessage == null || this.mEditMessage.getText().length() == 0;
final boolean conference = c.getMode() == Conversation.MODE_MULTI;
if (conference && !c.getAccount().httpUploadAvailable()) {
@@ -1021,10 +1031,10 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
if (c.getMode() == Conversation.MODE_SINGLE) {
status = c.getContact().getMostAvailableStatus();
} else {
- status = c.getMucOptions().online() ? Presences.ONLINE : Presences.OFFLINE;
+ status = c.getMucOptions().online() ? Presence.Status.ONLINE : Presence.Status.OFFLINE;
}
} else {
- status = Presences.OFFLINE;
+ status = Presence.Status.OFFLINE;
}
this.mSendButton.setTag(action);
this.mSendButton.setImageResource(getSendButtonImageResource(action, status));
@@ -1032,6 +1042,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public void updateStatusMessages() {
synchronized (this.messageList) {
+ if (conversation.getLastClearHistory() != 0) {
+ this.messageList.add(0, Message.createLoadMoreMessage(conversation));
+ }
if (conversation.getMode() == Conversation.MODE_SINGLE) {
ChatState state = conversation.getIncomingChatState();
if (state == ChatState.COMPOSING) {
diff --git a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
index 3765c764..db3a451b 100644
--- a/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/EditAccountActivity.java
@@ -32,7 +32,10 @@ import android.widget.TableLayout;
import android.widget.TextView;
import android.widget.Toast;
+import java.util.Arrays;
+import java.util.List;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicInteger;
import de.thedevstack.conversationsplus.ui.listeners.ShowResourcesListDialogListener;
import eu.siacs.conversations.Config;
@@ -46,6 +49,7 @@ import eu.siacs.conversations.services.XmppConnectionService.OnCaptchaRequested;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
import eu.siacs.conversations.utils.CryptoHelper;
import eu.siacs.conversations.utils.UIHelper;
+import eu.siacs.conversations.xml.Element;
import eu.siacs.conversations.xmpp.OnKeyStatusUpdated;
import eu.siacs.conversations.xmpp.XmppConnection.Features;
import eu.siacs.conversations.xmpp.forms.Data;
@@ -54,7 +58,7 @@ import eu.siacs.conversations.xmpp.jid.Jid;
import eu.siacs.conversations.xmpp.pep.Avatar;
public class EditAccountActivity extends XmppActivity implements OnAccountUpdate,
- OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast {
+ OnKeyStatusUpdated, OnCaptchaRequested, KeyChainAliasCallback, XmppConnectionService.OnShowErrorToast, XmppConnectionService.OnMamPreferencesFetched {
private AutoCompleteTextView mAccountJid;
private EditText mPassword;
@@ -220,6 +224,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
finish();
}
};
+ private Toast mFetchingMamPrefsToast;
public void refreshUiReal() {
invalidateOptionsMenu();
@@ -467,6 +472,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
final MenuItem changePassword = menu.findItem(R.id.action_change_password_on_server);
final MenuItem clearDevices = menu.findItem(R.id.action_clear_devices);
final MenuItem renewCertificate = menu.findItem(R.id.action_renew_certificate);
+ final MenuItem mamPrefs = menu.findItem(R.id.action_mam_prefs);
renewCertificate.setVisible(mAccount != null && mAccount.getPrivateKeyAlias() != null);
@@ -477,6 +483,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
if (!mAccount.getXmppConnection().getFeatures().register()) {
changePassword.setVisible(false);
}
+ mamPrefs.setVisible(mAccount.getXmppConnection().getFeatures().mam());
Set<Integer> otherDevices = mAccount.getAxolotlService().getOwnDeviceIds();
if (otherDevices == null || otherDevices.isEmpty()) {
clearDevices.setVisible(false);
@@ -487,6 +494,7 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
showMoreInfo.setVisible(false);
changePassword.setVisible(false);
clearDevices.setVisible(false);
+ mamPrefs.setVisible(false);
}
return true;
}
@@ -570,6 +578,9 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
changePasswordIntent.putExtra(EXTRA_ACCOUNT, mAccount.getJid().toString());
startActivity(changePasswordIntent);
break;
+ case R.id.action_mam_prefs:
+ editMamPrefs();
+ break;
case R.id.action_clear_devices:
showWipePepDialog();
break;
@@ -810,6 +821,12 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
builder.create().show();
}
+ private void editMamPrefs() {
+ this.mFetchingMamPrefsToast = Toast.makeText(this, R.string.fetching_mam_prefs, Toast.LENGTH_LONG);
+ this.mFetchingMamPrefsToast.show();
+ xmppConnectionService.fetchMamPreferences(mAccount, this);
+ }
+
@Override
public void onKeyStatusUpdated(AxolotlService.FetchStatus report) {
refreshUi();
@@ -889,4 +906,49 @@ public class EditAccountActivity extends XmppActivity implements OnAccountUpdate
}
});
}
+
+ @Override
+ public void onPreferencesFetched(final Element prefs) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mFetchingMamPrefsToast != null) {
+ mFetchingMamPrefsToast.cancel();
+ }
+ AlertDialog.Builder builder = new Builder(EditAccountActivity.this);
+ builder.setTitle(R.string.mam_prefs);
+ String defaultAttr = prefs.getAttribute("default");
+ final List<String> defaults = Arrays.asList("never", "roster", "always");
+ final AtomicInteger choice = new AtomicInteger(Math.max(0,defaults.indexOf(defaultAttr)));
+ builder.setSingleChoiceItems(R.array.mam_prefs, choice.get(), new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ choice.set(which);
+ }
+ });
+ builder.setNegativeButton(R.string.cancel, null);
+ builder.setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
+ @Override
+ public void onClick(DialogInterface dialog, int which) {
+ prefs.setAttribute("default",defaults.get(choice.get()));
+ xmppConnectionService.pushMamPreferences(mAccount, prefs);
+ }
+ });
+ builder.create().show();
+ }
+ });
+ }
+
+ @Override
+ public void onPreferencesFetchFailed() {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mFetchingMamPrefsToast != null) {
+ mFetchingMamPrefsToast.cancel();
+ }
+ Toast.makeText(EditAccountActivity.this,R.string.unable_to_fetch_mam_prefs,Toast.LENGTH_LONG).show();
+ }
+ });
+ }
}
diff --git a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
index ba685dcf..cd1658e0 100644
--- a/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
+++ b/src/main/java/eu/siacs/conversations/ui/StartConversationActivity.java
@@ -64,6 +64,7 @@ import eu.siacs.conversations.entities.Bookmark;
import eu.siacs.conversations.entities.Contact;
import eu.siacs.conversations.entities.Conversation;
import eu.siacs.conversations.entities.ListItem;
+import eu.siacs.conversations.entities.Presence;
import eu.siacs.conversations.entities.Presences;
import eu.siacs.conversations.services.XmppConnectionService.OnRosterUpdate;
import eu.siacs.conversations.ui.adapter.KnownHostsAdapter;
@@ -727,9 +728,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
for (Account account : xmppConnectionService.getAccounts()) {
if (account.getStatus() != Account.State.DISABLED) {
for (Contact contact : account.getRoster().getContacts()) {
+ Presence p = contact.getPresences().getMostAvailablePresence();
+ Presence.Status s = p == null ? Presence.Status.OFFLINE : p.getStatus();
if (contact.showInRoster() && contact.match(needle)
&& (!this.mHideOfflineContacts
- || contact.getPresences().getMostAvailableStatus() < Presences.OFFLINE)) {
+ || s.compareTo(Presence.Status.OFFLINE) < 0)) {
this.contacts.add(contact);
}
}
diff --git a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
index d1db6667..78c8f67c 100644
--- a/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
+++ b/src/main/java/eu/siacs/conversations/ui/adapter/MessageAdapter.java
@@ -431,6 +431,19 @@ public class MessageAdapter extends ArrayAdapter<Message> {
viewHolder.image.setOnLongClickListener(openContextMenu);
}
+ private void loadMoreMessages(Conversation conversation) {
+ conversation.setLastClearHistory(0);
+ conversation.setHasMessagesLeftOnServer(true);
+ conversation.setFirstMamReference(null);
+ long timestamp = conversation.getLastMessageTransmitted();
+ if (timestamp == 0) {
+ timestamp = System.currentTimeMillis();
+ }
+ activity.setMessagesLoaded();
+ activity.xmppConnectionService.getMessageArchiveService().query(conversation, 0, timestamp);
+ Toast.makeText(activity, R.string.fetching_history_from_server,Toast.LENGTH_LONG).show();
+ }
+
@Override
public View getView(int position, View view, ViewGroup parent) {
final Message message = getItem(position);
@@ -487,6 +500,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
view = activity.getLayoutInflater().inflate(R.layout.message_status, parent, false);
viewHolder.contact_picture = (ImageView) view.findViewById(R.id.message_photo);
viewHolder.status_message = (TextView) view.findViewById(R.id.status_message);
+ viewHolder.load_more_messages = (Button) view.findViewById(R.id.load_more_messages);
break;
default:
viewHolder = null;
@@ -500,18 +514,33 @@ public class MessageAdapter extends ArrayAdapter<Message> {
}
}
- boolean darkBackground = (type == RECEIVED && !isInValidSession);
+ boolean darkBackground = (type == RECEIVED && (!isInValidSession || !mUseWhiteBackground));
if (type == STATUS) {
- if (conversation.getMode() == Conversation.MODE_SINGLE) {
+ if ("LOAD_MORE".equals(message.getBody())) {
+ viewHolder.status_message.setVisibility(View.GONE);
+ viewHolder.contact_picture.setVisibility(View.GONE);
+ viewHolder.load_more_messages.setVisibility(View.VISIBLE);
+ viewHolder.load_more_messages.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ loadMoreMessages(message.getConversation());
+ }
+ });
+ } else {
+ viewHolder.status_message.setVisibility(View.VISIBLE);
+ viewHolder.contact_picture.setVisibility(View.VISIBLE);
+ viewHolder.load_more_messages.setVisibility(View.GONE);
+ if (conversation.getMode() == Conversation.MODE_SINGLE) {
viewHolder.contact_picture.setImageBitmap(AvatarService.getInstance().get(conversation.getContact(),
activity.getPixel(32)));
- viewHolder.contact_picture.setAlpha(0.5f);
+ viewHolder.contact_picture.setAlpha(0.5f);
+ }
viewHolder.status_message.setText(message.getBody());
}
return view;
} else {
- loadAvatar(message,viewHolder.contact_picture);
+ loadAvatar(message, viewHolder.contact_picture);
}
viewHolder.contact_picture
@@ -661,6 +690,7 @@ public class MessageAdapter extends ArrayAdapter<Message> {
protected ImageView contact_picture;
protected TextView status_message;
protected TextView encryption;
+ public Button load_more_messages;
}
class BitmapWorkerTask extends AsyncTask<Message, Void, Bitmap> {