mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-17 21:29:54 +01:00
Merge branch '732-reveal-contacts-ui-join-notices' into 'master'
Add visibility and OPTIONS button to private group join notices   Closes #732 See merge request !408
This commit is contained in:
@@ -9,7 +9,7 @@
|
|||||||
style="@style/BriarAvatar"
|
style="@style/BriarAvatar"
|
||||||
android:layout_width="@dimen/blogs_avatar_normal_size"
|
android:layout_width="@dimen/blogs_avatar_normal_size"
|
||||||
android:layout_height="@dimen/blogs_avatar_normal_size"
|
android:layout_height="@dimen/blogs_avatar_normal_size"
|
||||||
android:layout_centerVertical="true"
|
android:layout_alignTop="@+id/authorName"
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
android:layout_marginRight="@dimen/margin_medium"
|
||||||
tools:src="@drawable/ic_launcher"/>
|
tools:src="@drawable/ic_launcher"/>
|
||||||
|
|
||||||
@@ -30,7 +30,6 @@
|
|||||||
android:id="@+id/authorName"
|
android:id="@+id/authorName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignTop="@+id/avatar"
|
|
||||||
android:layout_toEndOf="@+id/avatar"
|
android:layout_toEndOf="@+id/avatar"
|
||||||
android:layout_toRightOf="@+id/avatar"
|
android:layout_toRightOf="@+id/avatar"
|
||||||
android:textColor="@color/briar_text_primary"
|
android:textColor="@color/briar_text_primary"
|
||||||
|
|||||||
78
briar-android/res/layout/list_item_group_join_notice.xml
Normal file
78
briar-android/res/layout/list_item_group_join_notice.xml
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<RelativeLayout
|
||||||
|
android:id="@+id/layout"
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_marginLeft="@dimen/margin_medium"
|
||||||
|
android:baselineAligned="false"
|
||||||
|
android:orientation="vertical">
|
||||||
|
|
||||||
|
<View
|
||||||
|
android:id="@+id/top_divider"
|
||||||
|
style="@style/Divider.ForumList"
|
||||||
|
android:layout_alignParentTop="true"/>
|
||||||
|
|
||||||
|
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
||||||
|
android:id="@+id/text"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_below="@+id/top_divider"
|
||||||
|
android:layout_marginBottom="@dimen/margin_small"
|
||||||
|
android:layout_marginRight="@dimen/margin_medium"
|
||||||
|
android:layout_marginTop="@dimen/margin_medium"
|
||||||
|
android:textColor="@color/briar_text_secondary"
|
||||||
|
android:textSize="@dimen/text_size_medium"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="@string/groups_member_joined"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/icon"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignLeft="@+id/text"
|
||||||
|
android:layout_below="@+id/text"
|
||||||
|
android:layout_marginRight="@dimen/margin_small"
|
||||||
|
tools:ignore="ContentDescription"
|
||||||
|
tools:src="@drawable/ic_visibility"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/info"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignEnd="@+id/text"
|
||||||
|
android:layout_alignRight="@+id/text"
|
||||||
|
android:layout_below="@+id/text"
|
||||||
|
android:layout_toRightOf="@+id/icon"
|
||||||
|
android:gravity="center_vertical"
|
||||||
|
android:minHeight="24dp"
|
||||||
|
android:textColor="@color/briar_text_secondary"
|
||||||
|
android:textIsSelectable="true"
|
||||||
|
android:textSize="@dimen/text_size_tiny"
|
||||||
|
android:textStyle="italic"
|
||||||
|
tools:text="@string/groups_reveal_visible_revealed_by_contact"/>
|
||||||
|
|
||||||
|
<org.briarproject.android.view.AuthorView
|
||||||
|
android:id="@+id/author"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="@dimen/button_size"
|
||||||
|
android:layout_alignLeft="@+id/text"
|
||||||
|
android:layout_below="@+id/info"
|
||||||
|
android:gravity="center"
|
||||||
|
app:persona="commenter"/>
|
||||||
|
|
||||||
|
<Button
|
||||||
|
android:id="@+id/optionsButton"
|
||||||
|
style="@style/BriarButtonFlat.Positive.Tiny"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignEnd="@+id/text"
|
||||||
|
android:layout_alignRight="@+id/text"
|
||||||
|
android:layout_alignTop="@+id/author"
|
||||||
|
android:layout_toRightOf="@+id/author"
|
||||||
|
android:gravity="right|center_vertical"
|
||||||
|
android:text="@string/options"/>
|
||||||
|
|
||||||
|
</RelativeLayout>
|
||||||
@@ -6,8 +6,8 @@
|
|||||||
xmlns:tools="http://schemas.android.com/tools"
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:orientation="horizontal"
|
android:baselineAligned="false"
|
||||||
android:baselineAligned="false">
|
android:orientation="horizontal">
|
||||||
|
|
||||||
<RelativeLayout
|
<RelativeLayout
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -76,61 +76,59 @@
|
|||||||
android:id="@+id/text"
|
android:id="@+id/text"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginBottom="@dimen/margin_small"
|
android:paddingRight="@dimen/margin_medium"
|
||||||
android:layout_marginLeft="@dimen/margin_medium"
|
android:paddingTop="@dimen/margin_medium"
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
android:textColor="@color/briar_text_primary"
|
||||||
android:layout_marginTop="@dimen/margin_medium"
|
|
||||||
android:textIsSelectable="true"
|
android:textIsSelectable="true"
|
||||||
android:textSize="@dimen/text_size_medium"
|
android:textSize="@dimen/text_size_medium"
|
||||||
android:textColor="@color/briar_text_primary"
|
|
||||||
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."/>
|
tools:text="Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua."/>
|
||||||
|
|
||||||
<org.briarproject.android.view.AuthorView
|
<org.briarproject.android.view.AuthorView
|
||||||
android:id="@+id/author"
|
android:id="@+id/author"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="@dimen/button_size"
|
||||||
android:layout_alignLeft="@id/text"
|
android:layout_alignLeft="@id/text"
|
||||||
android:layout_below="@id/text"
|
android:layout_below="@id/text"
|
||||||
|
android:gravity="center"
|
||||||
app:persona="commenter"/>
|
app:persona="commenter"/>
|
||||||
|
|
||||||
<ImageView
|
|
||||||
android:id="@+id/chevron"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_alignParentRight="true"
|
|
||||||
android:layout_below="@id/text"
|
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
|
||||||
android:layout_marginTop="@dimen/margin_small"
|
|
||||||
android:clickable="true"
|
|
||||||
android:src="@drawable/selector_chevron"/>
|
|
||||||
|
|
||||||
<TextView
|
|
||||||
android:id="@+id/btn_reply"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_below="@id/text"
|
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
|
||||||
android:layout_toLeftOf="@id/chevron"
|
|
||||||
android:background="?attr/selectableItemBackground"
|
|
||||||
android:clickable="true"
|
|
||||||
android:padding="@dimen/margin_medium"
|
|
||||||
android:text="@string/btn_reply"
|
|
||||||
android:textColor="@color/briar_button_positive"
|
|
||||||
android:textSize="@dimen/text_size_tiny"/>
|
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/replies"
|
android:id="@+id/replies"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_alignBaseline="@id/btn_reply"
|
android:layout_alignBottom="@+id/author"
|
||||||
android:layout_toLeftOf="@id/btn_reply"
|
android:layout_alignTop="@+id/author"
|
||||||
|
android:layout_toLeftOf="@+id/btn_reply"
|
||||||
android:layout_toRightOf="@+id/author"
|
android:layout_toRightOf="@+id/author"
|
||||||
android:gravity="right|end"
|
android:ellipsize="end"
|
||||||
|
android:gravity="right|end|center_vertical"
|
||||||
android:maxLines="1"
|
android:maxLines="1"
|
||||||
android:padding="@dimen/margin_medium"
|
android:padding="@dimen/margin_medium"
|
||||||
android:textSize="@dimen/text_size_tiny"
|
android:textSize="@dimen/text_size_tiny"
|
||||||
tools:text="2 replies"/>
|
tools:text="2 replies"/>
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:id="@+id/btn_reply"
|
||||||
|
style="@style/BriarButtonFlat.Positive.Tiny"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:layout_alignBottom="@+id/author"
|
||||||
|
android:layout_toLeftOf="@+id/chevron"
|
||||||
|
android:text="@string/btn_reply"
|
||||||
|
android:textSize="@dimen/text_size_tiny"/>
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:id="@+id/chevron"
|
||||||
|
android:layout_width="@dimen/button_size"
|
||||||
|
android:layout_height="@dimen/button_size"
|
||||||
|
android:layout_alignBottom="@+id/author"
|
||||||
|
android:layout_alignParentRight="true"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
android:clickable="true"
|
||||||
|
android:padding="@dimen/margin_medium"
|
||||||
|
android:scaleType="center"
|
||||||
|
android:src="@drawable/selector_chevron"/>
|
||||||
|
|
||||||
<View
|
<View
|
||||||
android:id="@+id/top_divider"
|
android:id="@+id/top_divider"
|
||||||
style="@style/Divider.ForumList"
|
style="@style/Divider.ForumList"
|
||||||
|
|||||||
@@ -1,48 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<LinearLayout
|
|
||||||
android:id="@+id/layout"
|
|
||||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
|
||||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
|
||||||
xmlns:tools="http://schemas.android.com/tools"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginLeft="@dimen/margin_medium"
|
|
||||||
android:baselineAligned="false"
|
|
||||||
android:orientation="vertical">
|
|
||||||
|
|
||||||
<View
|
|
||||||
android:id="@+id/top_divider"
|
|
||||||
style="@style/Divider.ForumList"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="@dimen/margin_separator"/>
|
|
||||||
|
|
||||||
<LinearLayout
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
android:layout_marginBottom="@dimen/margin_small"
|
|
||||||
android:layout_marginLeft="@dimen/margin_medium"
|
|
||||||
android:layout_marginRight="@dimen/margin_medium"
|
|
||||||
android:layout_marginTop="@dimen/margin_medium"
|
|
||||||
android:orientation="horizontal">
|
|
||||||
|
|
||||||
<org.briarproject.android.view.AuthorView
|
|
||||||
android:id="@+id/author"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="wrap_content"
|
|
||||||
app:persona="commenter"/>
|
|
||||||
|
|
||||||
<org.thoughtcrime.securesms.components.emoji.EmojiTextView
|
|
||||||
android:id="@+id/text"
|
|
||||||
android:layout_width="match_parent"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:layout_marginLeft="@dimen/margin_medium"
|
|
||||||
android:gravity="center_vertical"
|
|
||||||
android:textColor="@color/briar_text_secondary"
|
|
||||||
android:textIsSelectable="true"
|
|
||||||
android:textSize="@dimen/text_size_medium"
|
|
||||||
android:textStyle="italic"
|
|
||||||
tools:text="@string/groups_member_joined"/>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
|
|
||||||
</LinearLayout>
|
|
||||||
@@ -31,6 +31,7 @@
|
|||||||
<dimen name="avatar_forum_size">48dp</dimen>
|
<dimen name="avatar_forum_size">48dp</dimen>
|
||||||
<dimen name="avatar_border_width">2dp</dimen>
|
<dimen name="avatar_border_width">2dp</dimen>
|
||||||
<dimen name="avatar_text_size">30sp</dimen>
|
<dimen name="avatar_text_size">30sp</dimen>
|
||||||
|
<dimen name="button_size">48dp</dimen>
|
||||||
|
|
||||||
<dimen name="unread_bubble_text_size">12sp</dimen>
|
<dimen name="unread_bubble_text_size">12sp</dimen>
|
||||||
<dimen name="unread_bubble_padding_horizontal">6dp</dimen>
|
<dimen name="unread_bubble_padding_horizontal">6dp</dimen>
|
||||||
|
|||||||
@@ -74,6 +74,7 @@
|
|||||||
<string name="delete">Delete</string>
|
<string name="delete">Delete</string>
|
||||||
<string name="accept">Accept</string>
|
<string name="accept">Accept</string>
|
||||||
<string name="decline">Decline</string>
|
<string name="decline">Decline</string>
|
||||||
|
<string name="options">Options</string>
|
||||||
<string name="online">Online</string>
|
<string name="online">Online</string>
|
||||||
<string name="offline">Offline</string>
|
<string name="offline">Offline</string>
|
||||||
<string name="send">Send</string>
|
<string name="send">Send</string>
|
||||||
@@ -169,7 +170,10 @@
|
|||||||
<string name="groups_message_received">Message received</string>
|
<string name="groups_message_received">Message received</string>
|
||||||
<string name="groups_member_list">Member List</string>
|
<string name="groups_member_list">Member List</string>
|
||||||
<string name="groups_invite_members">Invite Members</string>
|
<string name="groups_invite_members">Invite Members</string>
|
||||||
<string name="groups_member_joined">joined the group.</string>
|
<string name="groups_member_created_you">You created the group</string>
|
||||||
|
<string name="groups_member_created">%s created the group</string>
|
||||||
|
<string name="groups_member_joined_you">You joined the group</string>
|
||||||
|
<string name="groups_member_joined">%s joined the group</string>
|
||||||
<string name="groups_leave">Leave Group</string>
|
<string name="groups_leave">Leave Group</string>
|
||||||
<string name="groups_leave_dialog_title">Confirm Leaving Group</string>
|
<string name="groups_leave_dialog_title">Confirm Leaving Group</string>
|
||||||
<string name="groups_leave_dialog_message">Are you sure that you want to leave this group?</string>
|
<string name="groups_leave_dialog_message">Are you sure that you want to leave this group?</string>
|
||||||
@@ -220,7 +224,7 @@
|
|||||||
<string name="forum_new_entry_received">New forum entry</string>
|
<string name="forum_new_entry_received">New forum entry</string>
|
||||||
<string name="forum_new_message_hint">New Entry</string>
|
<string name="forum_new_message_hint">New Entry</string>
|
||||||
<string name="forum_message_reply_hint">New Reply</string>
|
<string name="forum_message_reply_hint">New Reply</string>
|
||||||
<string name="btn_reply">REPLY</string>
|
<string name="btn_reply">Reply</string>
|
||||||
<plurals name="message_replies">
|
<plurals name="message_replies">
|
||||||
<item quantity="one">%1$d reply</item>
|
<item quantity="one">%1$d reply</item>
|
||||||
<item quantity="other">%1$d replies</item>
|
<item quantity="other">%1$d replies</item>
|
||||||
|
|||||||
@@ -45,6 +45,12 @@
|
|||||||
<item name="android:padding">@dimen/margin_large</item>
|
<item name="android:padding">@dimen/margin_large</item>
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
|
<style name="BriarButtonFlat.Positive.Tiny" parent="BriarButtonFlat.Positive">
|
||||||
|
<item name="android:textSize">@dimen/text_size_tiny</item>
|
||||||
|
<item name="android:padding">@dimen/margin_medium</item>
|
||||||
|
<item name="android:minWidth">@dimen/button_size</item>
|
||||||
|
</style>
|
||||||
|
|
||||||
<style name="BriarTextTitle">
|
<style name="BriarTextTitle">
|
||||||
<item name="android:textSize">@dimen/text_size_medium</item>
|
<item name="android:textSize">@dimen/text_size_medium</item>
|
||||||
<item name="android:textColor">@android:color/primary_text_light</item>
|
<item name="android:textColor">@android:color/primary_text_light</item>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import android.content.DialogInterface.OnClickListener;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.ActivityOptionsCompat;
|
import android.support.v4.app.ActivityOptionsCompat;
|
||||||
@@ -26,6 +27,8 @@ import org.briarproject.android.threaded.ThreadListController;
|
|||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
import org.briarproject.api.forum.Forum;
|
import org.briarproject.api.forum.Forum;
|
||||||
import org.briarproject.api.forum.ForumPostHeader;
|
import org.briarproject.api.forum.ForumPostHeader;
|
||||||
|
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
|
||||||
|
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -35,8 +38,10 @@ import static android.support.v4.app.ActivityOptionsCompat.makeCustomAnimation;
|
|||||||
import static android.widget.Toast.LENGTH_SHORT;
|
import static android.widget.Toast.LENGTH_SHORT;
|
||||||
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
import static org.briarproject.api.forum.ForumConstants.MAX_FORUM_POST_BODY_LENGTH;
|
||||||
|
|
||||||
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
public class ForumActivity extends
|
public class ForumActivity extends
|
||||||
ThreadListActivity<Forum, ForumItem, ForumPostHeader> {
|
ThreadListActivity<Forum, ThreadItemAdapter<ForumItem>, ForumItem, ForumPostHeader> {
|
||||||
|
|
||||||
private static final int REQUEST_FORUM_SHARED = 3;
|
private static final int REQUEST_FORUM_SHARED = 3;
|
||||||
|
|
||||||
@@ -54,7 +59,7 @@ public class ForumActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
|
|||||||
@@ -0,0 +1,26 @@
|
|||||||
|
package org.briarproject.android.privategroup;
|
||||||
|
|
||||||
|
import android.support.annotation.StringRes;
|
||||||
|
|
||||||
|
import org.briarproject.R;
|
||||||
|
import org.briarproject.api.privategroup.Visibility;
|
||||||
|
|
||||||
|
public class VisibilityStringProvider {
|
||||||
|
|
||||||
|
@StringRes
|
||||||
|
public static int getVisibilityStringId(Visibility v) {
|
||||||
|
switch (v) {
|
||||||
|
case VISIBLE:
|
||||||
|
return R.string.groups_reveal_visible;
|
||||||
|
case REVEALED_BY_US:
|
||||||
|
return R.string.groups_reveal_visible_revealed_by_us;
|
||||||
|
case REVEALED_BY_CONTACT:
|
||||||
|
return R.string.groups_reveal_visible_revealed_by_contact;
|
||||||
|
case INVISIBLE:
|
||||||
|
return R.string.groups_reveal_invisible;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown visibility");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -5,6 +5,7 @@ import android.content.DialogInterface.OnClickListener;
|
|||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.support.annotation.LayoutRes;
|
import android.support.annotation.LayoutRes;
|
||||||
|
import android.support.annotation.Nullable;
|
||||||
import android.support.annotation.StringRes;
|
import android.support.annotation.StringRes;
|
||||||
import android.support.v4.app.ActivityCompat;
|
import android.support.v4.app.ActivityCompat;
|
||||||
import android.support.v4.app.ActivityOptionsCompat;
|
import android.support.v4.app.ActivityOptionsCompat;
|
||||||
@@ -26,10 +27,13 @@ import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
|
|||||||
import org.briarproject.android.threaded.ThreadListActivity;
|
import org.briarproject.android.threaded.ThreadListActivity;
|
||||||
import org.briarproject.android.threaded.ThreadListController;
|
import org.briarproject.android.threaded.ThreadListController;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
|
import org.briarproject.api.identity.AuthorId;
|
||||||
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
|
import org.briarproject.api.nullsafety.MethodsNotNullByDefault;
|
||||||
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
|
import org.briarproject.api.nullsafety.ParametersNotNullByDefault;
|
||||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||||
import org.briarproject.api.privategroup.PrivateGroup;
|
import org.briarproject.api.privategroup.PrivateGroup;
|
||||||
|
import org.briarproject.api.privategroup.Visibility;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
@@ -40,7 +44,7 @@ import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_
|
|||||||
@MethodsNotNullByDefault
|
@MethodsNotNullByDefault
|
||||||
@ParametersNotNullByDefault
|
@ParametersNotNullByDefault
|
||||||
public class GroupActivity extends
|
public class GroupActivity extends
|
||||||
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader>
|
ThreadListActivity<PrivateGroup, GroupMessageAdapter, GroupMessageItem, GroupMessageHeader>
|
||||||
implements GroupListener, OnClickListener {
|
implements GroupListener, OnClickListener {
|
||||||
|
|
||||||
private final static int REQUEST_INVITE = 2;
|
private final static int REQUEST_INVITE = 2;
|
||||||
@@ -63,7 +67,7 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
Intent i = getIntent();
|
Intent i = getIntent();
|
||||||
@@ -105,7 +109,7 @@ public class GroupActivity extends
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void onNamedGroupLoaded(PrivateGroup group) {
|
protected void onNamedGroupLoaded(final PrivateGroup group) {
|
||||||
setTitle(group.getName());
|
setTitle(group.getName());
|
||||||
// Created by
|
// Created by
|
||||||
ActionBar actionBar = getSupportActionBar();
|
ActionBar actionBar = getSupportActionBar();
|
||||||
@@ -113,11 +117,12 @@ public class GroupActivity extends
|
|||||||
actionBar.setSubtitle(getString(R.string.groups_created_by,
|
actionBar.setSubtitle(getString(R.string.groups_created_by,
|
||||||
group.getCreator().getName()));
|
group.getCreator().getName()));
|
||||||
}
|
}
|
||||||
controller.isCreator(group,
|
controller.loadLocalAuthor(
|
||||||
new UiResultExceptionHandler<Boolean, DbException>(this) {
|
new UiResultExceptionHandler<LocalAuthor, DbException>(this) {
|
||||||
@Override
|
@Override
|
||||||
public void onResultUi(Boolean isCreator) {
|
public void onResultUi(LocalAuthor author) {
|
||||||
GroupActivity.this.isCreator = isCreator;
|
isCreator = group.getCreator().equals(author);
|
||||||
|
adapter.setPerspective(isCreator);
|
||||||
showMenuItems();
|
showMenuItems();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -272,6 +277,11 @@ public class GroupActivity extends
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onContactRelationshipRevealed(AuthorId memberId, Visibility v) {
|
||||||
|
adapter.updateVisibility(memberId, v);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onGroupDissolved() {
|
public void onGroupDissolved() {
|
||||||
setGroupEnabled(false);
|
setGroupEnabled(false);
|
||||||
|
|||||||
@@ -5,20 +5,26 @@ import android.support.annotation.UiThread;
|
|||||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||||
import org.briarproject.android.threaded.ThreadListController;
|
import org.briarproject.android.threaded.ThreadListController;
|
||||||
import org.briarproject.api.db.DbException;
|
import org.briarproject.api.db.DbException;
|
||||||
|
import org.briarproject.api.identity.AuthorId;
|
||||||
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||||
import org.briarproject.api.privategroup.PrivateGroup;
|
import org.briarproject.api.privategroup.PrivateGroup;
|
||||||
|
import org.briarproject.api.privategroup.Visibility;
|
||||||
|
|
||||||
public interface GroupController
|
public interface GroupController
|
||||||
extends
|
extends
|
||||||
ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
|
ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
|
||||||
|
|
||||||
void isCreator(PrivateGroup group,
|
void loadLocalAuthor(
|
||||||
ResultExceptionHandler<Boolean, DbException> handler);
|
ResultExceptionHandler<LocalAuthor, DbException> handler);
|
||||||
|
|
||||||
void isDissolved(
|
void isDissolved(
|
||||||
ResultExceptionHandler<Boolean, DbException> handler);
|
ResultExceptionHandler<Boolean, DbException> handler);
|
||||||
|
|
||||||
interface GroupListener extends ThreadListListener<GroupMessageHeader> {
|
interface GroupListener extends ThreadListListener<GroupMessageHeader> {
|
||||||
|
@UiThread
|
||||||
|
void onContactRelationshipRevealed(AuthorId memberId, Visibility v);
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
void onGroupDissolved();
|
void onGroupDissolved();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import org.briarproject.api.event.GroupMessageAddedEvent;
|
|||||||
import org.briarproject.api.identity.IdentityManager;
|
import org.briarproject.api.identity.IdentityManager;
|
||||||
import org.briarproject.api.identity.LocalAuthor;
|
import org.briarproject.api.identity.LocalAuthor;
|
||||||
import org.briarproject.api.lifecycle.LifecycleManager;
|
import org.briarproject.api.lifecycle.LifecycleManager;
|
||||||
|
import org.briarproject.api.privategroup.ContactRelationshipRevealedEvent;
|
||||||
import org.briarproject.api.privategroup.GroupMessage;
|
import org.briarproject.api.privategroup.GroupMessage;
|
||||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||||
@@ -33,7 +34,6 @@ import java.util.logging.Logger;
|
|||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
|
||||||
import static java.lang.Math.max;
|
import static java.lang.Math.max;
|
||||||
|
|
||||||
import static java.util.logging.Level.WARNING;
|
import static java.util.logging.Level.WARNING;
|
||||||
|
|
||||||
public class GroupControllerImpl extends
|
public class GroupControllerImpl extends
|
||||||
@@ -81,6 +81,18 @@ public class GroupControllerImpl extends
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
} else if (e instanceof ContactRelationshipRevealedEvent) {
|
||||||
|
final ContactRelationshipRevealedEvent c =
|
||||||
|
(ContactRelationshipRevealedEvent) e;
|
||||||
|
if (getGroupId().equals(c.getGroupId())) {
|
||||||
|
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||||
|
@Override
|
||||||
|
public void run() {
|
||||||
|
listener.onContactRelationshipRevealed(c.getMemberId(),
|
||||||
|
c.getVisibility());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
} else if (e instanceof GroupDissolvedEvent) {
|
} else if (e instanceof GroupDissolvedEvent) {
|
||||||
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
GroupDissolvedEvent g = (GroupDissolvedEvent) e;
|
||||||
if (getGroupId().equals(g.getGroupId())) {
|
if (getGroupId().equals(g.getGroupId())) {
|
||||||
@@ -178,22 +190,20 @@ public class GroupControllerImpl extends
|
|||||||
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
protected GroupMessageItem buildItem(GroupMessageHeader header,
|
||||||
String body) {
|
String body) {
|
||||||
if (header instanceof JoinMessageHeader) {
|
if (header instanceof JoinMessageHeader) {
|
||||||
return new JoinMessageItem(header, body);
|
return new JoinMessageItem((JoinMessageHeader) header, body);
|
||||||
}
|
}
|
||||||
return new GroupMessageItem(header, body);
|
return new GroupMessageItem(header, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void isCreator(final PrivateGroup group,
|
public void loadLocalAuthor(
|
||||||
final ResultExceptionHandler<Boolean, DbException> handler) {
|
final ResultExceptionHandler<LocalAuthor, DbException> handler) {
|
||||||
runOnDbThread(new Runnable() {
|
runOnDbThread(new Runnable() {
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
LocalAuthor author = identityManager.getLocalAuthor();
|
LocalAuthor author = identityManager.getLocalAuthor();
|
||||||
boolean isCreator =
|
handler.onResult(author);
|
||||||
author.getId().equals(group.getCreator().getId());
|
|
||||||
handler.onResult(isCreator);
|
|
||||||
} catch (DbException e) {
|
} catch (DbException e) {
|
||||||
if (LOG.isLoggable(WARNING))
|
if (LOG.isLoggable(WARNING))
|
||||||
LOG.log(WARNING, e.toString(), e);
|
LOG.log(WARNING, e.toString(), e);
|
||||||
|
|||||||
@@ -11,9 +11,17 @@ import org.briarproject.R;
|
|||||||
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
|
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
|
||||||
import org.briarproject.android.threaded.ThreadItemAdapter;
|
import org.briarproject.android.threaded.ThreadItemAdapter;
|
||||||
import org.briarproject.android.threaded.ThreadPostViewHolder;
|
import org.briarproject.android.threaded.ThreadPostViewHolder;
|
||||||
|
import org.briarproject.api.identity.AuthorId;
|
||||||
|
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||||
|
import org.briarproject.api.privategroup.Visibility;
|
||||||
|
|
||||||
|
import static android.support.v7.widget.RecyclerView.NO_POSITION;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
public class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
@NotNullByDefault
|
||||||
|
class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
||||||
|
|
||||||
|
private boolean isCreator = false;
|
||||||
|
|
||||||
public GroupMessageAdapter(ThreadItemListener<GroupMessageItem> listener,
|
public GroupMessageAdapter(ThreadItemListener<GroupMessageItem> listener,
|
||||||
LinearLayoutManager layoutManager) {
|
LinearLayoutManager layoutManager) {
|
||||||
@@ -33,10 +41,36 @@ public class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
|||||||
ViewGroup parent, int type) {
|
ViewGroup parent, int type) {
|
||||||
View v = LayoutInflater.from(parent.getContext())
|
View v = LayoutInflater.from(parent.getContext())
|
||||||
.inflate(type, parent, false);
|
.inflate(type, parent, false);
|
||||||
if (type == R.layout.list_item_thread_notice) {
|
if (type == R.layout.list_item_group_join_notice) {
|
||||||
return new JoinMessageItemViewHolder(v);
|
return new JoinMessageItemViewHolder(v, isCreator);
|
||||||
}
|
}
|
||||||
return new ThreadPostViewHolder<>(v);
|
return new ThreadPostViewHolder<>(v);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void setPerspective(boolean isCreator) {
|
||||||
|
this.isCreator = isCreator;
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
void updateVisibility(AuthorId memberId, Visibility v) {
|
||||||
|
int position = findItemPosition(memberId);
|
||||||
|
if (position != NO_POSITION) {
|
||||||
|
GroupMessageItem item = items.get(position);
|
||||||
|
if (item instanceof JoinMessageItem) {
|
||||||
|
((JoinMessageItem) item).setVisibility(v);
|
||||||
|
notifyItemChanged(getVisiblePos(item), item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private int findItemPosition(AuthorId a) {
|
||||||
|
int count = items.size();
|
||||||
|
for (int i = 0; i < count; i++) {
|
||||||
|
GroupMessageItem item = items.get(i);
|
||||||
|
if (item.getAuthor().getId().equals(a))
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
return NO_POSITION; // Not found
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import org.briarproject.android.threaded.ThreadItem;
|
|||||||
import org.briarproject.api.identity.Author;
|
import org.briarproject.api.identity.Author;
|
||||||
import org.briarproject.api.identity.Author.Status;
|
import org.briarproject.api.identity.Author.Status;
|
||||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||||
|
import org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
|
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
@@ -16,15 +17,23 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
class GroupMessageItem extends ThreadItem {
|
class GroupMessageItem extends ThreadItem {
|
||||||
|
|
||||||
private GroupMessageItem(MessageId messageId, MessageId parentId,
|
private final GroupId groupId;
|
||||||
|
|
||||||
|
private GroupMessageItem(MessageId messageId, GroupId groupId,
|
||||||
|
MessageId parentId,
|
||||||
String text, long timestamp, Author author, Status status,
|
String text, long timestamp, Author author, Status status,
|
||||||
boolean isRead) {
|
boolean isRead) {
|
||||||
super(messageId, parentId, text, timestamp, author, status, isRead);
|
super(messageId, parentId, text, timestamp, author, status, isRead);
|
||||||
|
this.groupId = groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
GroupMessageItem(GroupMessageHeader h, String text) {
|
GroupMessageItem(GroupMessageHeader h, String text) {
|
||||||
this(h.getId(), h.getParentId(), text, h.getTimestamp(), h.getAuthor(),
|
this(h.getId(), h.getGroupId(), h.getParentId(), text, h.getTimestamp(),
|
||||||
h.getAuthorStatus(), h.isRead());
|
h.getAuthor(), h.getAuthorStatus(), h.isRead());
|
||||||
|
}
|
||||||
|
|
||||||
|
public GroupId getGroupId() {
|
||||||
|
return groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
@LayoutRes
|
@LayoutRes
|
||||||
|
|||||||
@@ -4,7 +4,8 @@ import android.support.annotation.LayoutRes;
|
|||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
import org.briarproject.api.privategroup.JoinMessageHeader;
|
||||||
|
import org.briarproject.api.privategroup.Visibility;
|
||||||
|
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
|
||||||
@@ -12,9 +13,13 @@ import javax.annotation.concurrent.NotThreadSafe;
|
|||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
class JoinMessageItem extends GroupMessageItem {
|
class JoinMessageItem extends GroupMessageItem {
|
||||||
|
|
||||||
JoinMessageItem(GroupMessageHeader h,
|
private Visibility visibility;
|
||||||
String text) {
|
private final boolean isInitial;
|
||||||
|
|
||||||
|
JoinMessageItem(JoinMessageHeader h, String text) {
|
||||||
super(h, text);
|
super(h, text);
|
||||||
|
this.visibility = h.getVisibility();
|
||||||
|
this.isInitial = h.isInitial();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -29,7 +34,19 @@ class JoinMessageItem extends GroupMessageItem {
|
|||||||
|
|
||||||
@LayoutRes
|
@LayoutRes
|
||||||
public int getLayout() {
|
public int getLayout() {
|
||||||
return R.layout.list_item_thread_notice;
|
return R.layout.list_item_group_join_notice;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Visibility getVisibility() {
|
||||||
|
return visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setVisibility(Visibility visibility) {
|
||||||
|
this.visibility = visibility;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInitial() {
|
||||||
|
return isInitial;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,30 +1,108 @@
|
|||||||
package org.briarproject.android.privategroup.conversation;
|
package org.briarproject.android.privategroup.conversation;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
import android.support.annotation.UiThread;
|
import android.support.annotation.UiThread;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
import android.widget.Button;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
import org.briarproject.R;
|
import org.briarproject.R;
|
||||||
|
import org.briarproject.android.privategroup.reveal.RevealContactsActivity;
|
||||||
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
|
import org.briarproject.android.threaded.BaseThreadItemViewHolder;
|
||||||
import org.briarproject.android.threaded.ThreadItemAdapter;
|
import org.briarproject.android.threaded.ThreadItemAdapter;
|
||||||
import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
import org.briarproject.android.threaded.ThreadItemAdapter.ThreadItemListener;
|
||||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||||
|
|
||||||
|
import static org.briarproject.android.BriarActivity.GROUP_ID;
|
||||||
|
import static org.briarproject.android.privategroup.VisibilityStringProvider.getVisibilityStringId;
|
||||||
|
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||||
|
import static org.briarproject.api.identity.Author.Status.UNKNOWN;
|
||||||
|
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
||||||
|
|
||||||
@UiThread
|
@UiThread
|
||||||
@NotNullByDefault
|
@NotNullByDefault
|
||||||
public class JoinMessageItemViewHolder
|
class JoinMessageItemViewHolder
|
||||||
extends BaseThreadItemViewHolder<GroupMessageItem> {
|
extends BaseThreadItemViewHolder<GroupMessageItem> {
|
||||||
|
|
||||||
public JoinMessageItemViewHolder(View v) {
|
private final boolean isCreator;
|
||||||
|
private final ImageView icon;
|
||||||
|
private final TextView info;
|
||||||
|
private final Button options;
|
||||||
|
|
||||||
|
public JoinMessageItemViewHolder(View v, boolean isCreator) {
|
||||||
super(v);
|
super(v);
|
||||||
|
this.isCreator = isCreator;
|
||||||
|
icon = (ImageView) v.findViewById(R.id.icon);
|
||||||
|
info = (TextView) v.findViewById(R.id.info);
|
||||||
|
options = (Button) v.findViewById(R.id.optionsButton);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void bind(final ThreadItemAdapter<GroupMessageItem> adapter,
|
public void bind(ThreadItemAdapter<GroupMessageItem> adapter,
|
||||||
final ThreadItemListener<GroupMessageItem> listener,
|
ThreadItemListener<GroupMessageItem> listener,
|
||||||
final GroupMessageItem item, int pos) {
|
GroupMessageItem item, int pos) {
|
||||||
super.bind(adapter, listener, item, pos);
|
super.bind(adapter, listener, item, pos);
|
||||||
|
|
||||||
textView.setText(getContext().getString(R.string.groups_member_joined));
|
if (isCreator) bindForCreator((JoinMessageItem) item);
|
||||||
|
else bind((JoinMessageItem) item);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bindForCreator(final JoinMessageItem item) {
|
||||||
|
if (item.isInitial()) {
|
||||||
|
textView.setText(R.string.groups_member_created_you);
|
||||||
|
} else {
|
||||||
|
textView.setText(
|
||||||
|
getContext().getString(R.string.groups_member_joined,
|
||||||
|
item.getAuthor().getName()));
|
||||||
|
}
|
||||||
|
icon.setVisibility(View.GONE);
|
||||||
|
info.setVisibility(View.GONE);
|
||||||
|
options.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void bind(final JoinMessageItem item) {
|
||||||
|
final Context ctx = getContext();
|
||||||
|
|
||||||
|
if (item.isInitial()) {
|
||||||
|
textView.setText(ctx.getString(R.string.groups_member_created,
|
||||||
|
item.getAuthor().getName()));
|
||||||
|
} else {
|
||||||
|
if (item.getStatus() == OURSELVES) {
|
||||||
|
textView.setText(R.string.groups_member_joined_you);
|
||||||
|
} else {
|
||||||
|
textView.setText(ctx.getString(R.string.groups_member_joined,
|
||||||
|
item.getAuthor().getName()));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (item.getStatus() == OURSELVES || item.getStatus() == UNKNOWN) {
|
||||||
|
icon.setVisibility(View.GONE);
|
||||||
|
info.setVisibility(View.GONE);
|
||||||
|
options.setVisibility(View.GONE);
|
||||||
|
} else {
|
||||||
|
icon.setVisibility(View.VISIBLE);
|
||||||
|
info.setVisibility(View.VISIBLE);
|
||||||
|
info.setText(getVisibilityStringId(item.getVisibility()));
|
||||||
|
|
||||||
|
if (item.getVisibility() == INVISIBLE) {
|
||||||
|
icon.setImageResource(R.drawable.ic_visibility_off);
|
||||||
|
options.setVisibility(View.VISIBLE);
|
||||||
|
options.setOnClickListener(new View.OnClickListener() {
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
Intent i =
|
||||||
|
new Intent(ctx, RevealContactsActivity.class);
|
||||||
|
i.putExtra(GROUP_ID, item.getGroupId().getBytes());
|
||||||
|
ctx.startActivity(i);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
icon.setImageResource(R.drawable.ic_visibility);
|
||||||
|
options.setVisibility(View.GONE);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import org.briarproject.android.contactselection.BaseSelectableContactHolder;
|
|||||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import static org.briarproject.android.privategroup.VisibilityStringProvider.getVisibilityStringId;
|
||||||
import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
|
import static org.briarproject.android.util.AndroidUtils.GREY_OUT;
|
||||||
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
import static org.briarproject.api.privategroup.Visibility.INVISIBLE;
|
||||||
|
|
||||||
@@ -31,21 +32,7 @@ public class RevealableContactViewHolder
|
|||||||
OnContactClickListener<RevealableContactItem> listener) {
|
OnContactClickListener<RevealableContactItem> listener) {
|
||||||
super.bind(item, listener);
|
super.bind(item, listener);
|
||||||
|
|
||||||
switch (item.getVisibility()) {
|
info.setText(getVisibilityStringId(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) {
|
if (item.getVisibility() == INVISIBLE) {
|
||||||
icon.setImageResource(R.drawable.ic_visibility_off);
|
icon.setImageResource(R.drawable.ic_visibility_off);
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
|
|
||||||
static final int UNDEFINED = -1;
|
static final int UNDEFINED = -1;
|
||||||
|
|
||||||
private final NestedTreeList<I> items = new NestedTreeList<>();
|
protected final NestedTreeList<I> items = new NestedTreeList<>();
|
||||||
private final Map<I, ValueAnimator> animatingItems = new HashMap<>();
|
private final Map<I, ValueAnimator> animatingItems = new HashMap<>();
|
||||||
private final ThreadItemListener<I> listener;
|
private final ThreadItemListener<I> listener;
|
||||||
private final LinearLayoutManager layoutManager;
|
private final LinearLayoutManager layoutManager;
|
||||||
@@ -61,6 +61,11 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
ui.bind(this, listener, item, position);
|
ui.bind(this, listener, item, position);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Contrary to the super class adapter,
|
||||||
|
* this returns the number of <b>visible</b> items,
|
||||||
|
* not all items in the dataset.
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public int getItemCount() {
|
public int getItemCount() {
|
||||||
return getVisiblePos(null);
|
return getVisiblePos(null);
|
||||||
@@ -268,7 +273,7 @@ public class ThreadItemAdapter<I extends ThreadItem>
|
|||||||
* items if 'item' is null. If 'item' is not visible, NO_POSITION is
|
* items if 'item' is null. If 'item' is not visible, NO_POSITION is
|
||||||
* returned.
|
* returned.
|
||||||
*/
|
*/
|
||||||
private int getVisiblePos(@Nullable I item) {
|
protected int getVisiblePos(@Nullable I item) {
|
||||||
int visibleCounter = 0;
|
int visibleCounter = 0;
|
||||||
int levelLimit = UNDEFINED;
|
int levelLimit = UNDEFINED;
|
||||||
for (I i : items) {
|
for (I i : items) {
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ import org.briarproject.android.view.TextInputView.TextInputListener;
|
|||||||
import org.briarproject.api.clients.NamedGroup;
|
import org.briarproject.api.clients.NamedGroup;
|
||||||
import org.briarproject.api.clients.PostHeader;
|
import org.briarproject.api.clients.PostHeader;
|
||||||
import org.briarproject.api.db.DbException;
|
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 org.briarproject.api.sync.GroupId;
|
||||||
import org.briarproject.api.sync.MessageId;
|
import org.briarproject.api.sync.MessageId;
|
||||||
import org.briarproject.util.StringUtils;
|
import org.briarproject.util.StringUtils;
|
||||||
@@ -35,7 +37,9 @@ import static android.support.design.widget.Snackbar.make;
|
|||||||
import static android.view.View.GONE;
|
import static android.view.View.GONE;
|
||||||
import static android.view.View.VISIBLE;
|
import static android.view.View.VISIBLE;
|
||||||
|
|
||||||
public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadItem, H extends PostHeader>
|
@MethodsNotNullByDefault
|
||||||
|
@ParametersNotNullByDefault
|
||||||
|
public abstract class ThreadListActivity<G extends NamedGroup, A extends ThreadItemAdapter<I>, I extends ThreadItem, H extends PostHeader>
|
||||||
extends BriarActivity
|
extends BriarActivity
|
||||||
implements ThreadListListener<H>, TextInputListener,
|
implements ThreadListListener<H>, TextInputListener,
|
||||||
ThreadItemListener<I> {
|
ThreadItemListener<I> {
|
||||||
@@ -46,7 +50,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
private static final Logger LOG =
|
private static final Logger LOG =
|
||||||
Logger.getLogger(ThreadListActivity.class.getName());
|
Logger.getLogger(ThreadListActivity.class.getName());
|
||||||
|
|
||||||
protected ThreadItemAdapter<I> adapter;
|
protected A adapter;
|
||||||
protected BriarRecyclerView list;
|
protected BriarRecyclerView list;
|
||||||
protected TextInputView textInput;
|
protected TextInputView textInput;
|
||||||
protected GroupId groupId;
|
protected GroupId groupId;
|
||||||
@@ -57,7 +61,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
@CallSuper
|
@CallSuper
|
||||||
@Override
|
@Override
|
||||||
@SuppressWarnings("ConstantConditions")
|
@SuppressWarnings("ConstantConditions")
|
||||||
public void onCreate(final Bundle state) {
|
public void onCreate(@Nullable Bundle state) {
|
||||||
super.onCreate(state);
|
super.onCreate(state);
|
||||||
|
|
||||||
setContentView(getLayout());
|
setContentView(getLayout());
|
||||||
@@ -88,8 +92,7 @@ public abstract class ThreadListActivity<G extends NamedGroup, I extends ThreadI
|
|||||||
@LayoutRes
|
@LayoutRes
|
||||||
protected abstract int getLayout();
|
protected abstract int getLayout();
|
||||||
|
|
||||||
protected abstract ThreadItemAdapter<I> createAdapter(
|
protected abstract A createAdapter(LinearLayoutManager layoutManager);
|
||||||
LinearLayoutManager layoutManager);
|
|
||||||
|
|
||||||
protected void loadNamedGroup() {
|
protected void loadNamedGroup() {
|
||||||
getController().loadNamedGroup(
|
getController().loadNamedGroup(
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package org.briarproject.api.privategroup;
|
package org.briarproject.api.privategroup;
|
||||||
|
|
||||||
import org.briarproject.api.event.Event;
|
import org.briarproject.api.event.Event;
|
||||||
|
import org.briarproject.api.identity.AuthorId;
|
||||||
import org.briarproject.api.nullsafety.NotNullByDefault;
|
import org.briarproject.api.nullsafety.NotNullByDefault;
|
||||||
import org.briarproject.api.sync.GroupId;
|
import org.briarproject.api.sync.GroupId;
|
||||||
|
|
||||||
@@ -11,11 +12,13 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
public class ContactRelationshipRevealedEvent extends Event {
|
public class ContactRelationshipRevealedEvent extends Event {
|
||||||
|
|
||||||
private final GroupId groupId;
|
private final GroupId groupId;
|
||||||
|
private final AuthorId memberId;
|
||||||
private final Visibility visibility;
|
private final Visibility visibility;
|
||||||
|
|
||||||
public ContactRelationshipRevealedEvent(GroupId groupId,
|
public ContactRelationshipRevealedEvent(GroupId groupId, AuthorId memberId,
|
||||||
Visibility visibility) {
|
Visibility visibility) {
|
||||||
this.groupId = groupId;
|
this.groupId = groupId;
|
||||||
|
this.memberId = memberId;
|
||||||
this.visibility = visibility;
|
this.visibility = visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -23,6 +26,10 @@ public class ContactRelationshipRevealedEvent extends Event {
|
|||||||
return groupId;
|
return groupId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public AuthorId getMemberId() {
|
||||||
|
return memberId;
|
||||||
|
}
|
||||||
|
|
||||||
public Visibility getVisibility() {
|
public Visibility getVisibility() {
|
||||||
return visibility;
|
return visibility;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,15 +9,21 @@ import javax.annotation.concurrent.Immutable;
|
|||||||
public class JoinMessageHeader extends GroupMessageHeader {
|
public class JoinMessageHeader extends GroupMessageHeader {
|
||||||
|
|
||||||
private final Visibility visibility;
|
private final Visibility visibility;
|
||||||
|
private final boolean isInitial;
|
||||||
|
|
||||||
public JoinMessageHeader(GroupMessageHeader h, Visibility visibility) {
|
public JoinMessageHeader(GroupMessageHeader h, Visibility visibility, boolean isInitial) {
|
||||||
super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
|
super(h.getGroupId(), h.getId(), h.getParentId(), h.getTimestamp(),
|
||||||
h.getAuthor(), h.getAuthorStatus(), h.isRead());
|
h.getAuthor(), h.getAuthorStatus(), h.isRead());
|
||||||
this.visibility = visibility;
|
this.visibility = visibility;
|
||||||
|
this.isInitial = isInitial;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Visibility getVisibility() {
|
public Visibility getVisibility() {
|
||||||
return visibility;
|
return visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isInitial() {
|
||||||
|
return isInitial;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ interface GroupConstants {
|
|||||||
String KEY_MEMBER_ID = "memberId";
|
String KEY_MEMBER_ID = "memberId";
|
||||||
String KEY_MEMBER_NAME = "memberName";
|
String KEY_MEMBER_NAME = "memberName";
|
||||||
String KEY_MEMBER_PUBLIC_KEY = "memberPublicKey";
|
String KEY_MEMBER_PUBLIC_KEY = "memberPublicKey";
|
||||||
|
String KEY_INITIAL_JOIN_MSG = "initialJoinMsg";
|
||||||
|
|
||||||
String GROUP_KEY_MEMBERS = "members";
|
String GROUP_KEY_MEMBERS = "members";
|
||||||
String GROUP_KEY_OUR_GROUP = "ourGroup";
|
String GROUP_KEY_OUR_GROUP = "ourGroup";
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import static org.briarproject.api.identity.AuthorConstants.MAX_SIGNATURE_LENGTH
|
|||||||
import static org.briarproject.api.privategroup.MessageType.JOIN;
|
import static org.briarproject.api.privategroup.MessageType.JOIN;
|
||||||
import static org.briarproject.api.privategroup.MessageType.POST;
|
import static org.briarproject.api.privategroup.MessageType.POST;
|
||||||
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
import static org.briarproject.api.privategroup.PrivateGroupConstants.MAX_GROUP_POST_BODY_LENGTH;
|
||||||
|
import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
|
||||||
@@ -99,10 +100,12 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
|
|
||||||
// invite is null if the member is the creator of the private group
|
// invite is null if the member is the creator of the private group
|
||||||
Author creator = pg.getCreator();
|
Author creator = pg.getCreator();
|
||||||
|
boolean isCreator = false;
|
||||||
BdfList invite = body.getOptionalList(3);
|
BdfList invite = body.getOptionalList(3);
|
||||||
if (invite == null) {
|
if (invite == null) {
|
||||||
if (!member.equals(creator))
|
if (!member.equals(creator))
|
||||||
throw new InvalidMessageException();
|
throw new InvalidMessageException();
|
||||||
|
isCreator = true;
|
||||||
} else {
|
} else {
|
||||||
if (member.equals(creator))
|
if (member.equals(creator))
|
||||||
throw new InvalidMessageException();
|
throw new InvalidMessageException();
|
||||||
@@ -149,6 +152,7 @@ class GroupMessageValidator extends BdfMessageValidator {
|
|||||||
|
|
||||||
// Return the metadata and no dependencies
|
// Return the metadata and no dependencies
|
||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
|
meta.put(KEY_INITIAL_JOIN_MSG, isCreator);
|
||||||
return new BdfMessageContext(meta);
|
return new BdfMessageContext(meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -60,6 +60,7 @@ import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_DISSOLVED;
|
|||||||
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_MEMBERS;
|
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_MEMBERS;
|
||||||
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
|
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_OUR_GROUP;
|
||||||
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
|
import static org.briarproject.privategroup.GroupConstants.GROUP_KEY_VISIBILITY;
|
||||||
|
import static org.briarproject.privategroup.GroupConstants.KEY_INITIAL_JOIN_MSG;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_ID;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_NAME;
|
||||||
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
|
import static org.briarproject.privategroup.GroupConstants.KEY_MEMBER_PUBLIC_KEY;
|
||||||
@@ -114,16 +115,17 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
|||||||
new BdfEntry(GROUP_KEY_DISSOLVED, false)
|
new BdfEntry(GROUP_KEY_DISSOLVED, false)
|
||||||
);
|
);
|
||||||
clientHelper.mergeGroupMetadata(txn, group.getId(), meta);
|
clientHelper.mergeGroupMetadata(txn, group.getId(), meta);
|
||||||
joinPrivateGroup(txn, joinMsg);
|
joinPrivateGroup(txn, joinMsg, creator);
|
||||||
} catch (FormatException e) {
|
} catch (FormatException e) {
|
||||||
throw new DbException(e);
|
throw new DbException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void joinPrivateGroup(Transaction txn, GroupMessage m)
|
private void joinPrivateGroup(Transaction txn, GroupMessage m,
|
||||||
throws DbException, FormatException {
|
boolean creator) throws DbException, FormatException {
|
||||||
BdfDictionary meta = new BdfDictionary();
|
BdfDictionary meta = new BdfDictionary();
|
||||||
meta.put(KEY_TYPE, JOIN.getInt());
|
meta.put(KEY_TYPE, JOIN.getInt());
|
||||||
|
meta.put(KEY_INITIAL_JOIN_MSG, creator);
|
||||||
addMessageMetadata(meta, m, true);
|
addMessageMetadata(meta, m, true);
|
||||||
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
|
clientHelper.addLocalMessage(txn, m.getMessage(), meta, true);
|
||||||
trackOutgoingMessage(txn, m.getMessage());
|
trackOutgoingMessage(txn, m.getMessage());
|
||||||
@@ -377,7 +379,8 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
|||||||
|
|
||||||
GroupMessageHeader header =
|
GroupMessageHeader header =
|
||||||
getGroupMessageHeader(txn, g, id, meta, statuses);
|
getGroupMessageHeader(txn, g, id, meta, statuses);
|
||||||
return new JoinMessageHeader(header, v);
|
boolean creator = meta.getBoolean(KEY_INITIAL_JOIN_MSG);
|
||||||
|
return new JoinMessageHeader(header, v, creator);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -451,7 +454,7 @@ public class PrivateGroupManagerImpl extends BdfIncomingMessageHook implements
|
|||||||
if (!foundMember) throw new ProtocolStateException();
|
if (!foundMember) throw new ProtocolStateException();
|
||||||
if (changed) {
|
if (changed) {
|
||||||
clientHelper.mergeGroupMetadata(txn, g, meta);
|
clientHelper.mergeGroupMetadata(txn, g, meta);
|
||||||
txn.attach(new ContactRelationshipRevealedEvent(g, v));
|
txn.attach(new ContactRelationshipRevealedEvent(g, a, v));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user