mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 11:19:04 +01:00
Merge branch '732-reveal-contacts-ui' into 'master'
Add UI for revealing contacts within a private group This addresses one part of #732. Join notices and onboarding will follow in separate MRs. Although this MR is technically not based on !402, it does require it to be merged first to compile.  See merge request !406
This commit is contained in:
@@ -142,6 +142,17 @@
|
||||
/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".android.privategroup.reveal.RevealContactsActivity"
|
||||
android:label="@string/groups_reveal_contacts"
|
||||
android:parentActivityName=".android.privategroup.conversation.GroupActivity"
|
||||
android:windowSoftInputMode="adjustResize|stateAlwaysHidden">
|
||||
<meta-data
|
||||
android:name="android.support.PARENT_ACTIVITY"
|
||||
android:value=".android.privategroup.conversation.GroupActivity"
|
||||
/>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".android.privategroup.creation.GroupInviteActivity"
|
||||
android:label="@string/groups_invite_members"
|
||||
|
||||
10
briar-android/res/drawable/ic_visibility.xml
Normal file
10
briar-android/res/drawable/ic_visibility.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:alpha="0.54"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
</vector>
|
||||
10
briar-android/res/drawable/ic_visibility_off.xml
Normal file
10
briar-android/res/drawable/ic_visibility_off.xml
Normal file
@@ -0,0 +1,10 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:alpha="0.53"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FF000000"
|
||||
android:pathData="M12,7c2.76,0 5,2.24 5,5 0,0.65 -0.13,1.26 -0.36,1.83l2.92,2.92c1.51,-1.26 2.7,-2.89 3.43,-4.75 -1.73,-4.39 -6,-7.5 -11,-7.5 -1.4,0 -2.74,0.25 -3.98,0.7l2.16,2.16C10.74,7.13 11.35,7 12,7zM2,4.27l2.28,2.28 0.46,0.46C3.08,8.3 1.78,10.02 1,12c1.73,4.39 6,7.5 11,7.5 1.55,0 3.03,-0.3 4.38,-0.84l0.42,0.42L19.73,22 21,20.73 3.27,3 2,4.27zM7.53,9.8l1.55,1.55c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.66 1.34,3 3,3 0.22,0 0.44,-0.03 0.65,-0.08l1.55,1.55c-0.67,0.33 -1.41,0.53 -2.2,0.53 -2.76,0 -5,-2.24 -5,-5 0,-0.79 0.2,-1.53 0.53,-2.2zM11.84,9.02l3.15,3.15 0.02,-0.16c0,-1.66 -1.34,-3 -3,-3l-0.17,0.01z"/>
|
||||
</vector>
|
||||
9
briar-android/res/drawable/ic_visibility_white.xml
Normal file
9
briar-android/res/drawable/ic_visibility_white.xml
Normal file
@@ -0,0 +1,9 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="24dp"
|
||||
android:height="24dp"
|
||||
android:viewportHeight="24.0"
|
||||
android:viewportWidth="24.0">
|
||||
<path
|
||||
android:fillColor="#FFFFFFFF"
|
||||
android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
|
||||
</vector>
|
||||
25
briar-android/res/layout/activity_reveal_contacts.xml
Normal file
25
briar-android/res/layout/activity_reveal_contacts.xml
Normal file
@@ -0,0 +1,25 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:orientation="vertical"
|
||||
tools:context=".android.privategroup.reveal.RevealContactsActivity">
|
||||
|
||||
<FrameLayout
|
||||
android:id="@+id/fragmentContainer"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="0dp"
|
||||
android:layout_weight="1"/>
|
||||
|
||||
<Button
|
||||
android:id="@+id/revealButton"
|
||||
style="@style/BriarButton"
|
||||
android:layout_marginEnd="@dimen/margin_small"
|
||||
android:layout_marginLeft="@dimen/margin_small"
|
||||
android:layout_marginRight="@dimen/margin_small"
|
||||
android:layout_marginStart="@dimen/margin_small"
|
||||
android:text="@string/groups_reveal_contacts"/>
|
||||
|
||||
</LinearLayout>
|
||||
76
briar-android/res/layout/list_item_revealable_contact.xml
Normal file
76
briar-android/res/layout/list_item_revealable_contact.xml
Normal file
@@ -0,0 +1,76 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
|
||||
|
||||
<RelativeLayout
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:background="?attr/selectableItemBackground"
|
||||
android:orientation="vertical"
|
||||
android:padding="@dimen/listitem_horizontal_margin">
|
||||
|
||||
<de.hdodenhof.circleimageview.CircleImageView
|
||||
android:id="@+id/avatarView"
|
||||
style="@style/BriarAvatar"
|
||||
android:layout_width="@dimen/listitem_selectable_picture_size"
|
||||
android:layout_height="@dimen/listitem_selectable_picture_size"
|
||||
android:layout_alignParentLeft="true"
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_marginEnd="@dimen/listitem_horizontal_margin"
|
||||
android:layout_marginRight="@dimen/listitem_horizontal_margin"
|
||||
android:transitionName="avatar"
|
||||
tools:src="@drawable/ic_launcher"/>
|
||||
|
||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||
android:id="@+id/nameView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_toRightOf="@+id/avatarView"
|
||||
android:textColor="@color/briar_text_primary"
|
||||
android:textSize="@dimen/text_size_large"
|
||||
tools:text="Revealable Contact"/>
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/visibilityView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/nameView"
|
||||
android:layout_marginRight="@dimen/margin_small"
|
||||
android:layout_toRightOf="@+id/avatarView"
|
||||
android:src="@drawable/ic_visibility"
|
||||
tools:ignore="ContentDescription"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/infoView"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@+id/nameView"
|
||||
android:layout_toLeftOf="@+id/checkBox"
|
||||
android:layout_toRightOf="@+id/visibilityView"
|
||||
android:gravity="center_vertical"
|
||||
android:text="@string/groups_reveal_visible"
|
||||
android:textColor="@color/briar_text_tertiary"
|
||||
android:textSize="@dimen/text_size_small"
|
||||
tools:visibility="visible"/>
|
||||
|
||||
<CheckBox
|
||||
android:id="@+id/checkBox"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_alignParentRight="true"
|
||||
android:layout_centerVertical="true"
|
||||
android:clickable="false"/>
|
||||
|
||||
</RelativeLayout>
|
||||
|
||||
<View style="@style/Divider.ContactList"/>
|
||||
|
||||
</LinearLayout>
|
||||
@@ -15,6 +15,12 @@
|
||||
android:title="@string/groups_member_list"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_group_reveal"
|
||||
android:icon="@drawable/ic_visibility_white"
|
||||
android:title="@string/groups_reveal_contacts"
|
||||
app:showAsAction="ifRoom"/>
|
||||
|
||||
<item
|
||||
android:id="@+id/action_group_invite"
|
||||
android:icon="@drawable/ic_add_white"
|
||||
|
||||
@@ -194,6 +194,13 @@
|
||||
<string name="groups_invitations_response_accepted_received">%s accepted the group invitation.</string>
|
||||
<string name="groups_invitations_response_declined_received">%s declined the group invitation.</string>
|
||||
|
||||
<!-- Private Groups Revealing Contacts -->
|
||||
<string name="groups_reveal_contacts">Reveal Contacts</string>
|
||||
<string name="groups_reveal_visible">Your relationship is visible to the group</string>
|
||||
<string name="groups_reveal_visible_revealed_by_us">Your relationship is visible to the group (revealed by you)</string>
|
||||
<string name="groups_reveal_visible_revealed_by_contact">Your relationship is visible to the group (revealed by contact)</string>
|
||||
<string name="groups_reveal_invisible">Your relationship is not visible to the group</string>
|
||||
|
||||
<!-- Forums -->
|
||||
<string name="no_forums">You don\'t have any forums yet.\n\nWhy don\'t you create a new one yourself by tapping the + icon at the top?\n\nYou can also ask your contacts to share forums with you.</string>
|
||||
<string name="create_forum_title">New Forum</string>
|
||||
|
||||
@@ -37,6 +37,8 @@ import org.briarproject.android.privategroup.creation.GroupInviteFragment;
|
||||
import org.briarproject.android.privategroup.invitation.GroupInvitationActivity;
|
||||
import org.briarproject.android.privategroup.list.GroupListFragment;
|
||||
import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
|
||||
import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
|
||||
import org.briarproject.android.privategroup.reveal.RevealContactsFragment;
|
||||
import org.briarproject.android.sharing.BlogInvitationActivity;
|
||||
import org.briarproject.android.sharing.BlogSharingStatusActivity;
|
||||
import org.briarproject.android.sharing.ForumInvitationActivity;
|
||||
@@ -91,6 +93,8 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(GroupMemberListActivity activity);
|
||||
|
||||
void inject(RevealContactsActivity activity);
|
||||
|
||||
void inject(CreateForumActivity activity);
|
||||
|
||||
void inject(ShareForumActivity activity);
|
||||
@@ -146,6 +150,8 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(GroupInviteFragment fragment);
|
||||
|
||||
void inject(RevealContactsFragment activity);
|
||||
|
||||
void inject(ForumListFragment fragment);
|
||||
|
||||
void inject(FeedFragment fragment);
|
||||
|
||||
@@ -31,6 +31,8 @@ import org.briarproject.android.privategroup.list.GroupListController;
|
||||
import org.briarproject.android.privategroup.list.GroupListControllerImpl;
|
||||
import org.briarproject.android.privategroup.memberlist.GroupMemberListController;
|
||||
import org.briarproject.android.privategroup.memberlist.GroupMemberListControllerImpl;
|
||||
import org.briarproject.android.privategroup.reveal.RevealContactsController;
|
||||
import org.briarproject.android.privategroup.reveal.RevealContactsControllerImpl;
|
||||
import org.briarproject.android.sharing.BlogInvitationController;
|
||||
import org.briarproject.android.sharing.BlogInvitationControllerImpl;
|
||||
import org.briarproject.android.sharing.ForumInvitationController;
|
||||
@@ -144,6 +146,13 @@ public class ActivityModule {
|
||||
return groupMemberListController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
protected RevealContactsController provideRevealContactsController(
|
||||
RevealContactsControllerImpl revealContactsController) {
|
||||
return revealContactsController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
protected ForumController provideForumController(
|
||||
|
||||
@@ -22,6 +22,7 @@ import org.briarproject.android.controller.handler.UiResultExceptionHandler;
|
||||
import org.briarproject.android.privategroup.conversation.GroupController.GroupListener;
|
||||
import org.briarproject.android.privategroup.creation.GroupInviteActivity;
|
||||
import org.briarproject.android.privategroup.memberlist.GroupMemberListActivity;
|
||||
import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
|
||||
import org.briarproject.android.threaded.ThreadListActivity;
|
||||
import org.briarproject.android.threaded.ThreadListController;
|
||||
import org.briarproject.api.db.DbException;
|
||||
@@ -48,8 +49,8 @@ public class GroupActivity extends
|
||||
GroupController controller;
|
||||
|
||||
private boolean isCreator, isDissolved = false;
|
||||
private MenuItem writeMenuItem, inviteMenuItem, leaveMenuItem,
|
||||
dissolveMenuItem;
|
||||
private MenuItem writeMenuItem, revealMenuItem, inviteMenuItem,
|
||||
leaveMenuItem, dissolveMenuItem;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
@@ -135,6 +136,7 @@ public class GroupActivity extends
|
||||
inflater.inflate(R.menu.group_actions, menu);
|
||||
|
||||
writeMenuItem = menu.findItem(R.id.action_group_compose_message);
|
||||
revealMenuItem = menu.findItem(R.id.action_group_reveal);
|
||||
inviteMenuItem = menu.findItem(R.id.action_group_invite);
|
||||
leaveMenuItem = menu.findItem(R.id.action_group_leave);
|
||||
dissolveMenuItem = menu.findItem(R.id.action_group_dissolve);
|
||||
@@ -157,10 +159,15 @@ public class GroupActivity extends
|
||||
i1.putExtra(GROUP_ID, groupId.getBytes());
|
||||
ActivityCompat.startActivity(this, i1, options.toBundle());
|
||||
return true;
|
||||
case R.id.action_group_invite:
|
||||
Intent i2 = new Intent(this, GroupInviteActivity.class);
|
||||
case R.id.action_group_reveal:
|
||||
Intent i2 = new Intent(this, RevealContactsActivity.class);
|
||||
i2.putExtra(GROUP_ID, groupId.getBytes());
|
||||
ActivityCompat.startActivityForResult(this, i2, REQUEST_INVITE,
|
||||
ActivityCompat.startActivity(this, i2, options.toBundle());
|
||||
return true;
|
||||
case R.id.action_group_invite:
|
||||
Intent i3 = new Intent(this, GroupInviteActivity.class);
|
||||
i3.putExtra(GROUP_ID, groupId.getBytes());
|
||||
ActivityCompat.startActivityForResult(this, i3, REQUEST_INVITE,
|
||||
options.toBundle());
|
||||
return true;
|
||||
case R.id.action_group_leave:
|
||||
@@ -218,10 +225,12 @@ public class GroupActivity extends
|
||||
private void showMenuItems() {
|
||||
if (leaveMenuItem == null || dissolveMenuItem == null) return;
|
||||
if (isCreator) {
|
||||
revealMenuItem.setVisible(false);
|
||||
inviteMenuItem.setVisible(true);
|
||||
leaveMenuItem.setVisible(false);
|
||||
dissolveMenuItem.setVisible(true);
|
||||
} else {
|
||||
revealMenuItem.setVisible(true);
|
||||
inviteMenuItem.setVisible(false);
|
||||
leaveMenuItem.setVisible(true);
|
||||
dissolveMenuItem.setVisible(false);
|
||||
|
||||
@@ -19,7 +19,7 @@ class MemberListItem {
|
||||
|
||||
public MemberListItem(GroupMember groupMember) {
|
||||
this.member = groupMember.getAuthor();
|
||||
this.sharing = groupMember.getVisibility() != INVISIBLE; // TODO #732
|
||||
this.sharing = groupMember.getVisibility() != INVISIBLE;
|
||||
this.status = groupMember.getStatus();
|
||||
}
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
@@ -28,7 +29,7 @@ class MemberListItemHolder extends RecyclerView.ViewHolder {
|
||||
protected void bind(MemberListItem item) {
|
||||
author.setAuthor(item.getMember());
|
||||
author.setAuthorStatus(item.getStatus());
|
||||
if (item.isSharing()) {
|
||||
if (item.isSharing() && item.getStatus() != OURSELVES) {
|
||||
sharing.setVisibility(VISIBLE);
|
||||
} else {
|
||||
sharing.setVisibility(INVISIBLE);
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.Button;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contactselection.ContactSelectorActivity;
|
||||
import org.briarproject.android.controller.handler.UiExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class RevealContactsActivity extends ContactSelectorActivity
|
||||
implements OnClickListener {
|
||||
|
||||
private Button button;
|
||||
|
||||
@Inject
|
||||
RevealContactsController controller;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("ConstantConditions")
|
||||
public void onCreate(@Nullable Bundle bundle) {
|
||||
super.onCreate(bundle);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra(GROUP_ID);
|
||||
if (b == null) throw new IllegalStateException("No GroupId");
|
||||
groupId = new GroupId(b);
|
||||
|
||||
button = (Button) findViewById(R.id.revealButton);
|
||||
button.setOnClickListener(this);
|
||||
button.setEnabled(false);
|
||||
|
||||
if (bundle == null) {
|
||||
RevealContactsFragment fragment =
|
||||
RevealContactsFragment.newInstance(groupId);
|
||||
getSupportFragmentManager().beginTransaction()
|
||||
.replace(R.id.fragmentContainer, fragment)
|
||||
.commit();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@LayoutRes
|
||||
protected int getLayout() {
|
||||
return R.layout.activity_reveal_contacts;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case android.R.id.home:
|
||||
onBackPressed();
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void contactsSelected(Collection<ContactId> contacts) {
|
||||
super.contactsSelected(contacts);
|
||||
button.setEnabled(!contacts.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
controller.reveal(groupId, contacts,
|
||||
new UiExceptionHandler<DbException>(this) {
|
||||
@Override
|
||||
public void onExceptionUi(DbException exception) {
|
||||
// TODO proper error handling
|
||||
finish();
|
||||
}
|
||||
});
|
||||
supportFinishAfterTransition();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.android.controller.handler.ExceptionHandler;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
@NotNullByDefault
|
||||
public interface RevealContactsController
|
||||
extends ContactSelectorController<RevealableContactItem> {
|
||||
|
||||
void reveal(GroupId g, Collection<ContactId> contacts,
|
||||
ExceptionHandler<DbException> handler);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,122 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import org.briarproject.android.controller.DbControllerImpl;
|
||||
import org.briarproject.android.controller.handler.ExceptionHandler;
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.api.clients.ProtocolStateException;
|
||||
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.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.privategroup.GroupMember;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.privategroup.invitation.GroupInvitationManager;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.annotation.concurrent.Immutable;
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
||||
|
||||
@Immutable
|
||||
@NotNullByDefault
|
||||
public class RevealContactsControllerImpl extends DbControllerImpl
|
||||
implements RevealContactsController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(RevealContactsControllerImpl.class.getName());
|
||||
|
||||
private final PrivateGroupManager groupManager;
|
||||
private final GroupInvitationManager groupInvitationManager;
|
||||
private final ContactManager contactManager;
|
||||
|
||||
@Inject
|
||||
public RevealContactsControllerImpl(@DatabaseExecutor Executor dbExecutor,
|
||||
LifecycleManager lifecycleManager, PrivateGroupManager groupManager,
|
||||
GroupInvitationManager groupInvitationManager,
|
||||
ContactManager contactManager) {
|
||||
super(dbExecutor, lifecycleManager);
|
||||
this.groupManager = groupManager;
|
||||
this.groupInvitationManager = groupInvitationManager;
|
||||
this.contactManager = contactManager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void loadContacts(final GroupId g,
|
||||
final Collection<ContactId> selection,
|
||||
final ResultExceptionHandler<Collection<RevealableContactItem>, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
Collection<RevealableContactItem> items =
|
||||
getItems(g, selection);
|
||||
handler.onResult(items);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@DatabaseExecutor
|
||||
private Collection<RevealableContactItem> getItems(GroupId g,
|
||||
Collection<ContactId> selection) throws DbException {
|
||||
Collection<GroupMember> members =
|
||||
groupManager.getMembers(g);
|
||||
Collection<Contact> contacts =
|
||||
contactManager.getActiveContacts();
|
||||
Collection<RevealableContactItem> items =
|
||||
new ArrayList<>(members.size());
|
||||
for (GroupMember m : members) {
|
||||
for (Contact c : contacts) {
|
||||
if (m.getAuthor().equals(c.getAuthor())) {
|
||||
boolean disabled = m.getVisibility() != INVISIBLE;
|
||||
boolean selected =
|
||||
disabled || selection.contains(c.getId());
|
||||
items.add(new RevealableContactItem(c, selected, disabled,
|
||||
m.getVisibility()));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reveal(final GroupId g, final Collection<ContactId> contacts,
|
||||
final ExceptionHandler<DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
for (ContactId c : contacts) {
|
||||
try {
|
||||
groupInvitationManager.revealRelationship(c, g);
|
||||
} catch (ProtocolStateException e) {
|
||||
// action is outdated, move to next contact
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.log(INFO, e.toString(), e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.android.contactselection.BaseContactSelectorFragment;
|
||||
import org.briarproject.android.contactselection.ContactSelectorController;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
|
||||
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static org.briarproject.android.BriarActivity.GROUP_ID;
|
||||
|
||||
@MethodsNotNullByDefault
|
||||
@ParametersNotNullByDefault
|
||||
public class RevealContactsFragment extends
|
||||
BaseContactSelectorFragment<RevealableContactItem, RevealableContactAdapter> {
|
||||
|
||||
private final static String TAG = RevealContactsFragment.class.getName();
|
||||
|
||||
@Inject
|
||||
RevealContactsController controller;
|
||||
|
||||
public static RevealContactsFragment newInstance(GroupId groupId) {
|
||||
Bundle args = new Bundle();
|
||||
args.putByteArray(GROUP_ID, groupId.getBytes());
|
||||
RevealContactsFragment fragment = new RevealContactsFragment();
|
||||
fragment.setArguments(args);
|
||||
return fragment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectFragment(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ContactSelectorController<RevealableContactItem> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected RevealableContactAdapter getAdapter(Context context,
|
||||
OnContactClickListener<RevealableContactItem> listener) {
|
||||
return new RevealableContactAdapter(context, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSelectionChanged() {
|
||||
Collection<ContactId> selected = adapter.getSelectedContactIds();
|
||||
Collection<ContactId> disabled = adapter.getDisabledContactIds();
|
||||
selected.removeAll(disabled);
|
||||
|
||||
// tell the activity which contacts have been selected
|
||||
listener.contactsSelected(selected);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueTag() {
|
||||
return TAG;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import android.content.Context;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contactselection.BaseContactSelectorAdapter;
|
||||
import org.briarproject.api.contact.ContactId;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
@NotNullByDefault
|
||||
class RevealableContactAdapter extends
|
||||
BaseContactSelectorAdapter<RevealableContactItem, RevealableContactViewHolder> {
|
||||
|
||||
RevealableContactAdapter(Context context,
|
||||
OnContactClickListener<RevealableContactItem> listener) {
|
||||
super(context, RevealableContactItem.class, listener);
|
||||
}
|
||||
|
||||
@Override
|
||||
public RevealableContactViewHolder onCreateViewHolder(ViewGroup viewGroup,
|
||||
int i) {
|
||||
View v = LayoutInflater.from(ctx).inflate(
|
||||
R.layout.list_item_revealable_contact, viewGroup, false);
|
||||
return new RevealableContactViewHolder(v);
|
||||
}
|
||||
|
||||
Collection<ContactId> getDisabledContactIds() {
|
||||
Collection<ContactId> disabled = new ArrayList<>();
|
||||
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
RevealableContactItem item = items.get(i);
|
||||
if (item.isDisabled()) disabled.add(item.getContact().getId());
|
||||
}
|
||||
return disabled;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import org.briarproject.android.contactselection.SelectableContactItem;
|
||||
import org.briarproject.api.contact.Contact;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.briarproject.api.privategroup.Visibility;
|
||||
|
||||
import javax.annotation.concurrent.NotThreadSafe;
|
||||
|
||||
@NotThreadSafe
|
||||
@NotNullByDefault
|
||||
public class RevealableContactItem extends SelectableContactItem {
|
||||
|
||||
private final Visibility visibility;
|
||||
|
||||
public RevealableContactItem(Contact contact, boolean selected,
|
||||
boolean disabled, Visibility visibility) {
|
||||
super(contact, selected, disabled);
|
||||
this.visibility = visibility;
|
||||
}
|
||||
|
||||
public Visibility getVisibility() {
|
||||
return visibility;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package org.briarproject.android.privategroup.reveal;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.contact.BaseContactListAdapter.OnContactClickListener;
|
||||
import org.briarproject.android.contactselection.BaseSelectableContactHolder;
|
||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
|
||||
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
||||
|
||||
@UiThread
|
||||
@NotNullByDefault
|
||||
public class RevealableContactViewHolder
|
||||
extends BaseSelectableContactHolder<RevealableContactItem> {
|
||||
|
||||
private final ImageView icon;
|
||||
|
||||
RevealableContactViewHolder(View v) {
|
||||
super(v);
|
||||
|
||||
icon = (ImageView) v.findViewById(R.id.visibilityView);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bind(RevealableContactItem item, @Nullable
|
||||
OnContactClickListener<RevealableContactItem> listener) {
|
||||
super.bind(item, listener);
|
||||
|
||||
switch (item.getVisibility()) {
|
||||
case VISIBLE:
|
||||
info.setText(R.string.groups_reveal_visible);
|
||||
break;
|
||||
case REVEALED_BY_US:
|
||||
info.setText(R.string.groups_reveal_visible_revealed_by_us);
|
||||
break;
|
||||
case REVEALED_BY_CONTACT:
|
||||
info.setText(
|
||||
R.string.groups_reveal_visible_revealed_by_contact);
|
||||
break;
|
||||
case INVISIBLE:
|
||||
info.setText(R.string.groups_reveal_invisible);
|
||||
break;
|
||||
}
|
||||
|
||||
if (item.getVisibility() == INVISIBLE) {
|
||||
icon.setImageResource(R.drawable.ic_visibility_off);
|
||||
} else {
|
||||
icon.setImageResource(R.drawable.ic_visibility);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void grayOutItem(boolean gray) {
|
||||
super.grayOutItem(gray);
|
||||
float alpha = gray ? GREY_OUT : 1f;
|
||||
icon.setAlpha(alpha);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -7,7 +7,6 @@ import android.support.annotation.UiThread;
|
||||
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.nullsafety.MethodsNotNullByDefault;
|
||||
|
||||
Reference in New Issue
Block a user