aboutsummaryrefslogtreecommitdiffstats
path: root/src/main
diff options
context:
space:
mode:
authorChristian Schneppe <christian@pix-art.de>2018-03-24 22:38:29 +0100
committerChristian Schneppe <christian@pix-art.de>2018-03-24 22:38:29 +0100
commit6e49572be6fdd7c54eb0d6f1939dce9fbb537024 (patch)
treedb4eadcb01743f2c2c6cdbfe63c56a3faeadad7d /src/main
parent91507dc103cbb758e49e861f8cff77ccdad09321 (diff)
WIP & fragment voodoo
Diffstat (limited to 'src/main')
-rw-r--r--src/main/AndroidManifest.xml2
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationActivity.java88
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationFragment.java162
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationsMainActivity.java239
-rw-r--r--src/main/java/de/pixart/messenger/ui/ConversationsOverviewFragment.java114
-rw-r--r--src/main/java/de/pixart/messenger/ui/StartConversationActivity.java5
-rw-r--r--src/main/java/de/pixart/messenger/ui/StartUI.java2
-rw-r--r--src/main/java/de/pixart/messenger/ui/XmppFragment.java39
-rw-r--r--src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java42
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnConversationArchived.java36
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnConversationRead.java36
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnConversationSelected.java36
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnConversationsListItemUpdated.java34
-rw-r--r--src/main/java/de/pixart/messenger/ui/interfaces/OnSwipeTouchListener.java57
-rw-r--r--src/main/java/de/pixart/messenger/ui/util/PendingItem.java45
-rw-r--r--src/main/res/layout-w945dp/activity_conversations.xml22
-rw-r--r--src/main/res/layout-w945dp/fragment_conversations_overview.xml30
-rw-r--r--src/main/res/layout/activity_conversations.xml35
-rw-r--r--src/main/res/layout/fragment_conversations_overview.xml33
-rw-r--r--src/main/res/menu/activity_conversations.xml15
20 files changed, 871 insertions, 201 deletions
diff --git a/src/main/AndroidManifest.xml b/src/main/AndroidManifest.xml
index 961c4df2a..872a9e9cd 100644
--- a/src/main/AndroidManifest.xml
+++ b/src/main/AndroidManifest.xml
@@ -77,7 +77,7 @@
</intent-filter>
</activity>
<activity
- android:name=".ui.ConversationActivity"
+ android:name=".ui.ConversationsMainActivity"
android:label="@string/app_name"
android:launchMode="singleTask"
android:minWidth="300dp"
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
index 4ad5d2d59..27512a3d1 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationActivity.java
@@ -2,11 +2,9 @@ package de.pixart.messenger.ui;
import android.annotation.SuppressLint;
import android.app.FragmentTransaction;
-import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
-import android.content.IntentSender.SendIntentException;
import android.content.SharedPreferences;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager;
@@ -31,13 +29,9 @@ import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
-import android.widget.PopupMenu;
-import android.widget.PopupMenu.OnMenuItemClickListener;
import android.widget.TextView;
import android.widget.Toast;
-import net.java.otr4j.session.SessionStatus;
-
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
@@ -59,7 +53,6 @@ import de.pixart.messenger.ui.adapter.ConversationAdapter;
import de.pixart.messenger.utils.ExceptionHelper;
import de.pixart.messenger.utils.UIHelper;
import de.pixart.messenger.xmpp.OnUpdateBlocklist;
-import de.pixart.messenger.xmpp.XmppConnection;
import de.pixart.messenger.xmpp.chatstate.ChatState;
import de.pixart.messenger.xmpp.jid.InvalidJidException;
import de.pixart.messenger.xmpp.jid.Jid;
@@ -165,6 +158,7 @@ public class ConversationActivity extends XmppActivity
}
}
+ @SuppressLint("ClickableViewAccessibility")
@Override
protected void onCreate(final Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
@@ -186,7 +180,7 @@ public class ConversationActivity extends XmppActivity
this.mConversationFragment = new ConversationFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
- transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation");
+ //transaction.replace(R.id.selected_conversation, this.mConversationFragment, "conversation");
transaction.commit();
listView = findViewById(R.id.list);
@@ -214,9 +208,9 @@ public class ConversationActivity extends XmppActivity
}
});
- mContentView = findViewById(R.id.content_view_spl);
+ //mContentView = findViewById(R.id.content_view_spl);
if (mContentView == null) {
- mContentView = findViewById(R.id.content_view_ll);
+ //mContentView = findViewById(R.id.content_view_ll);
}
if (mContentView instanceof SlidingPaneLayout) {
SlidingPaneLayout mSlidingPaneLayout = (SlidingPaneLayout) mContentView;
@@ -252,6 +246,10 @@ public class ConversationActivity extends XmppActivity
}
}
+ public boolean useBundledEmoji() {
+ return getPreferences().getBoolean(USE_BUNDLED_EMOJIS, getResources().getBoolean(R.bool.use_bundled_emoji));
+ }
+
private boolean isPackageInstalled(String targetPackage) {
List<ApplicationInfo> packages;
PackageManager pm;
@@ -454,41 +452,6 @@ public class ConversationActivity extends XmppActivity
}
}
- public void verifyOtrSessionDialog(final Conversation conversation, View view) {
- if (!conversation.hasValidOtrSession() || conversation.getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
- Toast.makeText(this, R.string.otr_session_not_started, Toast.LENGTH_LONG).show();
- return;
- }
- if (view == null) {
- return;
- }
- PopupMenu popup = new PopupMenu(this, view);
- popup.inflate(R.menu.verification_choices);
- popup.setOnMenuItemClickListener(new OnMenuItemClickListener() {
- @Override
- public boolean onMenuItemClick(MenuItem menuItem) {
- Intent intent = new Intent(ConversationActivity.this, VerifyOTRActivity.class);
- intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
- intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
- intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString());
- switch (menuItem.getItemId()) {
- case R.id.scan_fingerprint:
- intent.putExtra("mode", VerifyOTRActivity.MODE_SCAN_FINGERPRINT);
- break;
- case R.id.ask_question:
- intent.putExtra("mode", VerifyOTRActivity.MODE_ASK_QUESTION);
- break;
- case R.id.manual_verification:
- intent.putExtra("mode", VerifyOTRActivity.MODE_MANUAL_VERIFICATION);
- break;
- }
- startActivity(intent);
- return true;
- }
- });
- popup.show();
- }
-
@Override
public void onBackPressed() {
if (!isConversationsOverviewVisable() && mConversationFragment.isSearchFieldVisible()) {
@@ -914,11 +877,6 @@ public class ConversationActivity extends XmppActivity
}
}
- public long getMaxHttpUploadSize(Conversation conversation) {
- final XmppConnection connection = conversation.getAccount().getXmppConnection();
- return connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize();
- }
-
private String getBatteryOptimizationPreferenceKey() {
@SuppressLint("HardwareIds") String device = Settings.Secure.getString(getContentResolver(), Settings.Secure.ANDROID_ID);
return "show_battery_optimization" + (device == null ? "" : device);
@@ -974,30 +932,6 @@ public class ConversationActivity extends XmppActivity
listAdapter.notifyDataSetChanged();
}
- public void runIntent(PendingIntent pi, int requestCode) {
- try {
- this.startIntentSenderForResult(pi.getIntentSender(), requestCode,
- null, 0, 0, 0);
- } catch (final SendIntentException ignored) {
- }
- }
-
- public boolean useSendButtonToIndicateStatus() {
- return getPreferences().getBoolean("send_button_status", getResources().getBoolean(R.bool.send_button_status));
- }
-
- public boolean indicateReceived() {
- return getPreferences().getBoolean("indicate_received", getResources().getBoolean(R.bool.indicate_received));
- }
-
- public boolean useWhiteBackground() {
- return getPreferences().getBoolean("use_white_background", getResources().getBoolean(R.bool.use_white_background));
- }
-
- public boolean useBundledEmoji() {
- return getPreferences().getBoolean(USE_BUNDLED_EMOJIS, getResources().getBoolean(R.bool.use_bundled_emoji));
- }
-
@Override
protected void refreshUiReal() {
updateConversationList();
@@ -1040,10 +974,6 @@ public class ConversationActivity extends XmppActivity
this.refreshUi();
}
- public boolean enterIsSend() {
- return getPreferences().getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send));
- }
-
@Override
public void onShowErrorToast(final int resId) {
runOnUiThread(() -> Toast.makeText(ConversationActivity.this, resId, Toast.LENGTH_SHORT).show());
@@ -1066,4 +996,6 @@ public class ConversationActivity extends XmppActivity
startActivity(intent);
}
}
+
+
}
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
index 2b27d63cf..742c14495 100644
--- a/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
+++ b/src/main/java/de/pixart/messenger/ui/ConversationFragment.java
@@ -2,13 +2,13 @@ package de.pixart.messenger.ui;
import android.annotation.SuppressLint;
import android.app.Activity;
-import android.app.Fragment;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender.SendIntentException;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.databinding.DataBindingUtil;
import android.graphics.Bitmap;
@@ -18,6 +18,7 @@ import android.os.Build;
import android.os.Bundle;
import android.os.Handler;
import android.os.SystemClock;
+import android.preference.PreferenceManager;
import android.provider.MediaStore;
import android.support.media.ExifInterface;
import android.support.v13.view.inputmethod.InputConnectionCompat;
@@ -91,9 +92,11 @@ import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.services.MessageArchiveService;
import de.pixart.messenger.services.XmppConnectionService;
import de.pixart.messenger.ui.adapter.MessageAdapter;
+import de.pixart.messenger.ui.interfaces.OnSwipeTouchListener;
import de.pixart.messenger.ui.util.ActivityResult;
import de.pixart.messenger.ui.util.AttachmentTool;
import de.pixart.messenger.ui.util.ConversationMenuConfigurator;
+import de.pixart.messenger.ui.util.PendingItem;
import de.pixart.messenger.ui.util.PresenceSelector;
import de.pixart.messenger.ui.util.SendButtonAction;
import de.pixart.messenger.ui.util.SendButtonTool;
@@ -112,7 +115,7 @@ import static de.pixart.messenger.ui.XmppActivity.REQUEST_ANNOUNCE_PGP;
import static de.pixart.messenger.ui.XmppActivity.REQUEST_CHOOSE_PGP_ID;
import static de.pixart.messenger.xmpp.Patches.ENCRYPTION_EXCEPTIONS;
-public class ConversationFragment extends Fragment implements EditMessage.KeyboardListener {
+public class ConversationFragment extends XmppFragment implements EditMessage.KeyboardListener {
public static final int REQUEST_SEND_MESSAGE = 0x0201;
public static final int REQUEST_DECRYPT_PGP = 0x0202;
@@ -130,18 +133,21 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
public static final int ATTACHMENT_CHOICE_INVALID = 0x0399;
public static final String RECENTLY_USED_QUICK_ACTION = "recently_used_quick_action";
+ public static final String STATE_CONVERSATION_UUID = ConversationFragment.class.getName() + ".uuid";
+ public static final String STATE_SCROLL_POSITION = ConversationFragment.class.getName() + ".scroll_position";
final protected List<Message> messageList = new ArrayList<>();
final private List<Uri> mPendingImageUris = new ArrayList<>();
public Uri mPendingEditorContent = null;
- protected Conversation conversation;
- public FragmentConversationBinding binding;
+ private final PendingItem<ActivityResult> postponedActivityResult = new PendingItem<>();
+ private final PendingItem<String> pendingConversationsUuid = new PendingItem<>();
protected MessageAdapter messageListAdapter;
+ private Conversation conversation;
+ public FragmentConversationBinding binding;
protected Message lastHistoryMessage = null;
SimpleDateFormat sdf = new SimpleDateFormat("EEEE, dd. MMM yyyy", Locale.getDefault());
private Toast messageLoaderToast;
- private ActivityResult postponedActivityResult = null;
- private ConversationActivity activity;
+ private ConversationsMainActivity activity;
protected OnClickListener clickToVerify = new OnClickListener() {
@Override
public void onClick(View v) {
@@ -162,7 +168,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void onClick(View v) {
- activity.endConversation(conversation);
+ activity.onConversationArchived(conversation);
}
};
private OnClickListener joinMuc = new OnClickListener() {
@@ -904,6 +910,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
break;
case ATTACHMENT_CHOICE_TAKE_FROM_CAMERA:
+ //TODO save photo uri
final List<Uri> PhotoUris = AttachmentTool.extractUriFromIntent(data);
for (Iterator<Uri> i = PhotoUris.iterator(); i.hasNext(); i.remove()) {
Log.d(Config.LOGTAG, "ConversationsActivity.onActivityResult() - attaching image to conversations. TAKE_FROM_CAMERA");
@@ -918,7 +925,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
attachFileToConversation(conversation, i.next());
}
};
- if (conversation == null || conversation.getMode() == Conversation.MODE_MULTI || FileBackend.allFilesUnderSize(getActivity(), fileUris, activity.getMaxHttpUploadSize(conversation))) {
+ if (conversation == null || conversation.getMode() == Conversation.MODE_MULTI || FileBackend.allFilesUnderSize(getActivity(), fileUris, getMaxHttpUploadSize(conversation))) {
callback.onPresenceSelected();
} else {
activity.selectPresence(conversation, callback);
@@ -949,7 +956,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
if (activity != null && activity.xmppConnectionService != null) {
handleActivityResult(activityResult);
} else {
- this.postponedActivityResult = activityResult;
+ this.postponedActivityResult.push(activityResult);
}
}
@@ -958,13 +965,14 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
@Override
- public void onAttach(Context context) {
- if (context instanceof ConversationActivity) {
- this.activity = (ConversationActivity) context;
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ Log.d(Config.LOGTAG, "onAttach()");
+ if (activity instanceof ConversationsMainActivity) {
+ this.activity = (ConversationsMainActivity) activity;
} else {
throw new IllegalStateException("Trying to attach fragment to activity that is not the ConversationActivity");
}
- super.onAttach(context);
}
@Override
@@ -1001,7 +1009,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
binding.messagesView.setOnScrollListener(mOnScrollListener);
binding.messagesView.setTranscriptMode(ListView.TRANSCRIPT_MODE_NORMAL);
- messageListAdapter = new MessageAdapter((ConversationActivity) getActivity(), this.messageList);
+ messageListAdapter = new MessageAdapter((XmppActivity) getActivity(), this.messageList);
messageListAdapter.setOnContactPictureClicked(message -> {
final boolean received = message.getStatus() <= Message.STATUS_RECEIVED;
if (received) {
@@ -1074,7 +1082,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
binding.messagesView.setAdapter(messageListAdapter);
registerForContextMenu(binding.messagesView);
-
return binding.getRoot();
}
@@ -1253,7 +1260,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
handleAttachmentSelection(item);
break;
case R.id.action_archive_chat:
- activity.endConversation(conversation);
+ activity.onConversationArchived(conversation);
break;
case R.id.action_archive_muc:
getActivity().runOnUiThread(() -> {
@@ -1262,7 +1269,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
builder.setMessage(getString(R.string.leave_conference_warning));
builder.setNegativeButton(getString(R.string.cancel), null);
builder.setPositiveButton(getString(R.string.action_end_conversation_muc),
- (dialog, which) -> activity.endConversation(conversation));
+ (dialog, which) -> activity.onConversationArchived(conversation));
builder.create().show();
});
break;
@@ -1312,7 +1319,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
if (conversation == null) {
return;
}
- final ConversationFragment fragment = (ConversationFragment) getFragmentManager().findFragmentByTag("conversation");
switch (item.getItemId()) {
case R.id.encryption_choice_none:
conversation.setNextEncryption(Message.ENCRYPTION_NONE);
@@ -1345,7 +1351,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
break;
}
activity.xmppConnectionService.updateConversation(conversation);
- fragment.updateChatMsgHint();
+ updateChatMsgHint();
getActivity().invalidateOptionsMenu();
activity.refreshUi();
}
@@ -1384,7 +1390,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void userInputRequried(PendingIntent pi, Contact contact) {
- activity.runIntent(pi, attachmentChoice);
+ startPendingIntent(pi, attachmentChoice);
}
@Override
@@ -1478,9 +1484,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
builder.setPositiveButton(getString(R.string.delete_messages), (dialog, which) -> {
this.activity.xmppConnectionService.clearConversationHistory(conversation);
if (endConversationCheckBox.isChecked()) {
- this.activity.endConversation(conversation);
+ this.activity.onConversationArchived(conversation);
} else {
- activity.updateConversationList();
+ activity.onConversationsListItemUpdated();
updateMessages();
}
});
@@ -1625,7 +1631,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
private void deleteFile(Message message) {
if (activity.xmppConnectionService.getFileBackend().deleteFile(message)) {
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
- activity.updateConversationList();
+ activity.onConversationsListItemUpdated();
updateMessages();
}
}
@@ -1648,7 +1654,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
} else {
Toast.makeText(activity, R.string.file_deleted, Toast.LENGTH_SHORT).show();
message.setTransferable(new TransferablePlaceholder(Transferable.STATUS_DELETED));
- activity.updateConversationList();
+ activity.onConversationsListItemUpdated();
updateMessages();
return;
}
@@ -1693,7 +1699,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
private void retryDecryption(Message message) {
message.setEncryption(Message.ENCRYPTION_PGP);
- activity.updateConversationList();
+ activity.onConversationsListItemUpdated();
updateMessages();
conversation.getAccount().getPgpDecryptionService().decrypt(message, false);
}
@@ -1748,6 +1754,32 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
@Override
+ public void onSaveInstanceState(Bundle outState) {
+ super.onSaveInstanceState(outState);
+ if (conversation != null) {
+ outState.putString(STATE_CONVERSATION_UUID, conversation.getUuid());
+ }
+ }
+
+ @Override
+ public void onActivityCreated(Bundle savedInstanceState) {
+ super.onActivityCreated(savedInstanceState);
+ if (savedInstanceState == null) {
+ return;
+ }
+ String uuid = savedInstanceState.getString(STATE_CONVERSATION_UUID);
+ if (uuid != null) {
+ this.pendingConversationsUuid.push(uuid);
+ }
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ reInit(conversation);
+ }
+
+ @Override
public void onStop() {
super.onStop();
final Activity activity = getActivity();
@@ -1772,9 +1804,17 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
public boolean reInit(Conversation conversation) {
+ Log.d(Config.LOGTAG, "reInit()");
if (conversation == null) {
+ Log.d(Config.LOGTAG, "conversation was null :(");
return false;
}
+ if (this.activity == null) {
+ Log.d(Config.LOGTAG, "activity was null");
+ this.conversation = conversation;
+ return false;
+ }
+
setupIme();
if (this.conversation != null) {
final String msg = this.binding.textinput.getText().toString();
@@ -1799,6 +1839,13 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
this.binding.textinput.setKeyboardListener(this);
messageListAdapter.updatePreferences();
this.binding.messagesView.setAdapter(messageListAdapter);
+ this.binding.messagesView.setOnTouchListener(new OnSwipeTouchListener(getContext()) {
+ @Override
+ public void onSwipeRight() {
+ Log.d(Config.LOGTAG, "Swipe right detected");
+ activity.onBackPressed();
+ }
+ });
updateMessages();
this.conversation.messagesLoaded.set(true);
synchronized (this.messageList) {
@@ -1947,15 +1994,14 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
if (getView() == null) {
return;
}
- final ConversationActivity activity = (ConversationActivity) getActivity();
if (this.conversation != null) {
conversation.populateWithMessages(ConversationFragment.this.messageList);
updateSnackBar(conversation);
updateStatusMessages();
this.messageListAdapter.notifyDataSetChanged();
updateChatMsgHint();
- if (!activity.isConversationsOverviewVisable() || !activity.isConversationsOverviewHideable()) {
- activity.sendReadMarkerIfNecessary(conversation);
+ if (activity != null) {
+ activity.onConversationRead(this.conversation);
}
updateSendButton();
updateEditablity();
@@ -1988,6 +2034,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
mSendingPgpMessage.set(false);
}
+ public long getMaxHttpUploadSize(Conversation conversation) {
+ final XmppConnection connection = conversation.getAccount().getXmppConnection();
+ return connection == null ? -1 : connection.getFeatures().getMaxHttpUploadSize();
+ }
+
private void updateEditablity() {
boolean canWrite = this.conversation.getMode() == Conversation.MODE_SINGLE || this.conversation.getMucOptions().participating() || this.conversation.getNextCounterpart() != null;
this.binding.textinput.setFocusable(canWrite);
@@ -1997,11 +2048,12 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
public void updateSendButton() {
+ boolean useSendButtonToIndicateStatus = PreferenceManager.getDefaultSharedPreferences(getActivity()).getBoolean("send_button_status", getResources().getBoolean(R.bool.send_button_status));
final Conversation c = this.conversation;
final Presence.Status status;
final String text = this.binding.textinput == null ? "" : this.binding.textinput.getText().toString();
final SendButtonAction action = SendButtonTool.getAction(getActivity(), c, text);
- if (activity.useSendButtonToIndicateStatus() && c.getAccount().getStatus() == Account.State.ONLINE) {
+ if (useSendButtonToIndicateStatus && c.getAccount().getStatus() == Account.State.ONLINE) {
if (activity.xmppConnectionService != null && activity.xmppConnectionService.getMessageArchiveService().isCatchingUp(c)) {
status = Presence.Status.OFFLINE;
} else if (c.getMode() == Conversation.MODE_SINGLE) {
@@ -2166,13 +2218,11 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
protected void sendPlainTextMessage(Message message) {
- ConversationActivity activity = (ConversationActivity) getActivity();
activity.xmppConnectionService.sendMessage(message);
messageSent();
}
protected void sendPgpMessage(final Message message) {
- final ConversationActivity activity = (ConversationActivity) getActivity();
final XmppConnectionService xmppService = activity.xmppConnectionService;
final Contact contact = message.getConversation().getContact();
if (!activity.hasPgp()) {
@@ -2193,7 +2243,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void userInputRequried(PendingIntent pi, Contact contact) {
- activity.runIntent(pi, REQUEST_ENCRYPT_MESSAGE);
+ startPendingIntent(pi, REQUEST_ENCRYPT_MESSAGE);
}
@Override
@@ -2251,7 +2301,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public void userInputRequried(PendingIntent pi, Message message) {
- activity.runIntent(pi, REQUEST_SEND_MESSAGE);
+ startPendingIntent(pi, REQUEST_SEND_MESSAGE);
}
@Override
@@ -2288,9 +2338,7 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
}
protected void sendAxolotlMessage(final Message message) {
- final ConversationActivity activity = (ConversationActivity) getActivity();
- final XmppConnectionService xmppService = activity.xmppConnectionService;
- xmppService.sendMessage(message);
+ activity.xmppConnectionService.sendMessage(message);
messageSent();
}
@@ -2318,7 +2366,9 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
@Override
public boolean onEnterPressed() {
- if (activity.enterIsSend()) {
+ SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(getActivity());
+ final boolean enterIsSend = p.getBoolean("enter_is_send", getResources().getBoolean(R.bool.enter_is_send));
+ if (enterIsSend) {
sendMessage();
return true;
} else {
@@ -2336,7 +2386,6 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
if (broadcastLastActivity) {
activity.xmppConnectionService.sendPresence(conversation.getAccount(), false); //send new presence but don't include idle because we are not
}
- activity.hideConversationsOverview();
updateSendButton();
}
@@ -2474,17 +2523,44 @@ public class ConversationFragment extends Fragment implements EditMessage.Keyboa
return m != null && m.getMergedBody().toString().toLowerCase().contains(q.toLowerCase());
}
+ private void startPendingIntent(PendingIntent pendingIntent, int requestCode) {
+ try {
+ getActivity().startIntentSenderForResult(pendingIntent.getIntentSender(), requestCode, null, 0, 0, 0);
+ } catch (final SendIntentException ignored) {
+ }
+ }
+
+ @Override
public void onBackendConnected() {
- if (postponedActivityResult != null) {
- handleActivityResult(postponedActivityResult);
+ Log.d(Config.LOGTAG, "ConversationFragment.onBackendConnected()");
+ String uuid = pendingConversationsUuid.pop();
+ if (uuid != null) {
+ Conversation conversation = activity.xmppConnectionService.findConversationByUuid(uuid);
+ if (conversation == null) {
+ Log.d(Config.LOGTAG, "unable to restore activity");
+ clearPending();
+ return;
+ }
+ reInit(conversation);
}
- postponedActivityResult = null;
+ ActivityResult activityResult = postponedActivityResult.pop();
+ if (activityResult != null) {
+ handleActivityResult(activityResult);
+ }
+ }
+
+ @Override
+ void refresh() {
+
}
public void clearPending() {
- if (postponedActivityResult != null) {
+ if (postponedActivityResult.pop() != null) {
Log.d(Config.LOGTAG, "cleared pending intent with unhandled result left");
}
- postponedActivityResult = null;
+ }
+
+ public Conversation getConversation() {
+ return conversation;
}
}
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationsMainActivity.java b/src/main/java/de/pixart/messenger/ui/ConversationsMainActivity.java
new file mode 100644
index 000000000..14570af97
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/ConversationsMainActivity.java
@@ -0,0 +1,239 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui;
+
+import android.app.Fragment;
+import android.app.FragmentManager;
+import android.app.FragmentTransaction;
+import android.content.Intent;
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.support.annotation.IdRes;
+import android.support.v7.app.ActionBar;
+import android.util.Log;
+import android.view.Menu;
+import android.view.MenuItem;
+import android.view.View;
+import android.widget.PopupMenu;
+import android.widget.Toast;
+
+import net.java.otr4j.session.SessionStatus;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.ActivityConversationsBinding;
+import de.pixart.messenger.entities.Conversation;
+import de.pixart.messenger.services.EmojiService;
+import de.pixart.messenger.ui.interfaces.OnConversationArchived;
+import de.pixart.messenger.ui.interfaces.OnConversationRead;
+import de.pixart.messenger.ui.interfaces.OnConversationSelected;
+import de.pixart.messenger.ui.interfaces.OnConversationsListItemUpdated;
+
+import static de.pixart.messenger.ui.SettingsActivity.USE_BUNDLED_EMOJIS;
+
+public class ConversationsMainActivity extends XmppActivity implements OnConversationSelected, OnConversationArchived, OnConversationsListItemUpdated, OnConversationRead {
+
+ private ActivityConversationsBinding binding;
+
+ @Override
+ protected void refreshUiReal() {
+
+ }
+
+ @Override
+ void onBackendConnected() {
+ notifyFragment(R.id.main_fragment);
+ notifyFragment(R.id.secondary_fragment);
+ invalidateActionBarTitle();
+ }
+
+ private void notifyFragment(@IdRes int id) {
+ Fragment mainFragment = getFragmentManager().findFragmentById(id);
+ if (mainFragment != null && mainFragment instanceof XmppFragment) {
+ ((XmppFragment) mainFragment).onBackendConnected();
+ }
+ }
+
+ @Override
+ protected void onCreate(final Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ new EmojiService(this).init(useBundledEmoji());
+ this.binding = DataBindingUtil.setContentView(this, R.layout.activity_conversations);
+ this.getFragmentManager().addOnBackStackChangedListener(this::invalidateActionBarTitle);
+ this.initializeFragments();
+ this.invalidateActionBarTitle();
+ }
+
+ @Override
+ public boolean onCreateOptionsMenu(Menu menu) {
+ getMenuInflater().inflate(R.menu.activity_conversations, menu);
+ return super.onCreateOptionsMenu(menu);
+ }
+
+ @Override
+ public void onConversationSelected(Conversation conversation) {
+ Log.d(Config.LOGTAG, "selected " + conversation.getName());
+ ConversationFragment conversationFragment = (ConversationFragment) getFragmentManager().findFragmentById(R.id.secondary_fragment);
+ if (conversationFragment == null) {
+ conversationFragment = new ConversationFragment();
+ FragmentTransaction fragmentTransaction = getFragmentManager().beginTransaction();
+ fragmentTransaction.replace(R.id.main_fragment, conversationFragment);
+ fragmentTransaction.addToBackStack(null);
+ fragmentTransaction.commit();
+ }
+ conversationFragment.reInit(conversation);
+ }
+
+ @Override
+ public boolean onOptionsItemSelected(MenuItem item) {
+ switch (item.getItemId()) {
+ case android.R.id.home:
+ FragmentManager fm = getFragmentManager();
+ if (fm.getBackStackEntryCount() > 0) {
+ fm.popBackStack();
+ return true;
+ }
+ break;
+ }
+ return super.onOptionsItemSelected(item);
+ }
+
+ private void initializeFragments() {
+ FragmentTransaction transaction = getFragmentManager().beginTransaction();
+ Fragment mainFragment = getFragmentManager().findFragmentById(R.id.main_fragment);
+ Fragment secondaryFragment = getFragmentManager().findFragmentById(R.id.secondary_fragment);
+ if (mainFragment != null) {
+ Log.d(Config.LOGTAG, "initializeFragment(). main fragment exists");
+ if (binding.secondaryFragment != null) {
+ if (mainFragment instanceof ConversationFragment) {
+ Log.d(Config.LOGTAG, "gained secondary fragment. moving...");
+ getFragmentManager().popBackStack();
+ transaction.remove(mainFragment);
+ transaction.commit();
+ getFragmentManager().executePendingTransactions();
+ transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.secondary_fragment, mainFragment);
+ transaction.replace(R.id.main_fragment, new ConversationsOverviewFragment());
+ transaction.commit();
+ return;
+ }
+ } else {
+ if (secondaryFragment != null && secondaryFragment instanceof ConversationFragment) {
+ Log.d(Config.LOGTAG, "lost secondary fragment. moving...");
+ transaction.remove(secondaryFragment);
+ transaction.commit();
+ getFragmentManager().executePendingTransactions();
+ transaction = getFragmentManager().beginTransaction();
+ transaction.replace(R.id.main_fragment, secondaryFragment);
+ transaction.addToBackStack(null);
+ transaction.commit();
+ return;
+ }
+ }
+ } else {
+ transaction.replace(R.id.main_fragment, new ConversationsOverviewFragment());
+ }
+ if (binding.secondaryFragment != null) {
+ transaction.replace(R.id.secondary_fragment, new ConversationFragment());
+ }
+ transaction.commit();
+ }
+
+ private void invalidateActionBarTitle() {
+ final ActionBar actionBar = getSupportActionBar();
+ if (actionBar != null) {
+ Fragment mainFragment = getFragmentManager().findFragmentById(R.id.main_fragment);
+ if (mainFragment != null && mainFragment instanceof ConversationFragment) {
+ final Conversation conversation = ((ConversationFragment) mainFragment).getConversation();
+ if (conversation != null) {
+ actionBar.setTitle(conversation.getName());
+ actionBar.setDisplayHomeAsUpEnabled(true);
+ return;
+ }
+ }
+ actionBar.setTitle(R.string.app_name);
+ actionBar.setDisplayHomeAsUpEnabled(false);
+ }
+ }
+
+ public boolean useBundledEmoji() {
+ return getPreferences().getBoolean(USE_BUNDLED_EMOJIS, getResources().getBoolean(R.bool.use_bundled_emoji));
+ }
+
+ public void verifyOtrSessionDialog(final Conversation conversation, View view) {
+ if (!conversation.hasValidOtrSession() || conversation.getOtrSession().getSessionStatus() != SessionStatus.ENCRYPTED) {
+ Toast.makeText(this, R.string.otr_session_not_started, Toast.LENGTH_LONG).show();
+ return;
+ }
+ if (view == null) {
+ return;
+ }
+ PopupMenu popup = new PopupMenu(this, view);
+ popup.inflate(R.menu.verification_choices);
+ popup.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
+ @Override
+ public boolean onMenuItemClick(MenuItem menuItem) {
+ Intent intent = new Intent(ConversationsMainActivity.this, VerifyOTRActivity.class);
+ intent.setAction(VerifyOTRActivity.ACTION_VERIFY_CONTACT);
+ intent.putExtra("contact", conversation.getContact().getJid().toBareJid().toString());
+ intent.putExtra(EXTRA_ACCOUNT, conversation.getAccount().getJid().toBareJid().toString());
+ switch (menuItem.getItemId()) {
+ case R.id.scan_fingerprint:
+ intent.putExtra("mode", VerifyOTRActivity.MODE_SCAN_FINGERPRINT);
+ break;
+ case R.id.ask_question:
+ intent.putExtra("mode", VerifyOTRActivity.MODE_ASK_QUESTION);
+ break;
+ case R.id.manual_verification:
+ intent.putExtra("mode", VerifyOTRActivity.MODE_MANUAL_VERIFICATION);
+ break;
+ }
+ startActivity(intent);
+ return true;
+ }
+ });
+ popup.show();
+ }
+
+ @Override
+ public void onConversationArchived(Conversation conversation) {
+
+ }
+
+ @Override
+ public void onConversationsListItemUpdated() {
+
+ }
+
+ @Override
+ public void onConversationRead(Conversation conversation) {
+ Log.d(Config.LOGTAG, "read event for " + conversation.getName() + " received");
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/ConversationsOverviewFragment.java b/src/main/java/de/pixart/messenger/ui/ConversationsOverviewFragment.java
new file mode 100644
index 000000000..649bb09a2
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/ConversationsOverviewFragment.java
@@ -0,0 +1,114 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui;
+
+import android.app.Activity;
+import android.databinding.DataBindingUtil;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import de.pixart.messenger.Config;
+import de.pixart.messenger.R;
+import de.pixart.messenger.databinding.FragmentConversationsOverviewBinding;
+import de.pixart.messenger.entities.Conversation;
+import de.pixart.messenger.ui.adapter.ConversationAdapter;
+import de.pixart.messenger.ui.interfaces.OnConversationSelected;
+
+public class ConversationsOverviewFragment extends XmppFragment {
+
+ private final List<Conversation> conversations = new ArrayList<>();
+ private FragmentConversationsOverviewBinding binding;
+ private ConversationAdapter conversationsAdapter;
+ private XmppActivity activity;
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ Log.d(Config.LOGTAG, "on attach");
+ if (activity instanceof XmppActivity) {
+ this.activity = (XmppActivity) activity;
+ } else {
+ throw new IllegalStateException("Trying to attach fragment to activity that is not an XmppActivity");
+ }
+ }
+
+ @Override
+ public View onCreateView(final LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
+ Log.d(Config.LOGTAG, "onCreateView");
+ this.binding = DataBindingUtil.inflate(inflater, R.layout.fragment_conversations_overview, container, false);
+ this.binding.fab.setOnClickListener((view) -> StartConversationActivity.launch(getActivity()));
+
+ this.conversationsAdapter = new ConversationAdapter(this.activity, this.conversations);
+ this.binding.list.setAdapter(this.conversationsAdapter);
+ this.binding.list.setOnItemClickListener((parent, view, position, id) -> {
+ Conversation conversation = this.conversations.get(position);
+ if (activity instanceof OnConversationSelected) {
+ ((OnConversationSelected) activity).onConversationSelected(conversation);
+ } else {
+ Log.w(ConversationsOverviewFragment.class.getCanonicalName(), "Activity does not implement OnConversationSelected");
+ }
+ });
+
+ return binding.getRoot();
+ }
+
+ @Override
+ void onBackendConnected() {
+ Log.d(Config.LOGTAG, "nice!");
+ refresh();
+ }
+
+ @Override
+ public void onStart() {
+ super.onStart();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onStart()");
+ if (activity.xmppConnectionService != null) {
+ refresh();
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ Log.d(Config.LOGTAG, "ConversationsOverviewFragment.onResume()");
+ }
+
+ @Override
+ void refresh() {
+ this.activity.xmppConnectionService.populateWithOrderedConversations(this.conversations);
+ this.conversationsAdapter.notifyDataSetChanged();
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
index 540673242..5c88dc0d2 100644
--- a/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
+++ b/src/main/java/de/pixart/messenger/ui/StartConversationActivity.java
@@ -962,6 +962,11 @@ public class StartConversationActivity extends XmppActivity implements OnRosterU
invalidateOptionsMenu();
}
+ public static void launch(Context context) {
+ final Intent intent = new Intent(context, StartConversationActivity.class);
+ context.startActivity(intent);
+ }
+
@Override
public void OnUpdateBlocklist(final Status status) {
refreshUi();
diff --git a/src/main/java/de/pixart/messenger/ui/StartUI.java b/src/main/java/de/pixart/messenger/ui/StartUI.java
index 08bd844ba..78a5754cd 100644
--- a/src/main/java/de/pixart/messenger/ui/StartUI.java
+++ b/src/main/java/de/pixart/messenger/ui/StartUI.java
@@ -44,7 +44,7 @@ public class StartUI extends AppCompatActivity
if (EasyPermissions.hasPermissions(this, perms)) {
// Already have permission, start ConversationsActivity
Log.d(Config.LOGTAG, "All permissions granted, starting " + getString(R.string.app_name) + "(" + FirstStartTime + ")");
- Intent intent = new Intent(this, ConversationActivity.class);
+ Intent intent = new Intent(this, ConversationsMainActivity.class);
intent.putExtra(PREF_FIRST_START, FirstStartTime);
startActivity(intent);
finish();
diff --git a/src/main/java/de/pixart/messenger/ui/XmppFragment.java b/src/main/java/de/pixart/messenger/ui/XmppFragment.java
new file mode 100644
index 000000000..7c2eeb661
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/XmppFragment.java
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui;
+
+import android.app.Fragment;
+
+public abstract class XmppFragment extends Fragment {
+
+ abstract void onBackendConnected();
+
+ abstract void refresh();
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
index 45fbaf50e..ba240192f 100644
--- a/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
+++ b/src/main/java/de/pixart/messenger/ui/adapter/MessageAdapter.java
@@ -2,6 +2,7 @@ package de.pixart.messenger.ui.adapter;
import android.content.ActivityNotFoundException;
import android.content.Intent;
+import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.content.res.Resources;
@@ -12,6 +13,7 @@ import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.AsyncTask;
+import android.preference.PreferenceManager;
import android.support.annotation.ColorInt;
import android.support.v4.content.ContextCompat;
import android.text.Spannable;
@@ -68,8 +70,9 @@ import de.pixart.messenger.persistance.FileBackend;
import de.pixart.messenger.services.AudioPlayer;
import de.pixart.messenger.services.MessageArchiveService;
import de.pixart.messenger.services.NotificationService;
-import de.pixart.messenger.ui.ConversationActivity;
+import de.pixart.messenger.ui.ConversationFragment;
import de.pixart.messenger.ui.ShowFullscreenMessageActivity;
+import de.pixart.messenger.ui.XmppActivity;
import de.pixart.messenger.ui.text.DividerSpan;
import de.pixart.messenger.ui.text.FixedURLSpan;
import de.pixart.messenger.ui.text.QuoteSpan;
@@ -88,6 +91,8 @@ import de.pixart.messenger.xmpp.mam.MamReference;
public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextView.CopyHandler {
+ ConversationFragment mConversationFragment;
+
private static final int SENT = 0;
private static final int RECEIVED = 1;
private static final int STATUS = 2;
@@ -131,7 +136,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
}
};
- private final ConversationActivity activity;
+ private final XmppActivity activity;
private DisplayMetrics metrics;
@@ -144,7 +149,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
public final AudioPlayer audioPlayer;
private boolean mUseWhiteBackground = false;
- public MessageAdapter(ConversationActivity activity, List<Message> messages) {
+ public MessageAdapter(XmppActivity activity, List<Message> messages) {
super(activity, 0, messages);
this.audioPlayer = new AudioPlayer(this);
this.activity = activity;
@@ -296,7 +301,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
@Override
public void onClick(View v) {
- activity.mConversationFragment.resendMessage(mMessage);
+ mConversationFragment.resendMessage(mMessage);
}
});
} else if (!error && type == SENT) {
@@ -493,16 +498,18 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
final String nick = UIHelper.getMessageDisplayName(message);
SpannableStringBuilder body = message.getMergedBody();
boolean hasMeCommand = message.hasMeCommand();
- String searchQuery = activity.mConversationFragment.binding.searchfieldInput.getText().toString().toLowerCase().trim();
- if (((!searchQuery.isEmpty() || !searchQuery.contains("")) && searchQuery.length() >= 3) && body.toString().toLowerCase().contains(searchQuery)) {
- int ofe = body.toString().toLowerCase().indexOf(searchQuery, 0);
- for (int ofs = 0; ofs < body.length() && ofe != -1; ofs = ofe + 1) {
- ofe = body.toString().toLowerCase().indexOf(searchQuery, ofs);
- if (ofe == -1) {
- break;
- } else {
- body.setSpan(new StyleSpan(Typeface.BOLD), ofe, ofe + searchQuery.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
- body.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + searchQuery.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ if (mConversationFragment != null) {
+ String searchQuery = mConversationFragment.binding.searchfieldInput.getText().toString().toLowerCase().trim();
+ if (((!searchQuery.isEmpty() || !searchQuery.contains("")) && searchQuery.length() >= 3) && body.toString().toLowerCase().contains(searchQuery)) {
+ int ofe = body.toString().toLowerCase().indexOf(searchQuery, 0);
+ for (int ofs = 0; ofs < body.length() && ofe != -1; ofs = ofe + 1) {
+ ofe = body.toString().toLowerCase().indexOf(searchQuery, ofs);
+ if (ofe == -1) {
+ break;
+ } else {
+ body.setSpan(new StyleSpan(Typeface.BOLD), ofe, ofe + searchQuery.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ body.setSpan(new BackgroundColorSpan(0xFFFFFF00), ofe, ofe + searchQuery.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
+ }
}
}
}
@@ -594,7 +601,7 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
@Override
public void onClick(View v) {
- activity.mConversationFragment.startDownloadable(message);
+ mConversationFragment.startDownloadable(message);
}
});
}
@@ -1171,8 +1178,9 @@ public class MessageAdapter extends ArrayAdapter<Message> implements CopyTextVie
}
public void updatePreferences() {
- this.mIndicateReceived = activity.indicateReceived();
- this.mUseWhiteBackground = activity.useWhiteBackground();
+ SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(activity);
+ this.mIndicateReceived = p.getBoolean("indicate_received", activity.getResources().getBoolean(R.bool.indicate_received));
+ this.mUseWhiteBackground = p.getBoolean("use_white_background", activity.getResources().getBoolean(R.bool.use_white_background));
}
public TextView getMessageBody(View view) {
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationArchived.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationArchived.java
new file mode 100644
index 000000000..beb01e690
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationArchived.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui.interfaces;
+
+import de.pixart.messenger.entities.Conversation;
+
+public interface OnConversationArchived {
+ void onConversationArchived(Conversation conversation);
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationRead.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationRead.java
new file mode 100644
index 000000000..ab5cc607d
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationRead.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui.interfaces;
+
+import de.pixart.messenger.entities.Conversation;
+
+public interface OnConversationRead {
+ void onConversationRead(Conversation conversation);
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationSelected.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationSelected.java
new file mode 100644
index 000000000..bd40a22fc
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationSelected.java
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui.interfaces;
+
+import de.pixart.messenger.entities.Conversation;
+
+public interface OnConversationSelected {
+ void onConversationSelected(Conversation conversation);
+}
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationsListItemUpdated.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationsListItemUpdated.java
new file mode 100644
index 000000000..5e509dd54
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnConversationsListItemUpdated.java
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui.interfaces;
+
+public interface OnConversationsListItemUpdated {
+ void onConversationsListItemUpdated();
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/interfaces/OnSwipeTouchListener.java b/src/main/java/de/pixart/messenger/ui/interfaces/OnSwipeTouchListener.java
new file mode 100644
index 000000000..513e0a606
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/interfaces/OnSwipeTouchListener.java
@@ -0,0 +1,57 @@
+package de.pixart.messenger.ui.interfaces;
+
+import android.content.Context;
+import android.util.Log;
+import android.view.GestureDetector;
+import android.view.MotionEvent;
+import android.view.View;
+
+import de.pixart.messenger.Config;
+
+public class OnSwipeTouchListener implements View.OnTouchListener {
+
+ private final GestureDetector gestureDetector;
+
+ public OnSwipeTouchListener(Context context) {
+ gestureDetector = new GestureDetector(context, new GestureListener());
+ }
+
+ public void onSwipeLeft() {
+ }
+
+ public void onSwipeRight() {
+ }
+
+ public boolean onTouch(View v, MotionEvent event) {
+ return gestureDetector.onTouchEvent(event);
+ }
+
+ private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
+
+ private static final int SWIPE_DISTANCE_THRESHOLD = 100;
+ private static final int SWIPE_VELOCITY_THRESHOLD = 100;
+
+ @Override
+ public boolean onDown(MotionEvent e) {
+ return true;
+ }
+
+ @Override
+ public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
+ if (e1 == null || e2 == null) {
+ Log.d(Config.LOGTAG, "Error MotionEvent");
+ return false;
+ }
+ float distanceX = e2.getX() - e1.getX();
+ float distanceY = e2.getY() - e1.getY();
+ if (Math.abs(distanceX) > Math.abs(distanceY) && Math.abs(distanceX) > SWIPE_DISTANCE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
+ if (distanceX > 0)
+ onSwipeRight();
+ else
+ onSwipeLeft();
+ return true;
+ }
+ return false;
+ }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/de/pixart/messenger/ui/util/PendingItem.java b/src/main/java/de/pixart/messenger/ui/util/PendingItem.java
new file mode 100644
index 000000000..772f5e7e1
--- /dev/null
+++ b/src/main/java/de/pixart/messenger/ui/util/PendingItem.java
@@ -0,0 +1,45 @@
+/*
+ * Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice, this
+ * list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ * this list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * 3. Neither the name of the copyright holder nor the names of its contributors
+ * may be used to endorse or promote products derived from this software without
+ * specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package de.pixart.messenger.ui.util;
+
+public class PendingItem<T> {
+
+ private T item = null;
+
+ public synchronized void push(T item) {
+ this.item = item;
+ }
+
+ public synchronized T pop() {
+ final T item = this.item;
+ this.item = null;
+ return item;
+ }
+} \ No newline at end of file
diff --git a/src/main/res/layout-w945dp/activity_conversations.xml b/src/main/res/layout-w945dp/activity_conversations.xml
new file mode 100644
index 000000000..6084155e7
--- /dev/null
+++ b/src/main/res/layout-w945dp/activity_conversations.xml
@@ -0,0 +1,22 @@
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <LinearLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:orientation="horizontal">
+
+ <FrameLayout
+ android:id="@+id/main_fragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="1" />
+
+ <FrameLayout
+ android:id="@+id/secondary_fragment"
+ android:layout_width="0dp"
+ android:layout_height="match_parent"
+ android:layout_weight="2" />
+
+ </LinearLayout>
+
+</layout> \ No newline at end of file
diff --git a/src/main/res/layout-w945dp/fragment_conversations_overview.xml b/src/main/res/layout-w945dp/fragment_conversations_overview.xml
deleted file mode 100644
index 3176ad814..000000000
--- a/src/main/res/layout-w945dp/fragment_conversations_overview.xml
+++ /dev/null
@@ -1,30 +0,0 @@
-<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content_view_ll"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
-
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:background="@color/grey50"
- android:orientation="vertical">
-
- <ListView
- android:id="@+id/list"
- android:layout_width="fill_parent"
- android:layout_height="wrap_content"
- android:background="@color/grey50"
- android:divider="@color/black12"
- android:dividerHeight="1dp" />
- </LinearLayout>
-
- <LinearLayout
- android:id="@+id/selected_conversation"
- android:layout_width="fill_parent"
- android:layout_height="match_parent"
- android:layout_weight="2"
- android:orientation="vertical">
- </LinearLayout>
-
-</android.support.v4.widget.SlidingPaneLayout> \ No newline at end of file
diff --git a/src/main/res/layout/activity_conversations.xml b/src/main/res/layout/activity_conversations.xml
new file mode 100644
index 000000000..567b17ac9
--- /dev/null
+++ b/src/main/res/layout/activity_conversations.xml
@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+ ~ Copyright (c) 2018, Daniel Gultsch All rights reserved.
+ ~
+ ~ Redistribution and use in source and binary forms, with or without modification,
+ ~ are permitted provided that the following conditions are met:
+ ~
+ ~ 1. Redistributions of source code must retain the above copyright notice, this
+ ~ list of conditions and the following disclaimer.
+ ~
+ ~ 2. Redistributions in binary form must reproduce the above copyright notice,
+ ~ this list of conditions and the following disclaimer in the documentation and/or
+ ~ other materials provided with the distribution.
+ ~
+ ~ 3. Neither the name of the copyright holder nor the names of its contributors
+ ~ may be used to endorse or promote products derived from this software without
+ ~ specific prior written permission.
+ ~
+ ~ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ ~ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ ~ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ ~ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ ~ ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ ~ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ ~ LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ ~ ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ ~ (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ ~ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ -->
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
+
+ <FrameLayout
+ android:id="@+id/main_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent" />
+</layout> \ No newline at end of file
diff --git a/src/main/res/layout/fragment_conversations_overview.xml b/src/main/res/layout/fragment_conversations_overview.xml
index 493f962ec..336142428 100644
--- a/src/main/res/layout/fragment_conversations_overview.xml
+++ b/src/main/res/layout/fragment_conversations_overview.xml
@@ -1,14 +1,8 @@
-<android.support.v4.widget.SlidingPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:id="@+id/content_view_spl"
- android:layout_width="match_parent"
- android:layout_height="match_parent">
+<layout xmlns:android="http://schemas.android.com/apk/res/android">
- <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
- android:layout_width="fill_parent"
- android:layout_weight="1"
- android:layout_height="match_parent"
- android:background="@color/grey50"
- android:orientation="vertical">
+ <FrameLayout
+ android:layout_width="match_parent"
+ android:layout_height="match_parent">
<ListView
android:id="@+id/list"
@@ -17,14 +11,13 @@
android:background="@color/grey50"
android:divider="@color/black12"
android:dividerHeight="1dp" />
- </LinearLayout>
- <LinearLayout
- android:id="@+id/selected_conversation"
- android:layout_width="fill_parent"
- android:layout_height="match_parent"
- android:layout_weight="1"
- android:orientation="vertical">
- </LinearLayout>
-
-</android.support.v4.widget.SlidingPaneLayout> \ No newline at end of file
+ <android.support.design.widget.FloatingActionButton
+ android:id="@+id/fab"
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="end|bottom"
+ android:layout_margin="16dp"
+ android:src="?attr/icon_new" />
+ </FrameLayout>
+</layout> \ No newline at end of file
diff --git a/src/main/res/menu/activity_conversations.xml b/src/main/res/menu/activity_conversations.xml
index 80a4f2bd3..6cd9000fd 100644
--- a/src/main/res/menu/activity_conversations.xml
+++ b/src/main/res/menu/activity_conversations.xml
@@ -2,21 +2,14 @@
xmlns:app="http://schemas.android.com/apk/res-auto">
<item
- android:id="@+id/action_add"
- android:icon="?attr/icon_new"
- android:orderInCategory="10"
- app:showAsAction="always"
- android:title="@string/action_add"/>
-
- <item
android:id="@+id/action_accounts"
android:orderInCategory="90"
- app:showAsAction="never"
- android:title="@string/action_accounts"/>
+ android:title="@string/action_accounts"
+ app:showAsAction="never" />
<item
android:id="@+id/action_settings"
android:orderInCategory="100"
- app:showAsAction="never"
- android:title="@string/action_settings"/>
+ android:title="@string/action_settings"
+ app:showAsAction="never" />
</menu> \ No newline at end of file