diff --git a/app/build.gradle b/app/build.gradle index 7042a5b..ac76dc6 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -90,12 +90,12 @@ dependencies { annotationProcessor "com.jakewharton:butterknife-compiler:$butterKnifeVersion" // support libraries - implementation 'androidx.appcompat:appcompat:1.0.2' + implementation 'androidx.appcompat:appcompat:1.1.0-beta01' implementation 'com.google.android.material:material:1.0.0' implementation 'androidx.legacy:legacy-support-v4:1.0.0' implementation 'androidx.vectordrawable:vectordrawable:1.0.1' implementation 'androidx.cardview:cardview:1.0.0' - implementation 'androidx.constraintlayout:constraintlayout:1.1.3' + implementation 'androidx.constraintlayout:constraintlayout:2.0.0-beta2' implementation 'androidx.recyclerview:recyclerview:1.0.0' testImplementation 'junit:junit:4.12' diff --git a/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java b/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java index 900ec31..3a28925 100644 --- a/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java +++ b/app/src/main/java/org/mercury_im/messenger/MercuryImApplication.java @@ -5,6 +5,7 @@ import android.app.NotificationChannel; import android.app.NotificationManager; import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.Build; import org.mercury_im.messenger.di.component.AppComponent; diff --git a/app/src/main/java/org/mercury_im/messenger/di/component/AppComponent.java b/app/src/main/java/org/mercury_im/messenger/di/component/AppComponent.java index 9947d16..4b9d868 100644 --- a/app/src/main/java/org/mercury_im/messenger/di/component/AppComponent.java +++ b/app/src/main/java/org/mercury_im/messenger/di/component/AppComponent.java @@ -6,6 +6,7 @@ import org.mercury_im.messenger.di.module.RepositoryModule; import org.mercury_im.messenger.di.module.RoomModule; import org.mercury_im.messenger.service.XmppConnectionService; import org.mercury_im.messenger.ui.MainActivity; +import org.mercury_im.messenger.ui.RoomRosterHandler; import org.mercury_im.messenger.ui.chat.ChatActivity; import org.mercury_im.messenger.ui.chat.ChatInputFragment; import org.mercury_im.messenger.ui.chat.ChatInputViewModel; @@ -15,7 +16,6 @@ import org.mercury_im.messenger.ui.login.AccountsViewModel; import org.mercury_im.messenger.ui.login.LoginActivity; import org.mercury_im.messenger.ui.login.LoginViewModel; import org.mercury_im.messenger.ui.roster.RosterViewModel; -import org.mercury_im.messenger.xmpp_database_connector.RosterConnector; import javax.inject.Singleton; @@ -63,5 +63,5 @@ public interface AppComponent { // Connectors - void inject(RosterConnector connector); + void inject(RoomRosterHandler roomRosterHandler); } diff --git a/app/src/main/java/org/mercury_im/messenger/di/module/RepositoryModule.java b/app/src/main/java/org/mercury_im/messenger/di/module/RepositoryModule.java index da2f8d0..ed54d8f 100644 --- a/app/src/main/java/org/mercury_im/messenger/di/module/RepositoryModule.java +++ b/app/src/main/java/org/mercury_im/messenger/di/module/RepositoryModule.java @@ -1,11 +1,20 @@ package org.mercury_im.messenger.di.module; import org.mercury_im.messenger.persistence.repository.AccountRepository; +import org.mercury_im.messenger.persistence.repository.ChatRepository; import org.mercury_im.messenger.persistence.repository.ContactRepository; +import org.mercury_im.messenger.persistence.repository.EntityRepository; +import org.mercury_im.messenger.persistence.repository.MessageRepository; import org.mercury_im.messenger.persistence.room.dao.AccountDao; +import org.mercury_im.messenger.persistence.room.dao.ChatDao; import org.mercury_im.messenger.persistence.room.dao.ContactDao; +import org.mercury_im.messenger.persistence.room.dao.EntityDao; +import org.mercury_im.messenger.persistence.room.dao.MessageDao; import org.mercury_im.messenger.persistence.room.repository.IAccountRepository; +import org.mercury_im.messenger.persistence.room.repository.IChatRepository; import org.mercury_im.messenger.persistence.room.repository.IContactRepository; +import org.mercury_im.messenger.persistence.room.repository.IEntityRepository; +import org.mercury_im.messenger.persistence.room.repository.IMessageRepository; import javax.inject.Singleton; @@ -23,7 +32,26 @@ public class RepositoryModule { @Singleton @Provides - ContactRepository provideRosterEntryRepository(ContactDao dao) { + EntityRepository provideEntityRepository(EntityDao dao) { + return new IEntityRepository(dao); + } + + @Singleton + @Provides + ContactRepository provideContactRepository(ContactDao dao) { return new IContactRepository(dao); } + + @Singleton + @Provides + ChatRepository provideChatRepository(ChatDao dao) { + return new IChatRepository(dao); + } + + @Singleton + @Provides + MessageRepository provideMessageRepository(MessageDao dao) { + return new IMessageRepository(dao); + } + } diff --git a/app/src/main/java/org/mercury_im/messenger/di/module/RoomModule.java b/app/src/main/java/org/mercury_im/messenger/di/module/RoomModule.java index a274f0e..be4bb83 100644 --- a/app/src/main/java/org/mercury_im/messenger/di/module/RoomModule.java +++ b/app/src/main/java/org/mercury_im/messenger/di/module/RoomModule.java @@ -3,8 +3,10 @@ package org.mercury_im.messenger.di.module; import org.mercury_im.messenger.MercuryImApplication; import org.mercury_im.messenger.persistence.room.AppDatabase; import org.mercury_im.messenger.persistence.room.dao.AccountDao; +import org.mercury_im.messenger.persistence.room.dao.EntityDao; import org.mercury_im.messenger.persistence.room.dao.MessageDao; import org.mercury_im.messenger.persistence.room.dao.ContactDao; +import org.w3c.dom.Entity; import javax.inject.Inject; import javax.inject.Singleton; @@ -48,4 +50,10 @@ public class RoomModule { MessageDao provideMessageDao() { return mAppDatabase.messageDao(); } + + @Singleton + @Provides + EntityDao provideEntityDao() { + return mAppDatabase.entityDao(); + } } diff --git a/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionService.java b/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionService.java index 4743c63..d2a8921 100644 --- a/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionService.java +++ b/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionService.java @@ -3,11 +3,8 @@ package org.mercury_im.messenger.service; import android.app.Notification; import android.app.PendingIntent; import android.app.Service; -import android.content.ComponentName; import android.content.Context; import android.content.Intent; -import android.content.ServiceConnection; -import android.os.Binder; import android.os.Handler; import android.os.IBinder; import android.os.Looper; @@ -16,9 +13,10 @@ import android.util.LongSparseArray; import android.widget.Toast; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; +import androidx.lifecycle.LiveData; +import androidx.lifecycle.Observer; import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.XMPPConnection; @@ -27,6 +25,7 @@ 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.jivesoftware.smack.packet.Presence; import org.jivesoftware.smack.roster.Roster; import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterLoadedListener; @@ -34,19 +33,31 @@ import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration; import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager; import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; import org.mercury_im.messenger.MercuryImApplication; import org.mercury_im.messenger.Notifications; import org.mercury_im.messenger.R; import org.mercury_im.messenger.persistence.model.AccountModel; +import org.mercury_im.messenger.persistence.model.ContactModel; import org.mercury_im.messenger.persistence.repository.AccountRepository; import org.mercury_im.messenger.persistence.repository.ContactRepository; -import org.mercury_im.messenger.persistence.room.AppDatabase; +import org.mercury_im.messenger.persistence.repository.EntityRepository; +import org.mercury_im.messenger.persistence.room.dao.ContactDao; +import org.mercury_im.messenger.persistence.room.dao.EntityDao; import org.mercury_im.messenger.persistence.room.model.RoomAccountModel; import org.mercury_im.messenger.persistence.room.model.RoomContactModel; +import org.mercury_im.messenger.persistence.room.model.RoomEntityModel; +import org.mercury_im.messenger.persistence.room.repository.IAccountRepository; +import org.mercury_im.messenger.persistence.room.repository.IContactRepository; +import org.mercury_im.messenger.persistence.room.repository.IEntityRepository; import org.mercury_im.messenger.ui.MainActivity; import org.mercury_im.messenger.xmpp_android.ParcelableXMPPTCPConnectionConfiguration; +import org.mercury_im.messenger.xmpp_core.ConnectionHolder; +import org.mercury_im.messenger.xmpp_core.MercuryConnection; +import org.mercury_im.messenger.xmpp_core.RosterHandler; import java.io.IOException; +import java.util.Collection; import java.util.List; import java.util.Set; @@ -56,11 +67,11 @@ import javax.inject.Inject; * Started, Bound Service, which is responsible for managing {@link XMPPConnection XMPPConnections} * affiliated with registered accounts. */ -public class XmppConnectionService extends Service { +public class XmppConnectionService extends Service implements ConnectionHolder { private static final String TAG = MercuryImApplication.TAG; - private static final String APP = "org.olomono.mercury"; + private static final String APP = "org.mercury-im.messenger"; private static final String SERVICE = APP + ".XmppConnectionService"; private static final String ACTION = SERVICE + ".ACTION"; @@ -87,14 +98,22 @@ public class XmppConnectionService extends Service { public static final String STATUS_SUCCESS = STATUS + ".SUCCESS"; public static final String STATUS_FAILURE = STATUS + ".FAILURE"; - @Inject - ContactRepository rosterRepository; + ContactRepository contactRepository; @Inject AccountRepository accountRepository; - private final LongSparseArray connections = new LongSparseArray<>(); + @Inject + EntityRepository entityRepository; + + @Inject + EntityDao entityDao; + + @Inject + ContactDao contactDao; + + private final LongSparseArray connections = new LongSparseArray<>(); private Handler uiHandler; @@ -125,23 +144,18 @@ public class XmppConnectionService extends Service { ServerPingWithAlarmManager.onDestroy(); } + @Override + public MercuryConnection getConnection(long accountId) { + return connections.get(accountId); + } + + @Override + public void putConnection(long accountId, MercuryConnection connection) { + connections.put(accountId, connection); + } + @Override public int onStartCommand(Intent intent, int flags, int startId) { - - if (uiHandler == null) { - uiHandler = new Handler(Looper.getMainLooper()) { - @Override - public void handleMessage(android.os.Message msg) { - switch (msg.what) { - case 1: - Message m = (Message) msg.obj; - Toast.makeText(XmppConnectionService.this, (m.getFrom() != null ? m.getFrom().toString() : "null") + ": " - + m.getBody(), Toast.LENGTH_LONG).show(); - } - } - }; - } - Log.d(TAG, "onStartCommand(" + intent + ")"); if (intent == null) { startAndDisplayForegroundNotification(); @@ -152,30 +166,10 @@ public class XmppConnectionService extends Service { switch (action) { case ACTION_START: startAndDisplayForegroundNotification(); - startConnections(); break; case ACTION_STOP: stopForeground(true); - break; - case ACTION_CONNECT: - ParcelableXMPPTCPConnectionConfiguration configuration = intent.getParcelableExtra(EXTRA_CONFIGURATION); - if (configuration == null) { - Log.e(TAG, "Configuration is null."); - return START_STICKY_COMPATIBILITY; - } - - long accountId = intent.getLongExtra(EXTRA_ACCOUNT_ID, -1); - if (accountId == -1) { - Log.d(TAG, "No AccountID provided."); - return START_STICKY_COMPATIBILITY; - } - - new Thread() { - public void run() { - XMPPConnection connection = startConnection(configuration, accountId); - connections.put(accountId, connection); - } - }.start(); + stopSelf(); break; default: break; @@ -204,100 +198,6 @@ public class XmppConnectionService extends Service { .build(); } - public void startConnections() { - new Thread() { - @Override - public void run() { - synchronized (connections) { - List accounts = accountRepository.getAllAccounts(); - if (accounts == null) return; - - for (AccountModel a : accounts) { - if (connections.get(a.getId()) != null) { - continue; - } - - // XMPPConnection connection = startConnection(a.getJid(), a.getPassword(), a.getId()); - // connections.put(a.getId(), connection); - } - } - } - }.start(); - } - - private XMPPConnection startConnection(ParcelableXMPPTCPConnectionConfiguration connectionConfiguration, long accountId) { - XMPPTCPConnection con = null; - try { - XMPPTCPConnectionConfiguration conf = connectionConfiguration.getConfiguration(); - con = new XMPPTCPConnection(conf); - con.connect().login(); - } catch ( - XMPPException e) { - e.printStackTrace(); - } catch ( - SmackException e) { - e.printStackTrace(); - } catch ( - IOException e) { - e.printStackTrace(); - } catch ( - InterruptedException e) { - e.printStackTrace(); - } - - NotificationManagerCompat.from(getApplicationContext()).notify(Notifications.FOREGROUND_SERVICE_ID, - getForegroundNotification(getApplicationContext(), connections.size())); - - Roster roster = Roster.getInstanceFor(con); - roster.addRosterLoadedListener(new RosterLoadedListener() { - @Override - public void onRosterLoaded(Roster roster) { - Set entries = roster.getEntries(); - for (RosterEntry e : entries) { - Log.d(TAG, "Inserting Roster entry " + e.getJid().toString()); - - RoomContactModel contact = new RoomContactModel(); - contact.setAccountId(accountId); - // TODO: Fix - } - } - - @Override - public void onRosterLoadingFailed(Exception exception) { - Log.d(TAG, "Roster Loading failed", exception); - } - }); - - try { - roster.reload(); - } catch (SmackException.NotLoggedInException e) { - e.printStackTrace(); - } catch (SmackException.NotConnectedException e) { - e.printStackTrace(); - } catch (InterruptedException e) { - e.printStackTrace(); - } - - ChatManager chatManager = ChatManager.getInstanceFor(con); - chatManager.addIncomingListener(new IncomingChatMessageListener() { - @Override - public void newIncomingMessage(EntityBareJid from, Message message, Chat chat) { - android.os.Message msg = uiHandler.obtainMessage(1, message); - msg.sendToTarget(); - } - }); - - return con; - } - - public XMPPConnection getConnection(long accountId) { - return connections.get(accountId); - } - - public void putConnection(int accountId, XMPPConnection connection) { - connections.put(accountId, connection); - } - public class Binder extends android.os.Binder { private final XmppConnectionService service; diff --git a/app/src/main/java/org/mercury_im/messenger/ui/BindingActivity.java b/app/src/main/java/org/mercury_im/messenger/ui/BindingActivity.java new file mode 100644 index 0000000..3287559 --- /dev/null +++ b/app/src/main/java/org/mercury_im/messenger/ui/BindingActivity.java @@ -0,0 +1,55 @@ +package org.mercury_im.messenger.ui; + +import android.content.ComponentName; +import android.content.Context; +import android.content.Intent; +import android.content.ServiceConnection; +import android.os.IBinder; + +import androidx.appcompat.app.AppCompatActivity; + +import org.mercury_im.messenger.service.XmppConnectionService; + +public abstract class BindingActivity extends AppCompatActivity { + + protected XmppConnectionService connectionService; + protected boolean bound; + + @Override + protected void onStart() { + super.onStart(); + Intent intent = new Intent(this, XmppConnectionService.class); + bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE); + } + + @Override + protected void onStop() { + super.onStop(); + unbindService(serviceConnection); + bound = false; + } + + protected void onServiceBound() { + + } + + protected void onServiceUnbound() { + + } + + private ServiceConnection serviceConnection = new ServiceConnection() { + @Override + public void onServiceConnected(ComponentName componentName, IBinder iBinder) { + XmppConnectionService.Binder binder = (XmppConnectionService.Binder) iBinder; + connectionService = binder.getService(); + bound = true; + onServiceBound(); + } + + @Override + public void onServiceDisconnected(ComponentName componentName) { + bound = false; + onServiceUnbound(); + } + }; +} diff --git a/app/src/main/java/org/mercury_im/messenger/ui/MainActivity.java b/app/src/main/java/org/mercury_im/messenger/ui/MainActivity.java index 6ecb5f7..159ba07 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/MainActivity.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/MainActivity.java @@ -1,13 +1,19 @@ package org.mercury_im.messenger.ui; import androidx.lifecycle.Observer; + +import android.content.ComponentName; +import android.content.Context; import android.content.Intent; +import android.content.ServiceConnection; import android.os.AsyncTask; import android.os.Bundle; import androidx.annotation.Nullable; import com.google.android.material.floatingactionbutton.FloatingActionButton; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; + +import android.os.IBinder; import android.view.Menu; import android.view.MenuItem; @@ -18,6 +24,7 @@ import org.mercury_im.messenger.persistence.room.AppDatabase; import org.mercury_im.messenger.persistence.room.model.RoomContactModel; import org.mercury_im.messenger.persistence.repository.AccountRepository; import org.mercury_im.messenger.persistence.repository.ContactRepository; +import org.mercury_im.messenger.service.XmppConnectionService; import org.mercury_im.messenger.ui.chat.ChatActivity; import org.mercury_im.messenger.ui.login.AccountsActivity; import org.mercury_im.messenger.ui.login.LoginActivity; @@ -27,7 +34,7 @@ import java.util.List; import javax.inject.Inject; -public class MainActivity extends AppCompatActivity { +public class MainActivity extends BindingActivity { @Inject diff --git a/app/src/main/java/org/mercury_im/messenger/ui/RoomRosterHandler.java b/app/src/main/java/org/mercury_im/messenger/ui/RoomRosterHandler.java new file mode 100644 index 0000000..4dc7808 --- /dev/null +++ b/app/src/main/java/org/mercury_im/messenger/ui/RoomRosterHandler.java @@ -0,0 +1,100 @@ +package org.mercury_im.messenger.ui; + +import android.util.Log; + +import org.jivesoftware.smack.packet.Presence; +import org.jivesoftware.smack.roster.Roster; +import org.jxmpp.jid.EntityBareJid; +import org.jxmpp.jid.Jid; +import org.mercury_im.messenger.MercuryImApplication; +import org.mercury_im.messenger.persistence.room.dao.ContactDao; +import org.mercury_im.messenger.persistence.room.dao.EntityDao; +import org.mercury_im.messenger.persistence.room.model.RoomContactModel; +import org.mercury_im.messenger.persistence.room.model.RoomEntityModel; +import org.mercury_im.messenger.xmpp_core.RosterHandler; + +import java.util.Collection; + +import javax.inject.Inject; + +import static androidx.constraintlayout.widget.Constraints.TAG; + +public class RoomRosterHandler implements RosterHandler { + + @Inject + ContactDao contactDao; + + @Inject + EntityDao entityDao; + + private final long accountId; + private final Roster roster; + + public RoomRosterHandler(long accountId, Roster roster) { + this.accountId = accountId; + this.roster = roster; + MercuryImApplication.getApplication().getAppComponent().inject(this); + } + + + @Override + public void entriesAdded(Collection addresses) { + for (Jid jid : addresses) { + RoomContactModel contactModel = getContactModel(jid); + contactModel.setNickname(roster.getEntry(jid.asBareJid()).getName()); + contactDao.insert(contactModel); + } + } + + @Override + public void entriesUpdated(Collection addresses) { + for (Jid jid : addresses) { + RoomContactModel contactModel = getContactModel(jid); + contactModel.setNickname(roster.getEntry(jid.asBareJid()).getName()); + contactDao.update(contactModel); + } + } + + @Override + public void entriesDeleted(Collection addresses) { + for (Jid jid : addresses) { + RoomContactModel contactModel = getContactModel(jid); + contactDao.delete(contactModel); + } + } + + @Override + public void presenceChanged(Presence presence) { + + } + + @Override + public void onRosterLoaded(Roster roster) { + + } + + @Override + public void onRosterLoadingFailed(Exception exception) { + + } + + private RoomContactModel getContactModel(Jid jid) { + Log.d(TAG, "Build entity " + jid + " " + accountId); + EntityBareJid entityBareJid = jid.asEntityBareJidOrThrow(); + RoomEntityModel entityModel = entityDao.getEntityForSync(accountId, entityBareJid); + if (entityModel == null) { + entityModel = new RoomEntityModel(); + entityModel.setAccountId(accountId); + entityModel.setJid(entityBareJid); + entityModel.setId(entityDao.insert(entityModel)); + } + + RoomContactModel contactModel = contactDao.syncGetContactForEntityId(entityModel.getId()); + if (contactModel == null) { + contactModel = new RoomContactModel(); + contactModel.setAccountId(accountId); + contactModel.setEntityId(entityModel.getId()); + } + return contactModel; + } +} diff --git a/app/src/main/java/org/mercury_im/messenger/ui/login/LoginActivity.java b/app/src/main/java/org/mercury_im/messenger/ui/login/LoginActivity.java index 9ce6532..54fc180 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/login/LoginActivity.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/login/LoginActivity.java @@ -2,6 +2,8 @@ package org.mercury_im.messenger.ui.login; import androidx.lifecycle.LiveData; import androidx.lifecycle.ViewModelProviders; + +import android.content.Context; import android.content.Intent; import android.os.Bundle; import androidx.appcompat.app.AppCompatActivity; @@ -16,14 +18,24 @@ import android.widget.TextView; import com.google.android.material.textfield.TextInputEditText; +import org.jivesoftware.smack.SmackException; +import org.jivesoftware.smack.XMPPException; +import org.jivesoftware.smack.roster.Roster; +import org.jivesoftware.smack.tcp.XMPPTCPConnection; import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.impl.JidCreate; +import org.jxmpp.stringprep.XmppStringprepException; import org.mercury_im.messenger.MercuryImApplication; import org.mercury_im.messenger.R; import org.mercury_im.messenger.persistence.model.AccountModel; import org.mercury_im.messenger.persistence.room.model.RoomAccountModel; import org.mercury_im.messenger.persistence.repository.AccountRepository; import org.mercury_im.messenger.service.XmppConnectionService; +import org.mercury_im.messenger.ui.BindingActivity; +import org.mercury_im.messenger.ui.RoomRosterHandler; +import org.mercury_im.messenger.xmpp_core.MercuryConnection; + +import java.io.IOException; import javax.inject.Inject; @@ -33,7 +45,7 @@ import butterknife.ButterKnife; /** * A login screen that offers login via email/password. */ -public class LoginActivity extends AppCompatActivity implements TextView.OnEditorActionListener { +public class LoginActivity extends BindingActivity implements TextView.OnEditorActionListener { @Inject AccountRepository accountRepository; @@ -45,6 +57,9 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito @BindView(R.id.password) TextInputEditText mPasswordView; + @BindView(R.id.sign_in_button) + Button mSignInView; + private LoginViewModel viewModel; @Override @@ -63,13 +78,25 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito mJidView.setOnEditorActionListener(this); mPasswordView.setOnEditorActionListener(this); - Button mEmailSignInButton = findViewById(R.id.sign_in_button); - mEmailSignInButton.setOnClickListener(new OnClickListener() { + mSignInView.setOnClickListener(new OnClickListener() { @Override public void onClick(View view) { loginDetailsEntered(); } }); + mSignInView.setEnabled(false); + } + + @Override + protected void onServiceBound() { + super.onServiceBound(); + mSignInView.setEnabled(true); + } + + @Override + protected void onServiceUnbound() { + super.onServiceUnbound(); + mSignInView.setEnabled(false); } private void displayCredentials(LiveData account) { @@ -115,16 +142,39 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito accountModel.setJid(jid); accountModel.setPassword(password); long id = accountRepository.insertAccount(accountModel); + accountModel.setId(id); Log.d(MercuryImApplication.TAG, "LoginActivity.loginDetailsEntered: Account " + id + " inserted."); - attemptLogin(jid, password, id); + attemptLogin(accountModel); } } - private void attemptLogin(EntityBareJid jid, String password, long accountId) { - Intent connectIntent = new Intent(getApplicationContext(), XmppConnectionService.class); - connectIntent.setAction(XmppConnectionService.ACTION_CONNECT); - connectIntent.putExtra(XmppConnectionService.EXTRA_ACCOUNT_ID, accountId); - startService(connectIntent); + private void attemptLogin(AccountModel accountModel) { + new Thread() { + @Override + public void run() { + try { + XMPPTCPConnection connection = new XMPPTCPConnection(accountModel.getJid().getLocalpart().asUnescapedString(), + accountModel.getPassword(), accountModel.getJid().getDomain().toString()); + MercuryConnection mercuryConnection = new MercuryConnection(connection, accountModel.getId()); + + connection.connect().login(); + if (bound) { + connectionService.putConnection(accountModel.getId(), mercuryConnection); + } + } catch (XmppStringprepException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } catch (SmackException e) { + e.printStackTrace(); + } catch (XMPPException e) { + e.printStackTrace(); + } + } + }.start(); + super.finish(); } /** diff --git a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterFragment.java b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterFragment.java index 0636883..1e68f04 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterFragment.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterFragment.java @@ -1,20 +1,27 @@ package org.mercury_im.messenger.ui.roster; -import androidx.lifecycle.Observer; -import androidx.lifecycle.ViewModelProviders; -import androidx.annotation.Nullable; -import androidx.fragment.app.Fragment; +import android.content.Context; import android.os.Bundle; -import androidx.recyclerview.widget.RecyclerView; +import android.util.Log; import android.view.LayoutInflater; +import android.view.MotionEvent; import android.view.View; import android.view.ViewGroup; +import androidx.annotation.NonNull; +import androidx.fragment.app.Fragment; +import androidx.lifecycle.ViewModelProviders; +import androidx.recyclerview.widget.RecyclerView; + +import org.bouncycastle.jcajce.provider.symmetric.Serpent; import org.mercury_im.messenger.R; -import org.mercury_im.messenger.persistence.room.model.RoomContactModel; import java.util.ArrayList; -import java.util.List; + +import butterknife.BindView; +import butterknife.ButterKnife; + +import static androidx.constraintlayout.widget.Constraints.TAG; /** * A placeholder fragment containing a simple view. @@ -22,8 +29,10 @@ import java.util.List; public class RosterFragment extends Fragment { private RosterViewModel rosterViewModel; + private RosterRecyclerViewAdapter recyclerViewAdapter; - private RecyclerView recyclerView; + + RecyclerView recyclerView; public RosterFragment() { @@ -38,21 +47,24 @@ public class RosterFragment extends Fragment { recyclerViewAdapter = new RosterRecyclerViewAdapter(new ArrayList<>()); recyclerView.setAdapter(recyclerViewAdapter); - rosterViewModel = ViewModelProviders.of(getActivity()).get(RosterViewModel.class); - observeViewModel(rosterViewModel); - return view; } + @Override + public void onAttach(Context context) { + super.onAttach(context); + rosterViewModel = ViewModelProviders.of(getActivity()).get(RosterViewModel.class); + observeViewModel(rosterViewModel); + } + private void observeViewModel(RosterViewModel viewModel) { - viewModel.getRosterEntryList().observe(this, new Observer>() { - @Override - public void onChanged(@Nullable List rosterEntries) { - if (rosterEntries == null) { - return; - } - recyclerViewAdapter.setItems(rosterEntries); + viewModel.getRosterEntryList().observe(this, rosterEntries -> { + if (rosterEntries == null) { + Log.d(TAG, "Displaying null roster entries"); + return; } + recyclerViewAdapter.setItems(rosterEntries); + Log.d(TAG, "Displaying " + rosterEntries.size() + " roster entries"); }); } } diff --git a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterItemViewModel.java b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterItemViewModel.java index 10c7b5e..944d1c5 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterItemViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterItemViewModel.java @@ -24,7 +24,7 @@ public class RosterItemViewModel extends AndroidViewModel { } public RosterItemViewModel setContactId(long id) { - this.contact = contactRepository.getRosterEntry(id); + this.contact = contactRepository.getContact(id); return this; } } diff --git a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterRecyclerViewAdapter.java b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterRecyclerViewAdapter.java index 0f92d5b..e3b9cdd 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterRecyclerViewAdapter.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterRecyclerViewAdapter.java @@ -16,7 +16,7 @@ import butterknife.BindView; import butterknife.ButterKnife; public class RosterRecyclerViewAdapter - extends RecyclerView.Adapter { + extends RecyclerView.Adapter { private List entryModelList; @@ -26,28 +26,15 @@ public class RosterRecyclerViewAdapter @NonNull @Override - public AbstractRosterItem onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { -// switch (viewType) { -// case RosterItemViewHolder.TYPE: - return new RosterItemViewHolder(LayoutInflater.from(parent.getContext()) - .inflate(R.layout.recycler_view_item_roster_entry, parent, false)); -// default: -// return new RosterItemViewHolder(LayoutInflater.from(parent.getContext()) -// .inflate(R.layout.recycler_view_item_roster_entry, parent, false)); -// } + public RosterItemViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { + return new RosterItemViewHolder(LayoutInflater.from(parent.getContext()) + .inflate(R.layout.recycler_view_item_roster_entry, parent, false)); } @Override - public void onBindViewHolder(@NonNull AbstractRosterItem holder, int position) { + public void onBindViewHolder(@NonNull RosterItemViewHolder holder, int position) { RoomContactModel model = entryModelList.get(position); -// switch (holder.getItemViewType()) { -// case RosterItemViewHolder.TYPE: - RosterItemViewHolder rosterItem = (RosterItemViewHolder) holder; - //rosterItem.jidView.setText(model.getJid().toString()); - rosterItem.nicknameView.setText(model.getNickname()); - rosterItem.itemView.setTag(model); -// break; -// } + holder.bind(model); } @Override @@ -60,31 +47,26 @@ public class RosterRecyclerViewAdapter notifyDataSetChanged(); } - public abstract class AbstractRosterItem extends RecyclerView.ViewHolder { + public class RosterItemViewHolder extends RecyclerView.ViewHolder { - public AbstractRosterItem(@NonNull View itemView) { - super(itemView); - } + private View view; - abstract void bind(RosterViewModel viewModel); - } - - public class RosterItemViewHolder extends AbstractRosterItem { - - @BindView(R.id.roster_entry__jid) TextView jidView; - @BindView(R.id.roster_entry__nickname) TextView nicknameView; public RosterItemViewHolder(View itemView) { super(itemView); - ButterKnife.bind(itemView); + this.view = itemView; + this.jidView = itemView.findViewById(R.id.roster_entry__jid); + this.nicknameView = itemView.findViewById(R.id.roster_entry__nickname); } - @Override - void bind(RosterViewModel viewModel) { - // viewModel.getRosterEntryList().observe(); + void bind(RoomContactModel contactModel) { + // jidView.setText("" + contactModel.getEntityId()); + String nick = contactModel.getNickname(); + nicknameView.setText(nick != null ? nick : ""); + } } } diff --git a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterViewModel.java b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterViewModel.java index d743860..774724b 100644 --- a/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterViewModel.java +++ b/app/src/main/java/org/mercury_im/messenger/ui/roster/RosterViewModel.java @@ -24,7 +24,7 @@ public class RosterViewModel extends AndroidViewModel { public RosterViewModel(@NonNull Application application) { super(application); MercuryImApplication.getApplication().getAppComponent().inject(this); - this.rosterEntryList = contactRepository.getAllRosterEntries(); + this.rosterEntryList = contactRepository.getAllContacts(); } public LiveData> getRosterEntryList() { diff --git a/app/src/main/java/org/mercury_im/messenger/xmpp_database_connector/RosterConnector.java b/app/src/main/java/org/mercury_im/messenger/xmpp_database_connector/RosterConnector.java deleted file mode 100644 index 61b1c6a..0000000 --- a/app/src/main/java/org/mercury_im/messenger/xmpp_database_connector/RosterConnector.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.mercury_im.messenger.xmpp_database_connector; - -import android.util.Log; - -import org.jivesoftware.smack.packet.Presence; -import org.jivesoftware.smack.roster.Roster; -import org.jivesoftware.smack.roster.RosterEntry; -import org.jxmpp.jid.Jid; -import org.mercury_im.messenger.MercuryImApplication; -import org.mercury_im.messenger.persistence.model.AccountModel; -import org.mercury_im.messenger.persistence.repository.AccountRepository; -import org.mercury_im.messenger.persistence.repository.ContactRepository; -import org.mercury_im.messenger.xmpp_core.MercuryConnection; -import org.mercury_im.messenger.xmpp_core.RosterHandler; - -import java.util.Collection; - -import javax.inject.Inject; - -import static androidx.constraintlayout.widget.Constraints.TAG; - -public class RosterConnector implements RosterHandler { - - @Inject - ContactRepository contactRepository; - - @Inject - AccountRepository accountRepository; - - private AccountModel account; - - private final MercuryConnection connection; - private final Roster roster; - - public RosterConnector(MercuryConnection connection) { - this.connection = connection; - this.roster = connection.getRoster(); - - MercuryImApplication.getApplication().getAppComponent().inject(this); - - account = (AccountModel) accountRepository.getAccount(connection.getAccountId()).getValue(); - } - - @Override - public void entriesAdded(Collection addresses) { - for (Jid j : addresses) { - RosterEntry entry = roster.getEntry(j.asBareJid()); - // ContactModel - } - } - - @Override - public void entriesUpdated(Collection addresses) { - - } - - @Override - public void entriesDeleted(Collection addresses) { - - } - - @Override - public void presenceChanged(Presence presence) { - - } - - @Override - public void onRosterLoaded(Roster roster) { - if (roster == connection.getRoster()) { - - } - } - - @Override - public void onRosterLoadingFailed(Exception exception) { - Log.e(TAG, "Loading roster for " + account.getJid().toString() + " failed.", exception); - } -} diff --git a/app/src/main/res/layout/fragment_account_list.xml b/app/src/main/res/layout/fragment_account_list.xml index 251633c..20a21c8 100644 --- a/app/src/main/res/layout/fragment_account_list.xml +++ b/app/src/main/res/layout/fragment_account_list.xml @@ -10,4 +10,4 @@ android:layout_marginRight="16dp" app:layoutManager="LinearLayoutManager" tools:context="org.mercury_im.messenger.ui.login.AccountsFragment" - tools:listitem="@layout/fragment_account" /> + tools:listitem="@layout/recycler_view_item_account" /> diff --git a/app/src/main/res/layout/recycler_view_item_roster_entry.xml b/app/src/main/res/layout/recycler_view_item_roster_entry.xml index 811be67..ded6ccf 100644 --- a/app/src/main/res/layout/recycler_view_item_roster_entry.xml +++ b/app/src/main/res/layout/recycler_view_item_roster_entry.xml @@ -1,11 +1,6 @@ - - - -