Primitive XMPP connection
This commit is contained in:
parent
8e51695e69
commit
7bea4d5308
30 changed files with 575 additions and 40 deletions
BIN
.idea/caches/build_file_checksums.ser
Normal file
BIN
.idea/caches/build_file_checksums.ser
Normal file
Binary file not shown.
29
.idea/codeStyles/Project.xml
Normal file
29
.idea/codeStyles/Project.xml
Normal file
|
@ -0,0 +1,29 @@
|
|||
<component name="ProjectCodeStyleConfiguration">
|
||||
<code_scheme name="Project" version="173">
|
||||
<Objective-C-extensions>
|
||||
<file>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Import" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Macro" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Typedef" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Enum" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Constant" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Global" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Struct" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="FunctionPredecl" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Function" />
|
||||
</file>
|
||||
<class>
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Property" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="Synthesize" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InitMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="StaticMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="InstanceMethod" />
|
||||
<option name="com.jetbrains.cidr.lang.util.OCDeclarationKind" value="DeallocMethod" />
|
||||
</class>
|
||||
<extensions>
|
||||
<pair source="cpp" header="h" fileNamingConvention="NONE" />
|
||||
<pair source="c" header="h" fileNamingConvention="NONE" />
|
||||
</extensions>
|
||||
</Objective-C-extensions>
|
||||
</code_scheme>
|
||||
</component>
|
|
@ -24,7 +24,7 @@
|
|||
</value>
|
||||
</option>
|
||||
</component>
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
||||
</component>
|
||||
<component name="ProjectType">
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
4
gradle/wrapper/gradle-wrapper.properties
vendored
4
gradle/wrapper/gradle-wrapper.properties
vendored
|
@ -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
|
||||
|
|
|
@ -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'
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
android:resource="@xml/automotive_app_desc" />
|
||||
|
||||
<service android:name=".service.MyMessagingService"/>
|
||||
<service android:name=".service.SlamXmppService" />
|
||||
|
||||
<receiver android:name=".receiver.MessageReadReceiver">
|
||||
<intent-filter>
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<T extends BasePresenter> {
|
||||
void setPresenter(T presenter);
|
||||
}
|
||||
|
||||
interface BasePresenter {
|
||||
|
||||
}
|
||||
}
|
|
@ -26,7 +26,7 @@ import de.vanitasvitae.slam.xmpp.Resource;
|
|||
*/
|
||||
public interface ContactDetailContract {
|
||||
|
||||
interface View {
|
||||
interface View extends BaseContract.BaseView<Presenter> {
|
||||
void setContactAvatar();
|
||||
void setNickname(String nickname);
|
||||
void setResources(List<Resource> 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();
|
||||
|
|
|
@ -31,7 +31,7 @@ import de.vanitasvitae.slam.xmpp.Contact;
|
|||
*/
|
||||
public interface ContactListContract {
|
||||
|
||||
interface View {
|
||||
interface View extends BaseContract.BaseView<Presenter> {
|
||||
void addContactListItems(List<Contact> 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();
|
||||
|
|
|
@ -30,14 +30,14 @@ import de.vanitasvitae.slam.xmpp.message.AbstractMessage;
|
|||
*/
|
||||
public interface ConversationContract {
|
||||
|
||||
interface View {
|
||||
interface View extends BaseContract.BaseView<Presenter> {
|
||||
void addMessageItems(List<AbstractMessage> 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);
|
||||
|
|
|
@ -29,13 +29,13 @@ import de.vanitasvitae.slam.xmpp.Conversation;
|
|||
*/
|
||||
public interface ConversationListContract {
|
||||
|
||||
interface View {
|
||||
interface View extends BaseContract.BaseView<Presenter> {
|
||||
void populateConversationList(List<Conversation> conversations);
|
||||
void navigateToConversation(BareJid contact);
|
||||
void navigateToContactDetail(BareJid contact);
|
||||
}
|
||||
|
||||
interface Presenter {
|
||||
interface Presenter extends BaseContract.BasePresenter {
|
||||
void onConversationClick();
|
||||
void onConversationLongClick();
|
||||
void load();
|
||||
|
|
|
@ -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<Presenter> {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,7 +25,7 @@ import java.util.List;
|
|||
*/
|
||||
public interface SearchContract {
|
||||
|
||||
interface View {
|
||||
interface View extends BaseContract.BaseView<Presenter> {
|
||||
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();
|
||||
|
|
|
@ -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<Presenter> {
|
||||
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();
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Message> dummyMessages = new ArrayList<>();
|
||||
private final List<AbstractMessage> 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
|
||||
|
|
|
@ -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() {
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<Contact> 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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<String, Integer> messageIdIndizes = new HashMap<>();
|
||||
List<AbstractMessage> 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<AbstractMessage> messages, boolean end) {
|
||||
if (end) {
|
||||
|
|
|
@ -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<Conversation> 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<Conversation> conversations) {
|
||||
this.conversations.clear();
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,6 +34,8 @@ import de.vanitasvitae.slam.xmpp.message.AbstractMessage;
|
|||
public abstract class MessageView<T extends AbstractMessage> extends RecyclerView.ViewHolder
|
||||
implements AbstractMessageContract.View {
|
||||
|
||||
protected AbstractMessageContract.Presenter presenter;
|
||||
|
||||
public MessageView(View itemView) {
|
||||
super(itemView);
|
||||
}
|
||||
|
@ -83,4 +85,9 @@ public abstract class MessageView<T extends AbstractMessage> extends RecyclerVie
|
|||
public void displayErrorMessage() {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPresenter(AbstractMessageContract.Presenter presenter) {
|
||||
this.presenter = presenter;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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<Account, SlamXmppConnection> 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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<LoginTask.Credentials, Void, SlamXmppConnection> {
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue