mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 10:49:06 +01:00
Add a controller for contact selection lists
This commit is contained in:
@@ -38,7 +38,7 @@ import org.briarproject.android.privategroup.list.GroupListFragment;
|
||||
import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
|
||||
import org.briarproject.android.sharing.BlogInvitationActivity;
|
||||
import org.briarproject.android.sharing.BlogSharingStatusActivity;
|
||||
import org.briarproject.android.sharing.ContactSelectorFragment;
|
||||
import org.briarproject.android.contactselection.ContactSelectorFragment;
|
||||
import org.briarproject.android.sharing.ForumInvitationActivity;
|
||||
import org.briarproject.android.sharing.ForumSharingStatusActivity;
|
||||
import org.briarproject.android.sharing.ShareBlogActivity;
|
||||
|
||||
@@ -35,6 +35,10 @@ import org.briarproject.android.sharing.BlogInvitationController;
|
||||
import org.briarproject.android.sharing.BlogInvitationControllerImpl;
|
||||
import org.briarproject.android.sharing.ForumInvitationController;
|
||||
import org.briarproject.android.sharing.ForumInvitationControllerImpl;
|
||||
import org.briarproject.android.sharing.ShareBlogController;
|
||||
import org.briarproject.android.sharing.ShareBlogControllerImpl;
|
||||
import org.briarproject.android.sharing.ShareForumController;
|
||||
import org.briarproject.android.sharing.ShareForumControllerImpl;
|
||||
|
||||
import dagger.Module;
|
||||
import dagger.Provides;
|
||||
@@ -148,6 +152,13 @@ public class ActivityModule {
|
||||
return forumController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
ShareForumController provideShareForumController(
|
||||
ShareForumControllerImpl shareForumController) {
|
||||
return shareForumController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
protected ForumInvitationController provideInvitationForumController(
|
||||
@@ -171,6 +182,13 @@ public class ActivityModule {
|
||||
return blogController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
ShareBlogController provideShareBlogController(
|
||||
ShareBlogControllerImpl shareBlogController) {
|
||||
return shareBlogController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
FeedController provideFeedController(FeedControllerImpl feedController) {
|
||||
|
||||
@@ -39,10 +39,8 @@ public abstract class BaseContactListAdapter<I extends ContactItem, VH extends C
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean areContentsTheSame(I c1, I c2) {
|
||||
// check for all properties that influence visual
|
||||
// representation of contact
|
||||
return c1.isConnected() == c2.isConnected();
|
||||
public boolean areContentsTheSame(ContactItem c1, ContactItem c2) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int findItemPosition(ContactId c) {
|
||||
|
||||
@@ -11,23 +11,12 @@ public class ContactItem {
|
||||
|
||||
private final Contact contact;
|
||||
|
||||
private boolean connected;
|
||||
|
||||
public ContactItem(Contact contact, boolean connected) {
|
||||
public ContactItem(Contact contact) {
|
||||
this.contact = contact;
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
public Contact getContact() {
|
||||
return contact;
|
||||
}
|
||||
|
||||
boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ public class ContactListAdapter extends
|
||||
if (c1.getTimestamp() != c2.getTimestamp()) {
|
||||
return false;
|
||||
}
|
||||
return super.areContentsTheSame(c1, c2);
|
||||
return c1.isConnected() == c2.isConnected();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -10,13 +10,14 @@ import javax.annotation.concurrent.NotThreadSafe;
|
||||
@NotNullByDefault
|
||||
public class ContactListItem extends ContactItem {
|
||||
|
||||
private boolean empty;
|
||||
private boolean connected, empty;
|
||||
private long timestamp;
|
||||
private int unread;
|
||||
|
||||
public ContactListItem(Contact contact, boolean connected,
|
||||
GroupCount count) {
|
||||
super(contact, connected);
|
||||
super(contact);
|
||||
this.connected = connected;
|
||||
this.empty = count.getMsgCount() == 0;
|
||||
this.unread = count.getUnreadCount();
|
||||
this.timestamp = count.getLatestMsgTime();
|
||||
@@ -29,6 +30,14 @@ public class ContactListItem extends ContactItem {
|
||||
unread++;
|
||||
}
|
||||
|
||||
boolean isConnected() {
|
||||
return connected;
|
||||
}
|
||||
|
||||
void setConnected(boolean connected) {
|
||||
this.connected = connected;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.briarproject.android.contact.BaseContactListAdapter;
|
||||
import org.briarproject.android.contact.ContactItemViewHolder;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
public abstract class BaseContactSelectorAdapter<I extends SelectableContactItem, H extends ContactItemViewHolder<I>>
|
||||
extends BaseContactListAdapter<I, H> {
|
||||
|
||||
BaseContactSelectorAdapter(Context context, Class<I> c,
|
||||
OnContactClickListener<I> listener) {
|
||||
super(context, c, listener);
|
||||
}
|
||||
|
||||
Collection<ContactId> getSelectedContactIds() {
|
||||
Collection<ContactId> selected = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
SelectableContactItem item = items.get(i);
|
||||
if (item.isSelected()) selected.add(item.getContact().getId());
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.CallSuper;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.transition.Fade;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.android.contact.ContactItemViewHolder;
|
||||
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.android.fragment.BaseFragment;
|
||||
import org.briarproject.android.view.BriarRecyclerView;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
import static org.briarproject.android.contactselection.ContactSelectorActivity.CONTACTS;
|
||||
import static org.briarproject.android.contactselection.ContactSelectorActivity.getContactsFromIds;
|
||||
import static org.briarproject.android.contactselection.ContactSelectorActivity.getContactsFromIntegers;
|
||||
import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
|
||||
|
||||
public abstract class BaseContactSelectorFragment<I extends SelectableContactItem, H extends ContactItemViewHolder<I>>
|
||||
extends BaseFragment
|
||||
implements OnContactClickListener<I> {
|
||||
|
||||
protected BriarRecyclerView list;
|
||||
protected BaseContactSelectorAdapter<I, H> adapter;
|
||||
protected Collection<ContactId> selectedContacts;
|
||||
protected ContactSelectorListener<I> listener;
|
||||
|
||||
private GroupId groupId;
|
||||
private ContactSelectorController<I> controller;
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
//noinspection unchecked
|
||||
listener = (ContactSelectorListener<I>) context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle args = getArguments();
|
||||
byte[] b = args.getByteArray(GROUP_ID);
|
||||
if (b == null) throw new IllegalStateException("No GroupId");
|
||||
groupId = new GroupId(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
@CallSuper
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View contentView = inflater.inflate(R.layout.list, container, false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setExitTransition(new Fade());
|
||||
}
|
||||
|
||||
list = (BriarRecyclerView) contentView.findViewById(R.id.list);
|
||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
list.setEmptyText(getString(R.string.no_contacts_selector));
|
||||
|
||||
// restore selected contacts if available
|
||||
if (savedInstanceState != null) {
|
||||
ArrayList<Integer> intContacts =
|
||||
savedInstanceState.getIntegerArrayList(CONTACTS);
|
||||
if (intContacts != null) {
|
||||
selectedContacts = getContactsFromIntegers(intContacts);
|
||||
}
|
||||
}
|
||||
return contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
controller = listener.getController();
|
||||
loadContacts(selectedContacts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
adapter.clear();
|
||||
list.showProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (adapter != null) {
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
outState.putIntegerArrayList(CONTACTS,
|
||||
getContactsFromIds(selectedContacts));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(View view, I item) {
|
||||
item.toggleSelected();
|
||||
adapter.notifyItemChanged(adapter.findItemPosition(item), item);
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
private void loadContacts(@Nullable final Collection<ContactId> selection) {
|
||||
controller.loadContacts(groupId, selection,
|
||||
new UiResultExceptionHandler<Collection<I>, DbException>(
|
||||
listener) {
|
||||
@Override
|
||||
public void onResultUi(Collection<I> contacts) {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExceptionUi(DbException exception) {
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract void onSelectionChanged();
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.android.sharing;
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.CallSuper;
|
||||
@@ -14,11 +14,13 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
public abstract class ContactSelectorActivity extends BriarActivity implements
|
||||
BaseFragmentListener, ContactSelectorListener {
|
||||
public abstract class ContactSelectorActivity<I extends SelectableContactItem>
|
||||
extends BriarActivity
|
||||
implements BaseFragmentListener, ContactSelectorListener<I> {
|
||||
|
||||
final static String CONTACTS = "contacts";
|
||||
|
||||
// Subclasses may initialise the group ID in different places
|
||||
protected GroupId groupId;
|
||||
protected Collection<ContactId> contacts;
|
||||
|
||||
@@ -29,6 +31,10 @@ public abstract class ContactSelectorActivity extends BriarActivity implements
|
||||
setContentView(R.layout.activity_fragment_container);
|
||||
|
||||
if (bundle != null) {
|
||||
// restore group ID if it was saved
|
||||
byte[] groupBytes = bundle.getByteArray(GROUP_ID);
|
||||
if (groupBytes != null) groupId = new GroupId(groupBytes);
|
||||
// restore selected contacts if a selection was saved
|
||||
ArrayList<Integer> intContacts =
|
||||
bundle.getIntegerArrayList(CONTACTS);
|
||||
if (intContacts != null) {
|
||||
@@ -40,6 +46,10 @@ public abstract class ContactSelectorActivity extends BriarActivity implements
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (groupId != null) {
|
||||
// save the group ID here regardless of how subclasses initialize it
|
||||
outState.putByteArray(GROUP_ID, groupId.getBytes());
|
||||
}
|
||||
if (contacts != null) {
|
||||
outState.putIntegerArrayList(CONTACTS,
|
||||
getContactsFromIds(contacts));
|
||||
@@ -49,9 +59,7 @@ public abstract class ContactSelectorActivity extends BriarActivity implements
|
||||
@CallSuper
|
||||
@UiThread
|
||||
@Override
|
||||
public void contactsSelected(GroupId groupId,
|
||||
Collection<ContactId> contacts) {
|
||||
this.groupId = groupId;
|
||||
public void contactsSelected(Collection<ContactId> contacts) {
|
||||
this.contacts = contacts;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
|
||||
public class ContactSelectorAdapter extends
|
||||
BaseContactSelectorAdapter<SelectableContactItem, SelectableContactHolder> {
|
||||
|
||||
ContactSelectorAdapter(Context context,
|
||||
OnContactClickListener<SelectableContactItem> listener) {
|
||||
super(context, SelectableContactItem.class, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectableContactHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||
int i) {
|
||||
View v = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.list_item_selectable_contact, viewGroup, false);
|
||||
return new SelectableContactHolder(v);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.android.controller.DbController;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ContactSelectorController<I extends SelectableContactItem>
|
||||
extends DbController {
|
||||
|
||||
void loadContacts(GroupId g, @Nullable Collection<ContactId> selection,
|
||||
ResultExceptionHandler<Collection<I>, DbException> handler);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import org.briarproject.android.controller.DbControllerImpl;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
public abstract class ContactSelectorControllerImpl<I extends SelectableContactItem>
|
||||
extends DbControllerImpl
|
||||
implements ContactSelectorController<I> {
|
||||
|
||||
protected static final Logger LOG =
|
||||
Logger.getLogger("ContactSelectorController");
|
||||
|
||||
private final ContactManager contactManager;
|
||||
|
||||
public ContactSelectorControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager, ContactManager contactManager) {
|
||||
super(dbExecutor, lifecycleManager);
|
||||
this.contactManager = contactManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadContacts(final GroupId g,
|
||||
@Nullable final Collection<ContactId> selection,
|
||||
final ResultExceptionHandler<Collection<I>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<I> contacts = new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
// was this contact already selected?
|
||||
boolean selected = isSelected(c, selection != null &&
|
||||
selection.contains(c.getId()));
|
||||
// can this contact be selected?
|
||||
boolean disabled = isDisabled(g, c);
|
||||
contacts.add(getItem(c, selected, disabled));
|
||||
}
|
||||
handler.onResult(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
protected abstract boolean isSelected(Contact c, boolean wasSelected);
|
||||
|
||||
@DatabaseExecutor
|
||||
protected abstract boolean isDisabled(GroupId g, Contact c)
|
||||
throws DbException;
|
||||
|
||||
protected abstract I getItem(Contact c, boolean selected, boolean disabled);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
|
||||
|
||||
public class ContactSelectorFragment extends
|
||||
BaseContactSelectorFragment<SelectableContactItem, SelectableContactHolder>
|
||||
implements OnContactClickListener<SelectableContactItem> {
|
||||
|
||||
public static final String TAG = ContactSelectorFragment.class.getName();
|
||||
|
||||
private Menu menu;
|
||||
|
||||
public static ContactSelectorFragment newInstance(GroupId groupId) {
|
||||
Bundle args = new Bundle();
|
||||
args.putByteArray(GROUP_ID, groupId.getBytes());
|
||||
ContactSelectorFragment fragment = new ContactSelectorFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
View contentView =
|
||||
super.onCreateView(inflater, container, savedInstanceState);
|
||||
adapter = new ContactSelectorAdapter(getActivity(), this);
|
||||
list.setAdapter(adapter);
|
||||
return contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.contact_selection_actions, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
this.menu = menu;
|
||||
// hide sharing action initially, if no contact is selected
|
||||
onSelectionChanged();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_contacts_selected:
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
listener.contactsSelected(selectedContacts);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged() {
|
||||
if (menu == null) return;
|
||||
MenuItem item = menu.findItem(R.id.action_contacts_selected);
|
||||
if (item == null) return;
|
||||
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
if (selectedContacts.size() > 0) {
|
||||
item.setVisible(true);
|
||||
} else {
|
||||
item.setVisible(false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import org.briarproject.android.DestroyableContext;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
interface ContactSelectorListener<I extends SelectableContactItem>
|
||||
extends DestroyableContext {
|
||||
|
||||
ContactSelectorController<I> getController();
|
||||
|
||||
@UiThread
|
||||
void contactsSelected(Collection<ContactId> contacts);
|
||||
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.android.sharing;
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
@@ -16,7 +16,7 @@ import static android.view.View.VISIBLE;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
class SelectableContactHolder
|
||||
public class SelectableContactHolder
|
||||
extends ContactItemViewHolder<SelectableContactItem> {
|
||||
|
||||
private final CheckBox checkBox;
|
||||
@@ -1,4 +1,4 @@
|
||||
package org.briarproject.android.sharing;
|
||||
package org.briarproject.android.contactselection;
|
||||
|
||||
import org.briarproject.android.contact.ContactItem;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
@@ -8,13 +8,13 @@ import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
class SelectableContactItem extends ContactItem {
|
||||
public class SelectableContactItem extends ContactItem {
|
||||
|
||||
private boolean selected, disabled;
|
||||
|
||||
SelectableContactItem(Contact contact, boolean connected,
|
||||
boolean selected, boolean disabled) {
|
||||
super(contact, connected);
|
||||
public SelectableContactItem(Contact contact, boolean selected,
|
||||
boolean disabled) {
|
||||
super(contact);
|
||||
this.selected = selected;
|
||||
this.disabled = disabled;
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
package org.briarproject.android.privategroup.creation;
|
||||
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contactselection.ContactSelectorActivity;
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
||||
import org.briarproject.android.sharing.ContactSelectorActivity;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
@@ -18,36 +17,20 @@ import javax.inject.Inject;
|
||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_INVITATION_MSG_LENGTH;
|
||||
|
||||
public abstract class BaseGroupInviteActivity
|
||||
extends ContactSelectorActivity
|
||||
extends ContactSelectorActivity<SelectableContactItem>
|
||||
implements MessageFragmentListener {
|
||||
|
||||
@Inject
|
||||
CreateGroupController controller;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
// Subclasses may initialise the group ID in different places,
|
||||
// restore it if it was saved
|
||||
if (bundle != null) {
|
||||
byte[] groupBytes = bundle.getByteArray(GROUP_ID);
|
||||
if (groupBytes != null) groupId = new GroupId(groupBytes);
|
||||
}
|
||||
public ContactSelectorController<SelectableContactItem> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (groupId != null) {
|
||||
outState.putByteArray(GROUP_ID, groupId.getBytes());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contactsSelected(GroupId groupId,
|
||||
Collection<ContactId> contacts) {
|
||||
super.contactsSelected(groupId, contacts);
|
||||
public void contactsSelected(Collection<ContactId> contacts) {
|
||||
super.contactsSelected(contacts);
|
||||
|
||||
CreateGroupMessageFragment fragment = new CreateGroupMessageFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
@@ -62,6 +45,8 @@ public abstract class BaseGroupInviteActivity
|
||||
|
||||
@Override
|
||||
public boolean onButtonClick(@NotNull String message) {
|
||||
if (groupId == null)
|
||||
throw new IllegalStateException("GroupId was not initialized");
|
||||
controller.sendInvitation(groupId, contacts, message,
|
||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||
@Override
|
||||
|
||||
@@ -7,12 +7,10 @@ import android.support.v4.app.ActivityOptionsCompat;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contactselection.ContactSelectorFragment;
|
||||
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.android.privategroup.conversation.GroupActivity;
|
||||
import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
||||
import org.briarproject.android.sharing.ContactSelectorFragment;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
@@ -38,13 +36,6 @@ public class CreateGroupActivity extends BaseGroupInviteActivity implements
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DatabaseExecutor
|
||||
public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
|
||||
// contacts can always be invited into a new group
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBackPressed() {
|
||||
if (getSupportFragmentManager().getBackStackEntryCount() == 1) {
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.android.privategroup.creation;
|
||||
|
||||
import org.briarproject.android.controller.DbController;
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
@@ -10,12 +11,13 @@ import org.briarproject.api.sync.GroupId;
|
||||
import java.util.Collection;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface CreateGroupController extends DbController {
|
||||
public interface CreateGroupController
|
||||
extends ContactSelectorController<SelectableContactItem> {
|
||||
|
||||
void createGroup(String name,
|
||||
ResultExceptionHandler<GroupId, DbException> result);
|
||||
|
||||
void sendInvitation(GroupId groupId, Collection<ContactId> contacts,
|
||||
void sendInvitation(GroupId g, Collection<ContactId> contacts,
|
||||
String message, ResultExceptionHandler<Void, DbException> result);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.briarproject.android.privategroup.creation;
|
||||
|
||||
import org.briarproject.android.controller.DbControllerImpl;
|
||||
import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
@@ -36,7 +37,8 @@ import static java.util.logging.Level.WARNING;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class CreateGroupControllerImpl extends DbControllerImpl
|
||||
public class CreateGroupControllerImpl
|
||||
extends ContactSelectorControllerImpl<SelectableContactItem>
|
||||
implements CreateGroupController {
|
||||
|
||||
private static final Logger LOG =
|
||||
@@ -61,7 +63,7 @@ public class CreateGroupControllerImpl extends DbControllerImpl
|
||||
PrivateGroupManager groupManager,
|
||||
GroupInvitationFactory groupInvitationFactory,
|
||||
GroupInvitationManager groupInvitationManager, Clock clock) {
|
||||
super(dbExecutor, lifecycleManager);
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.cryptoExecutor = cryptoExecutor;
|
||||
this.contactManager = contactManager;
|
||||
this.identityManager = identityManager;
|
||||
@@ -128,6 +130,22 @@ public class CreateGroupControllerImpl extends DbControllerImpl
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(Contact c, boolean wasSelected) {
|
||||
return wasSelected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabled(GroupId g, Contact c) throws DbException {
|
||||
return !groupInvitationManager.isInvitationAllowed(c, g);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelectableContactItem getItem(Contact c, boolean selected,
|
||||
boolean disabled) {
|
||||
return new SelectableContactItem(c, selected, disabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendInvitation(final GroupId g,
|
||||
final Collection<ContactId> contactIds, final String message,
|
||||
@@ -191,6 +209,7 @@ public class CreateGroupControllerImpl extends DbControllerImpl
|
||||
// Continue
|
||||
}
|
||||
}
|
||||
//noinspection ConstantConditions
|
||||
handler.onResult(null);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
|
||||
@@ -5,22 +5,13 @@ import android.os.Bundle;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contactselection.ContactSelectorFragment;
|
||||
import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
||||
import org.briarproject.android.sharing.ContactSelectorFragment;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class GroupInviteActivity extends BaseGroupInviteActivity
|
||||
implements MessageFragmentListener {
|
||||
|
||||
@Inject
|
||||
GroupInvitationManager groupInvitationManager;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
@@ -30,8 +21,6 @@ public class GroupInviteActivity extends BaseGroupInviteActivity
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
// Initialise the group ID,
|
||||
// it will be saved and restored by the superclass
|
||||
Intent i = getIntent();
|
||||
byte[] g = i.getByteArrayExtra(GROUP_ID);
|
||||
if (g == null) throw new IllegalStateException("No GroupId in intent.");
|
||||
@@ -46,10 +35,4 @@ public class GroupInviteActivity extends BaseGroupInviteActivity
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@DatabaseExecutor
|
||||
public boolean isDisabled(GroupId g, Contact c) throws DbException {
|
||||
return !groupInvitationManager.isInvitationAllowed(c, g);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,41 +0,0 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
class ContactSelectorAdapter extends
|
||||
BaseContactListAdapter<SelectableContactItem, SelectableContactHolder> {
|
||||
|
||||
ContactSelectorAdapter(Context context,
|
||||
OnContactClickListener<SelectableContactItem> listener) {
|
||||
super(context, SelectableContactItem.class, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectableContactHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||
int i) {
|
||||
View v = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.list_item_selectable_contact, viewGroup, false);
|
||||
return new SelectableContactHolder(v);
|
||||
}
|
||||
|
||||
Collection<ContactId> getSelectedContactIds() {
|
||||
Collection<ContactId> selected = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
SelectableContactItem item = items.get(i);
|
||||
if (item.isSelected()) selected.add(item.getContact().getId());
|
||||
}
|
||||
return selected;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,233 +0,0 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.transition.Fade;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.android.fragment.BaseFragment;
|
||||
import org.briarproject.android.view.BriarRecyclerView;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.plugins.ConnectionRegistry;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.android.sharing.ShareActivity.CONTACTS;
|
||||
import static org.briarproject.android.sharing.ShareActivity.getContactsFromIds;
|
||||
import static org.briarproject.android.sharing.ShareActivity.getContactsFromIntegers;
|
||||
import static org.briarproject.api.sharing.SharingConstants.GROUP_ID;
|
||||
|
||||
public class ContactSelectorFragment extends BaseFragment
|
||||
implements OnContactClickListener<SelectableContactItem> {
|
||||
|
||||
public static final String TAG = ContactSelectorFragment.class.getName();
|
||||
private static final Logger LOG = Logger.getLogger(TAG);
|
||||
|
||||
private Menu menu;
|
||||
private BriarRecyclerView list;
|
||||
private ContactSelectorAdapter adapter;
|
||||
private Collection<ContactId> selectedContacts;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
volatile ContactManager contactManager;
|
||||
@Inject
|
||||
volatile ConnectionRegistry connectionRegistry;
|
||||
|
||||
private volatile GroupId groupId;
|
||||
private volatile ContactSelectorListener listener;
|
||||
|
||||
public static ContactSelectorFragment newInstance(GroupId groupId) {
|
||||
Bundle args = new Bundle();
|
||||
args.putByteArray(GROUP_ID, groupId.getBytes());
|
||||
ContactSelectorFragment fragment = new ContactSelectorFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Context context) {
|
||||
super.onAttach(context);
|
||||
listener = (ContactSelectorListener) context;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
Bundle args = getArguments();
|
||||
byte[] b = args.getByteArray(GROUP_ID);
|
||||
if (b == null) throw new IllegalStateException("No GroupId");
|
||||
groupId = new GroupId(b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container,
|
||||
Bundle savedInstanceState) {
|
||||
|
||||
View contentView = inflater.inflate(R.layout.list, container, false);
|
||||
|
||||
if (Build.VERSION.SDK_INT >= 21) {
|
||||
setExitTransition(new Fade());
|
||||
}
|
||||
|
||||
adapter = new ContactSelectorAdapter(getActivity(), this);
|
||||
|
||||
list = (BriarRecyclerView) contentView.findViewById(R.id.list);
|
||||
list.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
list.setAdapter(adapter);
|
||||
list.setEmptyText(getString(R.string.no_contacts_selector));
|
||||
|
||||
// restore selected contacts if available
|
||||
if (savedInstanceState != null) {
|
||||
ArrayList<Integer> intContacts =
|
||||
savedInstanceState.getIntegerArrayList(CONTACTS);
|
||||
if (intContacts != null) {
|
||||
selectedContacts = getContactsFromIntegers(intContacts);
|
||||
}
|
||||
}
|
||||
return contentView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStart() {
|
||||
super.onStart();
|
||||
loadContacts(selectedContacts);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onStop() {
|
||||
super.onStop();
|
||||
adapter.clear();
|
||||
list.showProgressBar();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
if (adapter != null) {
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
outState.putIntegerArrayList(CONTACTS,
|
||||
getContactsFromIds(selectedContacts));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||
inflater.inflate(R.menu.contact_selection_actions, menu);
|
||||
super.onCreateOptionsMenu(menu, inflater);
|
||||
this.menu = menu;
|
||||
// hide sharing action initially, if no contact is selected
|
||||
updateMenuItem();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
// Handle presses on the action bar items
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_contacts_selected:
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
listener.contactsSelected(groupId, selectedContacts);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(View view, SelectableContactItem item) {
|
||||
item.toggleSelected();
|
||||
adapter.notifyItemChanged(adapter.findItemPosition(item), item);
|
||||
|
||||
updateMenuItem();
|
||||
}
|
||||
|
||||
private void loadContacts(@Nullable final Collection<ContactId> selection) {
|
||||
listener.runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
long now = System.currentTimeMillis();
|
||||
List<SelectableContactItem> contacts =
|
||||
new ArrayList<>();
|
||||
for (Contact c : contactManager.getActiveContacts()) {
|
||||
// is this contact online?
|
||||
boolean connected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
// was this contact already selected?
|
||||
boolean selected = selection != null &&
|
||||
selection.contains(c.getId());
|
||||
// do we have already some sharing with that contact?
|
||||
boolean disabled = listener.isDisabled(groupId, c);
|
||||
contacts.add(new SelectableContactItem(c, connected,
|
||||
selected, disabled));
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Load took " + duration + " ms");
|
||||
displayContacts(contacts);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayContacts(
|
||||
final List<SelectableContactItem> contacts) {
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
if (contacts.isEmpty()) list.showData();
|
||||
else adapter.addAll(contacts);
|
||||
updateMenuItem();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void updateMenuItem() {
|
||||
if (menu == null) return;
|
||||
MenuItem item = menu.findItem(R.id.action_contacts_selected);
|
||||
if (item == null) return;
|
||||
|
||||
selectedContacts = adapter.getSelectedContactIds();
|
||||
if (selectedContacts.size() > 0) {
|
||||
item.setVisible(true);
|
||||
} else {
|
||||
item.setVisible(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,28 +0,0 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
|
||||
import org.briarproject.android.DestroyableContext;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
interface ContactSelectorListener extends DestroyableContext {
|
||||
|
||||
@Deprecated
|
||||
void runOnDbThread(Runnable runnable);
|
||||
|
||||
@DatabaseExecutor
|
||||
boolean isDisabled(GroupId groupId, Contact c) throws DbException;
|
||||
|
||||
@UiThread
|
||||
void contactsSelected(GroupId groupId, Collection<ContactId> contacts);
|
||||
|
||||
@UiThread
|
||||
void onBackPressed();
|
||||
|
||||
}
|
||||
@@ -2,29 +2,22 @@ package org.briarproject.android.sharing;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.support.annotation.UiThread;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contactselection.ContactSelectorActivity;
|
||||
import org.briarproject.android.contactselection.ContactSelectorFragment;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.sharing.BaseMessageFragment.MessageFragmentListener;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
public abstract class ShareActivity extends ContactSelectorActivity implements
|
||||
MessageFragmentListener {
|
||||
|
||||
private final static Logger LOG =
|
||||
Logger.getLogger(ShareActivity.class.getName());
|
||||
public abstract class ShareActivity
|
||||
extends ContactSelectorActivity<SelectableContactItem>
|
||||
implements MessageFragmentListener {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle bundle) {
|
||||
@@ -46,9 +39,8 @@ public abstract class ShareActivity extends ContactSelectorActivity implements
|
||||
|
||||
@UiThread
|
||||
@Override
|
||||
public void contactsSelected(GroupId groupId,
|
||||
Collection<ContactId> contacts) {
|
||||
super.contactsSelected(groupId, contacts);
|
||||
public void contactsSelected(Collection<ContactId> contacts) {
|
||||
super.contactsSelected(contacts);
|
||||
|
||||
BaseMessageFragment messageFragment = getMessageFragment();
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
@@ -67,45 +59,12 @@ public abstract class ShareActivity extends ContactSelectorActivity implements
|
||||
@UiThread
|
||||
@Override
|
||||
public boolean onButtonClick(@NotNull String message) {
|
||||
share(groupId, contacts, message);
|
||||
share(contacts, message);
|
||||
setResult(RESULT_OK);
|
||||
supportFinishAfterTransition();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void share(final GroupId g, final Collection<ContactId> contacts,
|
||||
final String msg) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (ContactId c : contacts) {
|
||||
share(g, c, msg);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
// TODO proper error handling
|
||||
sharingError();
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
protected abstract void share(GroupId g, ContactId c, String msg)
|
||||
throws DbException;
|
||||
|
||||
private void sharingError() {
|
||||
runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
int res = getSharingError();
|
||||
Toast.makeText(ShareActivity.this, res, LENGTH_SHORT).show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected abstract @StringRes int getSharingError();
|
||||
abstract void share(Collection<ContactId> contacts, String msg);
|
||||
|
||||
}
|
||||
|
||||
@@ -1,22 +1,26 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.api.blogs.BlogSharingManager;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||
|
||||
public class ShareBlogActivity extends ShareActivity {
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
volatile BlogSharingManager blogSharingManager;
|
||||
ShareBlogController controller;
|
||||
|
||||
@Override
|
||||
BaseMessageFragment getMessageFragment() {
|
||||
@@ -29,23 +33,33 @@ public class ShareBlogActivity extends ShareActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
|
||||
return !blogSharingManager.canBeShared(groupId, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void share(GroupId g, ContactId c, String msg)
|
||||
throws DbException {
|
||||
blogSharingManager.sendInvitation(g, c, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSharingError() {
|
||||
return R.string.blogs_sharing_error;
|
||||
public ContactSelectorController<SelectableContactItem> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumMessageLength() {
|
||||
return MAX_MESSAGE_BODY_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
void share(Collection<ContactId> contacts, String msg) {
|
||||
controller.share(groupId, contacts, msg,
|
||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExceptionUi(DbException exception) {
|
||||
// TODO proper error handling
|
||||
Toast.makeText(ShareBlogActivity.this,
|
||||
R.string.blogs_sharing_error, LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ShareBlogController
|
||||
extends ContactSelectorController<SelectableContactItem> {
|
||||
|
||||
void share(GroupId g, Collection<ContactId> contacts, String msg,
|
||||
ResultExceptionHandler<Void, DbException> handler);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.blogs.BlogSharingManager;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
public class ShareBlogControllerImpl
|
||||
extends ContactSelectorControllerImpl<SelectableContactItem>
|
||||
implements ShareBlogController {
|
||||
|
||||
private final BlogSharingManager blogSharingManager;
|
||||
|
||||
@Inject
|
||||
public ShareBlogControllerImpl(
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
BlogSharingManager blogSharingManager) {
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.blogSharingManager = blogSharingManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(Contact c, boolean wasSelected) {
|
||||
return wasSelected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabled(GroupId g, Contact c) throws DbException {
|
||||
return !blogSharingManager.canBeShared(g, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelectableContactItem getItem(Contact c, boolean selected,
|
||||
boolean disabled) {
|
||||
return new SelectableContactItem(c, selected, disabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void share(final GroupId g, final Collection<ContactId> contacts,
|
||||
final String msg,
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (ContactId c : contacts) {
|
||||
blogSharingManager.sendInvitation(g, c, msg);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,22 +1,27 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.forum.ForumSharingManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static android.widget.Toast.LENGTH_SHORT;
|
||||
import static org.briarproject.api.sync.SyncConstants.MAX_MESSAGE_BODY_LENGTH;
|
||||
|
||||
public class ShareForumActivity extends ShareActivity {
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
volatile ForumSharingManager forumSharingManager;
|
||||
ShareForumController controller;
|
||||
|
||||
@Override
|
||||
BaseMessageFragment getMessageFragment() {
|
||||
@@ -29,23 +34,37 @@ public class ShareForumActivity extends ShareActivity {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisabled(GroupId groupId, Contact c) throws DbException {
|
||||
return !forumSharingManager.canBeShared(groupId, c);
|
||||
public ContactSelectorController<SelectableContactItem> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void share(GroupId g, ContactId c, String msg)
|
||||
throws DbException {
|
||||
forumSharingManager.sendInvitation(g, c, msg);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getSharingError() {
|
||||
return R.string.forum_share_error;
|
||||
public void onCreate(Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumMessageLength() {
|
||||
return MAX_MESSAGE_BODY_LENGTH;
|
||||
}
|
||||
|
||||
@Override
|
||||
void share(Collection<ContactId> contacts, String msg) {
|
||||
controller.share(groupId, contacts, msg,
|
||||
new UiResultExceptionHandler<Void, DbException>(this) {
|
||||
@Override
|
||||
public void onResultUi(Void result) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onExceptionUi(DbException exception) {
|
||||
// TODO proper error handling
|
||||
Toast.makeText(ShareForumActivity.this,
|
||||
R.string.forum_share_error, LENGTH_SHORT)
|
||||
.show();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
public interface ShareForumController
|
||||
extends ContactSelectorController<SelectableContactItem> {
|
||||
|
||||
void share(GroupId g, Collection<ContactId> contacts, String msg,
|
||||
ResultExceptionHandler<Void, DbException> handler);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
package org.briarproject.android.sharing;
|
||||
|
||||
import org.briarproject.android.contactselection.ContactSelectorControllerImpl;
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.contact.ContactManager;
|
||||
import org.briarproject.api.db.DatabaseExecutor;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.forum.ForumSharingManager;
|
||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
public class ShareForumControllerImpl
|
||||
extends ContactSelectorControllerImpl<SelectableContactItem>
|
||||
implements ShareForumController {
|
||||
|
||||
private final ForumSharingManager forumSharingManager;
|
||||
|
||||
@Inject
|
||||
public ShareForumControllerImpl(
|
||||
@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager,
|
||||
ContactManager contactManager,
|
||||
ForumSharingManager forumSharingManager) {
|
||||
super(dbExecutor, lifecycleManager, contactManager);
|
||||
this.forumSharingManager = forumSharingManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isSelected(Contact c, boolean wasSelected) {
|
||||
return wasSelected;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean isDisabled(GroupId g, Contact c) throws DbException {
|
||||
return !forumSharingManager.canBeShared(g, c);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected SelectableContactItem getItem(Contact c, boolean selected,
|
||||
boolean disabled) {
|
||||
return new SelectableContactItem(c, selected, disabled);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void share(final GroupId g, final Collection<ContactId> contacts,
|
||||
final String msg,
|
||||
final ResultExceptionHandler<Void, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
for (ContactId c : contacts) {
|
||||
forumSharingManager.sendInvitation(g, c, msg);
|
||||
}
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -11,7 +11,6 @@ import org.briarproject.android.contact.ContactItem;
|
||||
import org.briarproject.android.view.BriarRecyclerView;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.plugins.ConnectionRegistry;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -19,8 +18,6 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.WARNING;
|
||||
|
||||
abstract class SharingStatusActivity extends BriarActivity {
|
||||
@@ -32,10 +29,6 @@ abstract class SharingStatusActivity extends BriarActivity {
|
||||
private BriarRecyclerView sharedByList, sharedWithList;
|
||||
private SharingStatusAdapter sharedByAdapter, sharedWithAdapter;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject
|
||||
volatile ConnectionRegistry connectionRegistry;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
@@ -109,9 +102,7 @@ abstract class SharingStatusActivity extends BriarActivity {
|
||||
try {
|
||||
List<ContactItem> contactItems = new ArrayList<>();
|
||||
for (Contact c : getSharedBy()) {
|
||||
boolean isConnected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
ContactItem item = new ContactItem(c, isConnected);
|
||||
ContactItem item = new ContactItem(c);
|
||||
contactItems.add(item);
|
||||
}
|
||||
displaySharedBy(contactItems);
|
||||
@@ -140,9 +131,7 @@ abstract class SharingStatusActivity extends BriarActivity {
|
||||
try {
|
||||
List<ContactItem> contactItems = new ArrayList<>();
|
||||
for (Contact c : getSharedWith()) {
|
||||
boolean isConnected =
|
||||
connectionRegistry.isConnected(c.getId());
|
||||
ContactItem item = new ContactItem(c, isConnected);
|
||||
ContactItem item = new ContactItem(c);
|
||||
contactItems.add(item);
|
||||
}
|
||||
displaySharedWith(contactItems);
|
||||
|
||||
Reference in New Issue
Block a user