mirror of
https://codeberg.org/Mercury-IM/Mercury-IM
synced 2024-06-15 16:14:52 +02:00
Temp
This commit is contained in:
parent
f7697b9ba8
commit
ab66770fd7
|
@ -7,8 +7,6 @@ import android.view.Menu;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
import androidx.lifecycle.LiveData;
|
|
||||||
import androidx.lifecycle.Observer;
|
|
||||||
import androidx.lifecycle.ViewModelProviders;
|
import androidx.lifecycle.ViewModelProviders;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
import androidx.recyclerview.widget.RecyclerView;
|
import androidx.recyclerview.widget.RecyclerView;
|
||||||
|
@ -18,17 +16,27 @@ 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.model.AccountModel;
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||||
import org.mercury_im.messenger.persistence.model.MessageModel;
|
import org.mercury_im.messenger.persistence.model.MessageModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
import org.mercury_im.messenger.persistence.repository.MessageRepository;
|
import org.mercury_im.messenger.persistence.repository.MessageRepository;
|
||||||
|
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||||
|
|
||||||
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.logging.Level;
|
||||||
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import butterknife.BindView;
|
import butterknife.BindView;
|
||||||
import butterknife.ButterKnife;
|
import butterknife.ButterKnife;
|
||||||
import io.reactivex.Maybe;
|
import io.reactivex.Maybe;
|
||||||
|
import io.reactivex.Observable;
|
||||||
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
|
import io.reactivex.functions.Consumer;
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class ChatActivity extends AppCompatActivity implements ChatInputFragment.OnChatInputActionListener {
|
public class ChatActivity extends AppCompatActivity implements ChatInputFragment.OnChatInputActionListener {
|
||||||
|
|
||||||
|
@ -41,6 +49,9 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment
|
||||||
@Inject
|
@Inject
|
||||||
MessageRepository messageRepository;
|
MessageRepository messageRepository;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
RosterRepository rosterRepository;
|
||||||
|
|
||||||
@BindView(R.id.toolbar)
|
@BindView(R.id.toolbar)
|
||||||
Toolbar toolbar;
|
Toolbar toolbar;
|
||||||
|
|
||||||
|
@ -49,6 +60,8 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment
|
||||||
|
|
||||||
private ChatViewModel chatViewModel;
|
private ChatViewModel chatViewModel;
|
||||||
|
|
||||||
|
private final CompositeDisposable disposable = new CompositeDisposable();
|
||||||
|
|
||||||
private EntityBareJid jid;
|
private EntityBareJid jid;
|
||||||
|
|
||||||
private long accountId;
|
private long accountId;
|
||||||
|
@ -74,37 +87,53 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment
|
||||||
|
|
||||||
String jidString = savedInstanceState.getString(EXTRA_JID);
|
String jidString = savedInstanceState.getString(EXTRA_JID);
|
||||||
if (jidString != null) {
|
if (jidString != null) {
|
||||||
getSupportActionBar().setTitle(jidString);
|
|
||||||
jid = JidCreate.entityBareFromOrThrowUnchecked(jidString);
|
jid = JidCreate.entityBareFromOrThrowUnchecked(jidString);
|
||||||
accountId = savedInstanceState.getLong(EXTRA_ACCOUNT);
|
accountId = savedInstanceState.getLong(EXTRA_ACCOUNT);
|
||||||
|
|
||||||
Maybe<AccountModel> accountModel = accountRepository.getAccount(accountId);
|
Maybe<AccountModel> account = accountRepository.getAccount(accountId);
|
||||||
chatViewModel = ViewModelProviders.of(this).get(ChatViewModel.class);
|
chatViewModel = ViewModelProviders.of(this).get(ChatViewModel.class);
|
||||||
|
|
||||||
/*
|
disposable.add(
|
||||||
accountModel.observe(this, new Observer<AccountModel>() {
|
account.subscribeOn(Schedulers.io())
|
||||||
@Override
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
public void onChanged(AccountModel accountModel) {
|
.subscribe(accountModel -> {
|
||||||
chatViewModel.init(accountModel, jid);
|
chatViewModel.init(accountModel, jid);
|
||||||
}
|
}));
|
||||||
});
|
|
||||||
|
|
||||||
LiveData<List<MessageModel>> messages = messageRepository.getAllMessagesOfChat(accountId, jid);
|
disposable.add(
|
||||||
messages.observe(this, new Observer<List<MessageModel>>() {
|
rosterRepository.getContact(accountId, jid)
|
||||||
@Override
|
.toObservable()
|
||||||
public void onChanged(List<MessageModel> messageModels) {
|
.subscribeOn(Schedulers.io())
|
||||||
Log.d(MercuryImApplication.TAG, "Updating messages: " + messageModels.size());
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
adapter.updateMessages(messageModels);
|
.subscribe((Consumer<ContactModel>) o -> {
|
||||||
recyclerView.scrollToPosition(messageModels.size() - 1);
|
Logger.getLogger("AAAAAAAA").log(Level.INFO, "Title change?");
|
||||||
}
|
String title = o.getRosterName();
|
||||||
});
|
if (title == null) {
|
||||||
|
title = jidString;
|
||||||
|
}
|
||||||
|
getSupportActionBar().setTitle(title);
|
||||||
|
}));
|
||||||
|
|
||||||
getSupportFragmentManager().beginTransaction().replace(R.id.stub_compose, ChatInputFragment.newInstance())
|
Observable<List<MessageModel>> messages = messageRepository.getAllMessagesOfChat(accountId, jid);
|
||||||
.commitAllowingStateLoss();
|
disposable.add(
|
||||||
*/
|
messages.subscribeOn(Schedulers.io())
|
||||||
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
.doOnNext(messageModels -> Log.d(MercuryImApplication.TAG, "Updating messages: " + messageModels.size()))
|
||||||
|
.subscribe(messageModels -> {
|
||||||
|
adapter.updateMessages(messageModels);
|
||||||
|
recyclerView.scrollToPosition(messageModels.size() - 1);
|
||||||
|
}));
|
||||||
|
|
||||||
|
ChatInputFragment composer = (ChatInputFragment) getSupportFragmentManager()
|
||||||
|
.findFragmentById(R.id.fragment_compose);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void onStop() {
|
||||||
|
super.onStop();
|
||||||
|
disposable.clear();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu; this adds items to the action bar if it is present.
|
// Inflate the menu; this adds items to the action bar if it is present.
|
||||||
|
@ -135,6 +164,21 @@ public class ChatActivity extends AppCompatActivity implements ChatInputFragment
|
||||||
if (msg.isEmpty()) {
|
if (msg.isEmpty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
MessageModel messageModel = messageRepository.newMessageModel();
|
||||||
|
AccountModel account = (AccountModel) accountRepository.getAccount(accountId)
|
||||||
|
.subscribeOn(Schedulers.io()).blockingGet();
|
||||||
|
messageModel.setFrom(account.getJid());
|
||||||
|
messageModel.setTo(jid);
|
||||||
|
messageModel.setSendDate(new Date());
|
||||||
|
messageModel.setBody(msg);
|
||||||
|
messageModel.setIncoming(false);
|
||||||
|
messageModel.setAccountId(accountId);
|
||||||
|
|
||||||
|
disposable.add(messageRepository
|
||||||
|
.insertMessage(messageModel)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe());
|
||||||
/*
|
/*
|
||||||
new Thread() {
|
new Thread() {
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,10 +11,18 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
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.model.AccountModel;
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
|
|
||||||
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class AccountsActivity extends AppCompatActivity
|
public class AccountsActivity extends AppCompatActivity
|
||||||
implements AccountsFragment.OnAccountListItemClickListener {
|
implements AccountsFragment.OnAccountListItemClickListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
AccountRepository accountRepository;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onCreate(Bundle savedInstanceState) {
|
protected void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -40,4 +48,11 @@ public class AccountsActivity extends AppCompatActivity
|
||||||
});
|
});
|
||||||
builder.create().show();
|
builder.create().show();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onAccountListItemLongClick(AccountModel item) {
|
||||||
|
accountRepository.deleteAccount(item)
|
||||||
|
.subscribeOn(Schedulers.io())
|
||||||
|
.subscribe();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
*/
|
*/
|
||||||
public class AccountsFragment extends Fragment {
|
public class AccountsFragment extends Fragment {
|
||||||
|
|
||||||
private OnAccountListItemClickListener onAccountListItemClickListener;
|
private OnAccountListItemClickListener accountClickListener;
|
||||||
|
|
||||||
AccountsViewModel viewModel;
|
AccountsViewModel viewModel;
|
||||||
|
|
||||||
|
@ -40,7 +40,6 @@ public class AccountsFragment extends Fragment {
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: Customize parameter initialization
|
// TODO: Customize parameter initialization
|
||||||
@SuppressWarnings("unused")
|
|
||||||
public static AccountsFragment newInstance() {
|
public static AccountsFragment newInstance() {
|
||||||
AccountsFragment fragment = new AccountsFragment();
|
AccountsFragment fragment = new AccountsFragment();
|
||||||
return fragment;
|
return fragment;
|
||||||
|
@ -63,7 +62,7 @@ public class AccountsFragment extends Fragment {
|
||||||
recyclerView = (RecyclerView) view;
|
recyclerView = (RecyclerView) view;
|
||||||
Context context = view.getContext();
|
Context context = view.getContext();
|
||||||
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
recyclerView.setLayoutManager(new LinearLayoutManager(context));
|
||||||
this.adapter = new AccountsRecyclerViewAdapter(viewModel.getAccounts().getValue(), onAccountListItemClickListener);
|
this.adapter = new AccountsRecyclerViewAdapter(viewModel.getAccounts().getValue(), accountClickListener);
|
||||||
viewModel.getAccounts().observe(this, roomAccountModels -> adapter.setValues(roomAccountModels));
|
viewModel.getAccounts().observe(this, roomAccountModels -> adapter.setValues(roomAccountModels));
|
||||||
recyclerView.setAdapter(adapter);
|
recyclerView.setAdapter(adapter);
|
||||||
}
|
}
|
||||||
|
@ -76,7 +75,7 @@ public class AccountsFragment extends Fragment {
|
||||||
public void onAttach(Context context) {
|
public void onAttach(Context context) {
|
||||||
super.onAttach(context);
|
super.onAttach(context);
|
||||||
if (context instanceof OnAccountListItemClickListener) {
|
if (context instanceof OnAccountListItemClickListener) {
|
||||||
onAccountListItemClickListener = (OnAccountListItemClickListener) context;
|
accountClickListener = (OnAccountListItemClickListener) context;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(context.toString()
|
throw new RuntimeException(context.toString()
|
||||||
+ " must implement OnAccountListItemClickListener");
|
+ " must implement OnAccountListItemClickListener");
|
||||||
|
@ -86,7 +85,7 @@ public class AccountsFragment extends Fragment {
|
||||||
@Override
|
@Override
|
||||||
public void onDetach() {
|
public void onDetach() {
|
||||||
super.onDetach();
|
super.onDetach();
|
||||||
onAccountListItemClickListener = null;
|
accountClickListener = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -101,5 +100,7 @@ public class AccountsFragment extends Fragment {
|
||||||
*/
|
*/
|
||||||
public interface OnAccountListItemClickListener {
|
public interface OnAccountListItemClickListener {
|
||||||
void onAccountListItemClick(AccountModel item);
|
void onAccountListItemClick(AccountModel item);
|
||||||
|
|
||||||
|
void onAccountListItemLongClick(AccountModel item);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -56,6 +56,12 @@ public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRe
|
||||||
mListener.onAccountListItemClick(holder.accountModel);
|
mListener.onAccountListItemClick(holder.accountModel);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
holder.mView.setOnLongClickListener(v -> {
|
||||||
|
if (null != mListener) {
|
||||||
|
mListener.onAccountListItemLongClick(holder.accountModel);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setValues(List<AccountModel> values) {
|
public void setValues(List<AccountModel> values) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import android.widget.TextView;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.Observer;
|
||||||
import androidx.lifecycle.ViewModelProviders;
|
import androidx.lifecycle.ViewModelProviders;
|
||||||
|
|
||||||
import com.google.android.material.textfield.TextInputEditText;
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
|
@ -49,8 +50,33 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
|
||||||
ButterKnife.bind(this);
|
ButterKnife.bind(this);
|
||||||
|
|
||||||
viewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
|
viewModel = ViewModelProviders.of(this).get(LoginViewModel.class);
|
||||||
|
|
||||||
|
observeViewModel(viewModel);
|
||||||
displayCredentials(viewModel.getAccount());
|
displayCredentials(viewModel.getAccount());
|
||||||
|
|
||||||
|
mJidView.setOnEditorActionListener(this);
|
||||||
|
mPasswordView.setOnEditorActionListener(this);
|
||||||
|
|
||||||
|
mJidView.addTextChangedListener(new TextChangedListener() {
|
||||||
|
@Override
|
||||||
|
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());
|
||||||
|
}
|
||||||
|
|
||||||
|
private void observeViewModel(LoginViewModel viewModel) {
|
||||||
viewModel.getJidError().observe(this, jidError -> {
|
viewModel.getJidError().observe(this, jidError -> {
|
||||||
if (jidError == null) return;
|
if (jidError == null) return;
|
||||||
String errorMessage = null;
|
String errorMessage = null;
|
||||||
|
@ -88,26 +114,11 @@ public class LoginActivity extends AppCompatActivity implements TextView.OnEdito
|
||||||
mPasswordView.setError(errorMessage);
|
mPasswordView.setError(errorMessage);
|
||||||
});
|
});
|
||||||
|
|
||||||
mJidView.setOnEditorActionListener(this);
|
viewModel.getSigninSuccessful().observe(this, aBoolean -> {
|
||||||
mPasswordView.setOnEditorActionListener(this);
|
if (Boolean.TRUE.equals(aBoolean)) {
|
||||||
|
finish();
|
||||||
mJidView.addTextChangedListener(new TextChangedListener() {
|
|
||||||
@Override
|
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void displayCredentials(LiveData<? extends AccountModel> account) {
|
private void displayCredentials(LiveData<? extends AccountModel> account) {
|
||||||
|
|
|
@ -18,6 +18,7 @@ import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import io.reactivex.ObservableSource;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.observers.DisposableSingleObserver;
|
import io.reactivex.observers.DisposableSingleObserver;
|
||||||
|
@ -42,12 +43,18 @@ public class LoginViewModel extends ViewModel {
|
||||||
|
|
||||||
private MutableLiveData<AccountModel> account = new MutableLiveData<>();
|
private MutableLiveData<AccountModel> account = new MutableLiveData<>();
|
||||||
|
|
||||||
|
private MutableLiveData<Boolean> signinSuccessful = new MutableLiveData<>();
|
||||||
|
|
||||||
public LoginViewModel() {
|
public LoginViewModel() {
|
||||||
super();
|
super();
|
||||||
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
MercuryImApplication.getApplication().getAppComponent().inject(this);
|
||||||
init(accountRepository.newAccountModel());
|
init(accountRepository.newAccountModel());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public LiveData<Boolean> getSigninSuccessful() {
|
||||||
|
return signinSuccessful;
|
||||||
|
}
|
||||||
|
|
||||||
public enum JidError {
|
public enum JidError {
|
||||||
none,
|
none,
|
||||||
emptyJid,
|
emptyJid,
|
||||||
|
@ -140,6 +147,7 @@ public class LoginViewModel extends ViewModel {
|
||||||
accountModel.setId(aLong);
|
accountModel.setId(aLong);
|
||||||
Log.d(MercuryImApplication.TAG, "LoginActivity.loginDetailsEntered: Account " + aLong + " inserted.");
|
Log.d(MercuryImApplication.TAG, "LoginActivity.loginDetailsEntered: Account " + aLong + " inserted.");
|
||||||
connectionCenter.createConnection(accountModel);
|
connectionCenter.createConnection(accountModel);
|
||||||
|
signinSuccessful.setValue(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -1,33 +1,34 @@
|
||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<androidx.constraintlayout.widget.ConstraintLayout
|
<androidx.constraintlayout.widget.ConstraintLayout
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
tools:context=".ui.chat.ChatActivity">
|
|
||||||
|
|
||||||
<com.google.android.material.appbar.AppBarLayout
|
|
||||||
android:id="@+id/appbar_layout"
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="match_parent"
|
||||||
app:layout_constraintTop_toTopOf="parent">
|
tools:menu="@menu/menu_chat"
|
||||||
|
tools:context=".ui.chat.ChatActivity">
|
||||||
|
|
||||||
<androidx.appcompat.widget.Toolbar
|
<com.google.android.material.appbar.AppBarLayout
|
||||||
android:id="@+id/toolbar"
|
android:id="@+id/appbar_layout"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="?attr/actionBarSize"
|
android:layout_height="wrap_content"
|
||||||
android:background="?attr/colorPrimary">
|
app:layout_constraintTop_toTopOf="parent">
|
||||||
|
|
||||||
<de.hdodenhof.circleimageview.CircleImageView
|
<androidx.appcompat.widget.Toolbar
|
||||||
android:layout_width="40dp"
|
android:id="@+id/toolbar"
|
||||||
android:layout_height="40dp"
|
android:layout_width="match_parent"
|
||||||
android:src="@drawable/aldrin"
|
android:layout_height="?attr/actionBarSize"
|
||||||
android:transitionName="avatar"/>
|
android:background="?attr/colorPrimary">
|
||||||
|
|
||||||
</androidx.appcompat.widget.Toolbar>
|
<de.hdodenhof.circleimageview.CircleImageView
|
||||||
|
android:layout_width="40dp"
|
||||||
|
android:layout_height="40dp"
|
||||||
|
android:src="@drawable/aldrin"
|
||||||
|
android:transitionName="avatar"/>
|
||||||
|
|
||||||
</com.google.android.material.appbar.AppBarLayout>
|
</androidx.appcompat.widget.Toolbar>
|
||||||
|
|
||||||
|
</com.google.android.material.appbar.AppBarLayout>
|
||||||
|
|
||||||
<FrameLayout
|
<FrameLayout
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
|
@ -39,10 +40,12 @@ tools:context=".ui.chat.ChatActivity">
|
||||||
</FrameLayout>
|
</FrameLayout>
|
||||||
|
|
||||||
|
|
||||||
<FrameLayout
|
<fragment
|
||||||
android:id="@+id/stub_compose"
|
android:id="@+id/fragment_compose"
|
||||||
android:layout_width="match_parent"
|
android:name="org.mercury_im.messenger.ui.chat.ChatInputFragment"
|
||||||
android:layout_height="wrap_content"
|
android:layout_width="match_parent"
|
||||||
app:layout_constraintBottom_toBottomOf="parent" />
|
android:layout_height="wrap_content"
|
||||||
|
app:layout_constraintBottom_toBottomOf="parent"
|
||||||
|
tools:layout="@layout/view_compose"/>
|
||||||
|
|
||||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
</androidx.constraintlayout.widget.ConstraintLayout>
|
|
@ -1,5 +1,6 @@
|
||||||
package org.mercury_im.messenger.core;
|
package org.mercury_im.messenger.core;
|
||||||
|
|
||||||
|
import org.jivesoftware.smack.roster.Roster;
|
||||||
import org.jivesoftware.smack.roster.packet.RosterPacket;
|
import org.jivesoftware.smack.roster.packet.RosterPacket;
|
||||||
import org.jxmpp.jid.Jid;
|
import org.jxmpp.jid.Jid;
|
||||||
import org.mercury_im.messenger.persistence.model.ContactModel;
|
import org.mercury_im.messenger.persistence.model.ContactModel;
|
||||||
|
@ -8,6 +9,7 @@ import org.mercury_im.messenger.persistence.model.RosterInformationModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -17,6 +19,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.disposables.CompositeDisposable;
|
import io.reactivex.disposables.CompositeDisposable;
|
||||||
import io.reactivex.functions.Consumer;
|
import io.reactivex.functions.Consumer;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -48,12 +51,16 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
||||||
disposable.add(rosterRepository.getAllContactsOfAccount(accountId)
|
disposable.add(rosterRepository.getAllContactsOfAccount(accountId)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(Schedulers.computation())
|
.observeOn(Schedulers.computation())
|
||||||
.subscribe((Consumer<List<? extends ContactModel>>) o -> {
|
.subscribe((Consumer<List<? extends ContactModel>>) contactsList -> {
|
||||||
itemMap.clear();
|
itemMap.clear();
|
||||||
for (ContactModel c : o) {
|
for (ContactModel contactModel : contactsList) {
|
||||||
rosterRepository.getEntityForContact(c.getId()).subscribeOn(Schedulers.io())
|
rosterRepository.getEntityForContact(contactModel.getId())
|
||||||
.subscribe((Consumer<EntityModel>) o1 -> itemMap.put(o1.getJid(), fromModel(c)));
|
.subscribeOn(Schedulers.io())
|
||||||
LOGGER.log(Level.INFO, "Populate itemMap with " + o.size() + " items");
|
.subscribe((Consumer<EntityModel>) entityModel -> {
|
||||||
|
RosterPacket.Item item = fromModel(contactModel);
|
||||||
|
itemMap.put(entityModel.getJid(), item);
|
||||||
|
});
|
||||||
|
LOGGER.log(Level.INFO, "Populate itemMap with " + contactsList.size() + " items");
|
||||||
|
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
@ -113,16 +120,16 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean resetEntries(Collection<RosterPacket.Item> items, String version) {
|
public boolean resetEntries(Collection<RosterPacket.Item> items, String version) {
|
||||||
|
LOGGER.log(Level.INFO, "Reset Entries: " + Arrays.toString(items.toArray()));
|
||||||
// Update database
|
// Update database
|
||||||
for (RosterPacket.Item item : items) {
|
for (RosterPacket.Item item : items) {
|
||||||
rosterRepository.updateOrInsertContact(toModel(item))
|
ContactModel model = toModel(item);
|
||||||
|
rosterRepository.updateOrInsertContact(model)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(Schedulers.computation())
|
|
||||||
.subscribe();
|
.subscribe();
|
||||||
}
|
}
|
||||||
rosterRepository.updateRosterVersionForAccount(accountId, version)
|
rosterRepository.updateRosterVersionForAccount(accountId, version)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(Schedulers.computation())
|
|
||||||
.subscribe();
|
.subscribe();
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
@ -130,6 +137,7 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeEntry(Jid bareJid, String version) {
|
public boolean removeEntry(Jid bareJid, String version) {
|
||||||
|
LOGGER.log(Level.INFO, "Remove entry " + bareJid.toString());
|
||||||
rosterRepository.deleteContact(accountId, bareJid.asEntityBareJidOrThrow())
|
rosterRepository.deleteContact(accountId, bareJid.asEntityBareJidOrThrow())
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(Schedulers.computation())
|
.observeOn(Schedulers.computation())
|
||||||
|
@ -143,6 +151,7 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void resetStore() {
|
public void resetStore() {
|
||||||
|
LOGGER.log(Level.INFO, "Reset Store");
|
||||||
rosterRepository.deleteAllContactsOfAccount(accountId)
|
rosterRepository.deleteAllContactsOfAccount(accountId)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(Schedulers.computation())
|
.observeOn(Schedulers.computation())
|
||||||
|
@ -169,13 +178,12 @@ public class RosterStore implements org.jivesoftware.smack.roster.rosterstore.Ro
|
||||||
ContactModel contact = rosterRepository.newContactModel();
|
ContactModel contact = rosterRepository.newContactModel();
|
||||||
contact.setAccountId(accountId);
|
contact.setAccountId(accountId);
|
||||||
|
|
||||||
ContactModel attributes = rosterRepository.newContactModel();
|
contact.setRosterName(item.getName());
|
||||||
attributes.setRosterName(item.getName());
|
|
||||||
if (item.getItemType() != null) {
|
if (item.getItemType() != null) {
|
||||||
attributes.setDirection(convert(item.getItemType()));
|
contact.setDirection(convert(item.getItemType()));
|
||||||
}
|
}
|
||||||
attributes.setApproved(item.isApproved());
|
contact.setApproved(item.isApproved());
|
||||||
attributes.setSubscriptionPending(item.isSubscriptionPending());
|
contact.setSubscriptionPending(item.isSubscriptionPending());
|
||||||
|
|
||||||
EntityModel entity = rosterRepository.newEntityModel();
|
EntityModel entity = rosterRepository.newEntityModel();
|
||||||
entity.setAccountId(accountId);
|
entity.setAccountId(accountId);
|
||||||
|
|
|
@ -2,8 +2,129 @@
|
||||||
"formatVersion": 1,
|
"formatVersion": 1,
|
||||||
"database": {
|
"database": {
|
||||||
"version": 1,
|
"version": 1,
|
||||||
"identityHash": "cc1de3c4fd3350ea0e894d02f30312f3",
|
"identityHash": "fdd5152ff14dba77ae4dba978fc0bb11",
|
||||||
"entities": [
|
"entities": [
|
||||||
|
{
|
||||||
|
"tableName": "accounts",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_account_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `jid` TEXT, `password` TEXT, `enabled` INTEGER NOT NULL, `state` TEXT)",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "pk_account_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "jid",
|
||||||
|
"columnName": "jid",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "password",
|
||||||
|
"columnName": "password",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "enabled",
|
||||||
|
"columnName": "enabled",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "state",
|
||||||
|
"columnName": "state",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"pk_account_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_accounts_pk_account_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"pk_account_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_accounts_pk_account_id` ON `${TABLE_NAME}` (`pk_account_id`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tableName": "entities",
|
||||||
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_entity_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `jid` TEXT NOT NULL, `avatar` TEXT, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
||||||
|
"fields": [
|
||||||
|
{
|
||||||
|
"fieldPath": "id",
|
||||||
|
"columnName": "pk_entity_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "accountId",
|
||||||
|
"columnName": "fk_account_id",
|
||||||
|
"affinity": "INTEGER",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "jid",
|
||||||
|
"columnName": "jid",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": true
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"fieldPath": "avatarFile",
|
||||||
|
"columnName": "avatar",
|
||||||
|
"affinity": "TEXT",
|
||||||
|
"notNull": false
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"primaryKey": {
|
||||||
|
"columnNames": [
|
||||||
|
"pk_entity_id"
|
||||||
|
],
|
||||||
|
"autoGenerate": true
|
||||||
|
},
|
||||||
|
"indices": [
|
||||||
|
{
|
||||||
|
"name": "index_entities_pk_entity_id",
|
||||||
|
"unique": false,
|
||||||
|
"columnNames": [
|
||||||
|
"pk_entity_id"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE INDEX `index_entities_pk_entity_id` ON `${TABLE_NAME}` (`pk_entity_id`)"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "index_entities_fk_account_id_jid",
|
||||||
|
"unique": true,
|
||||||
|
"columnNames": [
|
||||||
|
"fk_account_id",
|
||||||
|
"jid"
|
||||||
|
],
|
||||||
|
"createSql": "CREATE UNIQUE INDEX `index_entities_fk_account_id_jid` ON `${TABLE_NAME}` (`fk_account_id`, `jid`)"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"foreignKeys": [
|
||||||
|
{
|
||||||
|
"table": "accounts",
|
||||||
|
"onDelete": "CASCADE",
|
||||||
|
"onUpdate": "NO ACTION",
|
||||||
|
"columns": [
|
||||||
|
"fk_account_id"
|
||||||
|
],
|
||||||
|
"referencedColumns": [
|
||||||
|
"pk_account_id"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"tableName": "contacts",
|
"tableName": "contacts",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_contact_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `fk_entity_id` INTEGER NOT NULL, `rostername` TEXT, `nickname` TEXT, `direction` TEXT, `sub_pending` INTEGER NOT NULL, `approved` INTEGER NOT NULL, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`fk_entity_id`) REFERENCES `entities`(`pk_entity_id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_contact_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `fk_entity_id` INTEGER NOT NULL, `rostername` TEXT, `nickname` TEXT, `direction` TEXT, `sub_pending` INTEGER NOT NULL, `approved` INTEGER NOT NULL, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE , FOREIGN KEY(`fk_entity_id`) REFERENCES `entities`(`pk_entity_id`) ON UPDATE NO ACTION ON DELETE RESTRICT )",
|
||||||
|
@ -82,11 +203,11 @@
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "index_contacts_fk_entity_id",
|
"name": "index_contacts_fk_entity_id",
|
||||||
"unique": false,
|
"unique": true,
|
||||||
"columnNames": [
|
"columnNames": [
|
||||||
"fk_entity_id"
|
"fk_entity_id"
|
||||||
],
|
],
|
||||||
"createSql": "CREATE INDEX `index_contacts_fk_entity_id` ON `${TABLE_NAME}` (`fk_entity_id`)"
|
"createSql": "CREATE UNIQUE INDEX `index_contacts_fk_entity_id` ON `${TABLE_NAME}` (`fk_entity_id`)"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "index_contacts_pk_contact_id_fk_entity_id",
|
"name": "index_contacts_pk_contact_id_fk_entity_id",
|
||||||
|
@ -124,36 +245,18 @@
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tableName": "accounts",
|
"tableName": "roster_information",
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_account_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `jid` TEXT, `password` TEXT, `enabled` INTEGER NOT NULL, `state` TEXT)",
|
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_account_id` INTEGER NOT NULL, `roster_version` TEXT, PRIMARY KEY(`pk_account_id`))",
|
||||||
"fields": [
|
"fields": [
|
||||||
{
|
{
|
||||||
"fieldPath": "id",
|
"fieldPath": "accountId",
|
||||||
"columnName": "pk_account_id",
|
"columnName": "pk_account_id",
|
||||||
"affinity": "INTEGER",
|
"affinity": "INTEGER",
|
||||||
"notNull": true
|
"notNull": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"fieldPath": "jid",
|
"fieldPath": "rosterVersion",
|
||||||
"columnName": "jid",
|
"columnName": "roster_version",
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "password",
|
|
||||||
"columnName": "password",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "enabled",
|
|
||||||
"columnName": "enabled",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "state",
|
|
||||||
"columnName": "state",
|
|
||||||
"affinity": "TEXT",
|
"affinity": "TEXT",
|
||||||
"notNull": false
|
"notNull": false
|
||||||
}
|
}
|
||||||
|
@ -162,16 +265,16 @@
|
||||||
"columnNames": [
|
"columnNames": [
|
||||||
"pk_account_id"
|
"pk_account_id"
|
||||||
],
|
],
|
||||||
"autoGenerate": true
|
"autoGenerate": false
|
||||||
},
|
},
|
||||||
"indices": [
|
"indices": [
|
||||||
{
|
{
|
||||||
"name": "index_accounts_pk_account_id",
|
"name": "index_roster_information_pk_account_id",
|
||||||
"unique": false,
|
"unique": true,
|
||||||
"columnNames": [
|
"columnNames": [
|
||||||
"pk_account_id"
|
"pk_account_id"
|
||||||
],
|
],
|
||||||
"createSql": "CREATE INDEX `index_accounts_pk_account_id` ON `${TABLE_NAME}` (`pk_account_id`)"
|
"createSql": "CREATE UNIQUE INDEX `index_roster_information_pk_account_id` ON `${TABLE_NAME}` (`pk_account_id`)"
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": []
|
"foreignKeys": []
|
||||||
|
@ -322,74 +425,6 @@
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
},
|
},
|
||||||
{
|
|
||||||
"tableName": "entities",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_entity_id` INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL, `fk_account_id` INTEGER NOT NULL, `jid` TEXT NOT NULL, `avatar` TEXT, FOREIGN KEY(`fk_account_id`) REFERENCES `accounts`(`pk_account_id`) ON UPDATE NO ACTION ON DELETE CASCADE )",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "id",
|
|
||||||
"columnName": "pk_entity_id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "accountId",
|
|
||||||
"columnName": "fk_account_id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "jid",
|
|
||||||
"columnName": "jid",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "avatarFile",
|
|
||||||
"columnName": "avatar",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"columnNames": [
|
|
||||||
"pk_entity_id"
|
|
||||||
],
|
|
||||||
"autoGenerate": true
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_entities_pk_entity_id",
|
|
||||||
"unique": false,
|
|
||||||
"columnNames": [
|
|
||||||
"pk_entity_id"
|
|
||||||
],
|
|
||||||
"createSql": "CREATE INDEX `index_entities_pk_entity_id` ON `${TABLE_NAME}` (`pk_entity_id`)"
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "index_entities_fk_account_id_jid",
|
|
||||||
"unique": true,
|
|
||||||
"columnNames": [
|
|
||||||
"fk_account_id",
|
|
||||||
"jid"
|
|
||||||
],
|
|
||||||
"createSql": "CREATE UNIQUE INDEX `index_entities_fk_account_id_jid` ON `${TABLE_NAME}` (`fk_account_id`, `jid`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": [
|
|
||||||
{
|
|
||||||
"table": "accounts",
|
|
||||||
"onDelete": "CASCADE",
|
|
||||||
"onUpdate": "NO ACTION",
|
|
||||||
"columns": [
|
|
||||||
"fk_account_id"
|
|
||||||
],
|
|
||||||
"referencedColumns": [
|
|
||||||
"pk_account_id"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"tableName": "avatars",
|
"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 )",
|
"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 )",
|
||||||
|
@ -491,47 +526,12 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"foreignKeys": []
|
"foreignKeys": []
|
||||||
},
|
|
||||||
{
|
|
||||||
"tableName": "roster_information",
|
|
||||||
"createSql": "CREATE TABLE IF NOT EXISTS `${TABLE_NAME}` (`pk_account_id` INTEGER NOT NULL, `roster_version` TEXT, PRIMARY KEY(`pk_account_id`))",
|
|
||||||
"fields": [
|
|
||||||
{
|
|
||||||
"fieldPath": "accountId",
|
|
||||||
"columnName": "pk_account_id",
|
|
||||||
"affinity": "INTEGER",
|
|
||||||
"notNull": true
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"fieldPath": "rosterVersion",
|
|
||||||
"columnName": "roster_version",
|
|
||||||
"affinity": "TEXT",
|
|
||||||
"notNull": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"primaryKey": {
|
|
||||||
"columnNames": [
|
|
||||||
"pk_account_id"
|
|
||||||
],
|
|
||||||
"autoGenerate": false
|
|
||||||
},
|
|
||||||
"indices": [
|
|
||||||
{
|
|
||||||
"name": "index_roster_information_pk_account_id",
|
|
||||||
"unique": true,
|
|
||||||
"columnNames": [
|
|
||||||
"pk_account_id"
|
|
||||||
],
|
|
||||||
"createSql": "CREATE UNIQUE INDEX `index_roster_information_pk_account_id` ON `${TABLE_NAME}` (`pk_account_id`)"
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"foreignKeys": []
|
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"views": [],
|
"views": [],
|
||||||
"setupQueries": [
|
"setupQueries": [
|
||||||
"CREATE TABLE IF NOT EXISTS room_master_table (id INTEGER PRIMARY KEY,identity_hash TEXT)",
|
"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, 'cc1de3c4fd3350ea0e894d02f30312f3')"
|
"INSERT OR REPLACE INTO room_master_table (id,identity_hash) VALUES(42, 'fdd5152ff14dba77ae4dba978fc0bb11')"
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -43,4 +43,7 @@ public interface AccountDao extends BaseDao<RoomAccountModel> {
|
||||||
|
|
||||||
@Query("update accounts set state = :state where pk_account_id = :accountId")
|
@Query("update accounts set state = :state where pk_account_id = :accountId")
|
||||||
Completable updateConnectionState(long accountId, String state);
|
Completable updateConnectionState(long accountId, String state);
|
||||||
|
|
||||||
|
@Query("DELETE FROM accounts WHERE pk_account_id = :accountId")
|
||||||
|
Completable deleteAccount(long accountId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ import static org.mercury_im.messenger.persistence.room.model.RoomContactModel.T
|
||||||
indices = {
|
indices = {
|
||||||
@Index(value = KEY_ID),
|
@Index(value = KEY_ID),
|
||||||
@Index(value = KEY_ACCOUNT_ID),
|
@Index(value = KEY_ACCOUNT_ID),
|
||||||
@Index(value = KEY_ENTITY_ID),
|
@Index(value = KEY_ENTITY_ID, unique = true),
|
||||||
@Index(value = {KEY_ID, KEY_ENTITY_ID}, unique = true)
|
@Index(value = {KEY_ID, KEY_ENTITY_ID}, unique = true)
|
||||||
},
|
},
|
||||||
foreignKeys = {
|
foreignKeys = {
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
package org.mercury_im.messenger.persistence.room.repository;
|
package org.mercury_im.messenger.persistence.room.repository;
|
||||||
|
|
||||||
|
import org.mercury_im.messenger.persistence.model.AccountModel;
|
||||||
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
import org.mercury_im.messenger.persistence.repository.AccountRepository;
|
||||||
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
import org.mercury_im.messenger.persistence.room.dao.AccountDao;
|
||||||
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
import org.mercury_im.messenger.persistence.room.model.RoomAccountModel;
|
||||||
|
@ -47,4 +48,14 @@ public class IAccountRepository implements AccountRepository<RoomAccountModel> {
|
||||||
public Completable updateState(long accountId, String state) {
|
public Completable updateState(long accountId, String state) {
|
||||||
return accountDao.updateConnectionState(accountId, state);
|
return accountDao.updateConnectionState(accountId, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Completable deleteAccount(long accountId) {
|
||||||
|
return accountDao.deleteAccount(accountId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Completable deleteAccount(RoomAccountModel item) {
|
||||||
|
return accountDao.delete(item);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package org.mercury_im.messenger.persistence.room.repository;
|
package org.mercury_im.messenger.persistence.room.repository;
|
||||||
|
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
import org.jxmpp.jid.EntityBareJid;
|
import org.jxmpp.jid.EntityBareJid;
|
||||||
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
import org.mercury_im.messenger.persistence.repository.RosterRepository;
|
||||||
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
import org.mercury_im.messenger.persistence.room.dao.ContactDao;
|
||||||
|
@ -18,6 +20,9 @@ import io.reactivex.CompletableSource;
|
||||||
import io.reactivex.Maybe;
|
import io.reactivex.Maybe;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
import io.reactivex.SingleObserver;
|
||||||
|
import io.reactivex.SingleSource;
|
||||||
|
import io.reactivex.functions.Consumer;
|
||||||
import io.reactivex.functions.Function;
|
import io.reactivex.functions.Function;
|
||||||
|
|
||||||
public class IRosterRepository extends RosterRepository<RoomEntityModel, RoomContactModel, RoomRosterInformationModel> {
|
public class IRosterRepository extends RosterRepository<RoomEntityModel, RoomContactModel, RoomRosterInformationModel> {
|
||||||
|
@ -58,20 +63,28 @@ public class IRosterRepository extends RosterRepository<RoomEntityModel, RoomCon
|
||||||
public Observable<List<RoomContactModel>> getAllContactsOfAccount(long accountId) {
|
public Observable<List<RoomContactModel>> getAllContactsOfAccount(long accountId) {
|
||||||
return contactDao.getContactsForAccount(accountId)
|
return contactDao.getContactsForAccount(accountId)
|
||||||
.flatMap(list -> {
|
.flatMap(list -> {
|
||||||
for (RoomContactModel contact : list) {
|
for (RoomContactModel contact : list) {
|
||||||
RoomEntityModel entity = getEntityForContact(contact).blockingGet();
|
RoomEntityModel entity = getEntityForContact(contact).blockingGet();
|
||||||
contact.setEntity(entity);
|
contact.setEntity(entity);
|
||||||
}
|
}
|
||||||
return Observable.just(list);
|
return Observable.just(list);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<Long> updateOrInsertContact(RoomContactModel contact) {
|
public Single<Long> updateOrInsertContact(RoomContactModel contact) {
|
||||||
return entityDao.insert((RoomEntityModel) contact.getEntity())
|
//noinspection unchecked
|
||||||
.flatMap(entityId -> {
|
return entityDao.getEntityFor(contact.getAccountId(), contact.getEntity().getJid())
|
||||||
contact.getEntity().setId(entityId);
|
.switchIfEmpty(insertOrReplaceEntity((RoomEntityModel) contact.getEntity())
|
||||||
contact.setEntityId(entityId);
|
.flatMap(entityId -> {
|
||||||
|
Log.d("Mercury", "Insert entity since maybe did not emit: " + entityId);
|
||||||
|
contact.getEntity().setId(entityId);
|
||||||
|
return (SingleSource<RoomEntityModel>) observer ->
|
||||||
|
observer.onSuccess((RoomEntityModel) contact.getEntity());
|
||||||
|
}))
|
||||||
|
.flatMap(entityModel -> {
|
||||||
|
contact.setEntityId(entityModel.getId());
|
||||||
|
contact.setEntity(entityModel);
|
||||||
return contactDao.insert(contact);
|
return contactDao.insert(contact);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,4 +20,8 @@ public interface AccountRepository<E extends AccountModel> {
|
||||||
Single<Long> insertAccount(E accountModel);
|
Single<Long> insertAccount(E accountModel);
|
||||||
|
|
||||||
Completable updateState(long accountId, String state);
|
Completable updateState(long accountId, String state);
|
||||||
|
|
||||||
|
Completable deleteAccount(E item);
|
||||||
|
|
||||||
|
Completable deleteAccount(long accountId);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ import io.reactivex.Completable;
|
||||||
import io.reactivex.Maybe;
|
import io.reactivex.Maybe;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
import io.reactivex.functions.Consumer;
|
||||||
|
|
||||||
public abstract class RosterRepository<E extends EntityModel, C extends ContactModel, V extends RosterInformationModel> {
|
public abstract class RosterRepository<E extends EntityModel, C extends ContactModel, V extends RosterInformationModel> {
|
||||||
|
|
||||||
|
@ -73,6 +74,10 @@ public abstract class RosterRepository<E extends EntityModel, C extends ContactM
|
||||||
*/
|
*/
|
||||||
public abstract Maybe<C> getContact(long id);
|
public abstract Maybe<C> getContact(long id);
|
||||||
|
|
||||||
|
public Maybe<C> getContact(long accountId, EntityBareJid jid) {
|
||||||
|
return getEntity(accountId, jid).flatMap(this::getContactForEntity);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Return the {@link ContactModel} which belongs to the given entityId, wrapped in a {@link Maybe}.
|
* Return the {@link ContactModel} which belongs to the given entityId, wrapped in a {@link Maybe}.
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in a new issue