Port Signal's emoji implementation to Briar

Add functionality to save and restore recently used Emojis

Update emoji and add new categories based on AOSP's XML file
This commit is contained in:
Torsten Grote
2016-09-13 18:55:17 -03:00
committed by akwizgran
parent 1fdbe65dde
commit d5beca5351
105 changed files with 4560 additions and 258 deletions

View File

@@ -40,6 +40,8 @@ import org.briarproject.android.sharing.ShareForumActivity;
import org.briarproject.android.sharing.ShareForumMessageFragment;
import org.briarproject.android.sharing.SharingStatusBlogActivity;
import org.briarproject.android.sharing.SharingStatusForumActivity;
import org.thoughtcrime.securesms.components.emoji.EmojiProvider;
import org.thoughtcrime.securesms.components.emoji.RecentEmojiPageModel;
import dagger.Component;
@@ -114,6 +116,9 @@ public interface ActivityComponent {
void inject(RssFeedManageActivity activity);
void inject(EmojiProvider emojiProvider);
void inject(RecentEmojiPageModel recentEmojiPageModel);
// Fragments
void inject(ContactListFragment fragment);
void inject(ForumListFragment fragment);

View File

@@ -25,7 +25,7 @@ import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.sharing.ShareBlogActivity;
import org.briarproject.android.sharing.SharingStatusBlogActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.blogs.BlogPostHeader;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.Author;

View File

@@ -15,7 +15,7 @@ import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.util.TextAvatarView;
import org.briarproject.android.view.TextAvatarView;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.sync.GroupId;

View File

@@ -18,7 +18,7 @@ import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
import org.briarproject.android.util.AuthorView;
import org.briarproject.android.view.AuthorView;
import org.briarproject.api.blogs.BlogCommentHeader;
import org.briarproject.api.blogs.BlogPostHeader;
import org.briarproject.api.identity.Author;

View File

@@ -22,7 +22,7 @@ import org.briarproject.android.blogs.BlogPostAdapter.OnBlogPostClickListener;
import org.briarproject.android.controller.handler.UiResultExceptionHandler;
import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.blogs.Blog;
import org.briarproject.api.blogs.BlogPostHeader;
import org.briarproject.api.db.DbException;

View File

@@ -14,7 +14,7 @@ import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.blogs.RssFeedAdapter.RssFeedListener;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.db.DbException;
import org.briarproject.api.feed.Feed;
import org.briarproject.api.feed.FeedManager;

View File

@@ -20,7 +20,7 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.keyagreement.KeyAgreementActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;

View File

@@ -16,9 +16,6 @@ import android.util.SparseArray;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -27,8 +24,11 @@ import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.contact.ConversationAdapter.IntroductionHandler;
import org.briarproject.android.introduction.IntroductionActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.android.view.TextInputView;
import org.briarproject.android.view.TextInputView.TextInputListener;
import org.briarproject.api.FormatException;
import org.briarproject.api.blogs.BlogSharingManager;
import org.briarproject.api.clients.SessionId;
@@ -93,8 +93,7 @@ import static org.briarproject.android.contact.ConversationItem.IncomingItem;
import static org.briarproject.android.contact.ConversationItem.OutgoingItem;
public class ConversationActivity extends BriarActivity
implements EventListener, OnClickListener,
ConversationAdapter.IntroductionHandler {
implements EventListener, IntroductionHandler, TextInputListener {
private static final Logger LOG =
Logger.getLogger(ConversationActivity.class.getName());
@@ -113,8 +112,7 @@ public class ConversationActivity extends BriarActivity
private ImageView toolbarStatus;
private TextView toolbarTitle;
private BriarRecyclerView list;
private EditText content;
private View sendButton;
private TextInputView textInputView;
// Fields that are accessed from background threads must be volatile
@Inject
@@ -139,6 +137,7 @@ public class ConversationActivity extends BriarActivity
private volatile boolean connected = false;
private volatile Map<MessageId, byte[]> bodyCache = new HashMap<>();
@SuppressWarnings("ConstantConditions")
@Override
public void onCreate(Bundle state) {
super.onCreate(state);
@@ -177,13 +176,8 @@ public class ConversationActivity extends BriarActivity
list.setAdapter(adapter);
list.setEmptyText(getString(R.string.no_private_messages));
content = (EditText) findViewById(R.id.input_text);
sendButton = findViewById(R.id.btn_send);
if (sendButton != null) {
// Enabled after loading the conversation
sendButton.setEnabled(false);
sendButton.setOnClickListener(this);
}
textInputView = (TextInputView) findViewById(R.id.text_input_container);
textInputView.setListener(this);
}
@Override
@@ -262,6 +256,10 @@ public class ConversationActivity extends BriarActivity
@Override
public void onBackPressed() {
if (textInputView.isEmojiDrawerOpen()) {
textInputView.hideEmojiDrawer();
return;
}
// FIXME disabled exit transition, because it doesn't work for some reason #318
//supportFinishAfterTransition();
finish();
@@ -367,7 +365,7 @@ public class ConversationActivity extends BriarActivity
runOnUiThread(new Runnable() {
@Override
public void run() {
sendButton.setEnabled(true);
textInputView.setSendButtonEnabled(true);
if (headers.isEmpty() && introductions.isEmpty() &&
invitations.isEmpty()) {
// we have no messages,
@@ -637,14 +635,12 @@ public class ConversationActivity extends BriarActivity
}
@Override
public void onClick(View view) {
public void onSendClick(String text) {
markMessagesRead();
String message = content.getText().toString();
if (message.equals("")) return;
if (text.equals("")) return;
long timestamp = System.currentTimeMillis();
timestamp = Math.max(timestamp, getMinTimestampForNewMessage());
createMessage(StringUtils.toUtf8(message), timestamp);
content.setText("");
createMessage(StringUtils.toUtf8(text), timestamp);
}
private long getMinTimestampForNewMessage() {

View File

@@ -21,8 +21,6 @@ import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
@@ -31,11 +29,13 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.controller.handler.UiResultHandler;
import org.briarproject.android.forum.ForumController.ForumPostListener;
import org.briarproject.android.sharing.ShareForumActivity;
import org.briarproject.android.sharing.SharingStatusForumActivity;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.util.TrustIndicatorView;
import org.briarproject.android.view.AuthorView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.android.view.TextInputView;
import org.briarproject.android.view.TextInputView.TextInputListener;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
@@ -48,8 +48,6 @@ import java.util.Map;
import javax.inject.Inject;
import im.delight.android.identicons.IdenticonDrawable;
import static android.content.Intent.FLAG_ACTIVITY_CLEAR_TOP;
import static android.content.Intent.FLAG_ACTIVITY_SINGLE_TOP;
import static android.support.v7.widget.RecyclerView.NO_POSITION;
@@ -59,7 +57,7 @@ import static android.view.View.VISIBLE;
import static android.widget.Toast.LENGTH_SHORT;
public class ForumActivity extends BriarActivity implements
ForumController.ForumPostListener {
ForumPostListener, TextInputListener {
static final String FORUM_NAME = "briar.FORUM_NAME";
@@ -80,8 +78,7 @@ public class ForumActivity extends BriarActivity implements
protected ForumAdapter forumAdapter;
private BriarRecyclerView recyclerView;
private EditText textInput;
private ViewGroup inputContainer;
private TextInputView textInput;
private LinearLayoutManager linearLayoutManager;
private volatile GroupId groupId = null;
@@ -101,9 +98,9 @@ public class ForumActivity extends BriarActivity implements
forumAdapter = new ForumAdapter();
inputContainer = (ViewGroup) findViewById(R.id.text_input_container);
inputContainer.setVisibility(GONE);
textInput = (EditText) findViewById(R.id.input_text);
textInput = (TextInputView) findViewById(R.id.text_input_container);
textInput.setVisibility(GONE);
textInput.setListener(this);
recyclerView =
(BriarRecyclerView) findViewById(R.id.forum_discussion_list);
recyclerView.setAdapter(forumAdapter);
@@ -140,7 +137,7 @@ public class ForumActivity extends BriarActivity implements
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
inputContainer.setVisibility(
textInput.setVisibility(
savedInstanceState.getBoolean(KEY_INPUT_VISIBILITY) ?
VISIBLE : GONE);
}
@@ -150,7 +147,7 @@ public class ForumActivity extends BriarActivity implements
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
outState.putBoolean(KEY_INPUT_VISIBILITY,
inputContainer.getVisibility() == VISIBLE);
textInput.getVisibility() == VISIBLE);
ForumEntry replyEntry = forumAdapter.getReplyEntry();
if (replyEntry != null) {
outState.putByteArray(KEY_REPLY_ID,
@@ -190,8 +187,10 @@ public class ForumActivity extends BriarActivity implements
@Override
public void onBackPressed() {
if (inputContainer.getVisibility() == VISIBLE) {
inputContainer.setVisibility(GONE);
if (textInput.isEmojiDrawerOpen()) {
textInput.hideEmojiDrawer();
} else if (textInput.getVisibility() == VISIBLE) {
textInput.setVisibility(GONE);
forumAdapter.setReplyEntry(null);
} else {
super.onBackPressed();
@@ -202,8 +201,8 @@ public class ForumActivity extends BriarActivity implements
// An animation here would be an overkill because of the keyboard
// popping up.
// only clear the text when the input container was not visible
if (inputContainer.getVisibility() != VISIBLE) {
inputContainer.setVisibility(VISIBLE);
if (textInput.getVisibility() != VISIBLE) {
textInput.setVisibility(VISIBLE);
textInput.setText("");
}
textInput.requestFocus();
@@ -260,8 +259,8 @@ public class ForumActivity extends BriarActivity implements
recyclerView.stopPeriodicUpdate();
}
public void sendMessage(View view) {
String text = textInput.getText().toString();
@Override
public void onSendClick(String text) {
if (text.trim().length() == 0)
return;
if (forumController.getForum() == null) return;
@@ -274,7 +273,7 @@ public class ForumActivity extends BriarActivity implements
replyEntry.getMessageId());
}
hideSoftKeyboard(textInput);
inputContainer.setVisibility(GONE);
textInput.setVisibility(GONE);
forumAdapter.setReplyEntry(null);
}
@@ -334,10 +333,9 @@ public class ForumActivity extends BriarActivity implements
static class ForumViewHolder extends RecyclerView.ViewHolder {
final TextView textView, lvlText, authorText, dateText, repliesText;
final TextView textView, lvlText, repliesText;
final AuthorView author;
final View[] lvls;
public final ImageView avatar;
final TrustIndicatorView trust;
final View chevron, replyButton;
final ViewGroup cell;
final View topDivider;
@@ -347,8 +345,7 @@ public class ForumActivity extends BriarActivity implements
textView = (TextView) v.findViewById(R.id.text);
lvlText = (TextView) v.findViewById(R.id.nested_line_text);
authorText = (TextView) v.findViewById(R.id.author);
dateText = (TextView) v.findViewById(R.id.date);
author = (AuthorView) v.findViewById(R.id.author);
repliesText = (TextView) v.findViewById(R.id.replies);
int[] nestedLineIds = {
R.id.nested_line_1, R.id.nested_line_2, R.id.nested_line_3,
@@ -358,8 +355,6 @@ public class ForumActivity extends BriarActivity implements
for (int i = 0; i < lvls.length; i++) {
lvls[i] = v.findViewById(nestedLineIds[i]);
}
avatar = (ImageView) v.findViewById(R.id.avatar);
trust = (TrustIndicatorView) v.findViewById(R.id.trustIndicator);
chevron = v.findViewById(R.id.chevron);
replyButton = v.findViewById(R.id.btn_reply);
cell = (ViewGroup) v.findViewById(R.id.forum_cell);
@@ -604,7 +599,7 @@ public class ForumActivity extends BriarActivity implements
public ForumViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.forum_discussion_cell, parent, false);
.inflate(R.layout.list_item_forum_post, parent, false);
return new ForumViewHolder(v);
}
@@ -635,10 +630,9 @@ public class ForumActivity extends BriarActivity implements
} else {
ui.lvlText.setVisibility(GONE);
}
ui.authorText.setText(data.getAuthor());
ui.dateText.setText(AndroidUtils
.formatDate(ForumActivity.this, data.getTimestamp()));
ui.trust.setTrustLevel(data.getStatus());
ui.author.setAuthor(data.getAuthor());
ui.author.setDate(data.getTimestamp());
ui.author.setAuthorStatus(data.getStatus());
int replies = getReplyCount(data);
if (replies == 0) {
@@ -648,8 +642,6 @@ public class ForumActivity extends BriarActivity implements
.getQuantityString(R.plurals.message_replies, replies,
replies));
}
ui.avatar.setImageDrawable(
new IdenticonDrawable(data.getAuthorId().getBytes()));
if (hasDescendants(data)) {
ui.chevron.setVisibility(VISIBLE);

View File

@@ -1,6 +1,7 @@
package org.briarproject.android.forum;
import org.briarproject.api.forum.ForumPostHeader;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.sync.MessageId;
@@ -11,26 +12,24 @@ public class ForumEntry {
private final String text;
private final int level;
private final long timestamp;
private final String author;
private final AuthorId authorId;
private final Author author;
private Status status;
private boolean isShowingDescendants = true;
private boolean isRead = true;
ForumEntry(ForumPostHeader h, String text, int level) {
this(h.getId(), text, level, h.getTimestamp(), h.getAuthor().getName(),
h.getAuthor().getId(), h.getAuthorStatus());
this(h.getId(), text, level, h.getTimestamp(), h.getAuthor(),
h.getAuthorStatus());
this.isRead = h.isRead();
}
public ForumEntry(MessageId messageId, String text, int level,
long timestamp, String author, AuthorId authorId, Status status) {
long timestamp, Author author, Status status) {
this.messageId = messageId;
this.text = text;
this.level = level;
this.timestamp = timestamp;
this.author = author;
this.authorId = authorId;
this.status = status;
}
@@ -46,14 +45,10 @@ public class ForumEntry {
return timestamp;
}
public String getAuthor() {
public Author getAuthor() {
return author;
}
AuthorId getAuthorId() {
return authorId;
}
public Status getStatus() {
return status;
}

View File

@@ -13,7 +13,7 @@ import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.util.TextAvatarView;
import org.briarproject.android.view.TextAvatarView;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.sync.GroupId;

View File

@@ -18,7 +18,7 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.api.AndroidNotificationManager;
import org.briarproject.android.fragment.BaseEventFragment;
import org.briarproject.android.sharing.InvitationsForumActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.db.DbException;
import org.briarproject.api.db.NoSuchGroupException;
import org.briarproject.api.event.ContactRemovedEvent;

View File

@@ -3,7 +3,8 @@ package org.briarproject.android.forum;
import org.briarproject.android.controller.handler.ResultHandler;
import org.briarproject.api.UniqueId;
import org.briarproject.api.forum.Forum;
import org.briarproject.api.identity.AuthorId;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.AuthorFactory;
import org.briarproject.api.sync.GroupId;
import org.briarproject.api.sync.MessageId;
@@ -20,34 +21,27 @@ import static org.briarproject.api.identity.Author.Status.UNVERIFIED;
public class ForumTestControllerImpl implements ForumController {
@Inject
AuthorFactory authorFactory;
private static final Logger LOG =
Logger.getLogger(ForumControllerImpl.class.getName());
private final static String[] AUTHORS = {
"Guðmundur",
"Jónas",
"Geir Þorsteinn Gísli Máni Halldórsson Guðjónsson Mogensen",
"Baldur Friðrik",
"Anna Katrín",
"Þór",
"Anna Þorbjörg",
"Guðrún",
"Helga",
"Haraldur"
private final Author[] AUTHORS = {
authorFactory.createAuthor("Guðmundur", new byte[42]),
authorFactory.createAuthor("Jónas", new byte[42]),
authorFactory.createAuthor(
"Geir Þorsteinn Gísli Máni Halldórsson Guðjónsson Mogensen",
new byte[42]),
authorFactory.createAuthor("Baldur Friðrik", new byte[42]),
authorFactory.createAuthor("Anna Katrín", new byte[42]),
authorFactory.createAuthor("Þór", new byte[42]),
authorFactory.createAuthor("Anna Þorbjörg", new byte[42]),
authorFactory.createAuthor("Guðrún", new byte[42]),
authorFactory.createAuthor("Helga", new byte[42]),
authorFactory.createAuthor("Haraldur", new byte[42])
};
private final static AuthorId[] AUTHOR_ID = new AuthorId[AUTHORS.length];
static {
SecureRandom random = new SecureRandom();
for (int i = 0; i < AUTHOR_ID.length; i++) {
byte[] b = new byte[UniqueId.LENGTH];
random.nextBytes(b);
AUTHOR_ID[i] = new AuthorId(b);
}
}
private final static String SAGA =
"Það er upphaf á sögu þessari að Hákon konungur " +
"Aðalsteinsfóstri réð fyrir Noregi og var þetta á ofanverðum " +
@@ -117,8 +111,7 @@ public class ForumTestControllerImpl implements ForumController {
random.nextBytes(b);
forumEntries[e] =
new ForumEntry(new MessageId(b), SAGA.substring(0, i[e]),
l[e], timestamp, AUTHORS[authorIndex],
AUTHOR_ID[authorIndex], UNVERIFIED);
l[e], timestamp, AUTHORS[authorIndex], UNVERIFIED);
}
LOG.info("forum entries: " + forumEntries.length);
resultHandler.onResult(true);

View File

@@ -17,7 +17,7 @@ import org.briarproject.android.contact.ContactListAdapter;
import org.briarproject.android.contact.ContactListItem;
import org.briarproject.android.contact.ConversationItem;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;

View File

@@ -23,7 +23,7 @@ import org.briarproject.R;
import org.briarproject.android.ActivityComponent;
import org.briarproject.android.api.AndroidExecutor;
import org.briarproject.android.fragment.BaseEventFragment;
import org.briarproject.android.util.CameraView;
import org.briarproject.android.view.CameraView;
import org.briarproject.android.util.QrCodeDecoder;
import org.briarproject.android.util.QrCodeUtils;
import org.briarproject.api.event.Event;

View File

@@ -17,7 +17,7 @@ import org.briarproject.android.ActivityComponent;
import org.briarproject.android.contact.BaseContactListAdapter;
import org.briarproject.android.contact.ContactListItem;
import org.briarproject.android.fragment.BaseFragment;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.contact.ContactId;
import org.briarproject.api.contact.ContactManager;

View File

@@ -10,7 +10,7 @@ import android.widget.Button;
import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.util.TextAvatarView;
import org.briarproject.android.view.TextAvatarView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.sharing.InvitationItem;
import org.briarproject.util.StringUtils;

View File

@@ -7,7 +7,7 @@ import android.widget.Toast;
import org.briarproject.R;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.event.ContactRemovedEvent;
import org.briarproject.api.event.Event;
import org.briarproject.api.event.EventBus;

View File

@@ -8,7 +8,7 @@ import android.view.MenuItem;
import org.briarproject.R;
import org.briarproject.android.BriarActivity;
import org.briarproject.android.contact.ContactListItem;
import org.briarproject.android.util.BriarRecyclerView;
import org.briarproject.android.view.BriarRecyclerView;
import org.briarproject.api.contact.Contact;
import org.briarproject.api.db.DbException;
import org.briarproject.api.identity.IdentityManager;

View File

@@ -15,7 +15,6 @@ import android.text.SpannableString;
import android.text.SpannableStringBuilder;
import android.text.Spanned;
import android.text.format.DateUtils;
import android.text.method.LinkMovementMethod;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.URLSpan;
@@ -23,6 +22,7 @@ import android.view.View;
import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.view.ArticleMovementMethod;
import org.briarproject.android.widget.LinkDialogFragment;
import org.briarproject.util.IoUtils;
import org.briarproject.util.StringUtils;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.text.Layout;
import android.text.Spannable;

View File

@@ -1,10 +1,11 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.content.Intent;
import android.content.res.TypedArray;
import android.graphics.Typeface;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.app.ActivityOptionsCompat;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
@@ -18,6 +19,8 @@ import android.widget.TextView;
import org.briarproject.R;
import org.briarproject.android.blogs.BlogActivity;
import org.briarproject.android.util.AndroidUtils;
import org.briarproject.android.view.TrustIndicatorView;
import org.briarproject.api.identity.Author;
import org.briarproject.api.identity.Author.Status;
import org.briarproject.api.sync.GroupId;
@@ -34,6 +37,7 @@ import static android.util.TypedValue.COMPLEX_UNIT_PX;
import static org.briarproject.android.BriarActivity.GROUP_ID;
import static org.briarproject.api.identity.Author.Status.OURSELVES;
@UiThread
public class AuthorView extends RelativeLayout {
private final CircleImageView avatar;

View File

@@ -1,7 +1,8 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.Nullable;
import android.support.v7.widget.RecyclerView;
import android.support.v7.widget.RecyclerView.Adapter;
import android.util.AttributeSet;
@@ -34,11 +35,11 @@ public class BriarRecyclerView extends FrameLayout {
this(context, null, 0);
}
public BriarRecyclerView(Context context, AttributeSet attrs) {
public BriarRecyclerView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public BriarRecyclerView(Context context, AttributeSet attrs,
public BriarRecyclerView(Context context, @Nullable AttributeSet attrs,
int defStyle) {
super(context, attrs, defStyle);

View File

@@ -1,4 +1,4 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.support.design.widget.CoordinatorLayout;

View File

@@ -1,4 +1,4 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.hardware.Camera;
@@ -12,6 +12,8 @@ import android.util.DisplayMetrics;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import org.briarproject.android.util.PreviewConsumer;
import java.io.IOException;
import java.util.Collections;
import java.util.List;

View File

@@ -1,8 +1,10 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.graphics.Color;
import android.graphics.drawable.Drawable;
import android.support.annotation.Nullable;
import android.support.annotation.UiThread;
import android.support.v4.content.ContextCompat;
import android.support.v7.widget.AppCompatTextView;
import android.util.AttributeSet;
@@ -16,6 +18,7 @@ import org.briarproject.api.identity.Author;
import de.hdodenhof.circleimageview.CircleImageView;
import im.delight.android.identicons.IdenticonDrawable;
@UiThread
public class TextAvatarView extends FrameLayout {
final private AppCompatTextView character;
@@ -23,7 +26,7 @@ public class TextAvatarView extends FrameLayout {
final private TextView badge;
private int unreadCount;
public TextAvatarView(Context context, AttributeSet attrs) {
public TextAvatarView(Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
LayoutInflater inflater = (LayoutInflater) context

View File

@@ -0,0 +1,171 @@
package org.briarproject.android.view;
import android.content.Context;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.annotation.StringRes;
import android.support.annotation.UiThread;
import android.util.AttributeSet;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import org.briarproject.R;
import org.thoughtcrime.securesms.components.KeyboardAwareRelativeLayout;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer;
import org.thoughtcrime.securesms.components.emoji.EmojiDrawer.EmojiEventListener;
import org.thoughtcrime.securesms.components.emoji.EmojiEditText;
import org.thoughtcrime.securesms.components.emoji.EmojiToggle;
import java.util.logging.Logger;
import static android.content.Context.INPUT_METHOD_SERVICE;
@UiThread
public class TextInputView extends KeyboardAwareRelativeLayout
implements EmojiEventListener {
private static final String TAG = TextInputView.class.getName();
private static final Logger LOG = Logger.getLogger(TAG);
private EmojiEditText editText;
private View sendButton;
private EmojiDrawer emojiDrawer;
private TextInputListener listener;
public TextInputView(Context context) {
this(context, null);
}
public TextInputView(Context context, @Nullable AttributeSet attrs) {
this(context, attrs, 0);
}
public TextInputView(Context context, @Nullable AttributeSet attrs,
int defStyleAttr) {
super(context, attrs, defStyleAttr);
LayoutInflater inflater = (LayoutInflater) context
.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
inflater.inflate(R.layout.text_input_view, this, true);
// find views
EmojiToggle emojiToggle = (EmojiToggle) findViewById(R.id.emoji_toggle);
editText = (EmojiEditText) findViewById(R.id.input_text);
emojiDrawer = (EmojiDrawer) findViewById(R.id.emoji_drawer);
sendButton = findViewById(R.id.btn_send);
emojiToggle.attach(emojiDrawer);
emojiToggle.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
onEmojiToggleClicked();
}
});
editText.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
showSoftKeyboard();
}
});
sendButton.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
if (listener != null) {
listener.onSendClick(editText.getText().toString());
editText.setText("");
}
}
});
emojiDrawer.setEmojiEventListener(this);
}
@Override
public void onKeyEvent(KeyEvent keyEvent) {
editText.dispatchKeyEvent(keyEvent);
}
@Override
public void onEmojiSelected(String emoji) {
editText.insertEmoji(emoji);
}
private void onEmojiToggleClicked() {
if (isEmojiDrawerOpen()) {
showSoftKeyboard();
} else {
showEmojiDrawer();
}
}
public void setText(String text) {
editText.setText(text);
}
public void setHint(@StringRes int res) {
editText.setHint(res);
}
public void setSendButtonEnabled(boolean enabled) {
sendButton.setEnabled(enabled);
}
public void setListener(TextInputListener listener) {
this.listener = listener;
}
public interface TextInputListener {
void onSendClick(String text);
}
public void showSoftKeyboard() {
if (isKeyboardOpen()) return;
if (emojiDrawer.isShowing()) {
postOnKeyboardOpen(new Runnable() {
@Override
public void run() {
hideEmojiDrawer();
}
});
}
editText.post(new Runnable() {
@Override
public void run() {
editText.requestFocus();
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).showSoftInput(editText, 0);
}
});
}
public void hideSoftKeyboard() {
IBinder token = editText.getWindowToken();
Object o = getContext().getSystemService(INPUT_METHOD_SERVICE);
((InputMethodManager) o).hideSoftInputFromWindow(token, 0);
}
public void showEmojiDrawer() {
if (isKeyboardOpen()) {
postOnKeyboardClose(new Runnable() {
@Override public void run() {
emojiDrawer.show(getKeyboardHeight());
}
});
hideSoftKeyboard();
} else {
emojiDrawer.show(getKeyboardHeight());
}
}
public void hideEmojiDrawer() {
emojiDrawer.hide();
}
public boolean isEmojiDrawerOpen() {
return emojiDrawer.isShowing();
}
}

View File

@@ -1,6 +1,7 @@
package org.briarproject.android.util;
package org.briarproject.android.view;
import android.content.Context;
import android.support.annotation.UiThread;
import android.support.v4.content.ContextCompat;
import android.util.AttributeSet;
import android.widget.ImageView;
@@ -10,6 +11,7 @@ import org.briarproject.api.identity.Author.Status;
import static org.briarproject.api.identity.Author.Status.OURSELVES;
@UiThread
public class TrustIndicatorView extends ImageView {
public TrustIndicatorView(Context context) {