mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-19 06:09:55 +01:00
Create ThreadListViewModels and move loading of named groups there
This commit is contained in:
@@ -35,6 +35,7 @@ import org.briarproject.briar.android.forum.ForumModule;
|
|||||||
import org.briarproject.briar.android.keyagreement.ContactExchangeModule;
|
import org.briarproject.briar.android.keyagreement.ContactExchangeModule;
|
||||||
import org.briarproject.briar.android.login.LoginModule;
|
import org.briarproject.briar.android.login.LoginModule;
|
||||||
import org.briarproject.briar.android.navdrawer.NavDrawerModule;
|
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.settings.SettingsModule;
|
||||||
import org.briarproject.briar.android.privategroup.list.GroupListModule;
|
import org.briarproject.briar.android.privategroup.list.GroupListModule;
|
||||||
import org.briarproject.briar.android.reporting.DevReportModule;
|
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
|
// below need to be within same scope as ViewModelProvider.Factory
|
||||||
ForumModule.BindsModule.class,
|
ForumModule.BindsModule.class,
|
||||||
GroupListModule.class,
|
GroupListModule.class,
|
||||||
|
GroupConversationModule.BindsModule.class,
|
||||||
})
|
})
|
||||||
public class AppModule {
|
public class AppModule {
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import org.briarproject.briar.android.sharing.ShareForumActivity;
|
|||||||
import org.briarproject.briar.android.threaded.ThreadItemAdapter;
|
import org.briarproject.briar.android.threaded.ThreadItemAdapter;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
|
import org.briarproject.briar.android.threaded.ThreadListViewModel;
|
||||||
import org.briarproject.briar.api.forum.Forum;
|
import org.briarproject.briar.api.forum.Forum;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
@@ -28,11 +29,13 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
|
||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_SHARE_FORUM;
|
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;
|
import static org.briarproject.briar.api.forum.ForumConstants.MAX_FORUM_POST_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -41,12 +44,18 @@ public class ForumActivity extends
|
|||||||
ThreadListActivity<Forum, ForumPostItem, ThreadItemAdapter<ForumPostItem>>
|
ThreadListActivity<Forum, ForumPostItem, ThreadItemAdapter<ForumPostItem>>
|
||||||
implements ForumListener {
|
implements ForumListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
@Inject
|
@Inject
|
||||||
ForumController forumController;
|
ForumController forumController;
|
||||||
|
|
||||||
|
private ForumViewModel viewModel;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||||
|
.get(ForumViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -54,6 +63,11 @@ public class ForumActivity extends
|
|||||||
return forumController;
|
return forumController;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ThreadListViewModel<Forum, ForumPostItem> getViewModel() {
|
||||||
|
return viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
@@ -62,8 +76,13 @@ public class ForumActivity extends
|
|||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
String groupName = i.getStringExtra(GROUP_NAME);
|
String groupName = i.getStringExtra(GROUP_NAME);
|
||||||
if (groupName != null) setTitle(groupName);
|
if (groupName != null) {
|
||||||
else loadNamedGroup();
|
setTitle(groupName);
|
||||||
|
} else {
|
||||||
|
observeOnce(viewModel.loadForum(), this, forum ->
|
||||||
|
setTitle(forum.getName())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
// Open member list on Toolbar click
|
// Open member list on Toolbar click
|
||||||
if (toolbar != null) {
|
if (toolbar != null) {
|
||||||
@@ -76,11 +95,6 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onNamedGroupLoaded(Forum forum) {
|
|
||||||
setTitle(forum.getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected ThreadItemAdapter<ForumPostItem> createAdapter(
|
protected ThreadItemAdapter<ForumPostItem> createAdapter(
|
||||||
LinearLayoutManager layoutManager) {
|
LinearLayoutManager layoutManager) {
|
||||||
@@ -88,7 +102,8 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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);
|
super.onActivityResult(request, result, data);
|
||||||
|
|
||||||
if (request == REQUEST_SHARE_FORUM && result == RESULT_OK) {
|
if (request == REQUEST_SHARE_FORUM && result == RESULT_OK) {
|
||||||
@@ -108,25 +123,24 @@ public class ForumActivity extends
|
|||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
// Handle presses on the action bar items
|
// Handle presses on the action bar items
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.action_forum_share:
|
if (itemId == R.id.action_forum_share) {
|
||||||
Intent i2 = new Intent(this, ShareForumActivity.class);
|
Intent i2 = new Intent(this, ShareForumActivity.class);
|
||||||
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
i2.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
i2.putExtra(GROUP_ID, groupId.getBytes());
|
i2.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivityForResult(i2, REQUEST_SHARE_FORUM);
|
startActivityForResult(i2, REQUEST_SHARE_FORUM);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_forum_sharing_status:
|
} else if (itemId == R.id.action_forum_sharing_status) {
|
||||||
Intent i3 = new Intent(this, ForumSharingStatusActivity.class);
|
Intent i3 = new Intent(this, ForumSharingStatusActivity.class);
|
||||||
i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
i3.setFlags(FLAG_ACTIVITY_CLEAR_TOP);
|
||||||
i3.putExtra(GROUP_ID, groupId.getBytes());
|
i3.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivity(i3);
|
startActivity(i3);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_forum_delete:
|
} else if (itemId == R.id.action_forum_delete) {
|
||||||
showUnsubscribeDialog();
|
showUnsubscribeDialog();
|
||||||
return true;
|
return true;
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -19,6 +19,11 @@ public class ForumModule {
|
|||||||
@IntoMap
|
@IntoMap
|
||||||
@ViewModelKey(ForumListViewModel.class)
|
@ViewModelKey(ForumListViewModel.class)
|
||||||
ViewModel bindForumListViewModel(ForumListViewModel forumListViewModel);
|
ViewModel bindForumListViewModel(ForumListViewModel forumListViewModel);
|
||||||
|
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(ForumViewModel.class)
|
||||||
|
ViewModel bindForumViewModel(ForumViewModel forumViewModel);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
|
|||||||
@@ -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<Forum, ForumPostItem> {
|
||||||
|
|
||||||
|
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<Forum> loadForum() {
|
||||||
|
MutableLiveData<Forum> forum = new MutableLiveData<>();
|
||||||
|
runOnDbThread(() -> {
|
||||||
|
try {
|
||||||
|
Forum f = forumManager.getForum(groupId);
|
||||||
|
forum.postValue(f);
|
||||||
|
} catch (DbException e) {
|
||||||
|
logException(LOG, WARNING, e);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
return forum;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -11,7 +11,6 @@ import android.view.MenuItem;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
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.MethodsNotNullByDefault;
|
||||||
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.bramble.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.briar.R;
|
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.privategroup.reveal.RevealContactsActivity;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
import org.briarproject.briar.android.threaded.ThreadListActivity;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
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.PrivateGroup;
|
||||||
import org.briarproject.briar.api.privategroup.Visibility;
|
import org.briarproject.briar.api.privategroup.Visibility;
|
||||||
|
|
||||||
@@ -32,11 +32,13 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.appcompat.app.AlertDialog;
|
import androidx.appcompat.app.AlertDialog;
|
||||||
import androidx.appcompat.widget.Toolbar;
|
import androidx.appcompat.widget.Toolbar;
|
||||||
|
import androidx.lifecycle.ViewModelProvider;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
import static org.briarproject.briar.android.activity.RequestCodes.REQUEST_GROUP_INVITE;
|
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;
|
import static org.briarproject.briar.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_TEXT_LENGTH;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -45,9 +47,13 @@ public class GroupActivity extends
|
|||||||
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageAdapter>
|
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageAdapter>
|
||||||
implements GroupListener, OnClickListener {
|
implements GroupListener, OnClickListener {
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
ViewModelProvider.Factory viewModelFactory;
|
||||||
@Inject
|
@Inject
|
||||||
GroupController controller;
|
GroupController controller;
|
||||||
|
|
||||||
|
private GroupViewModel viewModel;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Boolean isCreator = null;
|
private Boolean isCreator = null;
|
||||||
private boolean isDissolved = false;
|
private boolean isDissolved = false;
|
||||||
@@ -57,6 +63,8 @@ public class GroupActivity extends
|
|||||||
@Override
|
@Override
|
||||||
public void injectActivity(ActivityComponent component) {
|
public void injectActivity(ActivityComponent component) {
|
||||||
component.inject(this);
|
component.inject(this);
|
||||||
|
viewModel = new ViewModelProvider(this, viewModelFactory)
|
||||||
|
.get(GroupViewModel.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -64,6 +72,11 @@ public class GroupActivity extends
|
|||||||
return controller;
|
return controller;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected ThreadListViewModel<PrivateGroup, GroupMessageItem> getViewModel() {
|
||||||
|
return viewModel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(@Nullable Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
@@ -73,7 +86,14 @@ public class GroupActivity extends
|
|||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
String groupName = i.getStringExtra(GROUP_NAME);
|
String groupName = i.getStringExtra(GROUP_NAME);
|
||||||
if (groupName != null) setTitle(groupName);
|
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
|
// Open member list on Toolbar click
|
||||||
if (toolbar != null) {
|
if (toolbar != null) {
|
||||||
@@ -111,25 +131,6 @@ public class GroupActivity extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
protected void onNamedGroupLoaded(PrivateGroup group) {
|
|
||||||
setTitle(group.getName());
|
|
||||||
controller.loadLocalAuthor(
|
|
||||||
new UiResultExceptionHandler<LocalAuthor, DbException>(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
|
@Override
|
||||||
public boolean onCreateOptionsMenu(Menu menu) {
|
public boolean onCreateOptionsMenu(Menu menu) {
|
||||||
// Inflate the menu items for use in the action bar
|
// Inflate the menu items for use in the action bar
|
||||||
@@ -155,42 +156,44 @@ public class GroupActivity extends
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
int itemId = item.getItemId();
|
||||||
case R.id.action_group_member_list:
|
if (itemId == R.id.action_group_member_list) {
|
||||||
Intent i1 = new Intent(this, GroupMemberListActivity.class);
|
Intent i1 = new Intent(this, GroupMemberListActivity.class);
|
||||||
i1.putExtra(GROUP_ID, groupId.getBytes());
|
i1.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivity(i1);
|
startActivity(i1);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_group_reveal:
|
} else if (itemId == R.id.action_group_reveal) {
|
||||||
if (isCreator == null || isCreator)
|
if (isCreator == null || isCreator)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
Intent i2 = new Intent(this, RevealContactsActivity.class);
|
Intent i2 = new Intent(this, RevealContactsActivity.class);
|
||||||
i2.putExtra(GROUP_ID, groupId.getBytes());
|
i2.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivity(i2);
|
startActivity(i2);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_group_invite:
|
} else if (itemId == R.id.action_group_invite) {
|
||||||
if (isCreator == null || !isCreator)
|
if (isCreator == null || !isCreator)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
Intent i3 = new Intent(this, GroupInviteActivity.class);
|
Intent i3 = new Intent(this, GroupInviteActivity.class);
|
||||||
i3.putExtra(GROUP_ID, groupId.getBytes());
|
i3.putExtra(GROUP_ID, groupId.getBytes());
|
||||||
startActivityForResult(i3, REQUEST_GROUP_INVITE);
|
startActivityForResult(i3, REQUEST_GROUP_INVITE);
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_group_leave:
|
} else if (itemId == R.id.action_group_leave) {
|
||||||
if (isCreator == null || isCreator)
|
if (isCreator == null || isCreator)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
showLeaveGroupDialog();
|
showLeaveGroupDialog();
|
||||||
return true;
|
return true;
|
||||||
case R.id.action_group_dissolve:
|
} else if (itemId == R.id.action_group_dissolve) {
|
||||||
if (isCreator == null || !isCreator)
|
if (isCreator == null || !isCreator)
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
showDissolveGroupDialog();
|
showDissolveGroupDialog();
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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) {
|
if (request == REQUEST_GROUP_INVITE && result == RESULT_OK) {
|
||||||
displaySnackbar(R.string.groups_invitation_sent);
|
displaySnackbar(R.string.groups_invitation_sent);
|
||||||
} else super.onActivityResult(request, result, data);
|
} else super.onActivityResult(request, result, data);
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ package org.briarproject.briar.android.privategroup.conversation;
|
|||||||
import org.briarproject.bramble.api.contact.ContactId;
|
import org.briarproject.bramble.api.contact.ContactId;
|
||||||
import org.briarproject.bramble.api.db.DbException;
|
import org.briarproject.bramble.api.db.DbException;
|
||||||
import org.briarproject.bramble.api.identity.AuthorId;
|
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.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.briar.android.threaded.ThreadListController;
|
import org.briarproject.briar.android.threaded.ThreadListController;
|
||||||
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
import org.briarproject.briar.api.privategroup.PrivateGroup;
|
||||||
@@ -14,9 +13,6 @@ import androidx.annotation.UiThread;
|
|||||||
public interface GroupController
|
public interface GroupController
|
||||||
extends ThreadListController<PrivateGroup, GroupMessageItem> {
|
extends ThreadListController<PrivateGroup, GroupMessageItem> {
|
||||||
|
|
||||||
void loadLocalAuthor(
|
|
||||||
ResultExceptionHandler<LocalAuthor, DbException> handler);
|
|
||||||
|
|
||||||
void isDissolved(
|
void isDissolved(
|
||||||
ResultExceptionHandler<Boolean, DbException> handler);
|
ResultExceptionHandler<Boolean, DbException> handler);
|
||||||
|
|
||||||
|
|||||||
@@ -210,20 +210,6 @@ class GroupControllerImpl extends
|
|||||||
return new GroupMessageItem(header, text);
|
return new GroupMessageItem(header, text);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadLocalAuthor(
|
|
||||||
ResultExceptionHandler<LocalAuthor, DbException> handler) {
|
|
||||||
runOnDbThread(() -> {
|
|
||||||
try {
|
|
||||||
LocalAuthor author = identityManager.getLocalAuthor();
|
|
||||||
handler.onResult(author);
|
|
||||||
} catch (DbException e) {
|
|
||||||
logException(LOG, WARNING, e);
|
|
||||||
handler.onException(e);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void isDissolved(
|
public void isDissolved(
|
||||||
ResultExceptionHandler<Boolean, DbException> handler) {
|
ResultExceptionHandler<Boolean, DbException> handler) {
|
||||||
|
|||||||
@@ -2,13 +2,25 @@ package org.briarproject.briar.android.privategroup.conversation;
|
|||||||
|
|
||||||
import org.briarproject.briar.android.activity.ActivityScope;
|
import org.briarproject.briar.android.activity.ActivityScope;
|
||||||
import org.briarproject.briar.android.activity.BaseActivity;
|
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.Module;
|
||||||
import dagger.Provides;
|
import dagger.Provides;
|
||||||
|
import dagger.multibindings.IntoMap;
|
||||||
|
|
||||||
@Module
|
@Module
|
||||||
public class GroupConversationModule {
|
public class GroupConversationModule {
|
||||||
|
|
||||||
|
@Module
|
||||||
|
public interface BindsModule {
|
||||||
|
@Binds
|
||||||
|
@IntoMap
|
||||||
|
@ViewModelKey(GroupViewModel.class)
|
||||||
|
ViewModel bindGroupViewModel(GroupViewModel groupViewModel);
|
||||||
|
}
|
||||||
|
|
||||||
@ActivityScope
|
@ActivityScope
|
||||||
@Provides
|
@Provides
|
||||||
GroupController provideGroupController(BaseActivity activity,
|
GroupController provideGroupController(BaseActivity activity,
|
||||||
|
|||||||
@@ -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<PrivateGroup, GroupMessageItem> {
|
||||||
|
|
||||||
|
private static final Logger LOG = getLogger(GroupViewModel.class.getName());
|
||||||
|
|
||||||
|
private final PrivateGroupManager privateGroupManager;
|
||||||
|
private final GroupMessageFactory groupMessageFactory;
|
||||||
|
|
||||||
|
MutableLiveData<PrivateGroup> privateGroup = new MutableLiveData<>();
|
||||||
|
MutableLiveData<Boolean> 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<PrivateGroup> getPrivateGroup() {
|
||||||
|
return privateGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
LiveData<Boolean> isCreator() {
|
||||||
|
return isCreator;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -39,11 +39,11 @@ import javax.inject.Inject;
|
|||||||
|
|
||||||
import androidx.annotation.CallSuper;
|
import androidx.annotation.CallSuper;
|
||||||
import androidx.annotation.StringRes;
|
import androidx.annotation.StringRes;
|
||||||
import androidx.annotation.UiThread;
|
|
||||||
import androidx.appcompat.app.ActionBar;
|
import androidx.appcompat.app.ActionBar;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
|
||||||
|
import static java.util.logging.Logger.getLogger;
|
||||||
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
import static org.briarproject.bramble.util.StringUtils.isNullOrEmpty;
|
||||||
|
|
||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@@ -56,7 +56,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
protected static final String KEY_REPLY_ID = "replyId";
|
protected static final String KEY_REPLY_ID = "replyId";
|
||||||
|
|
||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ThreadListActivity.class.getName());
|
getLogger(ThreadListActivity.class.getName());
|
||||||
|
|
||||||
protected A adapter;
|
protected A adapter;
|
||||||
private ThreadScrollListener<I> scrollListener;
|
private ThreadScrollListener<I> scrollListener;
|
||||||
@@ -72,6 +72,8 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
|
|
||||||
protected abstract ThreadListController<G, I> getController();
|
protected abstract ThreadListController<G, I> getController();
|
||||||
|
|
||||||
|
protected abstract ThreadListViewModel<G, I> getViewModel();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected SharingController sharingController;
|
protected SharingController sharingController;
|
||||||
|
|
||||||
@@ -87,6 +89,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
if (b == null) throw new IllegalStateException("No GroupId in intent.");
|
if (b == null) throw new IllegalStateException("No GroupId in intent.");
|
||||||
groupId = new GroupId(b);
|
groupId = new GroupId(b);
|
||||||
getController().setGroupId(groupId);
|
getController().setGroupId(groupId);
|
||||||
|
getViewModel().setGroupId(groupId);
|
||||||
|
|
||||||
textInput = findViewById(R.id.text_input_container);
|
textInput = findViewById(R.id.text_input_container);
|
||||||
sendController = new TextSendController(textInput, this, false);
|
sendController = new TextSendController(textInput, this, false);
|
||||||
@@ -142,24 +145,6 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
|
|
||||||
protected abstract A createAdapter(LinearLayoutManager layoutManager);
|
protected abstract A createAdapter(LinearLayoutManager layoutManager);
|
||||||
|
|
||||||
protected void loadNamedGroup() {
|
|
||||||
getController().loadNamedGroup(
|
|
||||||
new UiResultExceptionHandler<G, DbException>(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() {
|
protected void loadItems() {
|
||||||
int revision = adapter.getRevision();
|
int revision = adapter.getRevision();
|
||||||
getController().loadItems(
|
getController().loadItems(
|
||||||
@@ -256,13 +241,11 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean onOptionsItemSelected(MenuItem item) {
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
switch (item.getItemId()) {
|
if (item.getItemId() == android.R.id.home) {
|
||||||
case android.R.id.home:
|
supportFinishAfterTransition();
|
||||||
supportFinishAfterTransition();
|
return true;
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
return super.onOptionsItemSelected(item);
|
|
||||||
}
|
}
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|||||||
@@ -22,8 +22,6 @@ public interface ThreadListController<G extends NamedGroup, I extends ThreadItem
|
|||||||
|
|
||||||
void setGroupId(GroupId groupId);
|
void setGroupId(GroupId groupId);
|
||||||
|
|
||||||
void loadNamedGroup(ResultExceptionHandler<G, DbException> handler);
|
|
||||||
|
|
||||||
void loadSharingContacts(
|
void loadSharingContacts(
|
||||||
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
ResultExceptionHandler<Collection<ContactId>, DbException> handler);
|
||||||
|
|
||||||
|
|||||||
@@ -130,23 +130,6 @@ public abstract class ThreadListControllerImpl<G extends NamedGroup, I extends T
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void loadNamedGroup(
|
|
||||||
ResultExceptionHandler<G, DbException> 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
|
@DatabaseExecutor
|
||||||
protected abstract G loadNamedGroup() throws DbException;
|
protected abstract G loadNamedGroup() throws DbException;
|
||||||
|
|
||||||
|
|||||||
@@ -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<G extends NamedGroup, I extends ThreadItem>
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user