mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-13 19:29:06 +01:00
Implement first prototype of private group message threads
This commit is contained in:
@@ -28,6 +28,7 @@ import org.briarproject.android.keyagreement.KeyAgreementActivity;
|
||||
import org.briarproject.android.keyagreement.ShowQrCodeFragment;
|
||||
import org.briarproject.android.panic.PanicPreferencesActivity;
|
||||
import org.briarproject.android.panic.PanicResponderActivity;
|
||||
import org.briarproject.android.privategroup.conversation.GroupActivity;
|
||||
import org.briarproject.android.privategroup.list.GroupListFragment;
|
||||
import org.briarproject.android.sharing.ContactSelectorFragment;
|
||||
import org.briarproject.android.sharing.InvitationsBlogActivity;
|
||||
@@ -72,6 +73,8 @@ public interface ActivityComponent {
|
||||
|
||||
void inject(InvitationsBlogActivity activity);
|
||||
|
||||
void inject(GroupActivity activity);
|
||||
|
||||
void inject(CreateForumActivity activity);
|
||||
|
||||
void inject(ShareForumActivity activity);
|
||||
|
||||
@@ -21,6 +21,8 @@ import org.briarproject.android.controller.SetupController;
|
||||
import org.briarproject.android.controller.SetupControllerImpl;
|
||||
import org.briarproject.android.forum.ForumController;
|
||||
import org.briarproject.android.forum.ForumControllerImpl;
|
||||
import org.briarproject.android.privategroup.conversation.GroupController;
|
||||
import org.briarproject.android.privategroup.conversation.GroupControllerImpl;
|
||||
import org.briarproject.android.privategroup.list.GroupListController;
|
||||
import org.briarproject.android.privategroup.list.GroupListControllerImpl;
|
||||
|
||||
@@ -99,6 +101,13 @@ public class ActivityModule {
|
||||
return groupListController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
protected GroupController provideGroupController(
|
||||
GroupControllerImpl groupController) {
|
||||
return groupController;
|
||||
}
|
||||
|
||||
@ActivityScope
|
||||
@Provides
|
||||
protected ForumController provideForumController(
|
||||
|
||||
@@ -35,6 +35,7 @@ import org.briarproject.api.messaging.MessagingManager;
|
||||
import org.briarproject.api.messaging.PrivateMessageFactory;
|
||||
import org.briarproject.api.plugins.ConnectionRegistry;
|
||||
import org.briarproject.api.plugins.PluginManager;
|
||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.settings.SettingsManager;
|
||||
import org.briarproject.plugins.AndroidPluginsModule;
|
||||
@@ -96,6 +97,8 @@ public interface AndroidComponent extends CoreEagerSingletons {
|
||||
|
||||
PrivateGroupManager privateGroupManager();
|
||||
|
||||
GroupMessageFactory groupMessageFactory();
|
||||
|
||||
ForumManager forumManager();
|
||||
|
||||
ForumSharingManager forumSharingManager();
|
||||
|
||||
@@ -166,8 +166,7 @@ public class ForumControllerImpl
|
||||
p.getMessage().getTimestamp(),
|
||||
p.getAuthor(), OURSELVES, true);
|
||||
|
||||
resultHandler.onResult(new ForumEntry(h,
|
||||
bodyCache.get(p.getMessage().getId())));
|
||||
resultHandler.onResult(buildItem(h));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import android.os.Bundle;
|
||||
import android.support.annotation.LayoutRes;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.ActivityComponent;
|
||||
import org.briarproject.android.threaded.ThreadListActivity;
|
||||
import org.briarproject.android.threaded.ThreadListController;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
public class GroupActivity extends
|
||||
ThreadListActivity<PrivateGroup, GroupMessageItem, GroupMessageHeader, GroupMessageAdapter> {
|
||||
|
||||
@Inject
|
||||
protected GroupController controller;
|
||||
|
||||
@Override
|
||||
public void injectActivity(ActivityComponent component) {
|
||||
component.inject(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> getController() {
|
||||
return controller;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(state);
|
||||
list.setEmptyText(R.string.groups_no_messages);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected @LayoutRes int getLayout() {
|
||||
return R.layout.activity_forum;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GroupMessageAdapter createAdapter(
|
||||
LinearLayoutManager layoutManager) {
|
||||
return new GroupMessageAdapter(this, layoutManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu menu) {
|
||||
// Inflate the menu items for use in the action bar
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.group_actions, menu);
|
||||
|
||||
return super.onCreateOptionsMenu(menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(final MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.action_group_compose_message:
|
||||
showTextInput(null);
|
||||
return true;
|
||||
default:
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemPostedString() {
|
||||
return R.string.groups_message_sent;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected int getItemReceivedString() {
|
||||
return R.string.groups_message_received;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import org.briarproject.android.threaded.ThreadListController;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
|
||||
public interface GroupController
|
||||
extends
|
||||
ThreadListController<PrivateGroup, GroupMessageItem, GroupMessageHeader> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.briarproject.android.controller.handler.ResultExceptionHandler;
|
||||
import org.briarproject.android.threaded.ThreadListControllerImpl;
|
||||
import org.briarproject.api.FormatException;
|
||||
import org.briarproject.api.db.DbException;
|
||||
import org.briarproject.api.event.Event;
|
||||
import org.briarproject.api.event.GroupMessageAddedEvent;
|
||||
import org.briarproject.api.identity.LocalAuthor;
|
||||
import org.briarproject.api.privategroup.GroupMessage;
|
||||
import org.briarproject.api.privategroup.GroupMessageFactory;
|
||||
import org.briarproject.api.privategroup.GroupMessageHeader;
|
||||
import org.briarproject.api.privategroup.PrivateGroup;
|
||||
import org.briarproject.api.privategroup.PrivateGroupManager;
|
||||
import org.briarproject.api.sync.MessageId;
|
||||
|
||||
import java.security.GeneralSecurityException;
|
||||
import java.util.Collection;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static org.briarproject.api.identity.Author.Status.OURSELVES;
|
||||
|
||||
public class GroupControllerImpl
|
||||
extends ThreadListControllerImpl<PrivateGroup, GroupMessageItem, GroupMessageHeader>
|
||||
implements GroupController {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(GroupControllerImpl.class.getName());
|
||||
|
||||
@Inject
|
||||
volatile GroupMessageFactory groupMessageFactory;
|
||||
@Inject
|
||||
volatile PrivateGroupManager privateGroupManager;
|
||||
|
||||
@Inject
|
||||
GroupControllerImpl() {
|
||||
super();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResume() {
|
||||
super.onActivityResume();
|
||||
notificationManager.clearForumPostNotification(groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void eventOccurred(Event e) {
|
||||
super.eventOccurred(e);
|
||||
|
||||
if (e instanceof GroupMessageAddedEvent) {
|
||||
final GroupMessageAddedEvent pe = (GroupMessageAddedEvent) e;
|
||||
if (!pe.isLocal() && pe.getGroupId().equals(groupId)) {
|
||||
LOG.info("Group message received, adding...");
|
||||
final GroupMessageHeader fph = pe.getHeader();
|
||||
updateNewestTimestamp(fph.getTimestamp());
|
||||
listener.runOnUiThreadUnlessDestroyed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
listener.onHeaderReceived(fph);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected PrivateGroup loadGroupItem() throws DbException {
|
||||
return privateGroupManager.getPrivateGroup(groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Collection<GroupMessageHeader> loadHeaders() throws DbException {
|
||||
return privateGroupManager.getHeaders(groupId);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadBodies(Collection<GroupMessageHeader> headers)
|
||||
throws DbException {
|
||||
for (GroupMessageHeader header : headers) {
|
||||
if (!bodyCache.containsKey(header.getId())) {
|
||||
String body =
|
||||
privateGroupManager.getMessageBody(header.getId());
|
||||
bodyCache.put(header.getId(), body);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void markRead(MessageId id) throws DbException {
|
||||
privateGroupManager.setReadFlag(groupId, id, true);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void send(final String body, @Nullable final MessageId parentId,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
cryptoExecutor.execute(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
LOG.info("Create message...");
|
||||
long timestamp = System.currentTimeMillis();
|
||||
timestamp = Math.max(timestamp, newestTimeStamp.get());
|
||||
GroupMessage gm;
|
||||
try {
|
||||
LocalAuthor a = identityManager.getLocalAuthor();
|
||||
gm = groupMessageFactory.createGroupMessage(groupId,
|
||||
timestamp, parentId, a, body);
|
||||
} catch (GeneralSecurityException | FormatException e) {
|
||||
throw new RuntimeException(e);
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
return;
|
||||
}
|
||||
bodyCache.put(gm.getMessage().getId(), body);
|
||||
storeMessage(gm, handler);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void storeMessage(final GroupMessage gm,
|
||||
final ResultExceptionHandler<GroupMessageItem, DbException> handler) {
|
||||
runOnDbThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
LOG.info("Store message...");
|
||||
long now = System.currentTimeMillis();
|
||||
privateGroupManager.addLocalMessage(gm);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if (LOG.isLoggable(INFO))
|
||||
LOG.info("Storing message took " + duration + " ms");
|
||||
|
||||
GroupMessageHeader h = new GroupMessageHeader(groupId,
|
||||
gm.getMessage().getId(), gm.getParent(),
|
||||
gm.getMessage().getTimestamp(), gm.getAuthor(),
|
||||
OURSELVES, true);
|
||||
|
||||
handler.onResult(buildItem(h));
|
||||
} catch (DbException e) {
|
||||
if (LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
handler.onException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void deleteGroupItem(PrivateGroup group) throws DbException {
|
||||
privateGroupManager.removePrivateGroup(group.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected GroupMessageItem buildItem(GroupMessageHeader header) {
|
||||
return new GroupMessageItem(header, bodyCache.get(header.getId()));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import android.support.annotation.UiThread;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.threaded.ThreadItemAdapter;
|
||||
|
||||
@UiThread
|
||||
public class GroupMessageAdapter extends ThreadItemAdapter<GroupMessageItem> {
|
||||
|
||||
public GroupMessageAdapter(ThreadItemListener<GroupMessageItem> listener,
|
||||
LinearLayoutManager layoutManager) {
|
||||
super(listener, layoutManager);
|
||||
}
|
||||
|
||||
@Override
|
||||
public GroupMessageViewHolder onCreateViewHolder(ViewGroup parent,
|
||||
int viewType) {
|
||||
View v = LayoutInflater.from(parent.getContext())
|
||||
.inflate(R.layout.list_item_forum_post, parent, false);
|
||||
return new GroupMessageViewHolder(v);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.briarproject.android.privategroup.conversation;
|
||||
|
||||
import android.view.View;
|
||||
|
||||
import org.briarproject.android.threaded.ThreadItemViewHolder;
|
||||
|
||||
public class GroupMessageViewHolder
|
||||
extends ThreadItemViewHolder<GroupMessageItem> {
|
||||
|
||||
public GroupMessageViewHolder(View v) {
|
||||
super(v);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
package org.briarproject.android.privategroup.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package org.briarproject.android.privategroup.list;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.app.ActivityOptionsCompat;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
@@ -10,13 +12,18 @@ import android.widget.Button;
|
||||
import android.widget.TextView;
|
||||
|
||||
import org.briarproject.R;
|
||||
import org.briarproject.android.privategroup.conversation.GroupActivity;
|
||||
import org.briarproject.android.util.AndroidUtils;
|
||||
import org.briarproject.android.view.TextAvatarView;
|
||||
import org.briarproject.api.sync.GroupId;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import static android.support.v4.content.ContextCompat.getColor;
|
||||
import static android.support.v4.content.ContextCompat.startActivities;
|
||||
import static android.view.View.GONE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static org.briarproject.android.BriarActivity.GROUP_ID;
|
||||
import static org.briarproject.android.BriarActivity.GROUP_NAME;
|
||||
|
||||
class GroupViewHolder extends RecyclerView.ViewHolder {
|
||||
|
||||
@@ -44,7 +51,7 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
|
||||
remove = (Button) v.findViewById(R.id.removeButton);
|
||||
}
|
||||
|
||||
void bindView(Context ctx, @Nullable final GroupItem group,
|
||||
void bindView(final Context ctx, @Nullable final GroupItem group,
|
||||
@NotNull final OnGroupRemoveClickListener listener) {
|
||||
if (group == null) return;
|
||||
|
||||
@@ -115,15 +122,15 @@ class GroupViewHolder extends RecyclerView.ViewHolder {
|
||||
layout.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
/*
|
||||
Intent i = new Intent(ctx, GroupActivity.class);
|
||||
GroupId id = item.getId();
|
||||
GroupId id = group.getId();
|
||||
i.putExtra(GROUP_ID, id.getBytes());
|
||||
i.putExtra(GROUP_NAME, group.getName());
|
||||
ActivityOptionsCompat options = ActivityOptionsCompat
|
||||
.makeCustomAnimation(ctx, android.R.anim.fade_in,
|
||||
android.R.anim.fade_out);
|
||||
ActivityCompat.startActivity(ctx, i, options.toBundle());
|
||||
*/
|
||||
Intent[] intents = {i};
|
||||
startActivities(ctx, intents, options.toBundle());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -90,8 +90,8 @@ public abstract class ThreadListActivity<G extends BaseGroup, I extends ThreadIt
|
||||
getController().loadGroupItem(
|
||||
new UiResultExceptionHandler<G, DbException>(this) {
|
||||
@Override
|
||||
public void onResultUi(G forum) {
|
||||
setTitle(forum.getName());
|
||||
public void onResultUi(G groupItem) {
|
||||
setTitle(groupItem.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user