From fafd8b9f6f5dda6dac4b3981b7a9bf9e67765f4c Mon Sep 17 00:00:00 2001 From: Paul Schaub Date: Mon, 10 Jun 2019 02:52:08 +0200 Subject: [PATCH] Temp --- app/build.gradle | 7 +- app/src/main/AndroidManifest.xml | 3 +- .../service/XmppConnectionService.java | 41 +++++++-- .../service/XmppConnectionServiceBinder.java | 7 -- .../ui/roster/RosterRecyclerViewAdapter.java | 2 +- .../main/res/layout/view_message_text_in.xml | 10 +-- .../main/res/layout/view_message_text_out.xml | 12 ++- app/src/main/res/values/strings.xml | 24 +++-- build.gradle | 2 +- persistence-room/README.md | 31 +++++++ .../1.json | 89 ++++++++++++------ .../persistence/room/dao/BaseDao.java | 10 ++- .../persistence/room/dao/ChatDao.java | 14 ++- .../persistence/room/dao/ContactDao.java | 7 +- .../room/model/RoomContactModel.java | 90 ++++++++++--------- .../room/model/RoomMessageModel.java | 31 ++++++- .../room/model/RoomXmppIdentityModel.java | 36 ++++++-- .../room/repository/IChatRepository.java | 44 +++++++-- persistence/README.md | 19 ++++ .../persistence/model/ChatModel.java | 2 - .../persistence/model/ContactModel.java | 12 +-- .../repository/ChatRepository.java | 17 +++- version.gradle | 2 + .../AndroidMercuryConnection.java | 1 + xmpp_core/build.gradle | 4 +- .../xmpp_core/MercuryConnection.java | 6 +- 26 files changed, 367 insertions(+), 156 deletions(-) delete mode 100644 app/src/main/java/org/mercury_im/messenger/service/XmppConnectionServiceBinder.java create mode 100644 persistence-room/README.md create mode 100644 persistence/README.md diff --git a/app/build.gradle b/app/build.gradle index 7b5195c..7042a5b 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -99,9 +99,12 @@ dependencies { implementation 'androidx.recyclerview:recyclerview:1.0.0' testImplementation 'junit:junit:4.12' - androidTestImplementation 'androidx.test:runner:1.1.1' - androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1' + androidTestImplementation 'androidx.test:runner:1.2.0' + androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' // circular image viewer for avatars implementation 'de.hdodenhof:circleimageview:2.2.0' + + // Smack Android + implementation "org.igniterealtime.smack:smack-android-extensions:$smackAndroidExtensionsVersion" } diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 9809d9d..ac6970c 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -24,11 +24,10 @@ android:theme="@style/AppTheme.NoActionBar"/> - 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 8495839..4743c63 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 @@ -15,6 +15,7 @@ import android.util.Log; 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; @@ -31,6 +32,7 @@ import org.jivesoftware.smack.roster.RosterEntry; import org.jivesoftware.smack.roster.RosterLoadedListener; 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.mercury_im.messenger.MercuryImApplication; import org.mercury_im.messenger.Notifications; @@ -96,11 +98,10 @@ public class XmppConnectionService extends Service { private Handler uiHandler; - @Nullable + @NonNull @Override public final IBinder onBind(Intent intent) { - // We are a started service, so we don't provide a binding and always return null. - return null; + return new Binder(this); } @Override @@ -108,6 +109,20 @@ public class XmppConnectionService extends Service { super.onCreate(); Log.d(TAG, "onCreate()"); MercuryImApplication.getApplication().getAppComponent().inject(this); + + // Begin life cycle of Ping Manager. + // The Manager will automatically detect newly created connections and ping the server + // every half hour if necessary. + ServerPingWithAlarmManager.onCreate(this); + } + + @Override + public void onDestroy() { + super.onDestroy(); + Log.d(TAG, "onDestroy()"); + + // End life cycle of Ping Manager. + ServerPingWithAlarmManager.onDestroy(); } @Override @@ -240,9 +255,10 @@ public class XmppConnectionService extends Service { Set entries = roster.getEntries(); for (RosterEntry e : entries) { Log.d(TAG, "Inserting Roster entry " + e.getJid().toString()); - RoomContactModel m = new RoomContactModel(e.getJid().asEntityBareJidIfPossible(), e.getName(), e.getName()); - m.setAccountId(accountId); - rosterRepository.updateOrInsertRosterEntry(m); + + RoomContactModel contact = new RoomContactModel(); + contact.setAccountId(accountId); + // TODO: Fix } } @@ -281,4 +297,17 @@ public class XmppConnectionService extends Service { public void putConnection(int accountId, XMPPConnection connection) { connections.put(accountId, connection); } + + public class Binder extends android.os.Binder { + + private final XmppConnectionService service; + + public Binder(XmppConnectionService service) { + this.service = service; + } + + public XmppConnectionService getService() { + return service; + } + } } diff --git a/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionServiceBinder.java b/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionServiceBinder.java deleted file mode 100644 index eebb9f5..0000000 --- a/app/src/main/java/org/mercury_im/messenger/service/XmppConnectionServiceBinder.java +++ /dev/null @@ -1,7 +0,0 @@ -package org.mercury_im.messenger.service; - -import android.os.Binder; - -public class XmppConnectionServiceBinder extends Binder { - -} 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 1526541..0f92d5b 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 @@ -43,7 +43,7 @@ public class RosterRecyclerViewAdapter // switch (holder.getItemViewType()) { // case RosterItemViewHolder.TYPE: RosterItemViewHolder rosterItem = (RosterItemViewHolder) holder; - rosterItem.jidView.setText(model.getJid().toString()); + //rosterItem.jidView.setText(model.getJid().toString()); rosterItem.nicknameView.setText(model.getNickname()); rosterItem.itemView.setTag(model); // break; diff --git a/app/src/main/res/layout/view_message_text_in.xml b/app/src/main/res/layout/view_message_text_in.xml index 16a0cdb..e769a69 100644 --- a/app/src/main/res/layout/view_message_text_in.xml +++ b/app/src/main/res/layout/view_message_text_in.xml @@ -1,6 +1,5 @@ - - \ No newline at end of file diff --git a/app/src/main/res/layout/view_message_text_out.xml b/app/src/main/res/layout/view_message_text_out.xml index 069130b..f9eb97d 100644 --- a/app/src/main/res/layout/view_message_text_out.xml +++ b/app/src/main/res/layout/view_message_text_out.xml @@ -1,11 +1,14 @@ - + android:layout_height="match_parent"> - Mercury + + + MainActivity + + Log in - XMPP Address Password Sign in @@ -10,11 +14,21 @@ This password is too short This password is incorrect This field is required + Show Password + + Settings + Settings + + Not yet implemented! - + + Foreground Service + Service that keeps the app running + + General @@ -84,9 +98,5 @@ Silent Vibrate - MainActivity - Settings - Foreground Service - Service that keeps the app running - Show Password + diff --git a/build.gradle b/build.gradle index fc9436b..41794c9 100644 --- a/build.gradle +++ b/build.gradle @@ -7,7 +7,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:3.4.0' + classpath 'com.android.tools.build:gradle:3.4.1' // NOTE: Do not place your application dependencies here; they belong diff --git a/persistence-room/README.md b/persistence-room/README.md new file mode 100644 index 0000000..f2ee83d --- /dev/null +++ b/persistence-room/README.md @@ -0,0 +1,31 @@ +# Room Persistence Layer of Mercury + +This Android Module contains an implementation of the interfaces of the `persistence` module. +In particular it defines SQL schemes and provides DAOs as well as implementations of Model classes +and Repositories that utilize the [Room Database Framework](https://developer.android.com/topic/libraries/architecture/room). + +## Packages and Classes + +### `AppDatabase` +defines what makes up the database itself. It lists all available entities and provides dao classes. + +### `dao` package +Contains data access objects (DAOs) which provide CRUD methods (Create, Read, Update, Delete) for +all the models. + +Note, that the `BaseDao` interface already defines methods for creating, updating and deleting +entities and is extended by most DAO classes. + +### `model` package +Contains classes that represent the data itself in form of models. + +### `repository` package +Contains implementations of data repositories. Repositories are single sources of truth and provide +a user-friendly separation layer between the application and the DAOs. + +Ideally this layer would also provide access to the XMPP domain, but this is still subject to +discussion. + +### `type_converter` package +Contains Room specific type converter that convert non-basic data types into basic data types which +can be handled by the database and vice versa. \ No newline at end of file diff --git a/persistence-room/schemas/org.mercury_im.messenger.persistence.room.AppDatabase/1.json b/persistence-room/schemas/org.mercury_im.messenger.persistence.room.AppDatabase/1.json index a9307af..24dea8b 100644 --- a/persistence-room/schemas/org.mercury_im.messenger.persistence.room.AppDatabase/1.json +++ b/persistence-room/schemas/org.mercury_im.messenger.persistence.room.AppDatabase/1.json @@ -2,12 +2,18 @@ "formatVersion": 1, "database": { "version": 1, - "identityHash": "8cbb04481870b8e1320677566696f9ad", + "identityHash": "fb56e6a5615c4d1baa6c08d919560267", "entities": [ { - "tableName": "RoomContactModel", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `jid` TEXT NOT NULL, `rosterName` TEXT, `nickname` TEXT, `avatarFile` TEXT, PRIMARY KEY(`accountId`, `jid`), FOREIGN KEY(`accountId`) REFERENCES `accounts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`accountId`, `jid`) REFERENCES `entities`(`accountId`, `jid`) ON UPDATE NO ACTION ON DELETE RESTRICT )", + "tableName": "contacts", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `xmppId` INTEGER NOT NULL, `rosterName` TEXT, `nickname` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `accounts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`xmppId`) REFERENCES `entities`(`id`) ON UPDATE NO ACTION ON DELETE RESTRICT )", "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, { "fieldPath": "accountId", "columnName": "accountId", @@ -15,9 +21,9 @@ "notNull": true }, { - "fieldPath": "jid", - "columnName": "jid", - "affinity": "TEXT", + "fieldPath": "xmppIdentityId", + "columnName": "xmppId", + "affinity": "INTEGER", "notNull": true }, { @@ -31,30 +37,38 @@ "columnName": "nickname", "affinity": "TEXT", "notNull": false - }, - { - "fieldPath": "avatarFile", - "columnName": "avatarFile", - "affinity": "TEXT", - "notNull": false } ], "primaryKey": { "columnNames": [ - "accountId", - "jid" + "id" ], "autoGenerate": false }, "indices": [ { - "name": "index_RoomContactModel_accountId_jid", - "unique": true, + "name": "index_contacts_id", + "unique": false, "columnNames": [ - "accountId", - "jid" + "id" ], - "createSql": "CREATE UNIQUE INDEX `index_RoomContactModel_accountId_jid` ON `${TABLE_NAME}` (`accountId`, `jid`)" + "createSql": "CREATE INDEX `index_contacts_id` ON `${TABLE_NAME}` (`id`)" + }, + { + "name": "index_contacts_accountId", + "unique": false, + "columnNames": [ + "accountId" + ], + "createSql": "CREATE INDEX `index_contacts_accountId` ON `${TABLE_NAME}` (`accountId`)" + }, + { + "name": "index_contacts_xmppId", + "unique": false, + "columnNames": [ + "xmppId" + ], + "createSql": "CREATE INDEX `index_contacts_xmppId` ON `${TABLE_NAME}` (`xmppId`)" } ], "foreignKeys": [ @@ -74,12 +88,10 @@ "onDelete": "RESTRICT", "onUpdate": "NO ACTION", "columns": [ - "accountId", - "jid" + "xmppId" ], "referencedColumns": [ - "accountId", - "jid" + "id" ] } ] @@ -186,6 +198,14 @@ "id" ], "createSql": "CREATE INDEX `index_messages_id` ON `${TABLE_NAME}` (`id`)" + }, + { + "name": "index_messages_accountId", + "unique": false, + "columnNames": [ + "accountId" + ], + "createSql": "CREATE INDEX `index_messages_accountId` ON `${TABLE_NAME}` (`accountId`)" } ], "foreignKeys": [ @@ -204,8 +224,14 @@ }, { "tableName": "entities", - "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`accountId` INTEGER NOT NULL, `jid` TEXT NOT NULL, `avatarFile` TEXT, PRIMARY KEY(`accountId`, `jid`), FOREIGN KEY(`accountId`) REFERENCES `accounts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", + "createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`id` INTEGER NOT NULL, `accountId` INTEGER NOT NULL, `jid` TEXT NOT NULL, `avatar` TEXT, PRIMARY KEY(`id`), FOREIGN KEY(`accountId`) REFERENCES `accounts`(`id`) ON UPDATE NO ACTION ON DELETE CASCADE )", "fields": [ + { + "fieldPath": "id", + "columnName": "id", + "affinity": "INTEGER", + "notNull": true + }, { "fieldPath": "accountId", "columnName": "accountId", @@ -220,19 +246,26 @@ }, { "fieldPath": "avatarFile", - "columnName": "avatarFile", + "columnName": "avatar", "affinity": "TEXT", "notNull": false } ], "primaryKey": { "columnNames": [ - "accountId", - "jid" + "id" ], "autoGenerate": false }, "indices": [ + { + "name": "index_entities_id", + "unique": false, + "columnNames": [ + "id" + ], + "createSql": "CREATE INDEX `index_entities_id` ON `${TABLE_NAME}` (`id`)" + }, { "name": "index_entities_accountId_jid", "unique": true, @@ -261,7 +294,7 @@ "views": [], "setupQueries": [ "CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)", - "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, \"8cbb04481870b8e1320677566696f9ad\")" + "INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fb56e6a5615c4d1baa6c08d919560267')" ] } } \ No newline at end of file diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/BaseDao.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/BaseDao.java index 4cb877a..082e775 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/BaseDao.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/BaseDao.java @@ -10,8 +10,14 @@ public interface BaseDao { long insert(T entity); @Update - void upddate(T... entity); + void update(T entity); + + @Update + void update(T[] entities); @Delete - void delete(T... entity); + void delete(T entity); + + @Delete + void delete(T[] entities); } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ChatDao.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ChatDao.java index b67bb0a..edda80e 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ChatDao.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ChatDao.java @@ -4,17 +4,25 @@ import androidx.lifecycle.LiveData; import androidx.room.Query; import org.jxmpp.jid.EntityBareJid; +import org.mercury_im.messenger.persistence.model.XmppIdentityModel; import org.mercury_im.messenger.persistence.room.model.RoomChatModel; import java.util.List; public interface ChatDao extends BaseDao { - @Query("SELECT * FROM RoomChatModel") + @Query("SELECT * FROM chats") LiveData> getAllChats(); - @Query("SELECT * FROM RoomChatModel WHERE ") - LiveData getChatWith(EntityBareJid contact); + @Query("SELECT chats.* FROM chats JOIN entities WHERE accountId = :accountId") + LiveData> getAllChatsOf(long accountId); + @Query("SELECT * FROM chats WHERE xmppId = :identityId") + LiveData getChatWithIdentity(long identityId); + @Query("SELECT chats.* FROM chats JOIN entities WHERE accountId = :accountId AND jid = :jid") + LiveData getChatWithJid(long accountId, EntityBareJid jid); + + @Query("SELECT * FROM chats JOIN contacts WHERE contacts.id = :contactId") + LiveData getChatWithContact(long contactId); } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ContactDao.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ContactDao.java index 5dc909b..be770a6 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ContactDao.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/dao/ContactDao.java @@ -18,14 +18,15 @@ public interface ContactDao extends BaseDao { /** * Return a {@link LiveData} wrapping a {@link List} of all {@link RoomContactModel RosterEntries} * which are currently found in the database. + * * @return */ - @Query("select * from RoomContactModel") + @Query("SELECT * FROM contacts") LiveData> getAllRosterEntries(); - @Query("select * from RoomContactModel where jid = :jid") + @Query("SELECT contacts.* FROM contacts JOIN entities WHERE jid = :jid") RoomContactModel getRosterEntryByJid(EntityBareJid jid); - @Query("select * from RoomContactModel where accountId = :accountId") + @Query("SELECT * FROM contacts WHERE accountId = :accountId") LiveData> getRosterEntriesForAccount(long accountId); } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomContactModel.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomContactModel.java index b82813d..68c3a64 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomContactModel.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomContactModel.java @@ -1,67 +1,61 @@ package org.mercury_im.messenger.persistence.room.model; -import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; -import androidx.room.TypeConverters; +import androidx.room.PrimaryKey; -import org.jxmpp.jid.EntityBareJid; import org.mercury_im.messenger.persistence.model.ContactModel; -import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter; -import org.mercury_im.messenger.persistence.room.type_converter.FileConverter; - -import java.io.File; import static androidx.room.ForeignKey.CASCADE; import static androidx.room.ForeignKey.RESTRICT; +import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_ACCOUNT_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.KEY_XMPP_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.TABLE; -@Entity(primaryKeys = {"accountId", "jid"}, - indices = {@Index(value = {"accountId", "jid"}, unique = true)}, +@Entity(tableName = TABLE, + indices = { + @Index(value = KEY_ID), + @Index(value = KEY_ACCOUNT_ID), + @Index(value = KEY_XMPP_ID) + }, foreignKeys = { @ForeignKey(entity = RoomAccountModel.class, - parentColumns = "id", - childColumns = "accountId", + parentColumns = RoomAccountModel.KEY_ID, + childColumns = KEY_ACCOUNT_ID, onDelete = CASCADE), @ForeignKey(entity = RoomXmppIdentityModel.class, - parentColumns = {"accountId", "jid"}, - childColumns = {"accountId", "jid"}, + parentColumns = RoomXmppIdentityModel.KEY_ID, + childColumns = KEY_XMPP_ID, onDelete = RESTRICT)}) public class RoomContactModel implements ContactModel { + public static final String TABLE = "contacts"; + public static final String KEY_ID = "id"; + public static final String KEY_ACCOUNT_ID = "accountId"; + public static final String KEY_XMPP_ID = "xmppId"; + public static final String KEY_ROSTER_NAME = "rosterName"; + public static final String KEY_NICKNAME = "nickname"; + + @PrimaryKey + @ColumnInfo(name = KEY_ID) + private long id; + + @ColumnInfo(name = KEY_ACCOUNT_ID) private long accountId; - @NonNull - @TypeConverters(EntityBareJidConverter.class) - private EntityBareJid jid; + @ColumnInfo(name = KEY_XMPP_ID) + private long xmppIdentityId; + @ColumnInfo(name = KEY_ROSTER_NAME) private String rosterName; + @ColumnInfo(name = KEY_NICKNAME) private String nickname; - @TypeConverters(FileConverter.class) - private File avatarFile; - - public RoomContactModel(@NonNull EntityBareJid jid, - String rosterName, - String nickname) { - this.jid = jid; - this.nickname = nickname; - this.rosterName = rosterName; - } - - @NonNull - @Override - public EntityBareJid getJid() { - return jid; - } - - @Override - public void setJid(EntityBareJid jid) { - - } - @Override public String getRosterName() { return rosterName; @@ -82,6 +76,16 @@ public class RoomContactModel implements ContactModel { this.nickname = nickname; } + @Override + public long getId() { + return id; + } + + @Override + public void setId(long id) { + this.id = id; + } + @Override public long getAccountId() { return accountId; @@ -92,13 +96,13 @@ public class RoomContactModel implements ContactModel { this.accountId = accountId; } - public File getAvatarFile() { - return avatarFile; + @Override + public long getXmppIdentityId() { + return xmppIdentityId; } @Override - public void setAvatarFile(File file) { - this.avatarFile = file; + public void setXmppIdentityId(long id) { + this.xmppIdentityId = id; } - } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomMessageModel.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomMessageModel.java index 5e5a1a2..8eaf9f7 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomMessageModel.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomMessageModel.java @@ -1,5 +1,6 @@ package org.mercury_im.messenger.persistence.room.model; +import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; @@ -14,26 +15,50 @@ import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidCon import java.util.Date; import static androidx.room.ForeignKey.CASCADE; +import static org.mercury_im.messenger.persistence.room.model.RoomMessageModel.KEY_ACCOUNT_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomMessageModel.KEY_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomMessageModel.TABLE; -@Entity(tableName = "messages", foreignKeys = @ForeignKey(entity = RoomAccountModel.class, - parentColumns = "id", childColumns = "accountId", onDelete = CASCADE), - indices = {@Index("id")}) +@Entity(tableName = TABLE, + foreignKeys = { + @ForeignKey(entity = RoomAccountModel.class, + parentColumns = RoomAccountModel.KEY_ID, + childColumns = KEY_ACCOUNT_ID, + onDelete = CASCADE)}, + indices = { + @Index(KEY_ID), + @Index(KEY_ACCOUNT_ID) + }) public class RoomMessageModel implements MessageModel { + public static final String TABLE = "messages"; + public static final String KEY_ID = "id"; + public static final String KEY_ACCOUNT_ID = "accountId"; + public static final String KEY_BODY = "body"; + public static final String KEY_SEND_DATE = "sendDate"; + public static final String KEY_FROM = "from"; + public static final String KEY_TO = "to"; + @PrimaryKey(autoGenerate = true) + @ColumnInfo(name = KEY_ID) private long id; + @ColumnInfo(name = KEY_ACCOUNT_ID) private long accountId; + @ColumnInfo(name = KEY_BODY) private String body; @TypeConverters(DateConverter.class) + @ColumnInfo(name = KEY_SEND_DATE) private Date sendDate; @TypeConverters(EntityBareJidConverter.class) + @ColumnInfo(name = KEY_FROM) private EntityBareJid from; @TypeConverters(EntityBareJidConverter.class) + @ColumnInfo(name = KEY_TO) private EntityBareJid to; public RoomMessageModel() { diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomXmppIdentityModel.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomXmppIdentityModel.java index ee33e25..3dfc612 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomXmppIdentityModel.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/model/RoomXmppIdentityModel.java @@ -1,9 +1,11 @@ package org.mercury_im.messenger.persistence.room.model; import androidx.annotation.NonNull; +import androidx.room.ColumnInfo; import androidx.room.Entity; import androidx.room.ForeignKey; import androidx.room.Index; +import androidx.room.PrimaryKey; import androidx.room.TypeConverters; import org.jxmpp.jid.EntityBareJid; @@ -14,38 +16,54 @@ import org.mercury_im.messenger.persistence.room.type_converter.FileConverter; import java.io.File; import static androidx.room.ForeignKey.CASCADE; +import static org.mercury_im.messenger.persistence.room.model.RoomXmppIdentityModel.KEY_ACCOUNT_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomXmppIdentityModel.KEY_ID; +import static org.mercury_im.messenger.persistence.room.model.RoomXmppIdentityModel.KEY_JID; import static org.mercury_im.messenger.persistence.room.model.RoomXmppIdentityModel.TABLE; -@Entity(tableName = TABLE, primaryKeys = {"accountId", "jid"}, - indices = {@Index(value = {"accountId", "jid"}, unique = true)}, - foreignKeys = @ForeignKey(entity = RoomAccountModel.class, - parentColumns = "id", - childColumns = "accountId", - onDelete = CASCADE)) +@Entity(tableName = TABLE, + indices = { + @Index(value = KEY_ID), + @Index(value = {KEY_ACCOUNT_ID, KEY_JID}, unique = true) + }, + foreignKeys = { + @ForeignKey(entity = RoomAccountModel.class, + parentColumns = RoomAccountModel.KEY_ID, + childColumns = KEY_ACCOUNT_ID, + onDelete = CASCADE) + }) public class RoomXmppIdentityModel implements XmppIdentityModel { public static final String TABLE = "entities"; + public static final String KEY_ID = "id"; public static final String KEY_ACCOUNT_ID = "accountId"; public static final String KEY_JID = "jid"; public static final String KEY_AVATAR = "avatar"; + @PrimaryKey + @ColumnInfo(name = KEY_ID) + protected long id; + + @ColumnInfo(name = KEY_ACCOUNT_ID) protected long accountId; @NonNull @TypeConverters(EntityBareJidConverter.class) + @ColumnInfo(name = KEY_JID) protected EntityBareJid jid; @TypeConverters(FileConverter.class) + @ColumnInfo(name = KEY_AVATAR) protected File avatarFile; @Override public long getId() { - return 0; + return id; } @Override public void setId(long id) { - + this.id = id; } @NonNull @@ -55,7 +73,7 @@ public class RoomXmppIdentityModel implements XmppIdentityModel { } @Override - public void setJid(EntityBareJid jid) { + public void setJid(@NonNull EntityBareJid jid) { this.jid = jid; } diff --git a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IChatRepository.java b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IChatRepository.java index 6454f98..497f687 100644 --- a/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IChatRepository.java +++ b/persistence-room/src/main/java/org/mercury_im/messenger/persistence/room/repository/IChatRepository.java @@ -1,27 +1,57 @@ package org.mercury_im.messenger.persistence.room.repository; import androidx.lifecycle.LiveData; +import androidx.room.Index; +import org.jxmpp.jid.EntityBareJid; +import org.mercury_im.messenger.persistence.model.AccountModel; import org.mercury_im.messenger.persistence.model.ChatModel; +import org.mercury_im.messenger.persistence.model.ContactModel; import org.mercury_im.messenger.persistence.model.XmppIdentityModel; import org.mercury_im.messenger.persistence.repository.ChatRepository; +import org.mercury_im.messenger.persistence.room.dao.ChatDao; +import org.mercury_im.messenger.persistence.room.model.RoomChatModel; import java.util.List; -public class IChatRepository implements ChatRepository { +import javax.inject.Inject; - @Override - public LiveData> getAllChats() { - return null; +public class IChatRepository implements ChatRepository { + + private final ChatDao chatDao; + + @Inject + public IChatRepository(ChatDao dao) { + this.chatDao = dao; } @Override - public void getChatWith(XmppIdentityModel identity) { - + public LiveData> getAllChats() { + return chatDao.getAllChats(); } @Override - public void closeChat(ChatModel chat) { + public LiveData> getAllChatsOf(AccountModel accountModel) { + return chatDao.getAllChatsOf(accountModel.getId()); + } + @Override + public LiveData getChatWith(XmppIdentityModel identity) { + return chatDao.getChatWithIdentity(identity.getId()); + } + + @Override + public LiveData getChatWith(AccountModel account, EntityBareJid jid) { + return chatDao.getChatWithJid(account.getId(), jid); + } + + @Override + public LiveData getChatWith(ContactModel contact) { + return chatDao.getChatWithContact(contact.getId()); + } + + @Override + public void closeChat(RoomChatModel chat) { + chatDao.delete(chat); } } diff --git a/persistence/README.md b/persistence/README.md new file mode 100644 index 0000000..a711a37 --- /dev/null +++ b/persistence/README.md @@ -0,0 +1,19 @@ +# Abstract Persistence Layer of Mercury + +This Android module defines interfaces for a persistence backend. + +Ideally this module would at some point be a plain java (non-Android) module to allow for +non-Android implementations. This is currently being blocked by [LiveData](https://developer.android.com/topic/libraries/architecture/livedata) +being an Android library. We could fix this by replacing LiveData with RxJava, but this would +require us to manually handle LifeCycles of ViewModels etc. so for now we stick with LiveData. + +## Packages + +### `model` package +Contains interfaces that define the structure of data classes. + +### `repository` package +Repositories build a user-friendly interface to query and modify data in the backend. + +## Implementations +Currently the module is only being implemented by the `persistence-room` Android module. \ No newline at end of file diff --git a/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ChatModel.java b/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ChatModel.java index 076963d..7590787 100644 --- a/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ChatModel.java +++ b/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ChatModel.java @@ -1,7 +1,5 @@ package org.mercury_im.messenger.persistence.model; -import org.jxmpp.jid.EntityBareJid; - public interface ChatModel { long getId(); diff --git a/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ContactModel.java b/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ContactModel.java index 65872f9..2588fc6 100644 --- a/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ContactModel.java +++ b/persistence/src/main/java/org/mercury_im/messenger/persistence/model/ContactModel.java @@ -1,9 +1,5 @@ package org.mercury_im.messenger.persistence.model; -import org.jxmpp.jid.EntityBareJid; - -import java.io.File; - public interface ContactModel { long getId(); @@ -14,9 +10,9 @@ public interface ContactModel { void setAccountId(long id); - EntityBareJid getJid(); + long getXmppIdentityId(); - void setJid(EntityBareJid jid); + void setXmppIdentityId(long id); String getRosterName(); @@ -25,8 +21,4 @@ public interface ContactModel { String getNickname(); void setNickname(String nickname); - - File getAvatarFile(); - - void setAvatarFile(File file); } diff --git a/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/ChatRepository.java b/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/ChatRepository.java index f9c2bfe..b786616 100644 --- a/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/ChatRepository.java +++ b/persistence/src/main/java/org/mercury_im/messenger/persistence/repository/ChatRepository.java @@ -2,17 +2,26 @@ package org.mercury_im.messenger.persistence.repository; import androidx.lifecycle.LiveData; +import org.jxmpp.jid.EntityBareJid; +import org.mercury_im.messenger.persistence.model.AccountModel; import org.mercury_im.messenger.persistence.model.ChatModel; import org.mercury_im.messenger.persistence.model.ContactModel; import org.mercury_im.messenger.persistence.model.XmppIdentityModel; +import org.w3c.dom.Entity; import java.util.List; -public interface ChatRepository { +public interface ChatRepository { - LiveData> getAllChats(); + LiveData> getAllChats(); - LiveData getChatWith(XmppIdentityModel identity); + LiveData> getAllChatsOf(AccountModel account); - void closeChat(ChatModel chat); + LiveData getChatWith(AccountModel account, EntityBareJid jid); + + LiveData getChatWith(XmppIdentityModel identity); + + LiveData getChatWith(ContactModel contact); + + void closeChat(E chat); } diff --git a/version.gradle b/version.gradle index c9e34b9..e8057f3 100644 --- a/version.gradle +++ b/version.gradle @@ -20,6 +20,8 @@ ext { /*/ // Version strings for unique versions + // https://github.com/igniterealtime/Smack/wiki/How-to-use-Smack-snapshots + smackAndroidVersion = "4.4.0-alpha2-20190324.010646-51" smackAndroidExtensionsVersion = "4.4.0-alpha2-20190324.010646-51" smackCoreVersion = "4.4.0-alpha2-20190324.010647-51" diff --git a/xmpp_android/src/main/java/org/mercury_im/messenger/xmpp_android/AndroidMercuryConnection.java b/xmpp_android/src/main/java/org/mercury_im/messenger/xmpp_android/AndroidMercuryConnection.java index 08a6a50..18f1530 100644 --- a/xmpp_android/src/main/java/org/mercury_im/messenger/xmpp_android/AndroidMercuryConnection.java +++ b/xmpp_android/src/main/java/org/mercury_im/messenger/xmpp_android/AndroidMercuryConnection.java @@ -1,6 +1,7 @@ package org.mercury_im.messenger.xmpp_android; import org.jivesoftware.smack.XMPPConnection; +import org.jivesoftware.smackx.ping.android.ServerPingWithAlarmManager; import org.mercury_im.messenger.xmpp_core.MercuryConnection; public class AndroidMercuryConnection extends MercuryConnection { diff --git a/xmpp_core/build.gradle b/xmpp_core/build.gradle index 1b50911..d15cd8d 100644 --- a/xmpp_core/build.gradle +++ b/xmpp_core/build.gradle @@ -11,8 +11,8 @@ dependencies { 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" + // 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 diff --git a/xmpp_core/src/main/java/org/mercury_im/messenger/xmpp_core/MercuryConnection.java b/xmpp_core/src/main/java/org/mercury_im/messenger/xmpp_core/MercuryConnection.java index 5dd380b..5895427 100644 --- a/xmpp_core/src/main/java/org/mercury_im/messenger/xmpp_core/MercuryConnection.java +++ b/xmpp_core/src/main/java/org/mercury_im/messenger/xmpp_core/MercuryConnection.java @@ -5,9 +5,9 @@ import org.jivesoftware.smack.roster.Roster; public class MercuryConnection { - private final XMPPConnection connection; - private final long accountId; - private final Roster roster; + protected final XMPPConnection connection; + protected final long accountId; + protected final Roster roster; public MercuryConnection(XMPPConnection connection, long accountId) { this.connection = connection;