From ab43dd4986ac30385fdb9420312da1f727bb19cc Mon Sep 17 00:00:00 2001 From: Torsten Grote Date: Wed, 6 Jan 2021 10:59:20 -0300 Subject: [PATCH] Create ThreadListViewModels and move loading of named groups there --- .../briarproject/briar/android/AppModule.java | 2 + .../briar/android/forum/ForumActivity.java | 66 ++++++----- .../briar/android/forum/ForumModule.java | 5 + .../briar/android/forum/ForumViewModel.java | 82 +++++++++++++ .../conversation/GroupActivity.java | 109 +++++++++--------- .../conversation/GroupController.java | 4 - .../conversation/GroupControllerImpl.java | 14 --- .../conversation/GroupConversationModule.java | 12 ++ .../conversation/GroupViewModel.java | 102 ++++++++++++++++ .../android/threaded/ThreadListActivity.java | 35 ++---- .../threaded/ThreadListController.java | 2 - .../threaded/ThreadListControllerImpl.java | 17 --- .../android/threaded/ThreadListViewModel.java | 79 +++++++++++++ 13 files changed, 387 insertions(+), 142 deletions(-) create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/forum/ForumViewModel.java create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupViewModel.java create mode 100644 briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListViewModel.java diff --git a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java index f1904fdab..0163f415a 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/AppModule.java @@ -35,6 +35,7 @@ import org.briarproject.briar.android.forum.ForumModule; import org.briarproject.briar.android.keyagreement.ContactExchangeModule; import org.briarproject.briar.android.login.LoginModule; import org.briarproject.briar.android.navdrawer.NavDrawerModule; +import org.briarproject.briar.android.privategroup.conversation.GroupConversationModule; import org.briarproject.briar.android.settings.SettingsModule; import org.briarproject.briar.android.privategroup.list.GroupListModule; import org.briarproject.briar.android.reporting.DevReportModule; @@ -81,6 +82,7 @@ import static org.briarproject.briar.android.TestingConstants.IS_DEBUG_BUILD; // below need to be within same scope as ViewModelProvider.Factory ForumModule.BindsModule.class, GroupListModule.class, + GroupConversationModule.BindsModule.class, }) public class AppModule { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java index f77ac93e0..41ddde2cd 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumActivity.java @@ -21,6 +21,7 @@ import org.briarproject.briar.android.sharing.ShareForumActivity; import org.briarproject.briar.android.threaded.ThreadItemAdapter; import org.briarproject.briar.android.threaded.ThreadListActivity; import org.briarproject.briar.android.threaded.ThreadListController; +import org.briarproject.briar.android.threaded.ThreadListViewModel; import org.briarproject.briar.api.forum.Forum; import javax.annotation.Nullable; @@ -28,11 +29,13 @@ import javax.inject.Inject; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP; import static android.widget.Toast.LENGTH_SHORT; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM; +import static org.briarproject.briar.android.util.UiUtils.observeOnce; import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEXT_LENGTH; @MethodsNotNullByDefault @@ -41,12 +44,18 @@ public class ForumActivity extends ThreadListActivity> implements ForumListener { + @Inject + ViewModelProvider.Factory viewModelFactory; @Inject ForumController forumController; + private ForumViewModel viewModel; + @Override public void injectActivity(ActivityComponent component) { component.inject(this); + viewModel = new ViewModelProvider(this, viewModelFactory) + .get(ForumViewModel.class); } @Override @@ -54,6 +63,11 @@ public class ForumActivity extends return forumController; } + @Override + protected ThreadListViewModel getViewModel() { + return viewModel; + } + @Override public void onCreate(@Nullable Bundle state) { super.onCreate(state); @@ -62,8 +76,13 @@ public class ForumActivity extends Intent i = getIntent(); String groupName = i.getStringExtra(GROUP_NAME); - if (groupName != null) setTitle(groupName); - else loadNamedGroup(); + if (groupName != null) { + setTitle(groupName); + } else { + observeOnce(viewModel.loadForum(), this, forum -> + setTitle(forum.getName()) + ); + } // Open member list on Toolbar click if (toolbar != null) { @@ -76,11 +95,6 @@ public class ForumActivity extends } } - @Override - protected void onNamedGroupLoaded(Forum forum) { - setTitle(forum.getName()); - } - @Override protected ThreadItemAdapter createAdapter( LinearLayoutManager layoutManager) { @@ -88,7 +102,8 @@ public class ForumActivity extends } @Override - protected void onActivityResult(int request, int result, Intent data) { + protected void onActivityResult(int request, int result, + @Nullable Intent data) { super.onActivityResult(request, result, data); if (request == REQUEST_SHARE_FORUM && result == RESULT_OK) { @@ -108,25 +123,24 @@ public class ForumActivity extends @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle presses on the action bar items - switch (item.getItemId()) { - case R.id.action_forum_share: - Intent i2 = new Intent(this, ShareForumActivity.class); - i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP); - i2.putExtra(GROUP_ID, groupId.getBytes()); - startActivityForResult(i2, REQUEST_SHARE_FORUM); - return true; - case R.id.action_forum_sharing_status: - Intent i3 = new Intent(this, ForumSharingStatusActivity.class); - i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP); - i3.putExtra(GROUP_ID, groupId.getBytes()); - startActivity(i3); - return true; - case R.id.action_forum_delete: - showUnsubscribeDialog(); - return true; - default: - return super.onOptionsItemSelected(item); + int itemId = item.getItemId(); + if (itemId == R.id.action_forum_share) { + Intent i2 = new Intent(this, ShareForumActivity.class); + i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP); + i2.putExtra(GROUP_ID, groupId.getBytes()); + startActivityForResult(i2, REQUEST_SHARE_FORUM); + return true; + } else if (itemId == R.id.action_forum_sharing_status) { + Intent i3 = new Intent(this, ForumSharingStatusActivity.class); + i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP); + i3.putExtra(GROUP_ID, groupId.getBytes()); + startActivity(i3); + return true; + } else if (itemId == R.id.action_forum_delete) { + showUnsubscribeDialog(); + return true; } + return super.onOptionsItemSelected(item); } @Override diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java index 62394c76d..e2efac2d9 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumModule.java @@ -19,6 +19,11 @@ public class ForumModule { @IntoMap @ViewModelKey(ForumListViewModel.class) ViewModel bindForumListViewModel(ForumListViewModel forumListViewModel); + + @Binds + @IntoMap + @ViewModelKey(ForumViewModel.class) + ViewModel bindForumViewModel(ForumViewModel forumViewModel); } @ActivityScope diff --git a/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumViewModel.java new file mode 100644 index 000000000..f469bec8b --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/forum/ForumViewModel.java @@ -0,0 +1,82 @@ +package org.briarproject.briar.android.forum; + +import android.app.Application; + +import org.briarproject.bramble.api.crypto.CryptoExecutor; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.TransactionManager; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.android.threaded.ThreadListViewModel; +import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.forum.Forum; +import org.briarproject.briar.api.forum.ForumManager; +import org.briarproject.briar.api.forum.ForumSharingManager; + +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.util.LogUtils.logException; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +class ForumViewModel extends ThreadListViewModel { + + private static final Logger LOG = getLogger(ForumViewModel.class.getName()); + + private final ForumManager forumManager; + private final ForumSharingManager forumSharingManager; + + @Inject + ForumViewModel(Application application, + @DatabaseExecutor Executor dbExecutor, + LifecycleManager lifecycleManager, + TransactionManager db, + AndroidExecutor androidExecutor, + IdentityManager identityManager, + AndroidNotificationManager notificationManager, + @CryptoExecutor Executor cryptoExecutor, + Clock clock, + EventBus eventBus, + ForumManager forumManager, + ForumSharingManager forumSharingManager) { + super(application, dbExecutor, lifecycleManager, db, androidExecutor, + identityManager, notificationManager, cryptoExecutor, clock, + eventBus); + this.forumManager = forumManager; + this.forumSharingManager = forumSharingManager; + } + + @Override + public void eventOccurred(Event e) { + + } + + LiveData loadForum() { + MutableLiveData forum = new MutableLiveData<>(); + runOnDbThread(() -> { + try { + Forum f = forumManager.getForum(groupId); + forum.postValue(f); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + return forum; + } + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java index f81004ad2..a5079e5e0 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupActivity.java @@ -11,7 +11,6 @@ import android.view.MenuItem; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.identity.AuthorId; -import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; import org.briarproject.briar.R; @@ -24,6 +23,7 @@ import org.briarproject.briar.android.privategroup.memberlist.GroupMemberListAct import org.briarproject.briar.android.privategroup.reveal.RevealContactsActivity; import org.briarproject.briar.android.threaded.ThreadListActivity; import org.briarproject.briar.android.threaded.ThreadListController; +import org.briarproject.briar.android.threaded.ThreadListViewModel; import org.briarproject.briar.api.privategroup.PrivateGroup; import org.briarproject.briar.api.privategroup.Visibility; @@ -32,11 +32,13 @@ import javax.inject.Inject; import androidx.appcompat.app.AlertDialog; import androidx.appcompat.widget.Toolbar; +import androidx.lifecycle.ViewModelProvider; import androidx.recyclerview.widget.LinearLayoutManager; import static android.view.View.GONE; import static android.view.View.VISIBLE; import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE; +import static org.briarproject.briar.android.util.UiUtils.observeOnce; import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_TEXT_LENGTH; @MethodsNotNullByDefault @@ -45,9 +47,13 @@ public class GroupActivity extends ThreadListActivity implements GroupListener, OnClickListener { + @Inject + ViewModelProvider.Factory viewModelFactory; @Inject GroupController controller; + private GroupViewModel viewModel; + @Nullable private Boolean isCreator = null; private boolean isDissolved = false; @@ -57,6 +63,8 @@ public class GroupActivity extends @Override public void injectActivity(ActivityComponent component) { component.inject(this); + viewModel = new ViewModelProvider(this, viewModelFactory) + .get(GroupViewModel.class); } @Override @@ -64,6 +72,11 @@ public class GroupActivity extends return controller; } + @Override + protected ThreadListViewModel getViewModel() { + return viewModel; + } + @Override public void onCreate(@Nullable Bundle state) { super.onCreate(state); @@ -73,7 +86,14 @@ public class GroupActivity extends Intent i = getIntent(); String groupName = i.getStringExtra(GROUP_NAME); if (groupName != null) setTitle(groupName); - loadNamedGroup(); + observeOnce(viewModel.getPrivateGroup(), this, privateGroup -> + setTitle(privateGroup.getName()) + ); + observeOnce(viewModel.isCreator(), this, isCreator -> { + this.isCreator = isCreator; // TODO remove field + adapter.setPerspective(isCreator); + showMenuItems(); + }); // Open member list on Toolbar click if (toolbar != null) { @@ -111,25 +131,6 @@ public class GroupActivity extends }); } - @Override - protected void onNamedGroupLoaded(PrivateGroup group) { - setTitle(group.getName()); - controller.loadLocalAuthor( - new UiResultExceptionHandler(this) { - @Override - public void onResultUi(LocalAuthor author) { - isCreator = group.getCreator().equals(author); - adapter.setPerspective(isCreator); - showMenuItems(); - } - - @Override - public void onExceptionUi(DbException exception) { - handleException(exception); - } - }); - } - @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu items for use in the action bar @@ -155,42 +156,44 @@ public class GroupActivity extends @Override public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.action_group_member_list: - Intent i1 = new Intent(this, GroupMemberListActivity.class); - i1.putExtra(GROUP_ID, groupId.getBytes()); - startActivity(i1); - return true; - case R.id.action_group_reveal: - if (isCreator == null || isCreator) - throw new IllegalStateException(); - Intent i2 = new Intent(this, RevealContactsActivity.class); - i2.putExtra(GROUP_ID, groupId.getBytes()); - startActivity(i2); - return true; - case R.id.action_group_invite: - if (isCreator == null || !isCreator) - throw new IllegalStateException(); - Intent i3 = new Intent(this, GroupInviteActivity.class); - i3.putExtra(GROUP_ID, groupId.getBytes()); - startActivityForResult(i3, REQUEST_GROUP_INVITE); - return true; - case R.id.action_group_leave: - if (isCreator == null || isCreator) - throw new IllegalStateException(); - showLeaveGroupDialog(); - return true; - case R.id.action_group_dissolve: - if (isCreator == null || !isCreator) - throw new IllegalStateException(); - showDissolveGroupDialog(); - default: - return super.onOptionsItemSelected(item); + int itemId = item.getItemId(); + if (itemId == R.id.action_group_member_list) { + Intent i1 = new Intent(this, GroupMemberListActivity.class); + i1.putExtra(GROUP_ID, groupId.getBytes()); + startActivity(i1); + return true; + } else if (itemId == R.id.action_group_reveal) { + if (isCreator == null || isCreator) + throw new IllegalStateException(); + Intent i2 = new Intent(this, RevealContactsActivity.class); + i2.putExtra(GROUP_ID, groupId.getBytes()); + startActivity(i2); + return true; + } else if (itemId == R.id.action_group_invite) { + if (isCreator == null || !isCreator) + throw new IllegalStateException(); + Intent i3 = new Intent(this, GroupInviteActivity.class); + i3.putExtra(GROUP_ID, groupId.getBytes()); + startActivityForResult(i3, REQUEST_GROUP_INVITE); + return true; + } else if (itemId == R.id.action_group_leave) { + if (isCreator == null || isCreator) + throw new IllegalStateException(); + showLeaveGroupDialog(); + return true; + } else if (itemId == R.id.action_group_dissolve) { + if (isCreator == null || !isCreator) + throw new IllegalStateException(); + showDissolveGroupDialog(); + + return super.onOptionsItemSelected(item); } + return super.onOptionsItemSelected(item); } @Override - protected void onActivityResult(int request, int result, Intent data) { + protected void onActivityResult(int request, int result, + @Nullable Intent data) { if (request == REQUEST_GROUP_INVITE && result == RESULT_OK) { displaySnackbar(R.string.groups_invitation_sent); } else super.onActivityResult(request, result, data); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java index 571f55bf1..5965d6c98 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupController.java @@ -3,7 +3,6 @@ package org.briarproject.briar.android.privategroup.conversation; import org.briarproject.bramble.api.contact.ContactId; import org.briarproject.bramble.api.db.DbException; import org.briarproject.bramble.api.identity.AuthorId; -import org.briarproject.bramble.api.identity.LocalAuthor; import org.briarproject.briar.android.controller.handler.ResultExceptionHandler; import org.briarproject.briar.android.threaded.ThreadListController; import org.briarproject.briar.api.privategroup.PrivateGroup; @@ -14,9 +13,6 @@ import androidx.annotation.UiThread; public interface GroupController extends ThreadListController { - void loadLocalAuthor( - ResultExceptionHandler handler); - void isDissolved( ResultExceptionHandler handler); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java index 5b0b15ad8..e35d5b0c3 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupControllerImpl.java @@ -210,20 +210,6 @@ class GroupControllerImpl extends return new GroupMessageItem(header, text); } - @Override - public void loadLocalAuthor( - ResultExceptionHandler handler) { - runOnDbThread(() -> { - try { - LocalAuthor author = identityManager.getLocalAuthor(); - handler.onResult(author); - } catch (DbException e) { - logException(LOG, WARNING, e); - handler.onException(e); - } - }); - } - @Override public void isDissolved( ResultExceptionHandler handler) { diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java index 6fa102375..6dd2c65ab 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupConversationModule.java @@ -2,13 +2,25 @@ package org.briarproject.briar.android.privategroup.conversation; import org.briarproject.briar.android.activity.ActivityScope; import org.briarproject.briar.android.activity.BaseActivity; +import org.briarproject.briar.android.viewmodel.ViewModelKey; +import androidx.lifecycle.ViewModel; +import dagger.Binds; import dagger.Module; import dagger.Provides; +import dagger.multibindings.IntoMap; @Module public class GroupConversationModule { + @Module + public interface BindsModule { + @Binds + @IntoMap + @ViewModelKey(GroupViewModel.class) + ViewModel bindGroupViewModel(GroupViewModel groupViewModel); + } + @ActivityScope @Provides GroupController provideGroupController(BaseActivity activity, diff --git a/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupViewModel.java new file mode 100644 index 000000000..6fb39aeb6 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/privategroup/conversation/GroupViewModel.java @@ -0,0 +1,102 @@ +package org.briarproject.briar.android.privategroup.conversation; + +import android.app.Application; + +import org.briarproject.bramble.api.crypto.CryptoExecutor; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.DbException; +import org.briarproject.bramble.api.db.TransactionManager; +import org.briarproject.bramble.api.event.Event; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.identity.Author; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.android.threaded.ThreadListViewModel; +import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.privategroup.GroupMessageFactory; +import org.briarproject.briar.api.privategroup.PrivateGroup; +import org.briarproject.briar.api.privategroup.PrivateGroupManager; + +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import javax.inject.Inject; + +import androidx.lifecycle.LiveData; +import androidx.lifecycle.MutableLiveData; + +import static java.util.logging.Level.WARNING; +import static java.util.logging.Logger.getLogger; +import static org.briarproject.bramble.util.LogUtils.logException; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +class GroupViewModel + extends ThreadListViewModel { + + private static final Logger LOG = getLogger(GroupViewModel.class.getName()); + + private final PrivateGroupManager privateGroupManager; + private final GroupMessageFactory groupMessageFactory; + + MutableLiveData privateGroup = new MutableLiveData<>(); + MutableLiveData isCreator = new MutableLiveData<>(); + + @Inject + GroupViewModel(Application application, + @DatabaseExecutor Executor dbExecutor, + LifecycleManager lifecycleManager, + TransactionManager db, + AndroidExecutor androidExecutor, + EventBus eventBus, + IdentityManager identityManager, + AndroidNotificationManager notificationManager, + @CryptoExecutor Executor cryptoExecutor, + Clock clock, + PrivateGroupManager privateGroupManager, + GroupMessageFactory groupMessageFactory) { + super(application, dbExecutor, lifecycleManager, db, androidExecutor, + identityManager, notificationManager, cryptoExecutor, clock, + eventBus); + this.privateGroupManager = privateGroupManager; + this.groupMessageFactory = groupMessageFactory; + } + + @Override + public void eventOccurred(Event e) { + + } + + @Override + public void setGroupId(GroupId groupId) { + super.setGroupId(groupId); + loadPrivateGroup(groupId); + } + + private void loadPrivateGroup(GroupId groupId) { + runOnDbThread(() -> { + try { + PrivateGroup g = privateGroupManager.getPrivateGroup(groupId); + privateGroup.postValue(g); + Author author = identityManager.getLocalAuthor(); + isCreator.postValue(g.getCreator().equals(author)); + } catch (DbException e) { + logException(LOG, WARNING, e); + } + }); + } + + LiveData getPrivateGroup() { + return privateGroup; + } + + LiveData isCreator() { + return isCreator; + } + +} diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java index 828be5091..67088f84b 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListActivity.java @@ -39,11 +39,11 @@ import javax.inject.Inject; import androidx.annotation.CallSuper; import androidx.annotation.StringRes; -import androidx.annotation.UiThread; import androidx.appcompat.app.ActionBar; import androidx.recyclerview.widget.LinearLayoutManager; import static androidx.recyclerview.widget.RecyclerView.NO_POSITION; +import static java.util.logging.Logger.getLogger; import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty; @MethodsNotNullByDefault @@ -56,7 +56,7 @@ public abstract class ThreadListActivity scrollListener; @@ -72,6 +72,8 @@ public abstract class ThreadListActivity getController(); + protected abstract ThreadListViewModel getViewModel(); + @Inject protected SharingController sharingController; @@ -87,6 +89,7 @@ public abstract class ThreadListActivity(this) { - @Override - public void onResultUi(G groupItem) { - onNamedGroupLoaded(groupItem); - } - - @Override - public void onExceptionUi(DbException exception) { - handleException(exception); - } - }); - } - - @UiThread - protected abstract void onNamedGroupLoaded(G groupItem); - protected void loadItems() { int revision = adapter.getRevision(); getController().loadItems( @@ -256,13 +241,11 @@ public abstract class ThreadListActivity handler); - void loadSharingContacts( ResultExceptionHandler, DbException> handler); diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java index 61eeb2a9e..9435e3017 100644 --- a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListControllerImpl.java @@ -130,23 +130,6 @@ public abstract class ThreadListControllerImpl handler) { - checkGroupId(); - runOnDbThread(() -> { - try { - long start = now(); - G groupItem = loadNamedGroup(); - logDuration(LOG, "Loading group", start); - handler.onResult(groupItem); - } catch (DbException e) { - logException(LOG, WARNING, e); - handler.onException(e); - } - }); - } - @DatabaseExecutor protected abstract G loadNamedGroup() throws DbException; diff --git a/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListViewModel.java b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListViewModel.java new file mode 100644 index 000000000..dbdd4cf35 --- /dev/null +++ b/briar-android/src/main/java/org/briarproject/briar/android/threaded/ThreadListViewModel.java @@ -0,0 +1,79 @@ +package org.briarproject.briar.android.threaded; + +import android.app.Application; + +import org.briarproject.bramble.api.crypto.CryptoExecutor; +import org.briarproject.bramble.api.db.DatabaseExecutor; +import org.briarproject.bramble.api.db.TransactionManager; +import org.briarproject.bramble.api.event.EventBus; +import org.briarproject.bramble.api.event.EventListener; +import org.briarproject.bramble.api.identity.IdentityManager; +import org.briarproject.bramble.api.lifecycle.LifecycleManager; +import org.briarproject.bramble.api.nullsafety.MethodsNotNullByDefault; +import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault; +import org.briarproject.bramble.api.sync.GroupId; +import org.briarproject.bramble.api.system.AndroidExecutor; +import org.briarproject.bramble.api.system.Clock; +import org.briarproject.briar.android.viewmodel.DbViewModel; +import org.briarproject.briar.api.android.AndroidNotificationManager; +import org.briarproject.briar.api.client.NamedGroup; + +import java.util.concurrent.Executor; +import java.util.logging.Logger; + +import androidx.annotation.CallSuper; + +import static java.util.logging.Logger.getLogger; + +@MethodsNotNullByDefault +@ParametersNotNullByDefault +public abstract class ThreadListViewModel + extends DbViewModel implements EventListener { + + private static final Logger LOG = + getLogger(ThreadListViewModel.class.getName()); + + + protected final IdentityManager identityManager; + protected final AndroidNotificationManager notificationManager; + protected final Executor cryptoExecutor; + protected final Clock clock; + private final EventBus eventBus; + + protected volatile GroupId groupId; + + public ThreadListViewModel(Application application, + @DatabaseExecutor Executor dbExecutor, + LifecycleManager lifecycleManager, + TransactionManager db, + AndroidExecutor androidExecutor, + IdentityManager identityManager, + AndroidNotificationManager notificationManager, + @CryptoExecutor Executor cryptoExecutor, + Clock clock, + EventBus eventBus) { + super(application, dbExecutor, lifecycleManager, db, androidExecutor); + this.identityManager = identityManager; + this.notificationManager = notificationManager; + this.cryptoExecutor = cryptoExecutor; + this.clock = clock; + this.eventBus = eventBus; + this.eventBus.addListener(this); + } + + @Override + protected void onCleared() { + super.onCleared(); + eventBus.removeListener(this); + } + + /** + * Needs to be called right after initialization, + * before calling other methods. + */ + @CallSuper + public void setGroupId(GroupId groupId) { + this.groupId = groupId; + } + +}