diff --git a/.idea/caches/build_file_checksums.ser b/.idea/caches/build_file_checksums.ser
new file mode 100644
index 0000000..345092e
Binary files /dev/null and b/.idea/caches/build_file_checksums.ser differ
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..30aa626
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,29 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 635999d..ba7052b 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -24,7 +24,7 @@
-
+
diff --git a/build.gradle b/build.gradle
index 3cdefb4..05a0b71 100644
--- a/build.gradle
+++ b/build.gradle
@@ -8,12 +8,12 @@ buildscript {
}
ext {
- smackVersion="4.2.3-SNAPSHOT"
+ smackVersion="4.4.0-alpha2-SNAPSHOT"
}
dependencies {
- classpath 'com.android.tools.build:gradle:3.0.1'
+ classpath 'com.android.tools.build:gradle:3.1.3'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index c05b4e8..2358be7 100644
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Mon Jan 22 17:04:57 CET 2018
+#Wed Aug 01 11:38:19 CEST 2018
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-4.1-all.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip
diff --git a/mobile/build.gradle b/mobile/build.gradle
index f4e8665..130012d 100644
--- a/mobile/build.gradle
+++ b/mobile/build.gradle
@@ -29,18 +29,24 @@ dependencies {
implementation 'com.android.support:support-emoji:27.0.2'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
+ // The holy ButterKnife \o/
+ compile 'com.jakewharton:butterknife:8.8.1'
+ annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
- testImplementation 'junit:junit:4.12'
- androidTestImplementation 'com.android.support.test:runner:1.0.1'
- androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
+ // External UI
+ compile 'de.hdodenhof:circleimageview:2.0.0'
+ // Smack
compile "org.igniterealtime.smack:smack-android-extensions:$smackVersion"
compile "org.igniterealtime.smack:smack-omemo-signal:$smackVersion"
compile "org.igniterealtime.smack:smack-tcp:$smackVersion"
compile "org.igniterealtime.smack:smack-experimental:$smackVersion"
- compile 'com.jakewharton:butterknife:8.8.1'
- annotationProcessor 'com.jakewharton:butterknife-compiler:8.8.1'
+ // SQLCipher
+ compile 'net.zetetic:android-database-sqlcipher:3.5.9@aar'
- compile 'de.hdodenhof:circleimageview:2.0.0'
+ // Test stuff
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'com.android.support.test:runner:1.0.1'
+ androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.1'
}
diff --git a/mobile/src/main/AndroidManifest.xml b/mobile/src/main/AndroidManifest.xml
index 26a700f..cf42e47 100644
--- a/mobile/src/main/AndroidManifest.xml
+++ b/mobile/src/main/AndroidManifest.xml
@@ -34,6 +34,7 @@
android:resource="@xml/automotive_app_desc" />
+
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/SlamApplication.java b/mobile/src/main/java/de/vanitasvitae/slam/SlamApplication.java
index d2626c8..48792d5 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/SlamApplication.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/SlamApplication.java
@@ -18,14 +18,16 @@
package de.vanitasvitae.slam;
import android.app.Application;
+import android.content.Intent;
import de.vanitasvitae.slam.mvp.DummyPresenterFactory;
import de.vanitasvitae.slam.mvp.PresenterFactory;
+import de.vanitasvitae.slam.service.SlamXmppService;
public class SlamApplication extends Application {
public SlamApplication() {
super();
- PresenterFactory.setInstance(new DummyPresenterFactory());
+ PresenterFactory.setInstance(new PresenterFactory());
}
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/BaseContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/BaseContract.java
new file mode 100644
index 0000000..af7ed15
--- /dev/null
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/BaseContract.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2018 Paul Schaub
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package de.vanitasvitae.slam.mvp.contracts;
+
+/**
+ * Created by Paul Schaub on 24.02.18.
+ */
+public interface BaseContract {
+
+ interface BaseView {
+ void setPresenter(T presenter);
+ }
+
+ interface BasePresenter {
+
+ }
+}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactDetailContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactDetailContract.java
index 0c0837b..d75a50f 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactDetailContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactDetailContract.java
@@ -26,7 +26,7 @@ import de.vanitasvitae.slam.xmpp.Resource;
*/
public interface ContactDetailContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void setContactAvatar();
void setNickname(String nickname);
void setResources(List presences);
@@ -34,7 +34,7 @@ public interface ContactDetailContract {
void addFingerprints(List> fingerprints);
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void onAvatarClick();
void onSharedMediaClick();
void onAudioCallClick();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactListContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactListContract.java
index 74be62f..75787e2 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactListContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ContactListContract.java
@@ -31,7 +31,7 @@ import de.vanitasvitae.slam.xmpp.Contact;
*/
public interface ContactListContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void addContactListItems(List contacts);
void clearContactListItems();
void onUpdateContactPresence();
@@ -41,7 +41,7 @@ public interface ContactListContract {
void navigateToContactDetail(BareJid contact);
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void onContactListItemClick();
void onContactListItemLongClick();
void addNewContact();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationContract.java
index cbfdd29..95e0912 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationContract.java
@@ -30,14 +30,14 @@ import de.vanitasvitae.slam.xmpp.message.AbstractMessage;
*/
public interface ConversationContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void addMessageItems(List messages, boolean end);
void highlightMessageItem();
void correctMessageItem();
void navigateToContactProfile();
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void setPeersJid(EntityBareJid jid);
void onConversationScrolledToTop();
void onComposingMessageChanged(String composingMessage);
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationListContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationListContract.java
index 33abf0b..91a39f8 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationListContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/ConversationListContract.java
@@ -29,13 +29,13 @@ import de.vanitasvitae.slam.xmpp.Conversation;
*/
public interface ConversationListContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void populateConversationList(List conversations);
void navigateToConversation(BareJid contact);
void navigateToContactDetail(BareJid contact);
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void onConversationClick();
void onConversationLongClick();
void load();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/LoginContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/LoginContract.java
index afa439b..c81f7c4 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/LoginContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/LoginContract.java
@@ -17,13 +17,15 @@
*/
package de.vanitasvitae.slam.mvp.contracts;
+import de.vanitasvitae.slam.service.SlamXmppService;
+
/**
* Model-View-Presenter contract of the login screen.
* Created by Paul Schaub on 01.02.18.
*/
public interface LoginContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void showInvalidJidError();
void hideInvalidJidError();
void showInvalidPasswordError();
@@ -33,11 +35,15 @@ public interface LoginContract {
void showProgressIndicator();
void hideProgressIndicator();
void navigateToMainActivity();
+ void disableLoginButton();
+ void enableLoginButton();
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void jidChanged(String jid);
void passwordChanged(String password);
void loginClicked();
+ void bindService(SlamXmppService service);
+ void unbindService();
}
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/SearchContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/SearchContract.java
index 9d05788..c661837 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/SearchContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/SearchContract.java
@@ -25,7 +25,7 @@ import java.util.List;
*/
public interface SearchContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void addSearchResults(List> results);
void clearSearchResults();
void showLoadingIndicator();
@@ -34,7 +34,7 @@ public interface SearchContract {
void hideEmptySearchResults();
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void onSearchQueryChanged(String query);
void onSearchResultClick();
void onSearchScrolledToBottom();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/message/AbstractMessageContract.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/message/AbstractMessageContract.java
index c9c8132..42cd967 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/message/AbstractMessageContract.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/contracts/message/AbstractMessageContract.java
@@ -17,12 +17,14 @@
*/
package de.vanitasvitae.slam.mvp.contracts.message;
+import de.vanitasvitae.slam.mvp.contracts.BaseContract;
+
/**
* Model-View-Presenter contract for an abstract message.
*/
public interface AbstractMessageContract {
- interface View {
+ interface View extends BaseContract.BaseView {
void setDirection(Direction direction);
void setStatusSending();
void setStatusSendingFailed();
@@ -33,7 +35,7 @@ public interface AbstractMessageContract {
void displayErrorMessage();
}
- interface Presenter {
+ interface Presenter extends BaseContract.BasePresenter {
void onDeleteMessage();
void onReadMessage();
void onMessageClick();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/LoginPresenter.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/LoginPresenter.java
index 34e4770..5dc1de3 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/LoginPresenter.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/LoginPresenter.java
@@ -17,18 +17,38 @@
*/
package de.vanitasvitae.slam.mvp.presenter;
+import android.content.Context;
+import android.support.v7.app.AppCompatActivity;
+import android.util.Log;
+import android.widget.Toast;
+
+import org.jivesoftware.smack.SmackException;
+import org.jivesoftware.smack.XMPPException;
+import org.jivesoftware.smack.chat2.Chat;
+import org.jivesoftware.smack.chat2.ChatManager;
+import org.jivesoftware.smack.chat2.IncomingChatMessageListener;
+import org.jivesoftware.smack.packet.Message;
import org.jxmpp.jid.BareJid;
+import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
+import java.io.IOException;
+import java.net.UnknownHostException;
+
import de.vanitasvitae.slam.mvp.contracts.LoginContract;
+import de.vanitasvitae.slam.service.SlamXmppConnection;
+import de.vanitasvitae.slam.service.SlamXmppService;
+import de.vanitasvitae.slam.xmpp.Account;
public class LoginPresenter implements LoginContract.Presenter {
+ private static final String TAG = "LoginPresenter";
private final LoginContract.View view;
private BareJid jid;
private String password;
+ private SlamXmppService service;
public LoginPresenter(LoginContract.View view) {
this.view = view;
@@ -39,19 +59,115 @@ public class LoginPresenter implements LoginContract.Presenter {
try {
this.jid = JidCreate.entityBareFrom(jid);
view.hideInvalidJidError();
+
+ if (password != null && !password.isEmpty()) {
+ view.enableLoginButton();
+ }
+
} catch (XmppStringprepException e) {
this.jid = null;
view.showInvalidJidError();
+ view.disableLoginButton();
}
}
@Override
public void passwordChanged(String password) {
-
+ this.password = password;
+ if (password == null || password.isEmpty()) {
+ view.disableLoginButton();
+ } else if (jid != null) {
+ view.enableLoginButton();
+ }
}
@Override
public void loginClicked() {
+ if (jid == null) {
+ view.showInvalidJidError();
+ return;
+ }
+ if (password == null) {
+ view.showInvalidPasswordError();
+ return;
+ }
+
+ if (service != null) {
+ view.disableLoginButton();
+ final Account account = new Account(jid);
+
+ Thread loginThread = new Thread(new Runnable() {
+ @Override
+ public void run() {
+ SlamXmppConnection connection = null;
+ try {
+ connection = new SlamXmppConnection(
+ jid.asEntityBareJidOrThrow(), password);
+ } catch (UnknownHostException e) {
+ e.printStackTrace();
+ ((AppCompatActivity)view).runOnUiThread(new Runnable() {
+ public void run() {
+ Toast.makeText((Context)view, "Unknown host", Toast.LENGTH_SHORT).show();
+ }
+ });
+
+ return;
+ }
+
+ service.addConnection(account, connection);
+ final SlamXmppConnection finalConnection = connection;
+ connection.login(new SlamXmppConnection.LoginCallback() {
+ @Override
+ public void success() {
+ ((AppCompatActivity)view).runOnUiThread(new Runnable() {
+ public void run() {
+ view.navigateToMainActivity();
+ }
+ });
+ ChatManager.getInstanceFor(finalConnection.getConnection())
+ .addIncomingListener(new IncomingChatMessageListener() {
+ @Override
+ public void newIncomingMessage(final EntityBareJid from, final Message message, Chat chat) {
+ final AppCompatActivity activity = (AppCompatActivity) view;
+ activity.runOnUiThread(new Runnable() {
+ public void run() {
+ Toast.makeText(activity.getApplicationContext(), from.toString() + ": " + message.getBody(), Toast.LENGTH_LONG).show();
+ }
+ });
+ }
+ });
+ }
+
+ @Override
+ public void failure(final Exception e) {
+ e.printStackTrace();
+ ((AppCompatActivity)view).runOnUiThread(new Runnable() {
+ public void run() {
+ Toast.makeText((Context)view, e.getMessage(), Toast.LENGTH_LONG).show();
+ view.enableLoginButton();
+ }
+ });
+ }
+ });
+ }
+ });
+ loginThread.start();
+
+ } else {
+ view.showServerNotFoundError();
+ }
+ }
+
+ @Override
+ public void bindService(SlamXmppService service) {
+ Log.d(TAG, "bindService()");
+ this.service = service;
+ }
+
+ @Override
+ public void unbindService() {
+ Log.d(TAG, "unbindService()");
+ this.service = null;
}
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyConversationPresenter.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyConversationPresenter.java
index 8fc5da3..d5f4415 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyConversationPresenter.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyConversationPresenter.java
@@ -27,12 +27,13 @@ import java.util.ArrayList;
import java.util.List;
import de.vanitasvitae.slam.mvp.contracts.ConversationContract;
+import de.vanitasvitae.slam.xmpp.message.AbstractMessage;
public class DummyConversationPresenter implements ConversationContract.Presenter {
private final ConversationContract.View view;
- private final List dummyMessages = new ArrayList<>();
+ private final List dummyMessages = new ArrayList<>();
public DummyConversationPresenter(ConversationContract.View view) {
this.view = view;
@@ -41,6 +42,7 @@ public class DummyConversationPresenter implements ConversationContract.Presente
}
private void populateDummyMessages() {
+ /*
try {
BareJid alice = JidCreate.bareFrom("alice@wonderland.lit");
@@ -66,6 +68,7 @@ public class DummyConversationPresenter implements ConversationContract.Presente
} catch (XmppStringprepException e) {
e.printStackTrace();
}
+ */
}
@Override
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyLoginPresenter.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyLoginPresenter.java
index 1bde5e1..6414345 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyLoginPresenter.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/presenter/dummy/DummyLoginPresenter.java
@@ -23,6 +23,7 @@ import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
import de.vanitasvitae.slam.mvp.contracts.LoginContract;
+import de.vanitasvitae.slam.service.SlamXmppService;
/**
* Dummy presenter, that has no model.
@@ -82,4 +83,14 @@ public class DummyLoginPresenter implements LoginContract.Presenter {
}
}, 250);
}
+
+ @Override
+ public void bindService(SlamXmppService service) {
+
+ }
+
+ @Override
+ public void unbindService() {
+
+ }
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailActivity.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailActivity.java
index bfa88bc..863bf9b 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailActivity.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactDetailActivity.java
@@ -45,7 +45,7 @@ public class ContactDetailActivity extends ThemedAppCompatActivity
public static final String TAG = "Slam!";
- private final ContactDetailContract.Presenter presenter;
+ private ContactDetailContract.Presenter presenter;
private final ContactDetailResourcesFragment resourcesFragment = new ContactDetailResourcesFragment();
private final ContactDetailInfoFragment infoFragment = new ContactDetailInfoFragment();
@@ -71,7 +71,7 @@ public class ContactDetailActivity extends ThemedAppCompatActivity
private int animateProfileCirclePercent = 30;
public ContactDetailActivity() {
- this.presenter = PresenterFactory.getInstance().createContactDetailPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createContactDetailPresenter(this));
}
@Override
@@ -151,6 +151,11 @@ public class ContactDetailActivity extends ThemedAppCompatActivity
}
+ @Override
+ public void setPresenter(ContactDetailContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
+
class DetailFragmentPagerAdapter extends FragmentPagerAdapter {
public DetailFragmentPagerAdapter(FragmentManager fm) {
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactListFragment.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactListFragment.java
index 680e895..a01a35d 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactListFragment.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ContactListFragment.java
@@ -47,13 +47,13 @@ public class ContactListFragment extends Fragment implements ContactListContract
@BindView(R.id.recycler_list)
RecyclerView recyclerView;
- private final ContactListContract.Presenter presenter;
+ private ContactListContract.Presenter presenter;
private final List contacts = new ArrayList<>();
public ContactListFragment() {
super();
- this.presenter = PresenterFactory.getInstance().createContactListPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createContactListPresenter(this));
}
@Override
@@ -142,4 +142,8 @@ public class ContactListFragment extends Fragment implements ContactListContract
}
+ @Override
+ public void setPresenter(ContactListContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationFragment.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationFragment.java
index becb837..b253a4e 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationFragment.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationFragment.java
@@ -56,7 +56,7 @@ public class ConversationFragment extends Fragment implements ConversationContra
@BindView(R.id.recycler_chat)
RecyclerView recyclerView;
- private final ConversationContract.Presenter presenter;
+ private ConversationContract.Presenter presenter;
Map messageIdIndizes = new HashMap<>();
List messages = new ArrayList<>();
@@ -87,7 +87,7 @@ public class ConversationFragment extends Fragment implements ConversationContra
public ConversationFragment() {
super();
- this.presenter = PresenterFactory.getInstance().createConversationPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createConversationPresenter(this));
}
@Override
@@ -117,6 +117,11 @@ public class ConversationFragment extends Fragment implements ConversationContra
recyclerView.getAdapter().notifyDataSetChanged();
}
+ @Override
+ public void setPresenter(ConversationContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
+
@Override
public void addMessageItems(List messages, boolean end) {
if (end) {
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationListFragment.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationListFragment.java
index 4867017..d56c889 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationListFragment.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/ConversationListFragment.java
@@ -49,12 +49,12 @@ public class ConversationListFragment extends Fragment implements ConversationLi
@BindView(R.id.recycler_list)
RecyclerView recyclerView;
- private final ConversationListContract.Presenter presenter;
+ private ConversationListContract.Presenter presenter;
private final List conversations = new ArrayList<>();
public ConversationListFragment() {
super();
- this.presenter = PresenterFactory.getInstance().createConversationListPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createConversationListPresenter(this));
}
@Override
@@ -72,6 +72,11 @@ public class ConversationListFragment extends Fragment implements ConversationLi
recyclerView.getAdapter().notifyDataSetChanged();
}
+ @Override
+ public void setPresenter(ConversationListContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
+
@Override
public void populateConversationList(List conversations) {
this.conversations.clear();
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/LoginActivity.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/LoginActivity.java
index f93a13f..7252132 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/LoginActivity.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/LoginActivity.java
@@ -17,8 +17,12 @@
*/
package de.vanitasvitae.slam.mvp.view;
+import android.content.ComponentName;
+import android.content.Context;
import android.content.Intent;
+import android.content.ServiceConnection;
import android.os.Bundle;
+import android.os.IBinder;
import android.support.design.widget.TextInputEditText;
import android.support.design.widget.TextInputLayout;
import android.support.v7.widget.Toolbar;
@@ -40,8 +44,9 @@ import de.vanitasvitae.slam.R;
import de.vanitasvitae.slam.mvp.PresenterFactory;
import de.vanitasvitae.slam.mvp.view.abstr.ThemedAppCompatActivity;
import de.vanitasvitae.slam.mvp.contracts.LoginContract;
+import de.vanitasvitae.slam.service.SlamXmppService;
-public class LoginActivity extends ThemedAppCompatActivity implements LoginContract.View {
+public class LoginActivity extends ThemedAppCompatActivity implements LoginContract.View, ServiceConnection {
// Presenter of this view
private LoginContract.Presenter presenter;
@@ -67,9 +72,11 @@ public class LoginActivity extends ThemedAppCompatActivity implements LoginContr
@BindView(R.id.button_login)
Button buttonLogin;
+ private SlamXmppService slamService;
+
public LoginActivity() {
super();
- this.presenter = PresenterFactory.getInstance().createLoginPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createLoginPresenter(this));
}
@Override
@@ -103,8 +110,29 @@ public class LoginActivity extends ThemedAppCompatActivity implements LoginContr
});
}
+ @Override
+ protected void onResume() {
+ super.onResume();
+ // Start xmpp service
+ Intent serviceIntent = new Intent(this, SlamXmppService.class);
+ bindService(serviceIntent, this, Context.BIND_AUTO_CREATE);
+ }
+
+ @Override
+ protected void onPause() {
+ super.onPause();
+ unbindService(this);
+ }
+
+ @Override
+ public void setPresenter(LoginContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
+
@OnClick(R.id.button_login)
void login() {
+ Intent serviceIntent = new Intent(getApplicationContext(), SlamXmppService.class);
+ getApplicationContext().startService(serviceIntent);
presenter.loginClicked();
}
@@ -162,5 +190,28 @@ public class LoginActivity extends ThemedAppCompatActivity implements LoginContr
startActivity(new Intent(this, MainActivity.class));
finish();
}
+
+ @Override
+ public void disableLoginButton() {
+ buttonLogin.setEnabled(false);
+ }
+
+ @Override
+ public void enableLoginButton() {
+ buttonLogin.setEnabled(true);
+ }
+
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ SlamXmppService.SlamBinder binder = (SlamXmppService.SlamBinder) service;
+ slamService = binder.getService();
+ presenter.bindService(slamService);
+ }
+
+ @Override
+ public void onServiceDisconnected(ComponentName name) {
+ slamService = null;
+ presenter.unbindService();
+ }
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/SearchFragment.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/SearchFragment.java
index 71ff94a..c03bf5a 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/SearchFragment.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/SearchFragment.java
@@ -31,10 +31,10 @@ import de.vanitasvitae.slam.mvp.contracts.SearchContract;
*/
public class SearchFragment extends Fragment implements SearchContract.View {
- private final SearchContract.Presenter presenter;
+ private SearchContract.Presenter presenter;
public SearchFragment() {
- this.presenter = PresenterFactory.getInstance().createSearchPresenter(this);
+ setPresenter(PresenterFactory.getInstance().createSearchPresenter(this));
}
@Override
@@ -66,4 +66,9 @@ public class SearchFragment extends Fragment implements SearchContract.View {
public void hideEmptySearchResults() {
}
+
+ @Override
+ public void setPresenter(SearchContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/message/MessageView.java b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/message/MessageView.java
index 48ddcc1..b2dfb36 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/message/MessageView.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/mvp/view/message/MessageView.java
@@ -34,6 +34,8 @@ import de.vanitasvitae.slam.xmpp.message.AbstractMessage;
public abstract class MessageView extends RecyclerView.ViewHolder
implements AbstractMessageContract.View {
+ protected AbstractMessageContract.Presenter presenter;
+
public MessageView(View itemView) {
super(itemView);
}
@@ -83,4 +85,9 @@ public abstract class MessageView extends RecyclerVie
public void displayErrorMessage() {
}
+
+ @Override
+ public void setPresenter(AbstractMessageContract.Presenter presenter) {
+ this.presenter = presenter;
+ }
}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppConnection.java b/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppConnection.java
new file mode 100644
index 0000000..e72075b
--- /dev/null
+++ b/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppConnection.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright 2018 Paul Schaub
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package de.vanitasvitae.slam.service;
+
+import android.util.Log;
+
+import org.jivesoftware.smack.AbstractXMPPConnection;
+import org.jivesoftware.smack.tcp.XMPPTCPConnection;
+import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
+import org.jivesoftware.smack.util.StringUtils;
+import org.jxmpp.jid.EntityBareJid;
+import org.jxmpp.jid.parts.Resourcepart;
+import org.jxmpp.stringprep.XmppStringprepException;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+/**
+ * Created by Paul Schaub on 24.02.18.
+ */
+public class SlamXmppConnection {
+
+ private static final String TAG = "SlamConn";
+
+ private final EntityBareJid jid;
+ private final AbstractXMPPConnection connection;
+ private final Resourcepart resourcepart;
+
+ public SlamXmppConnection(EntityBareJid jid, String password) throws UnknownHostException {
+ this.jid = jid;
+ // Resource
+ String res = "Slam-" + StringUtils.randomString(12);
+ try {
+ this.resourcepart = Resourcepart.from(res);
+ } catch (XmppStringprepException e) {
+ throw new AssertionError("Resourcepart \"" + res + "\" appears to be invalid.", e);
+ }
+
+ // Configuration
+ XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
+ .setHost(this.jid.getDomain().toString())
+ .setHostAddress(InetAddress.getByName(jid.getDomain().toString()))
+ .setXmppDomain(jid.asDomainBareJid())
+ .setUsernameAndPassword(jid.getLocalpart().toString(), password)
+ .setResource(resourcepart)
+ .build();
+
+ this.connection = new XMPPTCPConnection(configuration);
+ }
+
+ public AbstractXMPPConnection getConnection() {
+ return connection;
+ }
+
+ public void login(final LoginCallback callback) {
+ try {
+ getConnection().connect().login();
+ Log.d(TAG, "Account " + jid.toString() + " logged in.");
+ callback.success();
+ } catch (Exception e) {
+ Log.d(TAG, "Account " + jid.toString() + " could not log in.");
+ e.printStackTrace();
+ callback.failure(e);
+ }
+ }
+
+ public interface LoginCallback {
+ void success();
+ void failure(Exception e);
+ }
+}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppService.java b/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppService.java
new file mode 100644
index 0000000..bf406f4
--- /dev/null
+++ b/mobile/src/main/java/de/vanitasvitae/slam/service/SlamXmppService.java
@@ -0,0 +1,78 @@
+/*
+ * Copyright 2018 Paul Schaub
+ *
+ * This code is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+package de.vanitasvitae.slam.service;
+
+import android.app.Service;
+import android.content.Intent;
+import android.os.Binder;
+import android.os.IBinder;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.util.Log;
+
+import java.util.HashMap;
+
+import de.vanitasvitae.slam.xmpp.Account;
+
+/**
+ * Created by Paul Schaub on 24.02.18.
+ */
+public class SlamXmppService extends Service {
+
+ private static final String TAG = "SlamService";
+
+ private final IBinder binder = new SlamBinder();
+ private Account currentAccount;
+ private final HashMap connections = new HashMap<>();
+
+ @Nullable
+ @Override
+ public IBinder onBind(Intent intent) {
+ return binder;
+ }
+
+ @Override
+ public int onStartCommand(Intent intent, int flags, int startId) {
+ Log.d(TAG,"onStartCommand()");
+ return Service.START_STICKY;
+ }
+
+ public void addConnection(@NonNull Account account, SlamXmppConnection connection) {
+ Log.d(TAG, "Adding a new connection for " + account.getJid().toString());
+ this.connections.put(account, connection);
+ }
+
+ @Override
+ public void onDestroy() {
+ Log.d(TAG, "onDestroy()");
+ for (SlamXmppConnection c : connections.values()) {
+ c.getConnection().disconnect();
+ }
+ super.onDestroy();
+ }
+
+ public SlamXmppConnection getConnection(@NonNull Account account) {
+ return connections.get(account);
+ }
+
+ public class SlamBinder extends Binder {
+ public SlamXmppService getService() {
+ return SlamXmppService.this;
+ }
+ }
+}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/task/LoginTask.java b/mobile/src/main/java/de/vanitasvitae/slam/task/LoginTask.java
new file mode 100644
index 0000000..37d73a8
--- /dev/null
+++ b/mobile/src/main/java/de/vanitasvitae/slam/task/LoginTask.java
@@ -0,0 +1,69 @@
+package de.vanitasvitae.slam.task;
+
+import android.os.AsyncTask;
+import android.support.annotation.NonNull;
+
+import org.jxmpp.jid.EntityBareJid;
+
+import java.net.InetAddress;
+import java.net.UnknownHostException;
+
+import de.vanitasvitae.slam.mvp.contracts.LoginContract;
+import de.vanitasvitae.slam.service.SlamXmppConnection;
+
+/**
+ * Created by Paul Schaub on 26.02.18.
+ */
+public class LoginTask extends AsyncTask {
+
+ private final LoginContract.View view;
+ private Exception exception;
+
+ public LoginTask(LoginContract.View view) {
+ this.view = view;
+ }
+
+ @Override
+ protected SlamXmppConnection doInBackground(Credentials... credentials) {
+ if (credentials.length != 1) {
+ throw new IllegalArgumentException("Please only present one set of credentials at a time.");
+ }
+
+ SlamXmppConnection connection;
+ try {
+ connection = new SlamXmppConnection(credentials[0].jid, credentials[0].password);
+ } catch (UnknownHostException e) {
+ exception = e;
+ return null;
+ }
+
+ return null;
+ }
+
+ @Override
+ protected void onPreExecute() {
+
+ }
+
+ @Override
+ protected void onPostExecute(SlamXmppConnection result) {
+ if (exception == null) {
+ return;
+ }
+
+ if (exception instanceof UnknownHostException) {
+ view.showServerNotFoundError();
+ return;
+ }
+ }
+
+ public static class Credentials {
+ private final EntityBareJid jid;
+ private final String password;
+
+ public Credentials(@NonNull EntityBareJid jid, @NonNull String password) {
+ this.jid = jid;
+ this.password = password;
+ }
+ }
+}
diff --git a/mobile/src/main/java/de/vanitasvitae/slam/xmpp/Account.java b/mobile/src/main/java/de/vanitasvitae/slam/xmpp/Account.java
index 2a9a04d..6a9612d 100644
--- a/mobile/src/main/java/de/vanitasvitae/slam/xmpp/Account.java
+++ b/mobile/src/main/java/de/vanitasvitae/slam/xmpp/Account.java
@@ -17,8 +17,20 @@
*/
package de.vanitasvitae.slam.xmpp;
+import org.jxmpp.jid.BareJid;
+
/**
* Created by Paul Schaub on 24.02.18.
*/
public class Account {
+
+ private final BareJid jid;
+
+ public Account(BareJid jid) {
+ this.jid = jid;
+ }
+
+ public BareJid getJid() {
+ return jid;
+ }
}