Hacked Roster loading
This commit is contained in:
parent
ac2037e06c
commit
b469f6de95
|
@ -1,14 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="WizardSettings">
|
|
||||||
<option name="children">
|
|
||||||
<map>
|
|
||||||
<entry key="vectorWizard">
|
|
||||||
<value>
|
|
||||||
<PersistentState />
|
|
||||||
</value>
|
|
||||||
</entry>
|
|
||||||
</map>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
|
@ -12,9 +12,13 @@
|
||||||
<set>
|
<set>
|
||||||
<option value="$PROJECT_DIR$" />
|
<option value="$PROJECT_DIR$" />
|
||||||
<option value="$PROJECT_DIR$/app" />
|
<option value="$PROJECT_DIR$/app" />
|
||||||
|
<option value="$PROJECT_DIR$/persistence" />
|
||||||
|
<option value="$PROJECT_DIR$/persistence-room" />
|
||||||
|
<option value="$PROJECT_DIR$/xmpp_core" />
|
||||||
</set>
|
</set>
|
||||||
</option>
|
</option>
|
||||||
<option name="resolveModulePerSourceSet" value="false" />
|
<option name="resolveModulePerSourceSet" value="false" />
|
||||||
|
<option name="useQualifiedModuleNames" value="true" />
|
||||||
</GradleProjectSettings>
|
</GradleProjectSettings>
|
||||||
</option>
|
</option>
|
||||||
</component>
|
</component>
|
||||||
|
|
|
@ -1,49 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="CMakeSettings">
|
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="1.8" project-jdk-type="JavaSDK">
|
||||||
<configurations>
|
<output url="file://$PROJECT_DIR$/classes" />
|
||||||
<configuration PROFILE_NAME="Debug" CONFIG_NAME="Debug" />
|
|
||||||
</configurations>
|
|
||||||
</component>
|
|
||||||
<component name="NullableNotNullManager">
|
|
||||||
<option name="myDefaultNullable" value="android.support.annotation.Nullable" />
|
|
||||||
<option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
|
|
||||||
<option name="myNullables">
|
|
||||||
<value>
|
|
||||||
<list size="10">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="javax.annotation.CheckForNull" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
|
|
||||||
<item index="4" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
|
|
||||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.Nullable" />
|
|
||||||
<item index="6" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNullable" />
|
|
||||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.Nullable" />
|
|
||||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableDecl" />
|
|
||||||
<item index="9" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NullableType" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
<option name="myNotNulls">
|
|
||||||
<value>
|
|
||||||
<list size="9">
|
|
||||||
<item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
|
|
||||||
<item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
|
|
||||||
<item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
|
|
||||||
<item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
|
|
||||||
<item index="4" class="java.lang.String" itemvalue="androidx.annotation.NonNull" />
|
|
||||||
<item index="5" class="java.lang.String" itemvalue="androidx.annotation.RecentlyNonNull" />
|
|
||||||
<item index="6" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.qual.NonNull" />
|
|
||||||
<item index="7" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullDecl" />
|
|
||||||
<item index="8" class="java.lang.String" itemvalue="org.checkerframework.checker.nullness.compatqual.NonNullType" />
|
|
||||||
</list>
|
|
||||||
</value>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" project-jdk-name="JDK" project-jdk-type="JavaSDK">
|
|
||||||
<output url="file://$PROJECT_DIR$/build/classes" />
|
|
||||||
</component>
|
|
||||||
<component name="ProjectType">
|
|
||||||
<option name="id" value="Android" />
|
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -1,6 +1,6 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project version="4">
|
<project version="4">
|
||||||
<component name="VcsDirectoryMappings">
|
<component name="VcsDirectoryMappings">
|
||||||
<mapping directory="" vcs="Git" />
|
<mapping directory="$PROJECT_DIR$" vcs="Git" />
|
||||||
</component>
|
</component>
|
||||||
</project>
|
</project>
|
|
@ -71,6 +71,12 @@ check.configure {
|
||||||
|
|
||||||
// Dependency versions are located in version.gradle
|
// Dependency versions are located in version.gradle
|
||||||
dependencies {
|
dependencies {
|
||||||
|
|
||||||
|
implementation project(":xmpp_core")
|
||||||
|
implementation(project(':persistence-room')) {
|
||||||
|
transitive = true
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
architecture components for database and lifecycle management
|
architecture components for database and lifecycle management
|
||||||
*/
|
*/
|
||||||
|
@ -79,10 +85,6 @@ dependencies {
|
||||||
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
|
implementation "androidx.lifecycle:lifecycle-extensions:$lifecycleVersion"
|
||||||
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycleVersion"
|
annotationProcessor "androidx.lifecycle:lifecycle-compiler:$lifecycleVersion"
|
||||||
|
|
||||||
// Room
|
|
||||||
implementation "androidx.room:room-runtime:$roomVersion"
|
|
||||||
annotationProcessor "androidx.room:room-compiler:$roomVersion"
|
|
||||||
|
|
||||||
// Dagger 2 for dependency injection
|
// Dagger 2 for dependency injection
|
||||||
implementation "com.google.dagger:dagger:$daggerVersion"
|
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||||
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||||
|
@ -101,24 +103,4 @@ dependencies {
|
||||||
|
|
||||||
// circular image viewer for avatars
|
// circular image viewer for avatars
|
||||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||||
|
|
||||||
// Smack
|
|
||||||
// Not all of those are needed, but it may be a good idea to define those versions explicitly
|
|
||||||
implementation "org.igniterealtime.smack:smack-android:$smackAndroidVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-android-extensions:$smackAndroidExtensionsVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-core:$smackCoreVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-experimental:$smackExperimentalVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-extensions:$smackExtensionsVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-im:$smackImVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-omemo:$smackOmemoVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-omemo-signal:$smackOmemoSignalVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-openpgp:$smackOpenPGPVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-resolver-minidns:$smackResolverMiniDnsVersion"
|
|
||||||
implementation "org.igniterealtime.smack:smack-tcp:$smackTcpVersion"
|
|
||||||
|
|
||||||
// Exclude XmlPullParser from Smack dependencies, as its now provided by Android
|
|
||||||
// https://stackoverflow.com/questions/48488563/gradle-xpp3-error/48746294#48746294
|
|
||||||
configurations {
|
|
||||||
all*.exclude group: 'xpp3', module: 'xpp3'
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
package org.mercury_im.messenger.di.module;
|
package org.mercury_im.messenger.di.module;
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
|
import org.mercury_im.messenger.persistence.repository.RosterEntryRepository;
|
||||||
import org.mercury_im.messenger.persistence.repository.account.AccountRepository;
|
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||||
import org.mercury_im.messenger.persistence.repository.account.AccountRepositoryImpl;
|
import org.mercury_im.messenger.persistence.room.dao.RosterEntryDao;
|
||||||
import org.mercury_im.messenger.persistence.repository.roster.RosterEntryRepository;
|
import org.mercury_im.messenger.persistence.room.repository.IAccountRepository;
|
||||||
import org.mercury_im.messenger.persistence.repository.roster.RosterEntryRepositoryImpl;
|
import org.mercury_im.messenger.persistence.room.repository.IRosterEntryRepository;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -18,12 +18,12 @@ public class RepositoryModule {
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
AccountRepository provideAccountRepository(AccountDao dao) {
|
AccountRepository provideAccountRepository(AccountDao dao) {
|
||||||
return new AccountRepositoryImpl(dao);
|
return new IAccountRepository(dao);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
RosterEntryRepository provideRosterEntryRepository(RosterEntryDao dao) {
|
RosterEntryRepository provideRosterEntryRepository(RosterEntryDao dao) {
|
||||||
return new RosterEntryRepositoryImpl(dao);
|
return new IRosterEntryRepository(dao);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
package org.mercury_im.messenger.di.module;
|
package org.mercury_im.messenger.di.module;
|
||||||
|
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
import org.mercury_im.messenger.persistence.database.AppDatabase;
|
import org.mercury_im.messenger.persistence.room.AppDatabase;
|
||||||
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
|
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||||
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
|
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
|
||||||
|
import org.mercury_im.messenger.persistence.room.dao.RosterEntryDao;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -41,4 +42,10 @@ public class RoomModule {
|
||||||
RosterEntryDao provideRosterEntryDao() {
|
RosterEntryDao provideRosterEntryDao() {
|
||||||
return mAppDatabase.rosterEntryDao();
|
return mAppDatabase.rosterEntryDao();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Singleton
|
||||||
|
@Provides
|
||||||
|
MessageDao provideMessageDao() {
|
||||||
|
return mAppDatabase.messageDao();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,52 +0,0 @@
|
||||||
package org.mercury_im.messenger.persistence.database.dao;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.annotation.WorkerThread;
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.TypeConverters;
|
|
||||||
import androidx.room.Update;
|
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
|
||||||
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
@TypeConverters(EntityBareJidConverter.class)
|
|
||||||
@WorkerThread
|
|
||||||
public interface AccountDao {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a {@link LiveData} wrapping a {@link List} which contains all
|
|
||||||
* {@link AccountModel Accounts} which are currently stored in the database.
|
|
||||||
*
|
|
||||||
* @return live updating account list
|
|
||||||
*/
|
|
||||||
@Query("select * from AccountModel")
|
|
||||||
LiveData<List<AccountModel>> getAllAccounts();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the {@link AccountModel Account} which is identified by the given id.
|
|
||||||
*
|
|
||||||
* @param id id of the account
|
|
||||||
* @return account or null
|
|
||||||
*/
|
|
||||||
@Query("select * from AccountModel where id = :id")
|
|
||||||
LiveData<AccountModel> getAccountById(long id);
|
|
||||||
|
|
||||||
@Query("select * from AccountModel where jid = :jid")
|
|
||||||
LiveData<AccountModel> getAccountByJid(EntityBareJid jid);
|
|
||||||
|
|
||||||
@Insert
|
|
||||||
long insertAccount(AccountModel account);
|
|
||||||
|
|
||||||
@Update
|
|
||||||
void updateAccount(AccountModel account);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void deleteAccount(AccountModel account);
|
|
||||||
}
|
|
|
@ -1,40 +0,0 @@
|
||||||
package org.mercury_im.messenger.persistence.database.dao;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.room.Dao;
|
|
||||||
import androidx.room.Delete;
|
|
||||||
import androidx.room.Insert;
|
|
||||||
import androidx.room.Query;
|
|
||||||
import androidx.room.TypeConverters;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static androidx.room.OnConflictStrategy.REPLACE;
|
|
||||||
|
|
||||||
@Dao
|
|
||||||
@TypeConverters(EntityBareJidConverter.class)
|
|
||||||
public interface RosterEntryDao {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a {@link LiveData} wrapping a {@link List} of all {@link RosterEntryModel RosterEntries}
|
|
||||||
* which are currently found in the database.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
@Query("select * from RosterEntryModel")
|
|
||||||
LiveData<List<RosterEntryModel>> getAllRosterEntries();
|
|
||||||
|
|
||||||
@Query("select * from RosterEntryModel where id = :id")
|
|
||||||
RosterEntryModel getRosterEntryById(String id);
|
|
||||||
|
|
||||||
@Query("select * from RosterEntryModel where accountId = :accountId")
|
|
||||||
LiveData<List<RosterEntryModel>> getRosterEntriesForAccount(String accountId);
|
|
||||||
|
|
||||||
@Insert(onConflict = REPLACE)
|
|
||||||
void addRosterEntry(RosterEntryModel rosterEntry);
|
|
||||||
|
|
||||||
@Delete
|
|
||||||
void deleteRosterEntry(RosterEntryModel rosterEntry);
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
package org.mercury_im.messenger.persistence.repository.account;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface AccountRepository {
|
|
||||||
|
|
||||||
LiveData<AccountModel> getAccount(long accountId);
|
|
||||||
|
|
||||||
LiveData<List<AccountModel>> getAllAccounts();
|
|
||||||
|
|
||||||
long insertAccount(AccountModel accountModel);
|
|
||||||
}
|
|
|
@ -1,19 +0,0 @@
|
||||||
package org.mercury_im.messenger.persistence.repository.roster;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
|
|
||||||
import org.jivesoftware.smack.roster.RosterEntry;
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
|
||||||
import org.mercury_im.messenger.ui.roster.RosterViewModel;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public interface RosterEntryRepository {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return a {@link LiveData} object of a {@link RosterViewModel} which contains
|
|
||||||
* {@link RosterEntryModel} for all {@link RosterEntry RosterEntries} in the users roster.
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
LiveData<List<RosterEntryModel>> getAllRosterEntries();
|
|
||||||
}
|
|
|
@ -1,24 +0,0 @@
|
||||||
package org.mercury_im.messenger.persistence.repository.roster;
|
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
public class RosterEntryRepositoryImpl implements RosterEntryRepository {
|
|
||||||
|
|
||||||
private final RosterEntryDao rosterEntryDao;
|
|
||||||
|
|
||||||
public RosterEntryRepositoryImpl(RosterEntryDao dao) {
|
|
||||||
this.rosterEntryDao = dao;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public LiveData<List<RosterEntryModel>> getAllRosterEntries() {
|
|
||||||
return rosterEntryDao.getAllRosterEntries();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,14 +1,14 @@
|
||||||
package org.mercury_im.messenger.service;
|
package org.mercury_im.messenger.service;
|
||||||
|
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
|
||||||
public class MessengerXmppConnection {
|
public class MessengerXmppConnection {
|
||||||
|
|
||||||
private final XMPPConnection connection;
|
private final XMPPConnection connection;
|
||||||
private final AccountModel account;
|
private final RoomAccountModel account;
|
||||||
|
|
||||||
public MessengerXmppConnection(XMPPConnection connection, AccountModel account) {
|
public MessengerXmppConnection(XMPPConnection connection, RoomAccountModel account) {
|
||||||
this.connection = connection;
|
this.connection = connection;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,17 +3,23 @@ package org.mercury_im.messenger.service;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.PendingIntent;
|
import android.app.PendingIntent;
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
import androidx.core.app.NotificationCompat;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.util.LongSparseArray;
|
import android.util.LongSparseArray;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
import androidx.annotation.Nullable;
|
||||||
|
import androidx.core.app.NotificationCompat;
|
||||||
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
|
|
||||||
import org.jivesoftware.smack.SmackException;
|
import org.jivesoftware.smack.SmackException;
|
||||||
import org.jivesoftware.smack.XMPPConnection;
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
import org.jivesoftware.smack.XMPPException;
|
import org.jivesoftware.smack.XMPPException;
|
||||||
|
import org.jivesoftware.smack.roster.Roster;
|
||||||
|
import org.jivesoftware.smack.roster.RosterEntry;
|
||||||
|
import org.jivesoftware.smack.roster.RosterLoadedListener;
|
||||||
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
|
||||||
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
@ -21,11 +27,15 @@ import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
import org.mercury_im.messenger.Notifications;
|
import org.mercury_im.messenger.Notifications;
|
||||||
import org.mercury_im.messenger.R;
|
import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.persistence.database.AppDatabase;
|
import org.mercury_im.messenger.persistence.model.RosterEntryModel;
|
||||||
|
import org.mercury_im.messenger.persistence.repository.RosterEntryRepository;
|
||||||
|
import org.mercury_im.messenger.persistence.room.AppDatabase;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
import org.mercury_im.messenger.ui.MainActivity;
|
import org.mercury_im.messenger.ui.MainActivity;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.InetAddress;
|
import java.net.InetAddress;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -35,35 +45,38 @@ import javax.inject.Inject;
|
||||||
*/
|
*/
|
||||||
public class XmppService extends Service {
|
public class XmppService extends Service {
|
||||||
|
|
||||||
private static final String TAG = MercuryImApplication.TAG;
|
private static final String TAG = MercuryImApplication.TAG;
|
||||||
|
|
||||||
private static final String APP = "org.olomono.mercury";
|
private static final String APP = "org.olomono.mercury";
|
||||||
private static final String SERVICE = APP + ".XmppService";
|
private static final String SERVICE = APP + ".XmppService";
|
||||||
|
|
||||||
private static final String ACTION = SERVICE + ".ACTION";
|
private static final String ACTION = SERVICE + ".ACTION";
|
||||||
private static final String EVENT = SERVICE + ".EVENT";
|
private static final String EVENT = SERVICE + ".EVENT";
|
||||||
private static final String EXTRA = SERVICE + ".EXTRA";
|
private static final String EXTRA = SERVICE + ".EXTRA";
|
||||||
private static final String STATUS = SERVICE + ".STATUS";
|
private static final String STATUS = SERVICE + ".STATUS";
|
||||||
|
|
||||||
public static final String ACTION_START = ACTION + ".START";
|
public static final String ACTION_START = ACTION + ".START";
|
||||||
public static final String ACTION_STOP = ACTION + ".STOP";
|
public static final String ACTION_STOP = ACTION + ".STOP";
|
||||||
public static final String ACTION_CONNECT = ACTION + ".CONNECT";
|
public static final String ACTION_CONNECT = ACTION + ".CONNECT";
|
||||||
public static final String ACTION_DISCONNECT = ACTION + ".DISCONNECT";
|
public static final String ACTION_DISCONNECT = ACTION + ".DISCONNECT";
|
||||||
public static final String ACTION_PING = ACTION + ".PING";
|
public static final String ACTION_PING = ACTION + ".PING";
|
||||||
|
|
||||||
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
|
public static final String EVENT_INCOMING_MESSAGE = EVENT + ".INCOMING_MESSAGE";
|
||||||
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
|
public static final String EVENT_OUTGOING_MESSAGE = EVENT + ".OUTGOING_MESSAGE";
|
||||||
|
|
||||||
public static final String EXTRA_JID = EXTRA + ".JID";
|
public static final String EXTRA_JID = EXTRA + ".JID";
|
||||||
public static final String EXTRA_PASSWORD = EXTRA + ".PASSWORD";
|
public static final String EXTRA_PASSWORD = EXTRA + ".PASSWORD";
|
||||||
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
|
public static final String EXTRA_ACCOUNT_ID = EXTRA + ".ACCOUNT_ID";
|
||||||
|
|
||||||
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
|
public static final String STATUS_SUCCESS = STATUS + ".SUCCESS";
|
||||||
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
|
public static final String STATUS_FAILURE = STATUS + ".FAILURE";
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AppDatabase database;
|
AppDatabase database;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RosterEntryRepository rosterRepository;
|
||||||
|
|
||||||
private final LongSparseArray<XMPPConnection> connections = new LongSparseArray<>();
|
private final LongSparseArray<XMPPConnection> connections = new LongSparseArray<>();
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -119,9 +132,7 @@ public class XmppService extends Service {
|
||||||
public void run() {
|
public void run() {
|
||||||
|
|
||||||
XMPPTCPConnection con = null;
|
XMPPTCPConnection con = null;
|
||||||
try
|
try {
|
||||||
|
|
||||||
{
|
|
||||||
InetAddress address = InetAddress.getByName(bareJid.getDomain().toString());
|
InetAddress address = InetAddress.getByName(bareJid.getDomain().toString());
|
||||||
XMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration.builder()
|
XMPPTCPConnectionConfiguration conf = XMPPTCPConnectionConfiguration.builder()
|
||||||
.setXmppDomain(bareJid.asDomainBareJid())
|
.setXmppDomain(bareJid.asDomainBareJid())
|
||||||
|
@ -131,32 +142,53 @@ public class XmppService extends Service {
|
||||||
.build();
|
.build();
|
||||||
con = new XMPPTCPConnection(conf);
|
con = new XMPPTCPConnection(conf);
|
||||||
con.connect().login();
|
con.connect().login();
|
||||||
} catch(
|
} catch (
|
||||||
XMPPException e)
|
XMPPException e) {
|
||||||
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch(
|
} catch (
|
||||||
SmackException e)
|
SmackException e) {
|
||||||
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch(
|
} catch (
|
||||||
IOException e)
|
IOException e) {
|
||||||
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
} catch(
|
} catch (
|
||||||
InterruptedException e)
|
InterruptedException e) {
|
||||||
|
|
||||||
{
|
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
connections.put(intent.getLongExtra(EXTRA_ACCOUNT_ID,-1),con);
|
connections.put(intent.getLongExtra(EXTRA_ACCOUNT_ID, -1), con);
|
||||||
while (true) {
|
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<RosterEntry> entries = roster.getEntries();
|
||||||
|
for (RosterEntry e : entries) {
|
||||||
|
Log.d(TAG, "Inserting Roster entry " + e.getJid().toString());
|
||||||
|
RoomRosterEntryModel m = new RoomRosterEntryModel(e.getJid().asEntityBareJidIfPossible(), e.getName(), e.getName());
|
||||||
|
m.setAccountId(accountId);
|
||||||
|
rosterRepository.updateOrInsertRosterEntry(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@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();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}.start();
|
}.start();
|
||||||
break;
|
break;
|
||||||
|
@ -170,22 +202,23 @@ public class XmppService extends Service {
|
||||||
|
|
||||||
public void startAndDisplayForegroundNotification() {
|
public void startAndDisplayForegroundNotification() {
|
||||||
Log.d(TAG, "startAndDisplayForegroundNotification()");
|
Log.d(TAG, "startAndDisplayForegroundNotification()");
|
||||||
Intent startMainActivityIntent = new Intent(this, MainActivity.class);
|
Notification notification = getForegroundNotification(getApplicationContext(), connections.size());
|
||||||
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
|
|
||||||
startMainActivityIntent, 0);
|
|
||||||
|
|
||||||
Notification notification = new NotificationCompat.Builder(this,
|
|
||||||
Notifications.NOTIFICATION_CHANNEL__FOREGROUND_SERVICE)
|
|
||||||
.setContentTitle("Sticky Notification Title")
|
|
||||||
.setContentText("Notification Content Text")
|
|
||||||
.setSmallIcon(R.drawable.ic_send_black_24dp)
|
|
||||||
.setContentIntent(pendingIntent)
|
|
||||||
.setTicker("Notification Ticker Text")
|
|
||||||
.build();
|
|
||||||
|
|
||||||
startForeground(Notifications.FOREGROUND_SERVICE_ID, notification);
|
startForeground(Notifications.FOREGROUND_SERVICE_ID, notification);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Notification getForegroundNotification(Context context, int numConnections) {
|
||||||
|
Intent startMainActivityIntent = new Intent(context, MainActivity.class);
|
||||||
|
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0,
|
||||||
|
startMainActivityIntent, 0);
|
||||||
|
return new NotificationCompat.Builder(context, Notifications.NOTIFICATION_CHANNEL__FOREGROUND_SERVICE)
|
||||||
|
.setContentTitle("Mercury")
|
||||||
|
.setContentText(numConnections + " connections.")
|
||||||
|
.setSmallIcon(R.drawable.ic_send_black_24dp)
|
||||||
|
.setContentIntent(pendingIntent)
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
public XMPPConnection getConnection(long accountId) {
|
public XMPPConnection getConnection(long accountId) {
|
||||||
return connections.get(accountId);
|
return connections.get(accountId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,11 +15,11 @@ import android.view.View;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
import org.mercury_im.messenger.R;
|
import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.persistence.database.AppDatabase;
|
import org.mercury_im.messenger.persistence.room.AppDatabase;
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.account.AccountRepository;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
import org.mercury_im.messenger.persistence.repository.roster.RosterEntryRepository;
|
import org.mercury_im.messenger.persistence.repository.RosterEntryRepository;
|
||||||
import org.mercury_im.messenger.ui.chat.ChatActivity;
|
import org.mercury_im.messenger.ui.chat.ChatActivity;
|
||||||
import org.mercury_im.messenger.ui.login.LoginActivity;
|
import org.mercury_im.messenger.ui.login.LoginActivity;
|
||||||
import org.mercury_im.messenger.ui.settings.SettingsActivity;
|
import org.mercury_im.messenger.ui.settings.SettingsActivity;
|
||||||
|
@ -50,7 +50,7 @@ public class MainActivity extends AppCompatActivity {
|
||||||
fab.setOnClickListener(new View.OnClickListener() {
|
fab.setOnClickListener(new View.OnClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onClick(View view) {
|
public void onClick(View view) {
|
||||||
AccountModel account = new AccountModel();
|
RoomAccountModel account = new RoomAccountModel();
|
||||||
account.setJid(JidCreate.entityBareFromOrThrowUnchecked("alice@wonderland.lit"));
|
account.setJid(JidCreate.entityBareFromOrThrowUnchecked("alice@wonderland.lit"));
|
||||||
account.setPassword("swordfish");
|
account.setPassword("swordfish");
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
accountRepository.getAllAccounts().observe(this, new Observer<List<AccountModel>>() {
|
accountRepository.getAllAccounts().observe(this, new Observer<List<RoomAccountModel>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(@Nullable List<AccountModel> accountModels) {
|
public void onChanged(@Nullable List<RoomAccountModel> accountModels) {
|
||||||
if (accountModels == null || accountModels.isEmpty()) {
|
if (accountModels == null || accountModels.isEmpty()) {
|
||||||
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
|
startActivity(new Intent(getApplicationContext(), LoginActivity.class));
|
||||||
}
|
}
|
||||||
|
@ -96,11 +96,11 @@ public class MainActivity extends AppCompatActivity {
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addRosterEntry(AppDatabase database, RosterEntryModel rosterEntry) {
|
private void addRosterEntry(AppDatabase database, RoomRosterEntryModel rosterEntry) {
|
||||||
new addRosterEntry(database).execute(rosterEntry);
|
new addRosterEntry(database).execute(rosterEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class addRosterEntry extends AsyncTask<RosterEntryModel, Void, Void> {
|
private static class addRosterEntry extends AsyncTask<RoomRosterEntryModel, Void, Void> {
|
||||||
|
|
||||||
private AppDatabase database;
|
private AppDatabase database;
|
||||||
|
|
||||||
|
@ -109,8 +109,8 @@ public class MainActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Void doInBackground(RosterEntryModel... rosterEntryModels) {
|
protected Void doInBackground(RoomRosterEntryModel... rosterEntryModels) {
|
||||||
database.rosterEntryDao().addRosterEntry(rosterEntryModels[0]);
|
database.rosterEntryDao().insert(rosterEntryModels[0]);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,14 +3,14 @@ package org.mercury_im.messenger.ui.chat;
|
||||||
import androidx.lifecycle.ViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.mercury_im.messenger.persistence.database.model.Account;
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
|
||||||
public class ChatViewModel extends ViewModel {
|
public class ChatViewModel extends ViewModel {
|
||||||
|
|
||||||
private Account account;
|
private AccountModel account;
|
||||||
private EntityBareJid contact;
|
private EntityBareJid contact;
|
||||||
|
|
||||||
public void init(Account account, EntityBareJid contact) {
|
public void init(AccountModel account, EntityBareJid contact) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
this.contact = contact;
|
this.contact = contact;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,8 +17,8 @@ import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.jxmpp.jid.impl.JidCreate;
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
import org.mercury_im.messenger.R;
|
import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.account.AccountRepository;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
import org.mercury_im.messenger.service.XmppService;
|
import org.mercury_im.messenger.service.XmppService;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -101,7 +101,7 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
|
||||||
}
|
}
|
||||||
|
|
||||||
if (loginIntact) {
|
if (loginIntact) {
|
||||||
AccountModel accountModel = new AccountModel();
|
RoomAccountModel accountModel = new RoomAccountModel();
|
||||||
accountModel.setEnabled(true);
|
accountModel.setEnabled(true);
|
||||||
accountModel.setJid(jid);
|
accountModel.setJid(jid);
|
||||||
accountModel.setPassword(password);
|
accountModel.setPassword(password);
|
||||||
|
|
|
@ -5,8 +5,8 @@ import androidx.lifecycle.ViewModel;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.account.AccountRepository;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
@ -16,23 +16,23 @@ public class LoginViewModel extends ViewModel {
|
||||||
@Inject
|
@Inject
|
||||||
AccountRepository accountRepository;
|
AccountRepository accountRepository;
|
||||||
|
|
||||||
private MutableLiveData<AccountModel> account = new MutableLiveData<>();
|
private MutableLiveData<RoomAccountModel> account = new MutableLiveData<>();
|
||||||
|
|
||||||
public LoginViewModel() {
|
public LoginViewModel() {
|
||||||
super();
|
super();
|
||||||
init(new AccountModel());
|
init(new RoomAccountModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
public void init(@NonNull AccountModel account) {
|
public void init(@NonNull RoomAccountModel account) {
|
||||||
this.account.setValue(account);
|
this.account.setValue(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
public MutableLiveData<AccountModel> getAccount() {
|
public MutableLiveData<RoomAccountModel> getAccount() {
|
||||||
return account;
|
return account;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void login() {
|
public void login() {
|
||||||
AccountModel account = getAccount().getValue();
|
RoomAccountModel account = getAccount().getValue();
|
||||||
if (account != null && account.getJid() != null && !TextUtils.isEmpty(account.getPassword())) {
|
if (account != null && account.getJid() != null && !TextUtils.isEmpty(account.getPassword())) {
|
||||||
accountRepository.insertAccount(account);
|
accountRepository.insertAccount(account);
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,7 @@ import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
|
|
||||||
import org.mercury_im.messenger.R;
|
import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -45,9 +45,9 @@ public class RosterFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void observeViewModel(RosterViewModel viewModel) {
|
private void observeViewModel(RosterViewModel viewModel) {
|
||||||
viewModel.getRosterEntryList().observe(this, new Observer<List<RosterEntryModel>>() {
|
viewModel.getRosterEntryList().observe(this, new Observer<List<RoomRosterEntryModel>>() {
|
||||||
@Override
|
@Override
|
||||||
public void onChanged(@Nullable List<RosterEntryModel> rosterEntries) {
|
public void onChanged(@Nullable List<RoomRosterEntryModel> rosterEntries) {
|
||||||
if (rosterEntries == null) {
|
if (rosterEntries == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,16 +8,16 @@ import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.mercury_im.messenger.R;
|
import org.mercury_im.messenger.R;
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class RosterRecyclerViewAdapter
|
public class RosterRecyclerViewAdapter
|
||||||
extends RecyclerView.Adapter<RosterRecyclerViewAdapter.RecyclerViewHolder> {
|
extends RecyclerView.Adapter<RosterRecyclerViewAdapter.RecyclerViewHolder> {
|
||||||
|
|
||||||
private List<RosterEntryModel> entryModelList;
|
private List<RoomRosterEntryModel> entryModelList;
|
||||||
|
|
||||||
public RosterRecyclerViewAdapter(List<RosterEntryModel> entryModelList) {
|
public RosterRecyclerViewAdapter(List<RoomRosterEntryModel> entryModelList) {
|
||||||
this.entryModelList = entryModelList;
|
this.entryModelList = entryModelList;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,7 +30,7 @@ public class RosterRecyclerViewAdapter
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
|
public void onBindViewHolder(@NonNull RecyclerViewHolder holder, int position) {
|
||||||
RosterEntryModel model = entryModelList.get(position);
|
RoomRosterEntryModel model = entryModelList.get(position);
|
||||||
holder.jidView.setText(model.getJid().toString());
|
holder.jidView.setText(model.getJid().toString());
|
||||||
holder.nicknameView.setText(model.getNickname());
|
holder.nicknameView.setText(model.getNickname());
|
||||||
holder.itemView.setTag(model);
|
holder.itemView.setTag(model);
|
||||||
|
@ -41,7 +41,7 @@ public class RosterRecyclerViewAdapter
|
||||||
return entryModelList.size();
|
return entryModelList.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setItems(List<RosterEntryModel> rosterEntryModels) {
|
public void setItems(List<RoomRosterEntryModel> rosterEntryModels) {
|
||||||
this.entryModelList = rosterEntryModels;
|
this.entryModelList = rosterEntryModels;
|
||||||
notifyDataSetChanged();
|
notifyDataSetChanged();
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,8 +6,8 @@ import androidx.lifecycle.LiveData;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import org.mercury_im.messenger.MercuryImApplication;
|
import org.mercury_im.messenger.MercuryImApplication;
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.roster.RosterEntryRepository;
|
import org.mercury_im.messenger.persistence.repository.RosterEntryRepository;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -18,7 +18,7 @@ public class RosterViewModel extends AndroidViewModel {
|
||||||
@Inject
|
@Inject
|
||||||
RosterEntryRepository rosterEntryRepository;
|
RosterEntryRepository rosterEntryRepository;
|
||||||
|
|
||||||
private final LiveData<List<RosterEntryModel>> rosterEntryList;
|
private final LiveData<List<RoomRosterEntryModel>> rosterEntryList;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RosterViewModel(@NonNull Application application) {
|
public RosterViewModel(@NonNull Application application) {
|
||||||
|
@ -27,7 +27,7 @@ public class RosterViewModel extends AndroidViewModel {
|
||||||
this.rosterEntryList = rosterEntryRepository.getAllRosterEntries();
|
this.rosterEntryList = rosterEntryRepository.getAllRosterEntries();
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<RosterEntryModel>> getRosterEntryList() {
|
public LiveData<List<RoomRosterEntryModel>> getRosterEntryList() {
|
||||||
return rosterEntryList;
|
return rosterEntryList;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,43 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 19
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
api project(":persistence")
|
||||||
|
|
||||||
|
// Dagger 2 for dependency injection
|
||||||
|
implementation "com.google.dagger:dagger:$daggerVersion"
|
||||||
|
annotationProcessor "com.google.dagger:dagger-compiler:$daggerVersion"
|
||||||
|
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
|
|
||||||
|
// Room
|
||||||
|
api "androidx.room:room-runtime:$roomVersion"
|
||||||
|
annotationProcessor "androidx.room:room-compiler:$roomVersion"
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("org.mercury_im.messenger.persistence.room", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.mercury_im.messenger.persistence.room" />
|
|
@ -1,4 +1,4 @@
|
||||||
package org.mercury_im.messenger.persistence.database;
|
package org.mercury_im.messenger.persistence.room;
|
||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
|
|
||||||
|
@ -6,12 +6,14 @@ import androidx.room.Database;
|
||||||
import androidx.room.Room;
|
import androidx.room.Room;
|
||||||
import androidx.room.RoomDatabase;
|
import androidx.room.RoomDatabase;
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
|
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||||
import org.mercury_im.messenger.persistence.database.dao.RosterEntryDao;
|
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
import org.mercury_im.messenger.persistence.room.dao.RosterEntryDao;
|
||||||
import org.mercury_im.messenger.persistence.database.model.RosterEntryModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
|
|
||||||
@Database(entities = {RosterEntryModel.class, AccountModel.class}, version = 1)
|
@Database(entities = {RoomRosterEntryModel.class, RoomAccountModel.class, RoomMessageModel.class}, version = 1)
|
||||||
public abstract class AppDatabase extends RoomDatabase {
|
public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public static final String DB_NAME = "app_db";
|
public static final String DB_NAME = "app_db";
|
||||||
|
@ -27,5 +29,7 @@ public abstract class AppDatabase extends RoomDatabase {
|
||||||
|
|
||||||
public abstract RosterEntryDao rosterEntryDao();
|
public abstract RosterEntryDao rosterEntryDao();
|
||||||
|
|
||||||
|
public abstract MessageDao messageDao();
|
||||||
|
|
||||||
public abstract AccountDao accountDao();
|
public abstract AccountDao accountDao();
|
||||||
}
|
}
|
|
@ -0,0 +1,44 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.dao;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.annotation.WorkerThread;
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.TypeConverters;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
@TypeConverters(EntityBareJidConverter.class)
|
||||||
|
@WorkerThread
|
||||||
|
public interface AccountDao extends BaseDao<RoomAccountModel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a {@link LiveData} wrapping a {@link List} which contains all
|
||||||
|
* {@link RoomAccountModel Accounts} which are currently stored in the database.
|
||||||
|
*
|
||||||
|
* @return live updating account list
|
||||||
|
*/
|
||||||
|
@Query("select * from accounts")
|
||||||
|
LiveData<List<RoomAccountModel>> getAllAccounts();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the {@link RoomAccountModel Account} which is identified by the given id.
|
||||||
|
*
|
||||||
|
* @param id id of the account
|
||||||
|
* @return account or null
|
||||||
|
*/
|
||||||
|
@Query("select * from accounts where id = :id")
|
||||||
|
LiveData<RoomAccountModel> getAccountById(long id);
|
||||||
|
|
||||||
|
@Query("select * from accounts where jid = :jid")
|
||||||
|
LiveData<RoomAccountModel> getAccountByJid(EntityBareJid jid);
|
||||||
|
}
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.dao;
|
||||||
|
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Update;
|
||||||
|
|
||||||
|
public interface BaseDao<T> {
|
||||||
|
|
||||||
|
@Insert
|
||||||
|
long insert(T entity);
|
||||||
|
|
||||||
|
@Update
|
||||||
|
void update(T entity);
|
||||||
|
|
||||||
|
@Delete
|
||||||
|
void delete(T entity);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.dao;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityFullJidConverter;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
@TypeConverters(EntityFullJidConverter.class)
|
||||||
|
public interface MessageDao extends BaseDao<RoomMessageModel> {
|
||||||
|
|
||||||
|
@Query("SELECT * FROM messages WHERE accountId=:accountId ORDER BY sendDate DESC")
|
||||||
|
LiveData<List<RoomMessageModel>> getAllMessagesOf(long accountId);
|
||||||
|
|
||||||
|
@Query("SELECT * FROM messages WHERE accountId=:accountId AND `from`=:sender ORDER BY sendDate DESC")
|
||||||
|
LiveData<List<RoomMessageModel>> getAllMessagesFrom(long accountId, EntityFullJid sender);
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,35 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.dao;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.room.Dao;
|
||||||
|
import androidx.room.Delete;
|
||||||
|
import androidx.room.Insert;
|
||||||
|
import androidx.room.Query;
|
||||||
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.RosterEntryModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import static androidx.room.OnConflictStrategy.REPLACE;
|
||||||
|
|
||||||
|
@Dao
|
||||||
|
@TypeConverters(EntityBareJidConverter.class)
|
||||||
|
public interface RosterEntryDao extends BaseDao<RoomRosterEntryModel> {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return a {@link LiveData} wrapping a {@link List} of all {@link RoomRosterEntryModel RosterEntries}
|
||||||
|
* which are currently found in the database.
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
@Query("select * from roster")
|
||||||
|
LiveData<List<RoomRosterEntryModel>> getAllRosterEntries();
|
||||||
|
|
||||||
|
@Query("select * from roster where id = :id")
|
||||||
|
RoomRosterEntryModel getRosterEntryById(long id);
|
||||||
|
|
||||||
|
@Query("select * from roster where accountId = :accountId")
|
||||||
|
LiveData<List<RoomRosterEntryModel>> getRosterEntriesForAccount(long accountId);
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.mercury_im.messenger.persistence.database.model;
|
package org.mercury_im.messenger.persistence.room.model;
|
||||||
|
|
||||||
|
|
||||||
import androidx.room.ColumnInfo;
|
import androidx.room.ColumnInfo;
|
||||||
|
@ -7,10 +7,11 @@ import androidx.room.PrimaryKey;
|
||||||
import androidx.room.TypeConverters;
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||||
|
|
||||||
@Entity
|
@Entity(tableName = "accounts")
|
||||||
public class AccountModel implements Account {
|
public class RoomAccountModel implements AccountModel {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
@ColumnInfo(name = "id")
|
@ColumnInfo(name = "id")
|
||||||
|
@ -26,6 +27,16 @@ public class AccountModel implements Account {
|
||||||
@ColumnInfo(name = "enabled")
|
@ColumnInfo(name = "enabled")
|
||||||
private boolean enabled;
|
private boolean enabled;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public EntityBareJid getJid() {
|
public EntityBareJid getJid() {
|
||||||
return jid;
|
return jid;
|
|
@ -0,0 +1,101 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.model;
|
||||||
|
|
||||||
|
import androidx.room.Entity;
|
||||||
|
import androidx.room.ForeignKey;
|
||||||
|
import androidx.room.PrimaryKey;
|
||||||
|
import androidx.room.TypeConverter;
|
||||||
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
import org.mercury_im.messenger.persistence.model.MessageModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.DateConverter;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityFullJidConverter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
import static androidx.room.ForeignKey.CASCADE;
|
||||||
|
|
||||||
|
@Entity(tableName = "messages", foreignKeys = @ForeignKey(entity = RoomAccountModel.class,
|
||||||
|
parentColumns = "id", childColumns = "accountId", onDelete = CASCADE))
|
||||||
|
public class RoomMessageModel implements MessageModel {
|
||||||
|
|
||||||
|
@PrimaryKey(autoGenerate = true)
|
||||||
|
private long id;
|
||||||
|
|
||||||
|
private long accountId;
|
||||||
|
|
||||||
|
private String body;
|
||||||
|
|
||||||
|
@TypeConverters(DateConverter.class)
|
||||||
|
private Date sendDate;
|
||||||
|
|
||||||
|
@TypeConverters(EntityFullJidConverter.class)
|
||||||
|
private EntityFullJid from;
|
||||||
|
|
||||||
|
@TypeConverters(EntityFullJidConverter.class)
|
||||||
|
private EntityFullJid to;
|
||||||
|
|
||||||
|
public RoomMessageModel() {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setId(long val) {
|
||||||
|
this.id = val;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getAccountId() {
|
||||||
|
return accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setAccountId(long accountId) {
|
||||||
|
this.accountId = accountId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getBody() {
|
||||||
|
return body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setBody(String body) {
|
||||||
|
this.body = body;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Date getSendDate() {
|
||||||
|
return sendDate;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setSendDate(Date date) {
|
||||||
|
this.sendDate = date;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityFullJid getFrom() {
|
||||||
|
return from;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setFrom(EntityFullJid sender) {
|
||||||
|
this.from = sender;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public EntityFullJid getTo() {
|
||||||
|
return to;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setTo(EntityFullJid recipient) {
|
||||||
|
this.to = recipient;
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.mercury_im.messenger.persistence.database.model;
|
package org.mercury_im.messenger.persistence.room.model;
|
||||||
|
|
||||||
|
|
||||||
import androidx.room.Entity;
|
import androidx.room.Entity;
|
||||||
|
@ -7,20 +7,21 @@ import androidx.room.PrimaryKey;
|
||||||
import androidx.room.TypeConverters;
|
import androidx.room.TypeConverters;
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.mercury_im.messenger.persistence.database.type_converter.EntityBareJidConverter;
|
import org.mercury_im.messenger.persistence.model.RosterEntryModel;
|
||||||
|
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
|
||||||
|
|
||||||
import static androidx.room.ForeignKey.CASCADE;
|
import static androidx.room.ForeignKey.CASCADE;
|
||||||
|
|
||||||
@Entity(foreignKeys = @ForeignKey(entity = AccountModel.class,
|
@Entity(tableName = "roster", foreignKeys = @ForeignKey(entity = RoomAccountModel.class,
|
||||||
parentColumns = "id",
|
parentColumns = "id",
|
||||||
childColumns = "accountId",
|
childColumns = "accountId",
|
||||||
onDelete = CASCADE))
|
onDelete = CASCADE))
|
||||||
public class RosterEntryModel {
|
public class RoomRosterEntryModel implements RosterEntryModel {
|
||||||
|
|
||||||
@PrimaryKey(autoGenerate = true)
|
@PrimaryKey(autoGenerate = true)
|
||||||
public int id;
|
public long id;
|
||||||
|
|
||||||
private int accountId;
|
private long accountId;
|
||||||
|
|
||||||
@TypeConverters(EntityBareJidConverter.class)
|
@TypeConverters(EntityBareJidConverter.class)
|
||||||
private EntityBareJid jid;
|
private EntityBareJid jid;
|
||||||
|
@ -29,38 +30,54 @@ public class RosterEntryModel {
|
||||||
|
|
||||||
private String nickname;
|
private String nickname;
|
||||||
|
|
||||||
|
public RoomRosterEntryModel(EntityBareJid jid, String rosterName, String nickname) {
|
||||||
public RosterEntryModel(EntityBareJid jid, String rosterName, String nickname) {
|
|
||||||
this.jid = jid;
|
this.jid = jid;
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
this.rosterName = rosterName;
|
this.rosterName = rosterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getId() {
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setId(long id) {
|
||||||
|
this.id = id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public EntityBareJid getJid() {
|
public EntityBareJid getJid() {
|
||||||
return jid;
|
return jid;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getRosterName() {
|
public String getRosterName() {
|
||||||
return rosterName;
|
return rosterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setRosterName(String rosterName) {
|
public void setRosterName(String rosterName) {
|
||||||
this.rosterName = rosterName;
|
this.rosterName = rosterName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public String getNickname() {
|
public String getNickname() {
|
||||||
return nickname;
|
return nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void setNickname(String nickname) {
|
public void setNickname(String nickname) {
|
||||||
this.nickname = nickname;
|
this.nickname = nickname;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getAccountId() {
|
@Override
|
||||||
|
public long getAccountId() {
|
||||||
return accountId;
|
return accountId;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAccountId(int accountId) {
|
@Override
|
||||||
|
public void setAccountId(long accountId) {
|
||||||
this.accountId = accountId;
|
this.accountId = accountId;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,37 +1,39 @@
|
||||||
package org.mercury_im.messenger.persistence.repository.account;
|
package org.mercury_im.messenger.persistence.room.repository;
|
||||||
|
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
|
|
||||||
import org.mercury_im.messenger.persistence.database.dao.AccountDao;
|
import androidx.lifecycle.LiveData;
|
||||||
import org.mercury_im.messenger.persistence.database.model.AccountModel;
|
|
||||||
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
|
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
public class AccountRepositoryImpl implements AccountRepository {
|
public class IAccountRepository implements AccountRepository<RoomAccountModel> {
|
||||||
|
|
||||||
private final AccountDao accountDao;
|
private final AccountDao accountDao;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public AccountRepositoryImpl(AccountDao accountDao) {
|
public IAccountRepository(AccountDao accountDao) {
|
||||||
this.accountDao = accountDao;
|
this.accountDao = accountDao;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveData<AccountModel> getAccount(long accountId) {
|
public LiveData<RoomAccountModel> getAccount(long accountId) {
|
||||||
return accountDao.getAccountById(accountId);
|
return accountDao.getAccountById(accountId);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public LiveData<List<AccountModel>> getAllAccounts() {
|
public LiveData<List<RoomAccountModel>> getAllAccounts() {
|
||||||
return accountDao.getAllAccounts();
|
return accountDao.getAllAccounts();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public long insertAccount(AccountModel accountModel) {
|
public long insertAccount(RoomAccountModel accountModel) {
|
||||||
InsertAsyncTask task = new InsertAsyncTask(accountDao);
|
InsertAsyncTask task = new InsertAsyncTask(accountDao);
|
||||||
try {
|
try {
|
||||||
return task.execute(accountModel).get();
|
return task.execute(accountModel).get();
|
||||||
|
@ -43,7 +45,7 @@ public class AccountRepositoryImpl implements AccountRepository {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class InsertAsyncTask extends AsyncTask<AccountModel, Void, Long> {
|
private static class InsertAsyncTask extends AsyncTask<RoomAccountModel, Void, Long> {
|
||||||
|
|
||||||
private final AccountDao accountDao;
|
private final AccountDao accountDao;
|
||||||
|
|
||||||
|
@ -52,15 +54,15 @@ public class AccountRepositoryImpl implements AccountRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected Long doInBackground(AccountModel... accountModels) {
|
protected Long doInBackground(RoomAccountModel... accountModels) {
|
||||||
for (AccountModel accountModel : accountModels) {
|
for (RoomAccountModel accountModel : accountModels) {
|
||||||
return accountDao.insertAccount(accountModel);
|
return accountDao.insert(accountModel);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class QueryAsyncTask extends AsyncTask<Long, Void, LiveData<AccountModel>> {
|
private static class QueryAsyncTask extends AsyncTask<Long, Void, LiveData<RoomAccountModel>> {
|
||||||
|
|
||||||
private final AccountDao accountDao;
|
private final AccountDao accountDao;
|
||||||
|
|
||||||
|
@ -69,7 +71,7 @@ public class AccountRepositoryImpl implements AccountRepository {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected LiveData<AccountModel> doInBackground(Long... longs) {
|
protected LiveData<RoomAccountModel> doInBackground(Long... longs) {
|
||||||
return accountDao.getAccountById(longs[0]);
|
return accountDao.getAccountById(longs[0]);
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.repository;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.repository.MessageRepository;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
|
||||||
|
|
||||||
|
public class IMessageRepository implements MessageRepository<RoomMessageModel> {
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.repository;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.RosterEntryModel;
|
||||||
|
import org.mercury_im.messenger.persistence.repository.RosterEntryRepository;
|
||||||
|
import org.mercury_im.messenger.persistence.room.dao.RosterEntryDao;
|
||||||
|
import org.mercury_im.messenger.persistence.room.model.RoomRosterEntryModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class IRosterEntryRepository implements RosterEntryRepository<RoomRosterEntryModel> {
|
||||||
|
|
||||||
|
private final RosterEntryDao rosterEntryDao;
|
||||||
|
|
||||||
|
public IRosterEntryRepository(RosterEntryDao dao) {
|
||||||
|
this.rosterEntryDao = dao;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LiveData<List<RoomRosterEntryModel>> getAllRosterEntries() {
|
||||||
|
return rosterEntryDao.getAllRosterEntries();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void updateOrInsertRosterEntry(RoomRosterEntryModel rosterEntryModel) {
|
||||||
|
rosterEntryDao.insert(rosterEntryModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.mercury_im.messenger.persistence.database.type_converter;
|
package org.mercury_im.messenger.persistence.room.type_converter;
|
||||||
|
|
||||||
import androidx.room.TypeConverter;
|
import androidx.room.TypeConverter;
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.type_converter;
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public class DateConverter {
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static long toLong(Date date) {
|
||||||
|
return date.getTime();
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static Date toDate(long lon) {
|
||||||
|
return new Date(lon);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package org.mercury_im.messenger.persistence.database.type_converter;
|
package org.mercury_im.messenger.persistence.room.type_converter;
|
||||||
|
|
||||||
import androidx.room.TypeConverter;
|
import androidx.room.TypeConverter;
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room.type_converter;
|
||||||
|
|
||||||
|
import androidx.room.TypeConverter;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
import org.jxmpp.jid.impl.JidCreate;
|
||||||
|
import org.jxmpp.stringprep.XmppStringprepException;
|
||||||
|
|
||||||
|
public class EntityFullJidConverter {
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static String toString(EntityFullJid jid) {
|
||||||
|
return jid != null ? jid.toString() : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@TypeConverter
|
||||||
|
public static EntityFullJid toEntityFullJid(String string) {
|
||||||
|
try {
|
||||||
|
return string != null ? JidCreate.entityFullFrom(string) : null;
|
||||||
|
} catch (XmppStringprepException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">RoomDatabase</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.mercury_im.messenger.persistence.room;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,40 @@
|
||||||
|
apply plugin: 'com.android.library'
|
||||||
|
|
||||||
|
android {
|
||||||
|
compileSdkVersion 28
|
||||||
|
|
||||||
|
|
||||||
|
defaultConfig {
|
||||||
|
minSdkVersion 19
|
||||||
|
targetSdkVersion 28
|
||||||
|
versionCode 1
|
||||||
|
versionName "1.0"
|
||||||
|
|
||||||
|
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
buildTypes {
|
||||||
|
release {
|
||||||
|
minifyEnabled false
|
||||||
|
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
|
||||||
|
api('org.jxmpp:jxmpp-jid') {
|
||||||
|
version {
|
||||||
|
prefer 'latest.release'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||||
|
|
||||||
|
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||||
|
testImplementation 'junit:junit:4.12'
|
||||||
|
androidTestImplementation 'androidx.test:runner:1.1.1'
|
||||||
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
# Add project specific ProGuard rules here.
|
||||||
|
# You can control the set of applied configuration files using the
|
||||||
|
# proguardFiles setting in build.gradle.
|
||||||
|
#
|
||||||
|
# For more details, see
|
||||||
|
# http://developer.android.com/guide/developing/tools/proguard.html
|
||||||
|
|
||||||
|
# If your project uses WebView with JS, uncomment the following
|
||||||
|
# and specify the fully qualified class name to the JavaScript interface
|
||||||
|
# class:
|
||||||
|
#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
|
||||||
|
# public *;
|
||||||
|
#}
|
||||||
|
|
||||||
|
# Uncomment this to preserve the line number information for
|
||||||
|
# debugging stack traces.
|
||||||
|
#-keepattributes SourceFile,LineNumberTable
|
||||||
|
|
||||||
|
# If you keep the line number information, uncomment this to
|
||||||
|
# hide the original source file name.
|
||||||
|
#-renamesourcefileattribute SourceFile
|
|
@ -0,0 +1,27 @@
|
||||||
|
package org.mercury_im.messenger.persistence;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
|
||||||
|
import androidx.test.InstrumentationRegistry;
|
||||||
|
import androidx.test.runner.AndroidJUnit4;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Instrumented test, which will execute on an Android device.
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
@RunWith(AndroidJUnit4.class)
|
||||||
|
public class ExampleInstrumentedTest {
|
||||||
|
@Test
|
||||||
|
public void useAppContext() {
|
||||||
|
// Context of the app under test.
|
||||||
|
Context appContext = InstrumentationRegistry.getTargetContext();
|
||||||
|
|
||||||
|
assertEquals("org.mercury_im.messenger.persistence.test", appContext.getPackageName());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,2 @@
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="org.mercury_im.messenger.persistence" />
|
|
@ -1,8 +1,12 @@
|
||||||
package org.mercury_im.messenger.persistence.database.model;
|
package org.mercury_im.messenger.persistence.model;
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
|
||||||
public interface Account {
|
public interface AccountModel {
|
||||||
|
|
||||||
|
long getId();
|
||||||
|
|
||||||
|
void setId(long id);
|
||||||
|
|
||||||
String getPassword();
|
String getPassword();
|
||||||
|
|
|
@ -0,0 +1,32 @@
|
||||||
|
package org.mercury_im.messenger.persistence.model;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityFullJid;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
|
|
||||||
|
public interface MessageModel {
|
||||||
|
|
||||||
|
long getId();
|
||||||
|
|
||||||
|
void setId(long val);
|
||||||
|
|
||||||
|
long getAccountId();
|
||||||
|
|
||||||
|
void setAccountId(long accountId);
|
||||||
|
|
||||||
|
String getBody();
|
||||||
|
|
||||||
|
void setBody(String body);
|
||||||
|
|
||||||
|
Date getSendDate();
|
||||||
|
|
||||||
|
void setSendDate(Date date);
|
||||||
|
|
||||||
|
EntityFullJid getFrom();
|
||||||
|
|
||||||
|
void setFrom(EntityFullJid sender);
|
||||||
|
|
||||||
|
EntityFullJid getTo();
|
||||||
|
|
||||||
|
void setTo(EntityFullJid recipient);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
package org.mercury_im.messenger.persistence.model;
|
||||||
|
|
||||||
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
|
|
||||||
|
public interface RosterEntryModel {
|
||||||
|
|
||||||
|
long getId();
|
||||||
|
|
||||||
|
void setId(long id);
|
||||||
|
|
||||||
|
EntityBareJid getJid();
|
||||||
|
|
||||||
|
String getRosterName();
|
||||||
|
|
||||||
|
void setRosterName(String rosterName);
|
||||||
|
|
||||||
|
String getNickname();
|
||||||
|
|
||||||
|
void setNickname(String nickname);
|
||||||
|
|
||||||
|
long getAccountId();
|
||||||
|
|
||||||
|
void setAccountId(long accountId);
|
||||||
|
}
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.mercury_im.messenger.persistence.repository;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface AccountRepository<E extends AccountModel> {
|
||||||
|
|
||||||
|
LiveData<E> getAccount(long accountId);
|
||||||
|
|
||||||
|
LiveData<List<E>> getAllAccounts();
|
||||||
|
|
||||||
|
long insertAccount(E accountModel);
|
||||||
|
}
|
|
@ -0,0 +1,7 @@
|
||||||
|
package org.mercury_im.messenger.persistence.repository;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.MessageModel;
|
||||||
|
|
||||||
|
public interface MessageRepository<E extends MessageModel> {
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,14 @@
|
||||||
|
package org.mercury_im.messenger.persistence.repository;
|
||||||
|
|
||||||
|
import androidx.lifecycle.LiveData;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.RosterEntryModel;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public interface RosterEntryRepository<E extends RosterEntryModel> {
|
||||||
|
|
||||||
|
LiveData<List<E>> getAllRosterEntries();
|
||||||
|
|
||||||
|
void updateOrInsertRosterEntry(E rosterEntryModel);
|
||||||
|
}
|
|
@ -0,0 +1,3 @@
|
||||||
|
<resources>
|
||||||
|
<string name="app_name">Persistence</string>
|
||||||
|
</resources>
|
|
@ -0,0 +1,17 @@
|
||||||
|
package org.mercury_im.messenger.persistence;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.Assert.*;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Example local unit test, which will execute on the development machine (host).
|
||||||
|
*
|
||||||
|
* @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
|
||||||
|
*/
|
||||||
|
public class ExampleUnitTest {
|
||||||
|
@Test
|
||||||
|
public void addition_isCorrect() {
|
||||||
|
assertEquals(4, 2 + 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1 +1 @@
|
||||||
include ':app'
|
include ':app', ':xmpp_core', ':persistence-room', ':persistence'
|
||||||
|
|
|
@ -0,0 +1 @@
|
||||||
|
/build
|
|
@ -0,0 +1,26 @@
|
||||||
|
apply plugin: 'java-library'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
// Smack
|
||||||
|
// Not all of those are needed, but it may be a good idea to define those versions explicitly
|
||||||
|
api "org.igniterealtime.smack:smack-android:$smackAndroidVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-android-extensions:$smackAndroidExtensionsVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-core:$smackCoreVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-experimental:$smackExperimentalVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-extensions:$smackExtensionsVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-im:$smackImVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-omemo:$smackOmemoVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-omemo-signal:$smackOmemoSignalVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-openpgp:$smackOpenPGPVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-resolver-minidns:$smackResolverMiniDnsVersion"
|
||||||
|
api "org.igniterealtime.smack:smack-tcp:$smackTcpVersion"
|
||||||
|
|
||||||
|
// Exclude XmlPullParser from Smack dependencies, as its now provided by Android
|
||||||
|
// https://stackoverflow.com/questions/48488563/gradle-xpp3-error/48746294#48746294
|
||||||
|
configurations {
|
||||||
|
all*.exclude group: 'xpp3', module: 'xpp3'
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
sourceCompatibility = "8"
|
||||||
|
targetCompatibility = "8"
|
|
@ -0,0 +1,16 @@
|
||||||
|
package org.mercury_im.xmpp_core;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.XMPPConnection;
|
||||||
|
|
||||||
|
public class MercuryConnection {
|
||||||
|
|
||||||
|
private final XMPPConnection connection;
|
||||||
|
|
||||||
|
public MercuryConnection(XMPPConnection connection) {
|
||||||
|
this.connection = connection;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XMPPConnection getConnection() {
|
||||||
|
return connection;
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue