Merging exp2

This commit is contained in:
Paul Schaub 2019-08-03 19:13:07 +02:00
commit dd8f9cf6a3
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
17 changed files with 569 additions and 150 deletions

View File

@ -2,6 +2,7 @@ package org.mercury_im.messenger.di.component;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.di.module.AppModule;
import org.mercury_im.messenger.handler.AvatarHandler;
import org.mercury_im.messenger.handler.RoomPlainMessageHandler;
import org.mercury_im.messenger.handler.RoomRosterHandler;
import org.mercury_im.messenger.persistence.room.RoomModule;
@ -66,4 +67,6 @@ public interface AppComponent {
void inject(RoomRosterHandler roomRosterHandler);
void inject(RoomPlainMessageHandler messageHandler);
void inject(AvatarHandler avatarHandler);
}

View File

@ -1,5 +1,33 @@
package org.mercury_im.messenger.handler;
public class AvatarHandler {
import org.jivesoftware.smackx.avatar.UserAvatarManager;
import org.jivesoftware.smackx.avatar.element.MetadataExtension;
import org.jivesoftware.smackx.avatar.listener.AvatarListener;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.persistence.repository.AvatarRepository;
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
import javax.inject.Inject;
public class AvatarHandler implements AvatarListener {
private final long accountId;
@Inject
private AvatarRepository avatarRepository;
private UserAvatarManager avatarManager;
public AvatarHandler(long accountId, UserAvatarManager avatarManager) {
this.accountId = accountId;
this.avatarManager = avatarManager;
MercuryImApplication.getApplication().getAppComponent().inject(this);
}
@Override
public void onAvatarUpdateReceived(EntityBareJid user, MetadataExtension metadata) {
}
}

View File

@ -3,8 +3,6 @@ package org.mercury_im.messenger.ui.login;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.View.OnClickListener;
import android.view.inputmethod.EditorInfo;
import android.widget.Button;
import android.widget.TextView;
@ -15,43 +13,19 @@ import androidx.lifecycle.ViewModelProviders;
import com.google.android.material.textfield.TextInputEditText;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.R;
import org.mercury_im.messenger.handler.RoomPlainMessageHandler;
import org.mercury_im.messenger.handler.RoomRosterHandler;
import org.mercury_im.messenger.persistence.model.AccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
import org.mercury_im.messenger.core.MercuryConnection;
import java.io.IOException;
import javax.inject.Inject;
import org.mercury_im.messenger.util.TextChangedListener;
import butterknife.BindView;
import butterknife.ButterKnife;
import io.reactivex.Single;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
/**
* A login screen that offers login via email/password.
*/
public class LoginActivity extends AppCompatActivity implements TextView.OnEditorActionListener {
@Inject
AccountRepository accountRepository;
// UI references.
@BindView(R.id.jid)
TextInputEditText mJidView;
@ -77,15 +51,63 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
viewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
displayCredentials(viewModel.getAccount());
viewModel.getJidError().observe(this, jidError -> {
if (jidError == null) return;
String errorMessage = null;
switch (jidError) {
case none:
break;
case emptyJid:
errorMessage = getResources().getString(R.string.error_field_required);
break;
case invalidJid:
errorMessage = getResources().getString(R.string.error_invalid_jid);
break;
case unknownJid:
errorMessage = "Unknown Jid!";
}
mJidView.setError(errorMessage);
});
viewModel.getPasswordError().observe(this, passwordError -> {
if (passwordError == null) return;
String errorMessage = null;
switch (passwordError) {
case none:
break;
case emptyPassword:
errorMessage = getResources().getString(R.string.error_field_required);
break;
case invalidPassword:
errorMessage = getResources().getString(R.string.error_invalid_password);
break;
case incorrectPassword:
errorMessage = getResources().getString(R.string.error_incorrect_password);
break;
}
mPasswordView.setError(errorMessage);
});
mJidView.setOnEditorActionListener(this);
mPasswordView.setOnEditorActionListener(this);
mSignInView.setOnClickListener(new OnClickListener() {
mJidView.addTextChangedListener(new TextChangedListener() {
@Override
public void onClick(View view) {
loginDetailsEntered();
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
viewModel.onJidInputChanged(charSequence.toString());
Log.d("Mercury", "onTextChanged");
}
});
mPasswordView.addTextChangedListener(new TextChangedListener() {
@Override
public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
viewModel.onPasswordInputChanged(charSequence.toString());
Log.d("Mercury", "onTextChanged");
}
});
mSignInView.setOnClickListener(view -> viewModel.loginDetailsEntered());
mSignInView.setEnabled(false);
}
@ -105,106 +127,6 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
});
}
// TODO: Move to ViewModel
private void loginDetailsEntered() {
boolean loginIntact = true;
String jidInput = mJidView.getText().toString();
if (jidInput.isEmpty()) {
mJidView.setError(getResources().getString(R.string.error_field_required));
loginIntact = false;
}
EntityBareJid jid = asValidJidOrNull(jidInput);
if (jid == null) {
mJidView.setError(getResources().getString(R.string.error_invalid_jid));
loginIntact = false;
}
String password = mPasswordView.getText().toString();
if (!isPasswordValid(password)) {
mPasswordView.setError(getResources().getString(R.string.error_invalid_password));
loginIntact = false;
}
if (loginIntact) {
RoomAccountModel accountModel = new RoomAccountModel();
accountModel.setEnabled(true);
accountModel.setJid(jid);
accountModel.setPassword(password);
Single<Long> id = accountRepository.insertAccount(accountModel);
id.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Long>() {
@Override
public void onSubscribe(Disposable d) {
}
@Override
public void onSuccess(Long aLong) {
}
@Override
public void onError(Throwable e) {
}
});
accountModel.setId(id);
Log.d(MercuryImApplication.TAG, "LoginActivity.loginDetailsEntered: Account " + id + " inserted.");
attemptLogin(accountModel);
}
}
private void attemptLogin(AccountModel accountModel) {
XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
.setHost(accountModel.getJid().getDomain().toString())
.setXmppAddressAndPassword(accountModel.getJid(), accountModel.getPassword())
.setConnectTimeout(2 * 60 * 1000)
.build();
new Thread() {
@Override
public void run() {
try {
XMPPTCPConnection connection = new XMPPTCPConnection(configuration);
connection.setUseStreamManagementResumption(true);
connection.setUseStreamManagement(true);
MercuryConnection mercuryConnection = new MercuryConnection(connection, accountModel.getId());
mercuryConnection.setRosterHandler(new RoomRosterHandler(mercuryConnection));
mercuryConnection.setPlainMessageHandler(new RoomPlainMessageHandler(accountModel.getId()));
connection.connect().login();
Log.d(MercuryImApplication.TAG, "Logged in for " + accountModel.getJid().toString());
} catch (XmppStringprepException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
}
}.start();
super.finish();
}
/**
* Try to parse the input string into a {@link EntityBareJid} and return it.
* Return null on failure.
* @param input input string
* @return valid jid or null
*/
private EntityBareJid asValidJidOrNull(String input) {
return JidCreate.entityBareFromOrNull(input);
}
private boolean isPasswordValid(String password) {
return !password.isEmpty();
}
@Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
switch (v.getId()) {
@ -217,7 +139,7 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
case R.id.password:
if (actionId == EditorInfo.IME_ACTION_DONE || actionId == EditorInfo.IME_NULL) {
loginDetailsEntered();
viewModel.loginDetailsEntered();
return true;
}
}

View File

@ -1,12 +1,29 @@
package org.mercury_im.messenger.ui.login;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import androidx.annotation.NonNull;
import android.text.TextUtils;
import android.util.Log;
import org.jivesoftware.smack.SmackException;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.tcp.XMPPTCPConnection;
import org.jivesoftware.smack.tcp.XMPPTCPConnectionConfiguration;
import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate;
import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.MercuryImApplication;
import org.mercury_im.messenger.core.MercuryConnection;
import org.mercury_im.messenger.handler.RoomPlainMessageHandler;
import org.mercury_im.messenger.handler.RoomRosterHandler;
import org.mercury_im.messenger.persistence.model.AccountModel;
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.service.XmppConnectionService;
import java.io.IOException;
import javax.inject.Inject;
@ -16,13 +33,67 @@ public class LoginViewModel extends ViewModel {
@Inject
AccountRepository accountRepository;
private XmppConnectionService connectionService;
private String jid;
private String password;
private MutableLiveData<JidError> jidError = new MutableLiveData<>();
private MutableLiveData<PasswordError> passwordError = new MutableLiveData<>();
private MutableLiveData<RoomAccountModel> account = new MutableLiveData<>();
public LoginViewModel() {
super();
MercuryImApplication.getApplication().getAppComponent().inject(this);
init(new RoomAccountModel());
}
public enum JidError {
none,
emptyJid,
invalidJid,
unknownJid
}
public enum PasswordError {
none,
emptyPassword,
invalidPassword,
incorrectPassword
}
public void onJidInputChanged(String input) {
this.jid = input;
}
public void onPasswordInputChanged(String input) {
this.password = input;
}
public LiveData<JidError> getJidError() {
return jidError;
}
public LiveData<PasswordError> getPasswordError() {
return passwordError;
}
/**
* Try to parse the input string into a {@link EntityBareJid} and return it.
* Return null on failure.
* @param input input string
* @return valid jid or null
*/
private EntityBareJid asValidJidOrNull(String input) {
return JidCreate.entityBareFromOrNull(input);
}
private boolean isPasswordValid(String password) {
return !password.isEmpty();
}
public void init(@NonNull RoomAccountModel account) {
this.account.setValue(account);
}
@ -37,4 +108,73 @@ public class LoginViewModel extends ViewModel {
accountRepository.insertAccount(account);
}
}
public void loginDetailsEntered() {
boolean loginIntact = true;
if (jid.isEmpty()) {
jidError.postValue(JidError.emptyJid);
loginIntact = false;
}
EntityBareJid bareJid = asValidJidOrNull(jid);
if (bareJid == null) {
jidError.postValue(JidError.invalidJid);
loginIntact = false;
}
if (!isPasswordValid(password)) {
passwordError.postValue(PasswordError.invalidPassword);
loginIntact = false;
}
if (loginIntact) {
RoomAccountModel accountModel = new RoomAccountModel();
accountModel.setEnabled(true);
accountModel.setJid(bareJid);
accountModel.setPassword(password);
long id = accountRepository.insertAccount(accountModel);
accountModel.setId(id);
Log.d(MercuryImApplication.TAG, "LoginActivity.loginDetailsEntered: Account " + id + " inserted.");
attemptLogin(accountModel);
}
}
private void attemptLogin(AccountModel accountModel) {
XMPPTCPConnectionConfiguration configuration = XMPPTCPConnectionConfiguration.builder()
.setHost(accountModel.getJid().getDomain().toString())
.setXmppAddressAndPassword(accountModel.getJid(), accountModel.getPassword())
.setConnectTimeout(2 * 60 * 1000)
.build();
new Thread() {
@Override
public void run() {
try {
XMPPTCPConnection connection = new XMPPTCPConnection(configuration);
connection.setUseStreamManagementResumption(true);
connection.setUseStreamManagement(true);
MercuryConnection mercuryConnection = new MercuryConnection(connection, accountModel.getId());
connectionService.putConnection(accountModel.getId(), mercuryConnection);
mercuryConnection.setRosterHandler(new RoomRosterHandler(mercuryConnection));
mercuryConnection.setPlainMessageHandler(new RoomPlainMessageHandler(accountModel.getId()));
connection.connect().login();
Log.d(MercuryImApplication.TAG, "Logged in for " + accountModel.getJid().toString());
} catch (XmppStringprepException e) {
e.printStackTrace();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (SmackException e) {
e.printStackTrace();
} catch (XMPPException e) {
e.printStackTrace();
}
}
}.start();
}
public void setConnectionService(XmppConnectionService connectionService) {
this.connectionService = connectionService;
}
}

View File

@ -0,0 +1,16 @@
package org.mercury_im.messenger.util;
import android.text.Editable;
import android.text.TextWatcher;
public abstract class TextChangedListener implements TextWatcher {
@Override
public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
}
@Override
public void afterTextChanged(Editable editable) {
}
}

View File

@ -7,7 +7,7 @@ buildscript {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.4.1'
classpath 'com.android.tools.build:gradle:3.4.2'
// NOTE: Do not place your application dependencies here; they belong

View File

@ -0,0 +1,36 @@
package org.mercury_im.messenger.persistence.store;
import dagger.MembersInjector;
import javax.annotation.Generated;
import javax.inject.Provider;
import org.mercury_im.messenger.persistence.repository.ContactRepository;
@Generated(
value = "dagger.internal.codegen.ComponentProcessor",
comments = "https://dagger.dev"
)
@SuppressWarnings({
"unchecked",
"rawtypes"
})
public final class RosterStore_MembersInjector implements MembersInjector<RosterStore> {
private final Provider<ContactRepository> contactRepositoryProvider;
public RosterStore_MembersInjector(Provider<ContactRepository> contactRepositoryProvider) {
this.contactRepositoryProvider = contactRepositoryProvider;
}
public static MembersInjector<RosterStore> create(
Provider<ContactRepository> contactRepositoryProvider) {
return new RosterStore_MembersInjector(contactRepositoryProvider);}
@Override
public void injectMembers(RosterStore instance) {
injectContactRepository(instance, contactRepositoryProvider.get());
}
public static void injectContactRepository(RosterStore instance,
ContactRepository contactRepository) {
instance.contactRepository = contactRepository;
}
}

View File

@ -2,7 +2,7 @@
"formatVersion": 1,
"database": {
"version": 1,
"identityHash": "1149b7d295726ec2043486e660dcf75d",
"identityHash": "6f81947a36983067c387ec3ce77eb1cc",
"entities": [
{
"tableName": "contacts",
@ -371,12 +371,79 @@
]
}
]
},
{
"tableName": "avatars",
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_avatar_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_entity_id` INTEGER NOT NULL, `sha1sum` TEXT, `bytes` BLOB, FOREIGN KEY(`fk_entity_id`) REFERENCES `entities`(`pk_entity_id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
"fields": [
{
"fieldPath": "avatarId",
"columnName": "pk_avatar_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "entityId",
"columnName": "fk_entity_id",
"affinity": "INTEGER",
"notNull": true
},
{
"fieldPath": "sha1sum",
"columnName": "sha1sum",
"affinity": "TEXT",
"notNull": false
},
{
"fieldPath": "bytes",
"columnName": "bytes",
"affinity": "BLOB",
"notNull": false
}
],
"primaryKey": {
"columnNames": [
"pk_avatar_id"
],
"autoGenerate": true
},
"indices": [
{
"name": "index_avatars_pk_avatar_id",
"unique": false,
"columnNames": [
"pk_avatar_id"
],
"createSql": "CREATE INDEX `index_avatars_pk_avatar_id` ON `${TABLE_NAME}` (`pk_avatar_id`)"
},
{
"name": "index_avatars_fk_entity_id",
"unique": true,
"columnNames": [
"fk_entity_id"
],
"createSql": "CREATE UNIQUE INDEX `index_avatars_fk_entity_id` ON `${TABLE_NAME}` (`fk_entity_id`)"
}
],
"foreignKeys": [
{
"table": "entities",
"onDelete": "RESTRICT",
"onUpdate": "NO ACTION",
"columns": [
"fk_entity_id"
],
"referencedColumns": [
"pk_entity_id"
]
}
]
}
],
"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, '1149b7d295726ec2043486e660dcf75d')"
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, '6f81947a36983067c387ec3ce77eb1cc')"
]
}
}

View File

@ -10,42 +10,37 @@ import androidx.room.migration.Migration;
import androidx.sqlite.db.SupportSQLiteDatabase;
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
import org.mercury_im.messenger.persistence.room.model.RoomChatModel;
import org.mercury_im.messenger.persistence.room.model.RoomContactAttributes;
import org.mercury_im.messenger.persistence.room.model.RoomEntityModel;
import org.mercury_im.messenger.persistence.room.model.RoomMessageModel;
@Database(version = 2,
@Database(version = 1,
entities = {
RoomContactAttributes.class,
RoomAccountModel.class,
RoomChatModel.class,
RoomMessageModel.class,
RoomEntityModel.class
RoomEntityModel.class,
RoomAvatarModel.class
})
public abstract class AppDatabase extends RoomDatabase {
private static final String DB_NAME = "mercury_db";
private static AppDatabase INSTANCE;
static Migration m1_2 = new Migration(1, 2) {
@Override
public void migrate(@NonNull SupportSQLiteDatabase database) {
database.execSQL("ALTER TABLE accounts ADD COLUMN state TEXT");
}
};
public static AppDatabase getDatabase(final Context context) {
if (INSTANCE == null) {
INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
AppDatabase.class, DB_NAME)
.addMigrations(m1_2)
.build();
}
return INSTANCE;
@ -61,5 +56,7 @@ public abstract class AppDatabase extends RoomDatabase {
public abstract EntityDao entityDao();
public abstract ContactDao contactAndEntityDao();
public abstract ContactDao contactDao();
public abstract AvatarDao avatarDao();
}

View File

@ -3,6 +3,7 @@ package org.mercury_im.messenger.persistence.room;
import android.app.Application;
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
@ -69,4 +70,10 @@ public class RoomModule {
ContactDao provideContactAndEntityDao() {
return mAppDatabase.contactAndEntityDao();
}
@Singleton
@Provides
AvatarDao providerAvatarDao() {
return mAppDatabase.avatarDao();
}
}

View File

@ -1,18 +1,21 @@
package org.mercury_im.messenger.persistence.room;
import org.mercury_im.messenger.persistence.repository.AccountRepository;
import org.mercury_im.messenger.persistence.repository.AvatarRepository;
import org.mercury_im.messenger.persistence.repository.ChatRepository;
import org.mercury_im.messenger.persistence.repository.ContactRepository;
import org.mercury_im.messenger.persistence.repository.ContactAttributesRepository;
import org.mercury_im.messenger.persistence.repository.EntityRepository;
import org.mercury_im.messenger.persistence.repository.MessageRepository;
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
import org.mercury_im.messenger.persistence.room.dao.ChatDao;
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
import org.mercury_im.messenger.persistence.room.dao.ContactAttributesDao;
import org.mercury_im.messenger.persistence.room.dao.EntityDao;
import org.mercury_im.messenger.persistence.room.dao.MessageDao;
import org.mercury_im.messenger.persistence.room.repository.IAccountRepository;
import org.mercury_im.messenger.persistence.room.repository.IAvatarRepository;
import org.mercury_im.messenger.persistence.room.repository.IChatRepository;
import org.mercury_im.messenger.persistence.room.repository.IContactRepository;
import org.mercury_im.messenger.persistence.room.repository.IContactAttributesRepository;
@ -62,4 +65,10 @@ public class RoomRepositoryModule {
ContactRepository provideContactRepository(ContactDao dao) {
return new IContactRepository(dao);
}
@Singleton
@Provides
AvatarRepository provideAvatarRepository(AvatarDao avatarDao) {
return new IAvatarRepository(avatarDao);
}
}

View File

@ -0,0 +1,28 @@
package org.mercury_im.messenger.persistence.room.dao;
import androidx.annotation.WorkerThread;
import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Query;
import androidx.room.TypeConverters;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
import org.mercury_im.messenger.persistence.room.type_converter.EntityBareJidConverter;
@Dao
@TypeConverters(EntityBareJidConverter.class)
@WorkerThread
public interface AvatarDao extends BaseDao<RoomAvatarModel> {
@Query("SELECT * FROM avatars WHERE pk_avatar_id = :avatarId")
LiveData<RoomAvatarModel> getAvatarById(long avatarId);
@Query("SELECT * FROM avatars WHERE fk_entity_id = :entityId")
LiveData<RoomAvatarModel> getAvatarByEntityId(long entityId);
@Query("SELECT avatars.* " +
"FROM avatars INNER JOIN entities ON avatars.fk_entity_id = entities.pk_entity_id " +
"WHERE entities.jid = :jid")
LiveData<RoomAvatarModel> getAvatarByJid(EntityBareJid jid);
}

View File

@ -0,0 +1,87 @@
package org.mercury_im.messenger.persistence.room.model;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Index;
import androidx.room.PrimaryKey;
import org.mercury_im.messenger.persistence.model.AvatarModel;
import static androidx.room.ForeignKey.RESTRICT;
import static org.mercury_im.messenger.persistence.room.model.RoomAvatarModel.KEY_ENTITY_ID;
import static org.mercury_im.messenger.persistence.room.model.RoomAvatarModel.KEY_ID;
import static org.mercury_im.messenger.persistence.room.model.RoomAvatarModel.TABLE;
@Entity(tableName = TABLE,
indices = {
@Index(value = KEY_ID),
@Index(value = KEY_ENTITY_ID, unique = true)
},
foreignKeys = {
@ForeignKey(entity = RoomEntityModel.class,
parentColumns = RoomEntityModel.KEY_ID,
childColumns = KEY_ENTITY_ID,
onDelete = RESTRICT)
})
public class RoomAvatarModel implements AvatarModel {
public static final String TABLE = "avatars";
public static final String KEY_ID = "pk_avatar_id";
public static final String KEY_ENTITY_ID = "fk_entity_id";
public static final String KEY_SHA1_SUM = "sha1sum";
public static final String KEY_BYTES = "bytes";
@PrimaryKey(autoGenerate = true)
@ColumnInfo(name = KEY_ID)
private long avatarId;
@ColumnInfo(name = KEY_ENTITY_ID)
private long entityId;
@ColumnInfo(name = KEY_SHA1_SUM)
private String sha1Sum;
@ColumnInfo(name = KEY_BYTES)
private byte[] bytes;
@Override
public long getAvatarId() {
return avatarId;
}
@Override
public void setAvatarId(long id) {
this.avatarId = id;
}
@Override
public long entityId() {
return entityId;
}
@Override
public void setEntityId(long entityId) {
this.entityId = entityId;
}
@Override
public String getSha1Sum() {
return sha1Sum;
}
@Override
public void setSha1Sum(String sha1Sum) {
this.sha1Sum = sha1Sum;
}
@Override
public byte[] getBytes() {
return bytes.clone();
}
@Override
public void setBytes(byte[] bytes) {
this.bytes = bytes;
}
}

View File

@ -0,0 +1,40 @@
package org.mercury_im.messenger.persistence.room.repository;
import androidx.lifecycle.LiveData;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.repository.AvatarRepository;
import org.mercury_im.messenger.persistence.room.dao.AvatarDao;
import org.mercury_im.messenger.persistence.room.model.RoomAvatarModel;
import javax.inject.Inject;
public class IAvatarRepository implements AvatarRepository<RoomAvatarModel> {
private final AvatarDao dao;
@Inject
public IAvatarRepository(AvatarDao dao) {
this.dao = dao;
}
@Override
public LiveData<RoomAvatarModel> getAvatarById(long avatarId) {
return dao.getAvatarById(avatarId);
}
@Override
public LiveData<RoomAvatarModel> getAvatarByEntityId(long entityId) {
return dao.getAvatarByEntityId(entityId);
}
@Override
public LiveData<RoomAvatarModel> getAvatarByJid(EntityBareJid jid) {
return dao.getAvatarByJid(jid);
}
@Override
public long updateOrInsertAvatar(RoomAvatarModel avatarModel) {
return dao.insert(avatarModel);
}
}

View File

@ -0,0 +1,20 @@
package org.mercury_im.messenger.persistence.model;
public interface AvatarModel {
long getAvatarId();
void setAvatarId(long id);
long entityId();
void setEntityId(long entityId);
String getSha1Sum();
void setSha1Sum(String sha1Sum);
byte[] getBytes();
void setBytes(byte[] bytes);
}

View File

@ -0,0 +1,17 @@
package org.mercury_im.messenger.persistence.repository;
import androidx.lifecycle.LiveData;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.persistence.model.AvatarModel;
public interface AvatarRepository<E extends AvatarModel> {
LiveData<E> getAvatarById(long avatarId);
LiveData<E> getAvatarByEntityId(long entityId);
LiveData<E> getAvatarByJid(EntityBareJid jid);s
long updateOrInsertAvatar(E avatarModel);
}

View File

@ -3,8 +3,8 @@ ext {
// Quickly switch between unique and normal releases using the toggle below
// Version Strings for non-unique releases
/*
smackVersion = "4.4.0-alpha2-SNAPSHOT"
//*
smackVersion = "4.4.0-alpha3-SNAPSHOT"
smackAndroidVersion = smackVersion
smackAndroidExtensionsVersion = smackVersion
@ -71,11 +71,13 @@ ext {
// Architecture Components
lifecycleVersion = "2.2.0-alpha01"
roomVersion = "2.1.0"
roomRxJavaVersion = "2.1.0"
pagingVersion = "2.1.0"
appCompatVersion = "1.1.0-rc01"
// Room
roomVersion = "2.1.0"
roomRxJavaVersion = "2.1.0"
// RxJava2
rxJava2Version = "2.2.11"
rxAndroidVersion = "2.1.1"