From 382ac6ce74fde0a997802affb0000867dbf1d37a Mon Sep 17 00:00:00 2001 From: goapunk <goapunk@riseup.net> Date: Mon, 2 Jul 2018 14:54:45 +0200 Subject: [PATCH] use viewmodel+livedata for loading stuff --- mailbox-android/build.gradle | 6 + .../mailbox/activity/ActivityComponent.java | 2 +- .../mailbox/navdrawer/NavDrawerActivity.java | 2 +- .../mailbox/overview/OverviewFragment.java | 79 +++------- .../mailbox/settings/SettingsFragment.java | 31 ---- .../mailbox/viewmodel/BaseViewModel.java | 32 ++++ .../MailboxOwnerStatusViewModel.java | 147 ++++++++++++++++++ .../mailbox/viewmodel/ViewModelComponent.java | 13 ++ .../mailbox/viewmodel/ViewModelModule.java | 7 + .../mailbox/viewmodel/ViewModelScope.java | 11 ++ 10 files changed, 239 insertions(+), 91 deletions(-) create mode 100644 mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/BaseViewModel.java create mode 100644 mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/MailboxOwnerStatusViewModel.java create mode 100644 mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelComponent.java create mode 100644 mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelModule.java create mode 100644 mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelScope.java diff --git a/mailbox-android/build.gradle b/mailbox-android/build.gradle index b314bac09..56d8b3240 100644 --- a/mailbox-android/build.gradle +++ b/mailbox-android/build.gradle @@ -20,6 +20,12 @@ dependencies { implementation "com.android.support:cardview-v7:$supportVersion" implementation "com.android.support:support-annotations:$supportVersion" implementation 'com.android.support.constraint:constraint-layout:1.1.0' + def lifecycle_version = "1.1.1" + + // ViewModel and LiveData + implementation "android.arch.lifecycle:extensions:$lifecycle_version" + // alternately - if using Java8, use the following instead of compiler + implementation "android.arch.lifecycle:common-java8:$lifecycle_version" implementation('ch.acra:acra:4.9.1') { exclude module: 'support-v4' diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/activity/ActivityComponent.java b/mailbox-android/src/main/java/org/briarproject/mailbox/activity/ActivityComponent.java index c35c703b3..b31751029 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/activity/ActivityComponent.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/activity/ActivityComponent.java @@ -4,7 +4,7 @@ import android.app.Activity; import org.briarproject.mailbox.AndroidComponent; import org.briarproject.mailbox.StartupFailureActivity; -import org.briarproject.mailbox.fragment.OverviewFragment; +import org.briarproject.mailbox.overview.OverviewFragment; import org.briarproject.mailbox.fragment.ScreenFilterDialogFragment; import org.briarproject.mailbox.keyagreement.IntroFragment; import org.briarproject.mailbox.keyagreement.KeyAgreementActivity; diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/navdrawer/NavDrawerActivity.java b/mailbox-android/src/main/java/org/briarproject/mailbox/navdrawer/NavDrawerActivity.java index d7f50b415..928f2820f 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/navdrawer/NavDrawerActivity.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/navdrawer/NavDrawerActivity.java @@ -33,7 +33,7 @@ import org.briarproject.mailbox.activity.ActivityComponent; import org.briarproject.mailbox.activity.MailboxActivity; import org.briarproject.mailbox.controller.handler.UiResultHandler; import org.briarproject.mailbox.fragment.BaseFragment; -import org.briarproject.mailbox.fragment.OverviewFragment; +import org.briarproject.mailbox.overview.OverviewFragment; import org.briarproject.mailbox.logout.SignOutFragment; import org.briarproject.mailbox.settings.SettingsActivity; diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/overview/OverviewFragment.java b/mailbox-android/src/main/java/org/briarproject/mailbox/overview/OverviewFragment.java index 2718cd865..24209b122 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/overview/OverviewFragment.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/overview/OverviewFragment.java @@ -1,5 +1,6 @@ -package org.briarproject.mailbox.fragment; +package org.briarproject.mailbox.overview; +import android.arch.lifecycle.ViewModelProviders; import android.content.Intent; import android.os.Bundle; import android.view.LayoutInflater; @@ -11,33 +12,21 @@ import android.view.ViewGroup; import android.widget.ImageView; import android.widget.TextView; -import org.briarproject.bramble.api.contact.Contact; -import org.briarproject.bramble.api.contact.ContactManager; -import org.briarproject.bramble.api.db.DatabaseExecutor; -import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.event.Event; -import org.briarproject.bramble.api.lifecycle.LifecycleManager; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; -import org.briarproject.bramble.api.plugin.ConnectionRegistry; -import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent; -import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent; import org.briarproject.mailbox.R; import org.briarproject.mailbox.activity.ActivityComponent; +import org.briarproject.mailbox.fragment.BaseEventFragment; import org.briarproject.mailbox.keyagreement.MailboxExchangeActivity; +import org.briarproject.mailbox.viewmodel.MailboxOwnerStatusViewModel; -import java.util.Collection; -import java.util.concurrent.Executor; import java.util.logging.Logger; import javax.annotation.Nullable; import javax.annotation.ParametersAreNonnullByDefault; -import javax.inject.Inject; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; -import static java.util.logging.Level.WARNING; -import static org.briarproject.bramble.api.contact.ContactTypes.MAILBOX_OWNER; -import static org.briarproject.bramble.util.LogUtils.logException; import static org.briarproject.mailbox.R.drawable.contact_offline; import static org.briarproject.mailbox.R.drawable.contact_online; @@ -48,20 +37,8 @@ public class OverviewFragment extends BaseEventFragment { public static final String TAG = OverviewFragment.class.getName(); private static final Logger LOG = Logger.getLogger(TAG); - @Inject - volatile ContactManager contactManager; - @Inject - volatile ConnectionRegistry connectionRegistry; - @Inject - volatile LifecycleManager lifecycleManager; - @Inject - @DatabaseExecutor - Executor databaseExecutor; - private ImageView ownerStatus; private TextView ownerName; - @Nullable - private Contact owner = null; @Override public String getUniqueTag() { @@ -88,6 +65,22 @@ public class OverviewFragment extends BaseEventFragment { super.onViewCreated(view, savedInstanceState); ownerStatus = view.findViewById(R.id.ownerStatus); ownerName = view.findViewById(R.id.ownerName); + final MailboxOwnerStatusViewModel + viewModel = ViewModelProviders.of(this).get(MailboxOwnerStatusViewModel.class); + viewModel.mailboxOwnerStatusLiveData.observe(this, + mailboxOwnerStatus -> { + if (mailboxOwnerStatus == null) { + ownerName.setText(R.string.mailbox_unpaired); + ownerStatus.setVisibility(INVISIBLE); + } else { + ownerName.setText(mailboxOwnerStatus.getName()); + ownerStatus.setVisibility(VISIBLE); + if (mailboxOwnerStatus.isOnline()) + ownerStatus.setImageResource(contact_online); + else + ownerStatus.setImageResource(contact_offline); + } + }); } @Override @@ -99,46 +92,16 @@ public class OverviewFragment extends BaseEventFragment { @Override public void onStart() { super.onStart(); - loadOwner(); } @Override public void eventOccurred(Event e) { - if (e instanceof ContactConnectedEvent || - e instanceof ContactDisconnectedEvent) - displayOwnerStatus(); - } - private void loadOwner() { - databaseExecutor.execute(() -> { - try { - lifecycleManager.waitForDatabase(); - Collection<Contact> result = - contactManager.getContactsByType(MAILBOX_OWNER); - runOnUiThreadUnlessDestroyed(() -> { - if (!result.isEmpty()) - owner = result.iterator().next(); - displayOwnerStatus(); - }); - } catch (Exception e) { - logException(LOG, WARNING, e); - } - }); } private void displayOwnerStatus() { runOnUiThreadUnlessDestroyed(() -> { - if (owner == null) { - ownerName.setText(R.string.mailbox_unpaired); - ownerStatus.setVisibility(INVISIBLE); - } else { - ownerName.setText(owner.getAuthor().getName()); - ownerStatus.setVisibility(VISIBLE); - if (connectionRegistry.isConnected(owner.getId())) - ownerStatus.setImageResource(contact_online); - else - ownerStatus.setImageResource(contact_offline); - } + }); } diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/settings/SettingsFragment.java b/mailbox-android/src/main/java/org/briarproject/mailbox/settings/SettingsFragment.java index 87a6929d6..fda0eb236 100644 --- a/mailbox-android/src/main/java/org/briarproject/mailbox/settings/SettingsFragment.java +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/settings/SettingsFragment.java @@ -75,14 +75,7 @@ public class SettingsFragment extends PreferenceFragmentCompat private ListPreference language; private ListPreference enableBluetooth; private ListPreference torNetwork; - private CheckBoxPreference notifyPrivateMessages; - private CheckBoxPreference notifyGroupMessages; - private CheckBoxPreference notifyForumPosts; - private CheckBoxPreference notifyBlogPosts; - private CheckBoxPreference notifyVibration; - private CheckBoxPreference notifyLockscreen; - private Preference notifySound; // Fields that are accessed from background threads must be volatile volatile Settings settings; @@ -113,19 +106,6 @@ public class SettingsFragment extends PreferenceFragmentCompat (ListPreference) findPreference("pref_key_theme"); enableBluetooth = (ListPreference) findPreference("pref_key_bluetooth"); torNetwork = (ListPreference) findPreference("pref_key_tor_network"); - notifyPrivateMessages = (CheckBoxPreference) findPreference( - "pref_key_notify_private_messages"); - notifyGroupMessages = (CheckBoxPreference) findPreference( - "pref_key_notify_group_messages"); - notifyForumPosts = (CheckBoxPreference) findPreference( - "pref_key_notify_forum_posts"); - notifyBlogPosts = (CheckBoxPreference) findPreference( - "pref_key_notify_blog_posts"); - notifyVibration = (CheckBoxPreference) findPreference( - "pref_key_notify_vibration"); - notifyLockscreen = (CheckBoxPreference) findPreference( - "pref_key_notify_lock_screen"); - notifySound = findPreference("pref_key_notify_sound"); setSettingsEnabled(false); @@ -150,10 +130,6 @@ public class SettingsFragment extends PreferenceFragmentCompat }); enableBluetooth.setOnPreferenceChangeListener(this); torNetwork.setOnPreferenceChangeListener(this); - if (SDK_INT >= 21) { - notifyLockscreen.setVisible(true); - notifyLockscreen.setOnPreferenceChangeListener(this); - } findPreference("pref_key_send_feedback").setOnPreferenceClickListener( preference -> { @@ -270,13 +246,6 @@ public class SettingsFragment extends PreferenceFragmentCompat // theme not needed here, because handled by SharedPreferences enableBluetooth.setEnabled(enabled); torNetwork.setEnabled(enabled); - notifyPrivateMessages.setEnabled(enabled); - notifyGroupMessages.setEnabled(enabled); - notifyForumPosts.setEnabled(enabled); - notifyBlogPosts.setEnabled(enabled); - notifyVibration.setEnabled(enabled); - notifyLockscreen.setEnabled(enabled); - notifySound.setEnabled(enabled); } @TargetApi(26) diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/BaseViewModel.java b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/BaseViewModel.java new file mode 100644 index 000000000..78b091a0d --- /dev/null +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/BaseViewModel.java @@ -0,0 +1,32 @@ +package org.briarproject.mailbox.viewmodel; + +import android.app.Application; +import android.arch.lifecycle.AndroidViewModel; +import android.support.annotation.NonNull; + +import org.briarproject.mailbox.AndroidComponent; +import org.briarproject.mailbox.MailboxApplication; + +public abstract class BaseViewModel extends AndroidViewModel { + + public BaseViewModel( + @NonNull + Application application) { + super(application); + AndroidComponent applicationComponent = + ((MailboxApplication) getApplication()) + .getApplicationComponent(); + + ViewModelComponent viewModelComponent = + DaggerViewModelComponent.builder() + .androidComponent(applicationComponent) + .viewModelModule(new ViewModelModule()) + .build(); + + injectViewModel(viewModelComponent); + + } + + abstract void injectViewModel(ViewModelComponent viewModelComponent); + +} diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/MailboxOwnerStatusViewModel.java b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/MailboxOwnerStatusViewModel.java new file mode 100644 index 000000000..c06eb57ac --- /dev/null +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/MailboxOwnerStatusViewModel.java @@ -0,0 +1,147 @@ +package org.briarproject.mailbox.viewmodel; + +import android.app.Application; +import android.arch.lifecycle.MutableLiveData; +import android.support.annotation.NonNull; + +import org.briarproject.bramble.api.contact.Contact; +import org.briarproject.bramble.api.contact.ContactId; +import org.briarproject.bramble.api.contact.ContactManager; +import org.briarproject.bramble.api.contact.MailboxOwner; +import org.briarproject.bramble.api.contact.event.ContactAddedEvent; +import org.briarproject.bramble.api.contact.event.ContactRemovedEvent; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventListener; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.plugin.ConnectionRegistry; +import org.briarproject.bramble.api.plugin.event.ContactConnectedEvent; +import org.briarproject.bramble.api.plugin.event.ContactDisconnectedEvent; + +import java.util.Collection; +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import static java.util.logging.Level.WARNING; +import static org.briarproject.bramble.api.contact.ContactTypes.MAILBOX_OWNER; +import static org.briarproject.bramble.util.LogUtils.logException; + +public class MailboxOwnerStatusViewModel extends BaseViewModel implements + EventListener { + + public static final String TAG = + MailboxOwnerStatusViewModel.class.getName(); + private static final Logger LOG = Logger.getLogger(TAG); + public final MutableLiveData<MailboxOwnerStatus> + mailboxOwnerStatusLiveData = new MutableLiveData<>(); + @Inject + volatile ContactManager contactManager; + @Inject + volatile ConnectionRegistry connectionRegistry; + @Inject + volatile LifecycleManager lifecycleManager; + @Inject + @DatabaseExecutor + Executor databaseExecutor; + @Inject + EventBus eventBus; + private volatile MailboxOwnerStatus mailboxOwnerStatus; + + public MailboxOwnerStatusViewModel(@NonNull Application application) { + super(application); + loadOwner(); + eventBus.addListener(this); + } + + @Override + protected void onCleared() { + super.onCleared(); + eventBus.removeListener(this); + } + + @Override + void injectViewModel(ViewModelComponent viewModelComponent) { + viewModelComponent.inject(this); + } + + @Override + public void eventOccurred(Event e) { + if (e instanceof ContactConnectedEvent) + updateStatus(((ContactConnectedEvent) e).getContactId()); + else if (e instanceof ContactDisconnectedEvent) + updateStatus(((ContactDisconnectedEvent) e).getContactId()); + else if (e instanceof ContactAddedEvent) { + if (mailboxOwnerStatus == null) + loadOwner(); + } else if (e instanceof ContactRemovedEvent) { + if (mailboxOwnerStatus != null && + ((ContactRemovedEvent) e).getContactId() + .equals(mailboxOwnerStatus.getId())) { + mailboxOwnerStatus = null; + mailboxOwnerStatusLiveData.postValue(mailboxOwnerStatus); + } + } + + } + + private void updateStatus(ContactId contactId) { + if (mailboxOwnerStatus != null && + mailboxOwnerStatus.getId().equals(contactId)) { + mailboxOwnerStatus + .setOnline(connectionRegistry.isConnected(contactId)); + mailboxOwnerStatusLiveData.postValue(mailboxOwnerStatus); + } + } + + private void loadOwner() { + databaseExecutor.execute(() -> { + try { + lifecycleManager.waitForDatabase(); + Collection<Contact> result = + contactManager.getContactsByType(MAILBOX_OWNER); + if (!result.isEmpty()) { + MailboxOwner owner = + (MailboxOwner) result.iterator().next(); + mailboxOwnerStatus = + new MailboxOwnerStatus(owner, getStatus(owner)); + mailboxOwnerStatusLiveData.postValue(mailboxOwnerStatus); + } + } catch (Exception e) { + logException(LOG, WARNING, e); + } + }); + } + + private boolean getStatus(Contact owner) { + return connectionRegistry.isConnected(owner.getId()); + } + + public class MailboxOwnerStatus { + private final MailboxOwner mailboxOwner; + private boolean online; + + MailboxOwnerStatus(MailboxOwner mailboxOwner, boolean online) { + this.mailboxOwner = mailboxOwner; + this.online = online; + } + + public String getName() { + return mailboxOwner.getAuthor().getName(); + } + + public ContactId getId() { + return mailboxOwner.getId(); + } + + public boolean isOnline() { + return online; + } + + public void setOnline(boolean isOnline) { + online = isOnline; + } + } +} diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelComponent.java b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelComponent.java new file mode 100644 index 000000000..d9a164130 --- /dev/null +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelComponent.java @@ -0,0 +1,13 @@ +package org.briarproject.mailbox.viewmodel; + +import org.briarproject.mailbox.AndroidComponent; + +import dagger.Component; +@ViewModelScope +@Component(modules = {ViewModelModule.class}, + dependencies = {AndroidComponent.class}) +public interface ViewModelComponent { + + void inject(MailboxOwnerStatusViewModel mailboxOwnerStatusViewModel); + +} diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelModule.java b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelModule.java new file mode 100644 index 000000000..b21ee6378 --- /dev/null +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelModule.java @@ -0,0 +1,7 @@ +package org.briarproject.mailbox.viewmodel; + +import dagger.Module; + +@Module +public class ViewModelModule { +} diff --git a/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelScope.java b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelScope.java new file mode 100644 index 000000000..fe33771fd --- /dev/null +++ b/mailbox-android/src/main/java/org/briarproject/mailbox/viewmodel/ViewModelScope.java @@ -0,0 +1,11 @@ +package org.briarproject.mailbox.viewmodel; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +import javax.inject.Scope; + +@Scope +@Retention(RetentionPolicy.RUNTIME) +public @interface ViewModelScope { +} -- GitLab