Refactoring

This commit is contained in:
Paul Schaub 2020-07-13 18:49:29 +02:00
parent aebbe29836
commit dc5df7117f
Signed by: vanitasvitae
GPG Key ID: 62BEE9264BF17311
43 changed files with 283 additions and 246 deletions

View File

@ -3,12 +3,13 @@ package org.mercury_im.messenger.android.di.component;
import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.di.module.AndroidDatabaseModule; import org.mercury_im.messenger.android.di.module.AndroidDatabaseModule;
import org.mercury_im.messenger.android.di.module.AndroidSchedulersModule; import org.mercury_im.messenger.android.di.module.AndroidSchedulersModule;
import org.mercury_im.messenger.android.ui.account.AndroidAccountDetailsViewModel; import org.mercury_im.messenger.android.ui.account.detail.AndroidAccountDetailsViewModel;
import org.mercury_im.messenger.android.ui.roster.contacts.AndroidContactListViewModel; import org.mercury_im.messenger.android.ui.roster.contacts.AndroidContactListViewModel;
import org.mercury_im.messenger.core.di.module.RxMercuryMessageStoreFactoryModule; import org.mercury_im.messenger.core.di.module.RxMercuryMessageStoreFactoryModule;
import org.mercury_im.messenger.core.di.module.RxMercuryRosterStoreFactoryModule; import org.mercury_im.messenger.core.di.module.RxMercuryRosterStoreFactoryModule;
import org.mercury_im.messenger.core.di.module.XmppTcpConnectionFactoryModule; import org.mercury_im.messenger.core.di.module.XmppTcpConnectionFactoryModule;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel;
import org.mercury_im.messenger.data.di.RepositoryModule; import org.mercury_im.messenger.data.di.RepositoryModule;
import org.mercury_im.messenger.android.di.module.AppModule; import org.mercury_im.messenger.android.di.module.AppModule;
@ -16,17 +17,16 @@ import org.mercury_im.messenger.core.di.module.ViewModelModule;
import org.mercury_im.messenger.android.service.MercuryForegroundService; import org.mercury_im.messenger.android.service.MercuryForegroundService;
import org.mercury_im.messenger.core.store.caps.MercuryEntityCapsStore; import org.mercury_im.messenger.core.store.caps.MercuryEntityCapsStore;
import org.mercury_im.messenger.android.ui.MainActivity; import org.mercury_im.messenger.android.ui.MainActivity;
import org.mercury_im.messenger.android.ui.account.AndroidAccountsViewModel; import org.mercury_im.messenger.android.ui.account.list.AndroidAccountListViewModel;
import org.mercury_im.messenger.android.ui.account.AndroidLoginViewModel; import org.mercury_im.messenger.android.ui.account.login.AndroidLoginViewModel;
import org.mercury_im.messenger.android.ui.chat.ChatActivity; import org.mercury_im.messenger.android.ui.chat.ChatActivity;
import org.mercury_im.messenger.android.ui.chat.ChatInputFragment; import org.mercury_im.messenger.android.ui.chat.ChatInputFragment;
import org.mercury_im.messenger.android.ui.chat.ChatInputViewModel; import org.mercury_im.messenger.android.ui.chat.ChatInputViewModel;
import org.mercury_im.messenger.android.ui.chat.AndroidChatViewModel; import org.mercury_im.messenger.android.ui.chat.AndroidChatViewModel;
import org.mercury_im.messenger.android.ui.chatlist.ChatListViewModel; import org.mercury_im.messenger.android.ui.chatlist.AndroidChatListViewModel;
import org.mercury_im.messenger.android.ui.roster.contacts.detail.ContactDetailActivity; import org.mercury_im.messenger.android.ui.roster.contacts.detail.ContactDetailActivity;
import org.mercury_im.messenger.android.ui.roster.contacts.detail.ContactDetailViewModel; import org.mercury_im.messenger.android.ui.roster.contacts.detail.ContactDetailViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountsViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -79,9 +79,9 @@ public interface AppComponent {
void inject(AndroidLoginViewModel androidLoginViewModel); void inject(AndroidLoginViewModel androidLoginViewModel);
void inject(AndroidAccountsViewModel androidAccountsViewModel); void inject(AndroidAccountListViewModel androidAccountsViewModel);
void inject(ChatListViewModel chatListViewModel); void inject(AndroidChatListViewModel chatListViewModel);
void inject(ContactDetailViewModel contactDetailViewModel); void inject(ContactDetailViewModel contactDetailViewModel);
@ -95,7 +95,7 @@ public interface AppComponent {
// Common VMs // Common VMs
void inject(LoginViewModel loginViewModel); void inject(LoginViewModel loginViewModel);
void inject(AccountsViewModel accountsViewModel); void inject(AccountListViewModel accountsViewModel);
// Services // Services

View File

@ -16,13 +16,13 @@ import com.google.android.material.navigation.NavigationView;
import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.account.AccountDetailsFragment; import org.mercury_im.messenger.android.ui.account.detail.AccountDetailsFragment;
import org.mercury_im.messenger.android.ui.account.DeleteAccountDialogFragment; import org.mercury_im.messenger.android.ui.account.DeleteAccountDialogFragment;
import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener; import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener;
import org.mercury_im.messenger.android.ui.account.list.AccountListFragment;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.android.ui.chatlist.ChatListFragment; import org.mercury_im.messenger.android.ui.chatlist.ChatListFragment;
import org.mercury_im.messenger.android.ui.account.AccountsFragment;
import org.mercury_im.messenger.android.ui.roster.RosterFragment; import org.mercury_im.messenger.android.ui.roster.RosterFragment;
import org.mercury_im.messenger.android.ui.settings.SettingsActivity; import org.mercury_im.messenger.android.ui.settings.SettingsActivity;
@ -43,7 +43,7 @@ public class MainActivity extends AppCompatActivity
private ChatListFragment chatListFragment = new ChatListFragment(); private ChatListFragment chatListFragment = new ChatListFragment();
private RosterFragment rosterFragment = new RosterFragment(); private RosterFragment rosterFragment = new RosterFragment();
private AccountsFragment accountsFragment = new AccountsFragment(); private AccountListFragment accountListFragment = new AccountListFragment();
private SearchView.OnQueryTextListener searchViewListeningFragment; private SearchView.OnQueryTextListener searchViewListeningFragment;
@Inject @Inject
@ -103,8 +103,8 @@ public class MainActivity extends AppCompatActivity
return true; return true;
case R.id.entry_accounts: case R.id.entry_accounts:
transaction.replace(R.id.fragment, accountsFragment).commit(); transaction.replace(R.id.fragment, accountListFragment).commit();
searchViewListeningFragment = accountsFragment; searchViewListeningFragment = accountListFragment;
return true; return true;
} }
return false; return false;
@ -112,7 +112,7 @@ public class MainActivity extends AppCompatActivity
@Override @Override
public void onAccountListItemClick(Account item) { public void onAccountListItemClick(Account item) {
getSupportFragmentManager().beginTransaction().addToBackStack("ACCOUNT") getSupportFragmentManager().beginTransaction()
.replace(R.id.fragment, new AccountDetailsFragment(item.getId())).commit(); .replace(R.id.fragment, new AccountDetailsFragment(item.getId())).commit();
} }

View File

@ -9,12 +9,13 @@ import androidx.appcompat.app.AppCompatDialogFragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.account.list.AndroidAccountListViewModel;
import java.util.UUID; import java.util.UUID;
public class DeleteAccountDialogFragment extends AppCompatDialogFragment { public class DeleteAccountDialogFragment extends AppCompatDialogFragment {
private AndroidAccountsViewModel viewModel; private AndroidAccountListViewModel viewModel;
private final UUID accountId; private final UUID accountId;
public DeleteAccountDialogFragment(UUID accountId) { public DeleteAccountDialogFragment(UUID accountId) {
@ -24,7 +25,7 @@ public class DeleteAccountDialogFragment extends AppCompatDialogFragment {
@Override @Override
@NonNull @NonNull
public Dialog onCreateDialog(Bundle savedInstanceState) { public Dialog onCreateDialog(Bundle savedInstanceState) {
viewModel = new ViewModelProvider(requireActivity()).get(AndroidAccountsViewModel.class); viewModel = new ViewModelProvider(requireActivity()).get(AndroidAccountListViewModel.class);
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
builder.setMessage("Do you really want to delete this account?") builder.setMessage("Do you really want to delete this account?")
.setPositiveButton(R.string.button_delete, (dialog, id) -> viewModel.onDeleteAccount(accountId)) .setPositiveButton(R.string.button_delete, (dialog, id) -> viewModel.onDeleteAccount(accountId))

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.detail;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
@ -19,8 +19,8 @@ import com.google.android.material.card.MaterialCardView;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.ToggleableFingerprintsAdapter; import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
import org.mercury_im.messenger.android.util.OpenPgpV4FingerprintFormatter; import org.mercury_im.messenger.android.ui.openpgp.OpenPgpV4FingerprintFormatter;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.UUID; import java.util.UUID;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.detail;
import android.app.Application; import android.app.Application;
@ -15,8 +15,8 @@ import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel; import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.ArrayList; import java.util.ArrayList;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.list;
import android.content.Context; import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
@ -15,11 +15,10 @@ import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton; import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener;
import org.mercury_im.messenger.android.ui.account.login.AddAccountDialogFragment;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.logging.Level;
import java.util.logging.Logger;
import butterknife.BindView; import butterknife.BindView;
import butterknife.ButterKnife; import butterknife.ButterKnife;
@ -30,13 +29,13 @@ import butterknife.ButterKnife;
* Activities containing this fragment MUST implement the {@link OnAccountListItemClickListener} * Activities containing this fragment MUST implement the {@link OnAccountListItemClickListener}
* interface. * interface.
*/ */
public class AccountsFragment extends Fragment implements SearchView.OnQueryTextListener { public class AccountListFragment extends Fragment implements SearchView.OnQueryTextListener {
private OnAccountListItemClickListener accountClickListener; private OnAccountListItemClickListener accountClickListener;
AndroidAccountsViewModel viewModel; AndroidAccountListViewModel viewModel;
private AccountsRecyclerViewAdapter adapter; private AccountListRecyclerViewAdapter adapter;
@BindView(R.id.list) @BindView(R.id.list)
RecyclerView recyclerView; RecyclerView recyclerView;
@ -44,15 +43,15 @@ public class AccountsFragment extends Fragment implements SearchView.OnQueryText
@BindView(R.id.fab) @BindView(R.id.fab)
ExtendedFloatingActionButton fab; ExtendedFloatingActionButton fab;
public AccountsFragment() { public AccountListFragment() {
} }
@Override @Override
public void onCreate(Bundle savedInstanceState) { public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(AndroidAccountsViewModel.class); viewModel = new ViewModelProvider(this).get(AndroidAccountListViewModel.class);
this.adapter = new AccountsRecyclerViewAdapter(viewModel, accountClickListener); this.adapter = new AccountListRecyclerViewAdapter(viewModel, accountClickListener);
} }
@Override @Override

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.list;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -12,7 +12,8 @@ import androidx.recyclerview.widget.RecyclerView;
import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.NotNull;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountViewItem; import org.mercury_im.messenger.android.ui.account.OnAccountListItemClickListener;
import org.mercury_im.messenger.core.viewmodel.account.list.AccountViewItem;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable; import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable;
import org.mercury_im.messenger.android.util.AbstractDiffCallback; import org.mercury_im.messenger.android.util.AbstractDiffCallback;
@ -20,13 +21,13 @@ import org.mercury_im.messenger.android.util.AbstractDiffCallback;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
public class AccountsRecyclerViewAdapter extends RecyclerView.Adapter<AccountsRecyclerViewAdapter.ViewHolder> { public class AccountListRecyclerViewAdapter extends RecyclerView.Adapter<AccountListRecyclerViewAdapter.ViewHolder> {
private final List<AccountViewItem> connectionStates = new ArrayList<>(); private final List<AccountViewItem> connectionStates = new ArrayList<>();
private final OnAccountListItemClickListener onAccountClickListener; private final OnAccountListItemClickListener onAccountClickListener;
private final AndroidAccountsViewModel viewModel; private final AndroidAccountListViewModel viewModel;
public AccountsRecyclerViewAdapter(AndroidAccountsViewModel viewModel, OnAccountListItemClickListener listener) { public AccountListRecyclerViewAdapter(AndroidAccountListViewModel viewModel, OnAccountListItemClickListener listener) {
onAccountClickListener = listener; onAccountClickListener = listener;
this.viewModel = viewModel; this.viewModel = viewModel;
} }

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.list;
import android.app.Application; import android.app.Application;
@ -8,10 +8,10 @@ import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import org.mercury_im.messenger.android.MercuryImApplication; import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountViewItem; import org.mercury_im.messenger.core.viewmodel.account.list.AccountViewItem;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel; import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountsViewModel; import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -21,16 +21,16 @@ import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;
public class AndroidAccountsViewModel extends AndroidViewModel implements MercuryAndroidViewModel<AccountsViewModel> { public class AndroidAccountListViewModel extends AndroidViewModel implements MercuryAndroidViewModel<AccountListViewModel> {
private static final Logger LOGGER = Logger.getLogger(AndroidAccountsViewModel.class.getName()); private static final Logger LOGGER = Logger.getLogger(AndroidAccountListViewModel.class.getName());
private final MutableLiveData<List<AccountViewItem>> accounts = new MutableLiveData<>(Collections.emptyList()); private final MutableLiveData<List<AccountViewItem>> accounts = new MutableLiveData<>(Collections.emptyList());
@Inject @Inject
AccountsViewModel viewModel; AccountListViewModel viewModel;
public AndroidAccountsViewModel(@NonNull Application application) { public AndroidAccountListViewModel(@NonNull Application application) {
super(application); super(application);
MercuryImApplication.getApplication().getAppComponent().inject(this); MercuryImApplication.getApplication().getAppComponent().inject(this);
@ -48,7 +48,7 @@ public class AndroidAccountsViewModel extends AndroidViewModel implements Mercur
} }
@Override @Override
public AccountsViewModel getCommonViewModel() { public AccountListViewModel getCommonViewModel() {
return viewModel; return viewModel;
} }

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.login;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.Dialog; import android.app.Dialog;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.account; package org.mercury_im.messenger.android.ui.account.login;
import android.app.Application; import android.app.Application;
@ -13,7 +13,7 @@ import org.mercury_im.messenger.android.util.TextChangedListener;
import org.mercury_im.messenger.core.account.error.PasswordError; import org.mercury_im.messenger.core.account.error.PasswordError;
import org.mercury_im.messenger.core.account.error.UsernameError; import org.mercury_im.messenger.core.account.error.UsernameError;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import javax.inject.Inject; import javax.inject.Inject;

View File

@ -41,21 +41,9 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
@Inject @Inject
ChatViewModel commonViewModel; ChatViewModel commonViewModel;
@Inject
PeerRepository contactRepository;
@Inject
DirectChatRepository chatRepository;
@Inject
MessageRepository messageRepository;
@Inject @Inject
SchedulersFacade schedulers; SchedulersFacade schedulers;
@Inject
Messenger messenger;
private MutableLiveData<Peer> contact = new MutableLiveData<>(); private MutableLiveData<Peer> contact = new MutableLiveData<>();
private MutableLiveData<List<Message>> messages = new MutableLiveData<>(); private MutableLiveData<List<Message>> messages = new MutableLiveData<>();
private MutableLiveData<String> contactDisplayName = new MutableLiveData<>(); private MutableLiveData<String> contactDisplayName = new MutableLiveData<>();
@ -67,10 +55,8 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
} }
public void init(UUID accountId, EntityBareJid jid) { public void init(UUID accountId, EntityBareJid jid) {
disposable.add(contactRepository.getOrCreatePeer(accountId, jid.toString()) commonViewModel.init(accountId, jid);
.flatMap(peer -> chatRepository.getOrCreateChatWithPeer(peer))
.subscribe(this::init,
error -> LOGGER.log(Level.SEVERE, "Error subscribing to peer data", error)));
} }
public void init(DirectChat chat) { public void init(DirectChat chat) {
@ -79,8 +65,8 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
this.commonViewModel.init(chat); this.commonViewModel.init(chat);
// Subscribe peer // Subscribe peer
disposable.add(commonViewModel.getPeer() disposable.add(commonViewModel.getContactDisplayName()
.subscribe(peer -> contactDisplayName.setValue(peer.getName()), .subscribe(name -> contactDisplayName.setValue(name),
error -> LOGGER.log(Level.SEVERE, "Error subscribing display name to peer", error))); error -> LOGGER.log(Level.SEVERE, "Error subscribing display name to peer", error)));
// Subscribe messages // Subscribe messages
@ -112,20 +98,11 @@ public class AndroidChatViewModel extends ViewModel implements MercuryAndroidVie
} }
public void deleteContact() { public void deleteContact() {
Peer contact = getContact().getValue(); getCommonViewModel().deleteContact();
disposable.add(messenger.deleteContact(contact)
.subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler())
.subscribe(
() -> LOGGER.log(Level.INFO, "Contact deleted."),
e -> LOGGER.log(Level.SEVERE, e.getMessage(), e)));
} }
public void sendMessage(String body) { public void sendMessage(String body) {
disposable.add(messenger.sendEncryptedMessage(getContact().getValue(), body) getCommonViewModel().sendMessage(body);
.subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler())
.subscribe());
} }
@Override @Override

View File

@ -11,7 +11,7 @@ import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.entity.message.Message; import org.mercury_im.messenger.entity.message.Message;
import org.mercury_im.messenger.android.ui.util.MessageBackgroundDrawable; import org.mercury_im.messenger.android.ui.chat.util.MessageBackgroundDrawable;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.util; package org.mercury_im.messenger.android.ui.chat.util;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;

View File

@ -0,0 +1,55 @@
package org.mercury_im.messenger.android.ui.chatlist;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.viewmodel.chat.ChatListViewModel;
import org.mercury_im.messenger.entity.chat.DirectChat;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable;
public class AndroidChatListViewModel extends AndroidViewModel implements MercuryAndroidViewModel<ChatListViewModel> {
@Inject
DirectChatRepository chatRepository;
@Inject
ChatListViewModel commonViewModel;
@Inject
SchedulersFacade schedulers;
private final MutableLiveData<List<DirectChat>> chats = new MutableLiveData<>(new ArrayList<>());
public AndroidChatListViewModel(@NonNull Application application) {
super(application);
((MercuryImApplication) application).getAppComponent().inject(this);
addDisposable(commonViewModel.observeAllDirectChats()
.compose(schedulers.executeUiSafeObservable())
.subscribe(chats::setValue));
}
public LiveData<List<DirectChat>> getChats() {
return chats;
}
@Override
public ChatListViewModel getCommonViewModel() {
return commonViewModel;
}
}

View File

@ -25,7 +25,7 @@ import butterknife.ButterKnife;
public class ChatListFragment extends Fragment implements SearchView.OnQueryTextListener { public class ChatListFragment extends Fragment implements SearchView.OnQueryTextListener {
private ChatListViewModel viewModel; private AndroidChatListViewModel viewModel;
@BindView(R.id.chat_list__recycler_view) @BindView(R.id.chat_list__recycler_view)
RecyclerView recyclerView; RecyclerView recyclerView;
@ -37,7 +37,7 @@ public class ChatListFragment extends Fragment implements SearchView.OnQueryText
@Override @Override
public void onCreate(@Nullable Bundle savedInstanceState) { public void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
viewModel = new ViewModelProvider(this).get(ChatListViewModel.class); viewModel = new ViewModelProvider(this).get(AndroidChatListViewModel.class);
} }
@Nullable @Nullable

View File

@ -1,43 +0,0 @@
package org.mercury_im.messenger.android.ui.chatlist;
import androidx.lifecycle.LiveData;
import androidx.lifecycle.MutableLiveData;
import androidx.lifecycle.ViewModel;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.entity.chat.DirectChat;
import java.util.ArrayList;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.disposables.CompositeDisposable;
public class ChatListViewModel extends ViewModel {
@Inject
DirectChatRepository chatRepository;
private CompositeDisposable disposable = new CompositeDisposable();
private final MutableLiveData<List<DirectChat>> chats = new MutableLiveData<>(new ArrayList<>());
public ChatListViewModel() {
MercuryImApplication.getApplication().getAppComponent().inject(this);
disposable.add(chatRepository.observeAllDirectChats()
.subscribe(chats::setValue));
}
public LiveData<List<DirectChat>> getChats() {
return chats;
}
@Override
protected void onCleared() {
super.onCleared();
disposable.dispose();
}
}

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.ox; package org.mercury_im.messenger.android.ui.openpgp;
import android.app.Application; import android.app.Application;
@ -6,17 +6,14 @@ import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.MutableLiveData; import androidx.lifecycle.MutableLiveData;
import org.mercury_im.messenger.android.MercuryImApplication;
import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel; import org.mercury_im.messenger.android.ui.MercuryAndroidViewModel;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.ox.OxBackupRestoreError; import org.mercury_im.messenger.core.viewmodel.openpgp.OxBackupRestoreError;
import org.mercury_im.messenger.core.viewmodel.ox.OxSecretKeyBackupRestoreViewModel; import org.mercury_im.messenger.core.viewmodel.openpgp.OxSecretKeyBackupRestoreViewModel;
import java.util.logging.Level; import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject;
public class AndroidOxSecretKeyBackupRestoreViewModel extends AndroidViewModel public class AndroidOxSecretKeyBackupRestoreViewModel extends AndroidViewModel
implements MercuryAndroidViewModel<OxSecretKeyBackupRestoreViewModel> { implements MercuryAndroidViewModel<OxSecretKeyBackupRestoreViewModel> {

View File

@ -1,10 +1,11 @@
package org.mercury_im.messenger.android.util; package org.mercury_im.messenger.android.ui.openpgp;
import android.text.Spannable; import android.text.Spannable;
import android.text.SpannableString; import android.text.SpannableString;
import android.text.style.ForegroundColorSpan; import android.text.style.ForegroundColorSpan;
import org.jivesoftware.smackx.colors.ConsistentColor; import org.jivesoftware.smackx.colors.ConsistentColor;
import org.mercury_im.messenger.android.util.ColorUtil;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;
public class OpenPgpV4FingerprintFormatter { public class OpenPgpV4FingerprintFormatter {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui.ox; package org.mercury_im.messenger.android.ui.openpgp;
import android.os.Bundle; import android.os.Bundle;
import android.view.LayoutInflater; import android.view.LayoutInflater;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.android.ui; package org.mercury_im.messenger.android.ui.openpgp;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -10,8 +10,7 @@ import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.util.OpenPgpV4FingerprintFormatter; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.text.DateFormat; import java.text.DateFormat;

View File

@ -1,26 +0,0 @@
package org.mercury_im.messenger.android.ui.roster.contacts;
import android.app.Application;
import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel;
import androidx.lifecycle.LiveData;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.entity.contact.Peer;
import javax.inject.Inject;
public class ContactListItemViewModel extends AndroidViewModel {
@Inject
PeerRepository contactRepository;
private LiveData<Peer> contact;
@Inject
public ContactListItemViewModel(@NonNull Application application) {
super(application);
}
}

View File

@ -18,7 +18,6 @@ import androidx.annotation.Nullable;
import androidx.fragment.app.Fragment; import androidx.fragment.app.Fragment;
import androidx.lifecycle.ViewModelProvider; import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelStoreOwner; import androidx.lifecycle.ViewModelStoreOwner;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.card.MaterialCardView; import com.google.android.material.card.MaterialCardView;
@ -26,14 +25,12 @@ import com.google.android.material.chip.Chip;
import com.google.android.material.chip.ChipGroup; import com.google.android.material.chip.ChipGroup;
import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton; import com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton;
import org.mercury_im.messenger.android.ui.ToggleableFingerprintsAdapter; import org.mercury_im.messenger.android.ui.openpgp.ToggleableFingerprintsAdapter;
import org.mercury_im.messenger.android.util.OpenPgpV4FingerprintFormatter;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.R; import org.mercury_im.messenger.R;
import org.mercury_im.messenger.android.ui.chat.ChatActivity; import org.mercury_im.messenger.android.ui.chat.ChatActivity;
import org.mercury_im.messenger.android.util.ColorUtil; import org.mercury_im.messenger.android.util.ColorUtil;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;

View File

@ -24,7 +24,7 @@ import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.contact.Peer;
import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable; import org.mercury_im.messenger.android.ui.avatar.AvatarDrawable;
import org.mercury_im.messenger.core.util.CombinedPresenceListener; import org.mercury_im.messenger.core.util.CombinedPresenceListener;
@ -38,9 +38,7 @@ import java.util.UUID;
import javax.inject.Inject; import javax.inject.Inject;
import io.reactivex.Completable; import io.reactivex.Completable;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.CompositeDisposable; import io.reactivex.disposables.CompositeDisposable;
import io.reactivex.schedulers.Schedulers;
public class ContactDetailViewModel extends ViewModel { public class ContactDetailViewModel extends ViewModel {
@ -77,11 +75,12 @@ public class ContactDetailViewModel extends ViewModel {
public void bind(UUID accountId, String peerAddress) { public void bind(UUID accountId, String peerAddress) {
Log.d("MMMMMM", "Bind!"); Log.d("MMMMMM", "Bind!");
EntityBareJid peerJid = JidCreate.entityBareFromOrThrowUnchecked(peerAddress);
roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection()); roster = Roster.getInstanceFor(messenger.getConnectionManager().getConnection(accountId).getConnection());
roster.addPresenceEventListener(presenceEventListener); roster.addPresenceEventListener(presenceEventListener);
contactAddress.setValue(peerAddress); contactAddress.setValue(peerAddress);
contactAccountId.setValue(accountId); contactAccountId.setValue(accountId);
disposable.add(peerRepository.observePeerByAddress(accountId, peerAddress) disposable.add(peerRepository.observePeerByAddress(accountId, peerJid)
.subscribeOn(schedulers.getIoScheduler()) .subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler()) .observeOn(schedulers.getUiScheduler())
.subscribe(peerOptional -> { .subscribe(peerOptional -> {
@ -104,15 +103,13 @@ public class ContactDetailViewModel extends ViewModel {
} }
})); }));
EntityBareJid jid = JidCreate.entityBareFromOrThrowUnchecked(peerAddress); Presence presence = roster.getPresence(peerJid);
Presence presence = roster.getPresence(jid);
if (presence != null) { if (presence != null) {
contactPresenceMode.postValue(presence.getMode()); contactPresenceMode.postValue(presence.getMode());
contactPresenceStatus.postValue(presence.getStatus()); contactPresenceStatus.postValue(presence.getStatus());
} }
disposable.add(openPgpRepository.observeFingerprints(accountId, jid) disposable.add(openPgpRepository.observeFingerprints(accountId, peerJid)
.subscribeOn(schedulers.getIoScheduler()) .subscribeOn(schedulers.getIoScheduler())
.observeOn(schedulers.getUiScheduler()) .observeOn(schedulers.getUiScheduler())
.subscribe(list -> contactFingerprints.setValue(list))); .subscribe(list -> contactFingerprints.setValue(list)));

View File

@ -14,7 +14,7 @@
android:layout_marginLeft="16dp" android:layout_marginLeft="16dp"
android:layout_marginRight="16dp" android:layout_marginRight="16dp"
app:layoutManager="LinearLayoutManager" app:layoutManager="LinearLayoutManager"
tools:context=".android.ui.account.AccountsFragment" tools:context=".android.ui.account.list.AccountListFragment"
tools:listitem="@layout/list_item_account" /> tools:listitem="@layout/list_item_account" />
<com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton <com.google.android.material.floatingactionbutton.ExtendedFloatingActionButton

View File

@ -9,7 +9,7 @@ import org.jxmpp.stringprep.XmppStringprepException;
import org.mercury_im.messenger.cli.di.component.CliComponent; import org.mercury_im.messenger.cli.di.component.CliComponent;
import org.mercury_im.messenger.cli.di.component.DaggerCliComponent; import org.mercury_im.messenger.cli.di.component.DaggerCliComponent;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnection; import org.mercury_im.messenger.core.xmpp.MercuryConnection;
import java.util.List; import java.util.List;

View File

@ -3,14 +3,13 @@ package org.mercury_im.messenger.data.repository;
import org.bouncycastle.openpgp.PGPPublicKeyRing; import org.bouncycastle.openpgp.PGPPublicKeyRing;
import org.bouncycastle.openpgp.PGPPublicKeyRingCollection; import org.bouncycastle.openpgp.PGPPublicKeyRingCollection;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jivesoftware.smackx.bytestreams.ibb.packet.Open;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.jxmpp.jid.impl.JidCreate; import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.data.model.AnnouncedOpenPgpContactKey; import org.mercury_im.messenger.data.model.AnnouncedOpenPgpContactKey;
import org.mercury_im.messenger.data.model.OpenPgpKeyFetchDate; import org.mercury_im.messenger.data.model.OpenPgpKeyFetchDate;
import org.mercury_im.messenger.data.model.OpenPgpKeyTrust; import org.mercury_im.messenger.data.model.OpenPgpKeyTrust;

View File

@ -1,5 +1,6 @@
package org.mercury_im.messenger.data.repository; package org.mercury_im.messenger.data.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository; import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
@ -62,38 +63,38 @@ public class RxPeerRepository
} }
@Override @Override
public Observable<Optional<Peer>> observePeerByAddress(UUID accountId, String address) { public Observable<Optional<Peer>> observePeerByAddress(UUID accountId, EntityBareJid address) {
return data().select(PeerModel.class) return data().select(PeerModel.class)
.where(PeerModel.ACCOUNT_ID.eq(accountId)) .where(PeerModel.ACCOUNT_ID.eq(accountId))
.and(PeerModel.ADDRESS.eq(address)) .and(PeerModel.ADDRESS.eq(address.asEntityBareJidString()))
.get().observableResult() .get().observableResult()
.map(result -> new Optional<>(result.firstOrNull())) .map(result -> new Optional<>(result.firstOrNull()))
.map(peerMapping::toEntity); .map(peerMapping::toEntity);
} }
@Override @Override
public Single<Peer> getOrCreatePeer(UUID accountId, String address) { public Single<Peer> getOrCreatePeer(UUID accountId, EntityBareJid address) {
return accountRepository.getAccount(accountId).toSingle() return accountRepository.getAccount(accountId).toSingle()
.flatMap(account -> getOrCreatePeer(account, address)); .flatMap(account -> getOrCreatePeer(account, address));
} }
@Override @Override
public Maybe<Peer> getPeerByAddress(UUID accountId, String address) { public Maybe<Peer> getPeerByAddress(UUID accountId, EntityBareJid address) {
return data().select(PeerModel.class) return data().select(PeerModel.class)
.where(PeerModel.ACCOUNT_ID.eq(accountId)) .where(PeerModel.ACCOUNT_ID.eq(accountId))
.and(PeerModel.ADDRESS.eq(address)) .and(PeerModel.ADDRESS.eq(address.asEntityBareJidString()))
.get().maybe() .get().maybe()
.map(peerMapping::toEntity); .map(peerMapping::toEntity);
} }
@Override @Override
public Single<Peer> getOrCreatePeer(Account account, String address) { public Single<Peer> getOrCreatePeer(Account account, EntityBareJid address) {
return getPeerByAddress(account, address) return getPeerByAddress(account, address)
.switchIfEmpty( .switchIfEmpty(
Single.just(new Peer()) Single.just(new Peer())
.map(peer -> { .map(peer -> {
peer.setAccount(account); peer.setAccount(account);
peer.setAddress(address); peer.setAddress(address.asEntityBareJidString());
return peer; return peer;
}) })
.flatMap(this::upsertPeer)); .flatMap(this::upsertPeer));
@ -162,10 +163,10 @@ public class RxPeerRepository
} }
@Override @Override
public Completable deletePeer(UUID accountId, String address) { public Completable deletePeer(UUID accountId, EntityBareJid address) {
return data().delete(PeerModel.class) return data().delete(PeerModel.class)
.where(PeerModel.ACCOUNT_ID.eq(accountId) .where(PeerModel.ACCOUNT_ID.eq(accountId)
.and(PeerModel.ADDRESS.eq(address))) .and(PeerModel.ADDRESS.eq(address.asEntityBareJidString())))
.get().single().ignoreElement(); .get().single().ignoreElement();
} }

View File

@ -5,7 +5,7 @@ import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.accounts.FingerprintViewItem; import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;
import java.util.Date; import java.util.Date;

View File

@ -1,5 +1,6 @@
package org.mercury_im.messenger.core.data.repository; package org.mercury_im.messenger.core.data.repository;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.mercury_im.messenger.entity.contact.Peer; import org.mercury_im.messenger.entity.contact.Peer;
@ -24,21 +25,21 @@ public interface PeerRepository {
Maybe<Peer> getPeer(UUID PeerId); Maybe<Peer> getPeer(UUID PeerId);
default Observable<Optional<Peer>> observePeerByAddress(Account account, String address) { default Observable<Optional<Peer>> observePeerByAddress(Account account, EntityBareJid address) {
return observePeerByAddress(account.getId(), address); return observePeerByAddress(account.getId(), address);
} }
Observable<Optional<Peer>> observePeerByAddress(UUID accountId, String address); Observable<Optional<Peer>> observePeerByAddress(UUID accountId, EntityBareJid address);
default Maybe<Peer> getPeerByAddress(Account account, String address) { default Maybe<Peer> getPeerByAddress(Account account, EntityBareJid address) {
return getPeerByAddress(account.getId(), address); return getPeerByAddress(account.getId(), address);
} }
Maybe<Peer> getPeerByAddress(UUID accountId, String address); Maybe<Peer> getPeerByAddress(UUID accountId, EntityBareJid address);
Single<Peer> getOrCreatePeer(Account account, String address); Single<Peer> getOrCreatePeer(Account account, EntityBareJid address);
Single<Peer> getOrCreatePeer(UUID accountId, String address); Single<Peer> getOrCreatePeer(UUID accountId, EntityBareJid address);
Observable<List<Peer>> observeAllPeers(); Observable<List<Peer>> observeAllPeers();
@ -54,7 +55,7 @@ public interface PeerRepository {
Completable deletePeer(Peer Peer); Completable deletePeer(Peer Peer);
Completable deletePeer(UUID accountId, String address); Completable deletePeer(UUID accountId, EntityBareJid address);
default Completable deleteAllPeers(Account account) { default Completable deleteAllPeers(Account account) {
return deleteAllPeers(account.getId()); return deleteAllPeers(account.getId());

View File

@ -1,10 +1,10 @@
package org.mercury_im.messenger.core.di.component; package org.mercury_im.messenger.core.di.component;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountsViewModel; import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel;
import org.mercury_im.messenger.core.viewmodel.ox.OxSecretKeyBackupRestoreViewModel; import org.mercury_im.messenger.core.viewmodel.openpgp.OxSecretKeyBackupRestoreViewModel;
import dagger.Component; import dagger.Component;
@ -13,7 +13,7 @@ public interface CoreComponent {
void inject(LoginViewModel viewModel); void inject(LoginViewModel viewModel);
void inject(AccountsViewModel viewModel); void inject(AccountListViewModel viewModel);
void inject(AccountDetailsViewModel viewModel); void inject(AccountDetailsViewModel viewModel);

View File

@ -3,11 +3,15 @@ package org.mercury_im.messenger.core.di.module;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.AccountRepository; import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountDetailsViewModel; import org.mercury_im.messenger.core.viewmodel.account.detail.AccountDetailsViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.AccountsViewModel; import org.mercury_im.messenger.core.viewmodel.account.list.AccountListViewModel;
import org.mercury_im.messenger.core.viewmodel.accounts.LoginViewModel; import org.mercury_im.messenger.core.viewmodel.account.LoginViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatListViewModel;
import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel; import org.mercury_im.messenger.core.viewmodel.chat.ChatViewModel;
import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager; import org.mercury_im.messenger.core.xmpp.MercuryConnectionManager;
@ -29,11 +33,11 @@ public class ViewModelModule {
@Provides @Provides
@Singleton @Singleton
static AccountsViewModel provideAccountsViewModel(MercuryConnectionManager connectionManager, static AccountListViewModel provideAccountsViewModel(MercuryConnectionManager connectionManager,
AccountRepository accountRepository, AccountRepository accountRepository,
OpenPgpRepository openPgpRepository, OpenPgpRepository openPgpRepository,
SchedulersFacade schedulers) { SchedulersFacade schedulers) {
return new AccountsViewModel(connectionManager, accountRepository, openPgpRepository, schedulers); return new AccountListViewModel(connectionManager, accountRepository, openPgpRepository, schedulers);
} }
@Provides @Provides
@ -46,9 +50,20 @@ public class ViewModelModule {
@Provides @Provides
@Singleton @Singleton
static ChatViewModel provideChatViewModel(Messenger messenger, Repositories repositories, SchedulersFacade schedulers) { static ChatViewModel provideChatViewModel(Messenger messenger,
return new ChatViewModel(messenger, repositories, schedulers); PeerRepository peerRepository,
DirectChatRepository directChatRepository,
MessageRepository messageRepository,
SchedulersFacade schedulers) {
return new ChatViewModel(messenger, peerRepository, directChatRepository, messageRepository, schedulers);
} }
@Provides
@Singleton
static ChatListViewModel provideChatListViewModel(DirectChatRepository directChatRepository, SchedulersFacade schedulers) {
return new ChatListViewModel(directChatRepository, schedulers);
}
/* /*
@Provides @Provides
@Singleton @Singleton

View File

@ -72,7 +72,7 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
if (smackMessage.getBody() != null) { if (smackMessage.getBody() != null) {
message.setBody(smackMessage.getBody()); message.setBody(smackMessage.getBody());
} }
disposable.add(writeMessageToStore(from.asEntityBareJidString(), message)); disposable.add(writeMessageToStore(from, message));
} }
@Override @Override
@ -91,10 +91,10 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
if (smackMessage.getBody() != null) { if (smackMessage.getBody() != null) {
message.setBody(smackMessage.getBody()); message.setBody(smackMessage.getBody());
} }
disposable.add(writeMessageToStore(to.asEntityBareJidString(), message)); disposable.add(writeMessageToStore(to, message));
} }
private Disposable writeMessageToStore(String peer, Message message) { private Disposable writeMessageToStore(EntityBareJid peer, Message message) {
return peerRepository.getOrCreatePeer(account, peer) return peerRepository.getOrCreatePeer(account, peer)
.flatMap(directChatRepository::getOrCreateChatWithPeer) .flatMap(directChatRepository::getOrCreateChatWithPeer)
.flatMap(chat -> messageRepository.insertMessage(chat, message)) .flatMap(chat -> messageRepository.insertMessage(chat, message))
@ -119,6 +119,6 @@ public class MercuryMessageStore implements IncomingChatMessageListener, Outgoin
if (body != null) { if (body != null) {
message.setBody(body.getMessage()); message.setBody(body.getMessage());
} }
disposable.add(writeMessageToStore(contact.getJid().toString(), message)); disposable.add(writeMessageToStore(contact.getJid().asEntityBareJidOrThrow(), message));
} }
} }

View File

@ -112,7 +112,7 @@ public class MercuryRosterStore implements RosterStore {
} }
private void writeEntryToDatabase(RosterPacket.Item item) { private void writeEntryToDatabase(RosterPacket.Item item) {
disposable.add(peerRepository.getOrCreatePeer(accountId, item.getJid().asUnescapedString()) disposable.add(peerRepository.getOrCreatePeer(accountId, item.getJid().asEntityBareJidOrThrow())
.map(peer -> toEntity(item, peer)) .map(peer -> toEntity(item, peer))
.flatMap(peerRepository::upsertPeer) .flatMap(peerRepository::upsertPeer)
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
@ -158,7 +158,7 @@ public class MercuryRosterStore implements RosterStore {
public boolean removeEntry(Jid bareJid, String version) { public boolean removeEntry(Jid bareJid, String version) {
LOGGER.log(Level.INFO, "Remove entry " + bareJid.toString()); LOGGER.log(Level.INFO, "Remove entry " + bareJid.toString());
disposable.add(peerRepository.deletePeer(accountId, bareJid.asEntityBareJidOrThrow().asEntityBareJidString()) disposable.add(peerRepository.deletePeer(accountId, bareJid.asEntityBareJidOrThrow())
.subscribeOn(Schedulers.io()) .subscribeOn(Schedulers.io())
.observeOn(Schedulers.computation()) .observeOn(Schedulers.computation())
.subscribe( .subscribe(

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.accounts; package org.mercury_im.messenger.core.viewmodel.account;
import org.jivesoftware.smack.util.StringUtils; import org.jivesoftware.smack.util.StringUtils;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
@ -16,7 +16,6 @@ import org.mercury_im.messenger.core.xmpp.exception.InvalidCredentialsException;
import org.mercury_im.messenger.core.xmpp.exception.ServerUnreachableException; import org.mercury_im.messenger.core.xmpp.exception.ServerUnreachableException;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import java.util.logging.Level;
import java.util.logging.Logger; import java.util.logging.Logger;
import javax.inject.Inject; import javax.inject.Inject;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.accounts; package org.mercury_im.messenger.core.viewmodel.account.detail;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;
@ -7,6 +7,7 @@ import org.mercury_im.messenger.core.data.repository.AccountRepository;
import org.mercury_im.messenger.core.data.repository.OpenPgpRepository; import org.mercury_im.messenger.core.data.repository.OpenPgpRepository;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.core.viewmodel.openpgp.FingerprintViewItem;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;
import org.pgpainless.key.OpenPgpV4Fingerprint; import org.pgpainless.key.OpenPgpV4Fingerprint;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.accounts; package org.mercury_im.messenger.core.viewmodel.account.list;
import org.bouncycastle.openpgp.PGPSecretKeyRingCollection; import org.bouncycastle.openpgp.PGPSecretKeyRingCollection;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
@ -25,9 +25,9 @@ import io.reactivex.Observable;
import io.reactivex.ObservableSource; import io.reactivex.ObservableSource;
import io.reactivex.ObservableTransformer; import io.reactivex.ObservableTransformer;
public class AccountsViewModel implements MercuryViewModel { public class AccountListViewModel implements MercuryViewModel {
private static final Logger LOGGER = Logger.getLogger(AccountsViewModel.class.getName()); private static final Logger LOGGER = Logger.getLogger(AccountListViewModel.class.getName());
private final MercuryConnectionManager connectionManager; private final MercuryConnectionManager connectionManager;
private final AccountRepository accountRepository; private final AccountRepository accountRepository;
@ -35,10 +35,10 @@ public class AccountsViewModel implements MercuryViewModel {
private final SchedulersFacade schedulers; private final SchedulersFacade schedulers;
@Inject @Inject
public AccountsViewModel(MercuryConnectionManager connectionManager, public AccountListViewModel(MercuryConnectionManager connectionManager,
AccountRepository accountRepository, AccountRepository accountRepository,
OpenPgpRepository openPgpRepository, OpenPgpRepository openPgpRepository,
SchedulersFacade schedulers) { SchedulersFacade schedulers) {
this.connectionManager = connectionManager; this.connectionManager = connectionManager;
this.accountRepository = accountRepository; this.accountRepository = accountRepository;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.accounts; package org.mercury_im.messenger.core.viewmodel.account.list;
import org.mercury_im.messenger.core.xmpp.state.ConnectivityState; import org.mercury_im.messenger.core.xmpp.state.ConnectivityState;
import org.mercury_im.messenger.entity.Account; import org.mercury_im.messenger.entity.Account;

View File

@ -0,0 +1,28 @@
package org.mercury_im.messenger.core.viewmodel.chat;
import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
import org.mercury_im.messenger.entity.chat.DirectChat;
import java.util.List;
import javax.inject.Inject;
import io.reactivex.Observable;
public class ChatListViewModel implements MercuryViewModel {
private final SchedulersFacade schedulers;
private final DirectChatRepository directChatRepository;
@Inject
public ChatListViewModel(DirectChatRepository directChatRepository, SchedulersFacade schedulers) {
this.directChatRepository = directChatRepository;
this.schedulers = schedulers;
}
public Observable<List<DirectChat>> observeAllDirectChats() {
return directChatRepository.observeAllDirectChats();
}
}

View File

@ -1,7 +1,11 @@
package org.mercury_im.messenger.core.viewmodel.chat; package org.mercury_im.messenger.core.viewmodel.chat;
import org.jxmpp.jid.EntityBareJid;
import org.mercury_im.messenger.core.Messenger; import org.mercury_im.messenger.core.Messenger;
import org.mercury_im.messenger.core.SchedulersFacade; import org.mercury_im.messenger.core.SchedulersFacade;
import org.mercury_im.messenger.core.data.repository.DirectChatRepository;
import org.mercury_im.messenger.core.data.repository.MessageRepository;
import org.mercury_im.messenger.core.data.repository.PeerRepository;
import org.mercury_im.messenger.core.data.repository.Repositories; import org.mercury_im.messenger.core.data.repository.Repositories;
import org.mercury_im.messenger.core.util.Optional; import org.mercury_im.messenger.core.util.Optional;
import org.mercury_im.messenger.core.viewmodel.MercuryViewModel; import org.mercury_im.messenger.core.viewmodel.MercuryViewModel;
@ -10,6 +14,9 @@ import org.mercury_im.messenger.entity.contact.Peer;
import org.mercury_im.messenger.entity.message.Message; import org.mercury_im.messenger.entity.message.Message;
import java.util.List; import java.util.List;
import java.util.UUID;
import java.util.logging.Level;
import java.util.logging.Logger;
import io.reactivex.Observable; import io.reactivex.Observable;
import io.reactivex.subjects.BehaviorSubject; import io.reactivex.subjects.BehaviorSubject;
@ -17,13 +24,17 @@ import lombok.Getter;
public class ChatViewModel implements MercuryViewModel { public class ChatViewModel implements MercuryViewModel {
private static final Logger LOGGER = Logger.getLogger(ChatViewModel.class.getName());
private final Messenger messenger; private final Messenger messenger;
private final Repositories repositories; private final PeerRepository contactRepository;
private final DirectChatRepository directChatRepository;
private final MessageRepository messageRepository;
private final SchedulersFacade schedulers; private final SchedulersFacade schedulers;
private DirectChat chat; private DirectChat chat;
@Getter @Getter
private Observable<Peer> peer; private BehaviorSubject<Optional<Peer>> peer = BehaviorSubject.createDefault(new Optional<>());
@Getter @Getter
private Observable<List<Message>> messages; private Observable<List<Message>> messages;
@ -35,31 +46,58 @@ public class ChatViewModel implements MercuryViewModel {
public ChatViewModel(Messenger messenger, public ChatViewModel(Messenger messenger,
Repositories repositories, PeerRepository peerRepository,
DirectChatRepository directChatRepository,
MessageRepository messageRepository,
SchedulersFacade schedulers) { SchedulersFacade schedulers) {
this.messenger = messenger; this.messenger = messenger;
this.repositories = repositories; this.contactRepository = peerRepository;
this.directChatRepository = directChatRepository;
this.messageRepository = messageRepository;
this.schedulers = schedulers; this.schedulers = schedulers;
} }
public void init(UUID accountId, EntityBareJid contactJid) {
addDisposable(contactRepository.getOrCreatePeer(accountId, contactJid)
.flatMap(directChatRepository::getOrCreateChatWithPeer)
.subscribe(this::init,
e -> LOGGER.log(Level.SEVERE, "Error subscribing to peer data", e)));
}
public void init(DirectChat directChat) { public void init(DirectChat directChat) {
this.chat = directChat; this.chat = directChat;
//peer = repositories.getPeerRepository().observePeer(chat.getPeer());
messageQueryObservable.onNext(repositories.getMessageRepository().observeMessages(chat)); messageQueryObservable.onNext(messageRepository.observeMessages(chat));
messages = Observable.switchOnNext(messageQueryObservable); messages = Observable.switchOnNext(messageQueryObservable);
peer = repositories.getPeerRepository().observePeer(chat.getPeer().getId()) contactRepository.observePeer(chat.getPeer().getId()).subscribe(peer);
.filter(Optional::isPresent).map(Optional::getItem);
contactDisplayName = repositories.getPeerRepository().observePeer(chat.getPeer()) contactDisplayName = peer.map(optional -> optional.isPresent() ? optional.getItem().getDisplayName() : "DELETED");
.map(optional -> optional.isPresent() ? optional.getItem().getDisplayName() : "DELETED");
} }
public void onQueryTextChanged(String query) { public void onQueryTextChanged(String query) {
if (query.trim().isEmpty()) { if (query.trim().isEmpty()) {
messageQueryObservable.onNext(repositories.getMessageRepository().observeMessages(chat)); messageQueryObservable.onNext(messageRepository.observeMessages(chat));
} else { } else {
messageQueryObservable.onNext(repositories.getMessageRepository().findMessagesWithBody(chat, query)); messageQueryObservable.onNext(messageRepository.findMessagesWithBody(chat, query));
} }
} }
public void deleteContact() {
addDisposable(peer.single(new Optional<>())
.filter(Optional::isPresent)
.map(Optional::getItem)
.flatMapCompletable(messenger::deleteContact)
.compose(schedulers.executeUiSafeCompletable())
.subscribe(
() -> LOGGER.log(Level.INFO, "Contact deleted."),
e -> LOGGER.log(Level.SEVERE, "Error deleting contact.", e)));
}
public void sendMessage(String body) {
addDisposable(messenger.sendEncryptedMessage(getPeer().getValue().getItem(), body)
.compose(schedulers.executeUiSafeCompletable())
.subscribe(() -> LOGGER.log(Level.INFO, "Successfully sent encrypted message."),
e -> LOGGER.log(Level.SEVERE, "Error sending encrypted message.", e)));
}
} }

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.accounts; package org.mercury_im.messenger.core.viewmodel.openpgp;
import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore; import org.jivesoftware.smackx.ox.store.definition.OpenPgpTrustStore;
import org.jxmpp.jid.EntityBareJid; import org.jxmpp.jid.EntityBareJid;

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.ox; package org.mercury_im.messenger.core.viewmodel.openpgp;
public enum OxBackupRestoreError { public enum OxBackupRestoreError {

View File

@ -1,4 +1,4 @@
package org.mercury_im.messenger.core.viewmodel.ox; package org.mercury_im.messenger.core.viewmodel.openpgp;
import org.bouncycastle.openpgp.PGPException; import org.bouncycastle.openpgp.PGPException;
import org.jivesoftware.smack.SmackException; import org.jivesoftware.smack.SmackException;

View File

@ -101,9 +101,9 @@ public class XmppDirectMessageCenter
public void newIncomingMessage(EntityBareJid from, org.jivesoftware.smack.packet.Message message, Chat chat) { public void newIncomingMessage(EntityBareJid from, org.jivesoftware.smack.packet.Message message, Chat chat) {
disposable.add(peerRepository disposable.add(peerRepository
// get peer // get peer
.getOrCreatePeer(account, from.asEntityBareJidString()) .getOrCreatePeer(account, from)
// get chat // get chat
.flatMap(peer -> directChatRepository.getOrCreateChatWithPeer(peer)) .flatMap(directChatRepository::getOrCreateChatWithPeer)
// notify listeners // notify listeners
.subscribe(chatEntity -> { .subscribe(chatEntity -> {
for (IncomingDirectMessageListener listener : messageListeners) { for (IncomingDirectMessageListener listener : messageListeners) {