mirror of
https://code.briarproject.org/briar/briar.git
synced 2026-02-12 18:59:06 +01:00
Separated blog activities from group activities for more readable code.
This commit is contained in:
@@ -45,9 +45,25 @@
|
||||
android:label="@string/contact_list_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.CreateBlogActivity"
|
||||
android:name=".android.blogs.BlogActivity"
|
||||
android:label="@string/app_name" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.blogs.BlogListActivity"
|
||||
android:label="@string/blogs_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.blogs.CreateBlogActivity"
|
||||
android:label="@string/create_blog_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.blogs.ReadBlogPostActivity"
|
||||
android:label="@string/app_name" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.blogs.WriteBlogPostActivity"
|
||||
android:label="@string/compose_blog_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.CreateGroupActivity"
|
||||
android:label="@string/create_group_title" >
|
||||
@@ -58,16 +74,12 @@
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.GroupListActivity"
|
||||
android:label="@string/app_name" >
|
||||
android:label="@string/groups_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.ReadGroupMessageActivity"
|
||||
android:name=".android.groups.ReadGroupPostActivity"
|
||||
android:label="@string/app_name" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.WriteBlogPostActivity"
|
||||
android:label="@string/compose_blog_title" >
|
||||
</activity>
|
||||
<activity
|
||||
android:name=".android.groups.WriteGroupPostActivity"
|
||||
android:label="@string/compose_group_title" >
|
||||
|
||||
@@ -1,12 +1,13 @@
|
||||
package net.sf.briar.android.groups;
|
||||
package net.sf.briar.android;
|
||||
|
||||
import java.util.Comparator;
|
||||
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
|
||||
class GroupNameComparator implements Comparator<Group> {
|
||||
public class GroupNameComparator implements Comparator<Group> {
|
||||
|
||||
static final GroupNameComparator INSTANCE = new GroupNameComparator();
|
||||
public static final GroupNameComparator INSTANCE =
|
||||
new GroupNameComparator();
|
||||
|
||||
public int compare(Group a, Group b) {
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(a.getName(), b.getName());
|
||||
@@ -14,6 +14,7 @@ import java.util.logging.Logger;
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarService.BriarBinder;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.blogs.BlogListActivity;
|
||||
import net.sf.briar.android.contact.ContactListActivity;
|
||||
import net.sf.briar.android.groups.GroupListActivity;
|
||||
import net.sf.briar.android.messages.ConversationListActivity;
|
||||
@@ -183,12 +184,8 @@ public class HomeScreenActivity extends BriarActivity {
|
||||
groupsButton.setText(R.string.groups_button);
|
||||
groupsButton.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(HomeScreenActivity.this,
|
||||
GroupListActivity.class);
|
||||
i.putExtra("net.sf.briar.RESTRICTED", false);
|
||||
i.putExtra("net.sf.briar.TITLE",
|
||||
getResources().getString(R.string.groups_title));
|
||||
startActivity(i);
|
||||
startActivity(new Intent(HomeScreenActivity.this,
|
||||
GroupListActivity.class));
|
||||
}
|
||||
});
|
||||
buttons.add(groupsButton);
|
||||
@@ -201,12 +198,8 @@ public class HomeScreenActivity extends BriarActivity {
|
||||
blogsButton.setText(R.string.blogs_button);
|
||||
blogsButton.setOnClickListener(new OnClickListener() {
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(HomeScreenActivity.this,
|
||||
GroupListActivity.class);
|
||||
i.putExtra("net.sf.briar.RESTRICTED", true);
|
||||
i.putExtra("net.sf.briar.TITLE",
|
||||
getResources().getString(R.string.blogs_title));
|
||||
startActivity(i);
|
||||
startActivity(new Intent(HomeScreenActivity.this,
|
||||
BlogListActivity.class));
|
||||
}
|
||||
});
|
||||
buttons.add(blogsButton);
|
||||
|
||||
237
briar-android/src/net/sf/briar/android/blogs/BlogActivity.java
Normal file
237
briar-android/src/net/sf/briar/android/blogs/BlogActivity.java
Normal file
@@ -0,0 +1,237 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.android.blogs.ReadBlogPostActivity.RESULT_NEXT;
|
||||
import static net.sf.briar.android.blogs.ReadBlogPostActivity.RESULT_PREV;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.AscendingHeaderComparator;
|
||||
import net.sf.briar.android.BriarActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.widgets.HorizontalBorder;
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.android.DatabaseUiExecutor;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.db.NoSuchSubscriptionException;
|
||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.RatingChangedEvent;
|
||||
import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class BlogActivity extends BriarActivity implements DatabaseListener,
|
||||
OnClickListener, OnItemClickListener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(BlogActivity.class.getName());
|
||||
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
private String groupName = null;
|
||||
private BlogAdapter adapter = null;
|
||||
private ListView list = null;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject private volatile DatabaseComponent db;
|
||||
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
|
||||
private volatile GroupId groupId = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(null);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
groupName = i.getStringExtra("net.sf.briar.GROUP_NAME");
|
||||
if(groupName == null) throw new IllegalStateException();
|
||||
setTitle(groupName);
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_MATCH);
|
||||
layout.setOrientation(VERTICAL);
|
||||
layout.setGravity(CENTER_HORIZONTAL);
|
||||
|
||||
adapter = new BlogAdapter(this);
|
||||
list = new ListView(this);
|
||||
// Give me all the width and all the unused height
|
||||
list.setLayoutParams(MATCH_WRAP_1);
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(this);
|
||||
layout.addView(list);
|
||||
|
||||
layout.addView(new HorizontalBorder(this));
|
||||
|
||||
ImageButton composeButton = new ImageButton(this);
|
||||
composeButton.setBackgroundResource(0);
|
||||
composeButton.setImageResource(R.drawable.content_new_email);
|
||||
composeButton.setOnClickListener(this);
|
||||
layout.addView(composeButton);
|
||||
|
||||
setContentView(layout);
|
||||
|
||||
// Bind to the service so we can wait for it to start
|
||||
bindService(new Intent(BriarService.class.getName()),
|
||||
serviceConnection, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
db.addListener(this);
|
||||
loadHeaders();
|
||||
}
|
||||
|
||||
private void loadHeaders() {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(groupId);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Load took " + duration + " ms");
|
||||
displayHeaders(headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Subscription removed");
|
||||
finishOnUiThread();
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayHeaders(final Collection<GroupMessageHeader> headers) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
adapter.clear();
|
||||
for(GroupMessageHeader h : headers) adapter.add(h);
|
||||
adapter.sort(AscendingHeaderComparator.INSTANCE);
|
||||
adapter.notifyDataSetChanged();
|
||||
selectFirstUnread();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void selectFirstUnread() {
|
||||
int firstUnread = -1, count = adapter.getCount();
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(!adapter.getItem(i).isRead()) {
|
||||
firstUnread = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(firstUnread == -1) list.setSelection(count - 1);
|
||||
else list.setSelection(firstUnread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int request, int result, Intent data) {
|
||||
if(result == RESULT_PREV) {
|
||||
int position = request - 1;
|
||||
if(position >= 0 && position < adapter.getCount())
|
||||
displayMessage(position);
|
||||
} else if(result == RESULT_NEXT) {
|
||||
int position = request + 1;
|
||||
if(position >= 0 && position < adapter.getCount())
|
||||
displayMessage(position);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
db.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
|
||||
public void eventOccurred(DatabaseEvent e) {
|
||||
if(e instanceof GroupMessageAddedEvent) {
|
||||
GroupMessageAddedEvent g = (GroupMessageAddedEvent) e;
|
||||
if(g.getGroup().getId().equals(groupId)) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
|
||||
loadHeaders();
|
||||
}
|
||||
} else if(e instanceof MessageExpiredEvent) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message expired, reloading");
|
||||
loadHeaders();
|
||||
} else if(e instanceof RatingChangedEvent) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Rating changed, reloading");
|
||||
loadHeaders();
|
||||
} else if(e instanceof SubscriptionRemovedEvent) {
|
||||
SubscriptionRemovedEvent s = (SubscriptionRemovedEvent) e;
|
||||
if(s.getGroup().getId().equals(groupId)) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Subscription removed");
|
||||
finishOnUiThread();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
Intent i = new Intent(this, WriteBlogPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
displayMessage(position);
|
||||
}
|
||||
|
||||
private void displayMessage(int position) {
|
||||
GroupMessageHeader item = adapter.getItem(position);
|
||||
Intent i = new Intent(this, ReadBlogPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.GROUP_NAME", groupName);
|
||||
i.putExtra("net.sf.briar.MESSAGE_ID", item.getId().getBytes());
|
||||
Author author = item.getAuthor();
|
||||
if(author != null) {
|
||||
i.putExtra("net.sf.briar.AUTHOR_ID", author.getId().getBytes());
|
||||
i.putExtra("net.sf.briar.AUTHOR_NAME", author.getName());
|
||||
i.putExtra("net.sf.briar.RATING", item.getRating().toString());
|
||||
}
|
||||
i.putExtra("net.sf.briar.CONTENT_TYPE", item.getContentType());
|
||||
i.putExtra("net.sf.briar.TIMESTAMP", item.getTimestamp());
|
||||
startActivityForResult(i, position);
|
||||
}
|
||||
}
|
||||
114
briar-android/src/net/sf/briar/android/blogs/BlogAdapter.java
Normal file
114
briar-android/src/net/sf/briar/android/blogs/BlogAdapter.java
Normal file
@@ -0,0 +1,114 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.graphics.Typeface.BOLD;
|
||||
import static android.view.Gravity.CENTER_VERTICAL;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.text.DateFormat.SHORT;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1;
|
||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.widgets.HorizontalSpace;
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.messaging.Rating;
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
class BlogAdapter extends ArrayAdapter<GroupMessageHeader> {
|
||||
|
||||
BlogAdapter(Context ctx) {
|
||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
||||
new ArrayList<GroupMessageHeader>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
GroupMessageHeader item = getItem(position);
|
||||
Context ctx = getContext();
|
||||
|
||||
// FIXME: Use a RelativeLayout
|
||||
LinearLayout layout = new LinearLayout(ctx);
|
||||
layout.setOrientation(HORIZONTAL);
|
||||
if(!item.isRead()) {
|
||||
Resources res = ctx.getResources();
|
||||
layout.setBackgroundColor(res.getColor(R.color.unread_background));
|
||||
}
|
||||
|
||||
LinearLayout innerLayout = new LinearLayout(ctx);
|
||||
// Give me all the unused width
|
||||
innerLayout.setLayoutParams(WRAP_WRAP_1);
|
||||
innerLayout.setOrientation(VERTICAL);
|
||||
|
||||
LinearLayout authorLayout = new LinearLayout(ctx);
|
||||
authorLayout.setOrientation(HORIZONTAL);
|
||||
authorLayout.setGravity(CENTER_VERTICAL);
|
||||
|
||||
ImageView thumb = new ImageView(ctx);
|
||||
thumb.setPadding(10, 10, 10, 10);
|
||||
Rating rating = item.getRating();
|
||||
if(rating == GOOD) thumb.setImageResource(R.drawable.rating_good);
|
||||
else thumb.setImageResource(R.drawable.rating_bad);
|
||||
if(rating == UNRATED) thumb.setVisibility(INVISIBLE);
|
||||
authorLayout.addView(thumb);
|
||||
|
||||
TextView name = new TextView(ctx);
|
||||
// Give me all the unused width
|
||||
name.setLayoutParams(WRAP_WRAP_1);
|
||||
name.setTextSize(18);
|
||||
name.setMaxLines(1);
|
||||
name.setPadding(0, 10, 10, 10);
|
||||
Author author = item.getAuthor();
|
||||
Resources res = ctx.getResources();
|
||||
if(author == null) {
|
||||
name.setTextColor(res.getColor(R.color.anonymous_author));
|
||||
name.setText(R.string.anonymous);
|
||||
} else {
|
||||
name.setText(author.getName());
|
||||
}
|
||||
authorLayout.addView(name);
|
||||
innerLayout.addView(authorLayout);
|
||||
|
||||
if(item.getContentType().equals("text/plain")) {
|
||||
TextView subject = new TextView(ctx);
|
||||
subject.setTextSize(14);
|
||||
subject.setMaxLines(2);
|
||||
subject.setPadding(10, 0, 10, 10);
|
||||
if(!item.isRead()) subject.setTypeface(null, BOLD);
|
||||
String s = item.getSubject();
|
||||
subject.setText(s == null ? "" : s);
|
||||
innerLayout.addView(subject);
|
||||
} else {
|
||||
LinearLayout attachmentLayout = new LinearLayout(ctx);
|
||||
attachmentLayout.setOrientation(HORIZONTAL);
|
||||
ImageView attachment = new ImageView(ctx);
|
||||
attachment.setPadding(10, 0, 10, 10);
|
||||
attachment.setImageResource(R.drawable.content_attachment);
|
||||
attachmentLayout.addView(attachment);
|
||||
attachmentLayout.addView(new HorizontalSpace(ctx));
|
||||
innerLayout.addView(attachmentLayout);
|
||||
}
|
||||
layout.addView(innerLayout);
|
||||
|
||||
TextView date = new TextView(ctx);
|
||||
date.setTextSize(14);
|
||||
date.setPadding(0, 10, 10, 10);
|
||||
long then = item.getTimestamp(), now = System.currentTimeMillis();
|
||||
date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
|
||||
layout.addView(date);
|
||||
|
||||
return layout;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,314 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.view.Gravity.CENTER;
|
||||
import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarFragmentActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.widgets.HorizontalBorder;
|
||||
import net.sf.briar.android.widgets.HorizontalSpace;
|
||||
import net.sf.briar.api.android.DatabaseUiExecutor;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.db.NoSuchSubscriptionException;
|
||||
import net.sf.briar.api.db.event.DatabaseEvent;
|
||||
import net.sf.briar.api.db.event.DatabaseListener;
|
||||
import net.sf.briar.api.db.event.GroupMessageAddedEvent;
|
||||
import net.sf.briar.api.db.event.MessageExpiredEvent;
|
||||
import net.sf.briar.api.db.event.SubscriptionRemovedEvent;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ListView;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class BlogListActivity extends BriarFragmentActivity
|
||||
implements OnClickListener, DatabaseListener, NoBlogsDialog.Listener {
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(BlogListActivity.class.getName());
|
||||
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
private BlogListAdapter adapter = null;
|
||||
private ListView list = null;
|
||||
private ImageButton newBlogButton = null, composeButton = null;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject private volatile DatabaseComponent db;
|
||||
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(null);
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_MATCH);
|
||||
layout.setOrientation(VERTICAL);
|
||||
layout.setGravity(CENTER_HORIZONTAL);
|
||||
|
||||
adapter = new BlogListAdapter(this);
|
||||
list = new ListView(this);
|
||||
// Give me all the width and all the unused height
|
||||
list.setLayoutParams(MATCH_WRAP_1);
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(adapter);
|
||||
layout.addView(list);
|
||||
|
||||
layout.addView(new HorizontalBorder(this));
|
||||
|
||||
LinearLayout footer = new LinearLayout(this);
|
||||
footer.setLayoutParams(MATCH_WRAP);
|
||||
footer.setOrientation(HORIZONTAL);
|
||||
footer.setGravity(CENTER);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
newBlogButton = new ImageButton(this);
|
||||
newBlogButton.setBackgroundResource(0);
|
||||
newBlogButton.setImageResource(R.drawable.social_new_blog);
|
||||
newBlogButton.setOnClickListener(this);
|
||||
footer.addView(newBlogButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
composeButton = new ImageButton(this);
|
||||
composeButton.setBackgroundResource(0);
|
||||
composeButton.setImageResource(R.drawable.content_new_email);
|
||||
composeButton.setOnClickListener(this);
|
||||
footer.addView(composeButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
layout.addView(footer);
|
||||
|
||||
setContentView(layout);
|
||||
|
||||
// Bind to the service so we can wait for it to start
|
||||
bindService(new Intent(BriarService.class.getName()),
|
||||
serviceConnection, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onResume() {
|
||||
super.onResume();
|
||||
db.addListener(this);
|
||||
loadHeaders();
|
||||
}
|
||||
|
||||
private void loadHeaders() {
|
||||
clearHeaders();
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
Set<GroupId> local = new HashSet<GroupId>();
|
||||
for(Group g : db.getLocalGroups()) local.add(g.getId());
|
||||
for(Group g : db.getSubscriptions()) {
|
||||
if(!g.isRestricted()) continue;
|
||||
boolean postable = local.contains(g.getId());
|
||||
try {
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
displayHeaders(g, postable, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Subscription removed");
|
||||
}
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Full load took " + duration + " ms");
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void clearHeaders() {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
adapter.clear();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void displayHeaders(final Group g, final boolean postable,
|
||||
final Collection<GroupMessageHeader> headers) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
// Remove the old item, if any
|
||||
BlogListItem item = findGroup(g.getId());
|
||||
if(item != null) adapter.remove(item);
|
||||
// Add a new item
|
||||
adapter.add(new BlogListItem(g, postable, headers));
|
||||
adapter.sort(GroupComparator.INSTANCE);
|
||||
adapter.notifyDataSetChanged();
|
||||
selectFirstUnread();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private BlogListItem findGroup(GroupId g) {
|
||||
int count = adapter.getCount();
|
||||
for(int i = 0; i < count; i++) {
|
||||
BlogListItem item = adapter.getItem(i);
|
||||
if(item.getGroupId().equals(g)) return item;
|
||||
}
|
||||
return null; // Not found
|
||||
}
|
||||
|
||||
private void selectFirstUnread() {
|
||||
int firstUnread = -1, count = adapter.getCount();
|
||||
for(int i = 0; i < count; i++) {
|
||||
if(adapter.getItem(i).getUnreadCount() > 0) {
|
||||
firstUnread = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(firstUnread == -1) list.setSelection(count - 1);
|
||||
else list.setSelection(firstUnread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
db.removeListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if(view == newBlogButton) {
|
||||
startActivity(new Intent(this, CreateBlogActivity.class));
|
||||
} else if(view == composeButton) {
|
||||
if(countPostableGroups() == 0) {
|
||||
NoBlogsDialog dialog = new NoBlogsDialog();
|
||||
dialog.setListener(this);
|
||||
dialog.show(getSupportFragmentManager(), "NoGroupsDialog");
|
||||
} else {
|
||||
startActivity(new Intent(this, WriteBlogPostActivity.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int countPostableGroups() {
|
||||
int postable = 0, count = adapter.getCount();
|
||||
for(int i = 0; i < count; i++)
|
||||
if(adapter.getItem(i).isPostable()) postable++;
|
||||
return postable;
|
||||
}
|
||||
|
||||
public void eventOccurred(DatabaseEvent e) {
|
||||
if(e instanceof GroupMessageAddedEvent) {
|
||||
Group g = ((GroupMessageAddedEvent) e).getGroup();
|
||||
if(g.isRestricted()) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
|
||||
loadHeaders(g);
|
||||
}
|
||||
} else if(e instanceof MessageExpiredEvent) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message expired, reloading");
|
||||
loadHeaders();
|
||||
} else if(e instanceof SubscriptionRemovedEvent) {
|
||||
Group g = ((SubscriptionRemovedEvent) e).getGroup();
|
||||
if(g.isRestricted()) {
|
||||
// Reload the group, expecting NoSuchSubscriptionException
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
||||
loadHeaders(g);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void loadHeaders(final Group g) {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
boolean postable = db.getLocalGroups().contains(g);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Partial load took " + duration + " ms");
|
||||
displayHeaders(g, postable, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Subscription removed");
|
||||
removeGroup(g.getId());
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void removeGroup(final GroupId g) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
BlogListItem item = findGroup(g);
|
||||
if(item != null) {
|
||||
adapter.remove(item);
|
||||
selectFirstUnread();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void createGroupButtonClicked() {
|
||||
startActivity(new Intent(this, CreateBlogActivity.class));
|
||||
}
|
||||
|
||||
public void cancelButtonClicked() {
|
||||
// That's nice dear
|
||||
}
|
||||
|
||||
private static class GroupComparator implements Comparator<BlogListItem> {
|
||||
|
||||
private static final GroupComparator INSTANCE = new GroupComparator();
|
||||
|
||||
public int compare(BlogListItem a, BlogListItem b) {
|
||||
// The item with the newest message comes first
|
||||
long aTime = a.getTimestamp(), bTime = b.getTimestamp();
|
||||
if(aTime > bTime) return -1;
|
||||
if(aTime < bTime) return 1;
|
||||
// Break ties by group name
|
||||
String aName = a.getGroupName(), bName = b.getGroupName();
|
||||
return String.CASE_INSENSITIVE_ORDER.compare(aName, bName);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,108 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.graphics.Typeface.BOLD;
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.text.DateFormat.SHORT;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.widgets.HorizontalSpace;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.AdapterView.OnItemClickListener;
|
||||
import android.widget.ArrayAdapter;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
|
||||
class BlogListAdapter extends ArrayAdapter<BlogListItem>
|
||||
implements OnItemClickListener {
|
||||
|
||||
BlogListAdapter(Context ctx) {
|
||||
super(ctx, android.R.layout.simple_expandable_list_item_1,
|
||||
new ArrayList<BlogListItem>());
|
||||
}
|
||||
|
||||
@Override
|
||||
public View getView(int position, View convertView, ViewGroup parent) {
|
||||
BlogListItem item = getItem(position);
|
||||
Context ctx = getContext();
|
||||
Resources res = ctx.getResources();
|
||||
|
||||
LinearLayout layout = new LinearLayout(ctx);
|
||||
layout.setOrientation(HORIZONTAL);
|
||||
if(item.getUnreadCount() > 0)
|
||||
layout.setBackgroundColor(res.getColor(R.color.unread_background));
|
||||
|
||||
LinearLayout innerLayout = new LinearLayout(ctx);
|
||||
// Give me all the unused width
|
||||
innerLayout.setLayoutParams(WRAP_WRAP_1);
|
||||
innerLayout.setOrientation(VERTICAL);
|
||||
|
||||
TextView name = new TextView(ctx);
|
||||
name.setTextSize(18);
|
||||
name.setMaxLines(1);
|
||||
name.setPadding(10, 10, 10, 10);
|
||||
int unread = item.getUnreadCount();
|
||||
if(unread > 0) name.setText(item.getGroupName() + " (" + unread + ")");
|
||||
else name.setText(item.getGroupName());
|
||||
innerLayout.addView(name);
|
||||
|
||||
if(item.isEmpty()) {
|
||||
TextView noPosts = new TextView(ctx);
|
||||
noPosts.setTextSize(14);
|
||||
noPosts.setPadding(10, 0, 10, 10);
|
||||
noPosts.setTextColor(res.getColor(R.color.no_posts));
|
||||
noPosts.setText(R.string.no_posts);
|
||||
innerLayout.addView(noPosts);
|
||||
layout.addView(innerLayout);
|
||||
} else {
|
||||
if(item.getContentType().equals("text/plain")) {
|
||||
TextView subject = new TextView(ctx);
|
||||
subject.setTextSize(14);
|
||||
subject.setMaxLines(2);
|
||||
subject.setPadding(10, 0, 10, 10);
|
||||
if(item.getUnreadCount() > 0) subject.setTypeface(null, BOLD);
|
||||
String s = item.getSubject();
|
||||
subject.setText(s == null ? "" : s);
|
||||
innerLayout.addView(subject);
|
||||
} else {
|
||||
LinearLayout attachmentLayout = new LinearLayout(ctx);
|
||||
attachmentLayout.setOrientation(HORIZONTAL);
|
||||
ImageView attachment = new ImageView(ctx);
|
||||
attachment.setPadding(10, 0, 10, 10);
|
||||
attachment.setImageResource(R.drawable.content_attachment);
|
||||
attachmentLayout.addView(attachment);
|
||||
attachmentLayout.addView(new HorizontalSpace(ctx));
|
||||
innerLayout.addView(attachmentLayout);
|
||||
}
|
||||
layout.addView(innerLayout);
|
||||
|
||||
TextView date = new TextView(ctx);
|
||||
date.setTextSize(14);
|
||||
date.setPadding(0, 10, 10, 10);
|
||||
long then = item.getTimestamp(), now = System.currentTimeMillis();
|
||||
date.setText(DateUtils.formatSameDayTime(then, now, SHORT, SHORT));
|
||||
layout.addView(date);
|
||||
}
|
||||
|
||||
return layout;
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
long id) {
|
||||
BlogListItem item = getItem(position);
|
||||
Intent i = new Intent(getContext(), BlogActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", item.getGroupId().getBytes());
|
||||
i.putExtra("net.sf.briar.GROUP_NAME", item.getGroupName());
|
||||
getContext().startActivity(i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import net.sf.briar.android.DescendingHeaderComparator;
|
||||
import net.sf.briar.api.Author;
|
||||
import net.sf.briar.api.db.GroupMessageHeader;
|
||||
import net.sf.briar.api.messaging.Group;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
|
||||
class BlogListItem {
|
||||
|
||||
private final Group group;
|
||||
private final boolean postable, empty;
|
||||
private final String authorName, contentType, subject;
|
||||
private final long timestamp;
|
||||
private final int unread;
|
||||
|
||||
BlogListItem(Group group, boolean postable,
|
||||
Collection<GroupMessageHeader> headers) {
|
||||
this.group = group;
|
||||
this.postable = postable;
|
||||
empty = headers.isEmpty();
|
||||
if(empty) {
|
||||
authorName = null;
|
||||
contentType = null;
|
||||
subject = null;
|
||||
timestamp = 0;
|
||||
unread = 0;
|
||||
} else {
|
||||
List<GroupMessageHeader> list =
|
||||
new ArrayList<GroupMessageHeader>(headers);
|
||||
Collections.sort(list, DescendingHeaderComparator.INSTANCE);
|
||||
GroupMessageHeader newest = list.get(0);
|
||||
Author a = newest.getAuthor();
|
||||
if(a == null) authorName = null;
|
||||
else authorName = a.getName();
|
||||
contentType = newest.getContentType();
|
||||
subject = newest.getSubject();
|
||||
timestamp = newest.getTimestamp();
|
||||
int unread = 0;
|
||||
for(GroupMessageHeader h : list) if(!h.isRead()) unread++;
|
||||
this.unread = unread;
|
||||
}
|
||||
}
|
||||
|
||||
GroupId getGroupId() {
|
||||
return group.getId();
|
||||
}
|
||||
|
||||
String getGroupName() {
|
||||
return group.getName();
|
||||
}
|
||||
|
||||
boolean isPostable() {
|
||||
return postable;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
String getAuthorName() {
|
||||
return authorName;
|
||||
}
|
||||
|
||||
String getContentType() {
|
||||
return contentType;
|
||||
}
|
||||
|
||||
String getSubject() {
|
||||
return subject;
|
||||
}
|
||||
|
||||
long getTimestamp() {
|
||||
return timestamp;
|
||||
}
|
||||
|
||||
int getUnreadCount() {
|
||||
return unread;
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.sf.briar.android.groups;
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.text.InputType.TYPE_CLASS_TEXT;
|
||||
import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.sf.briar.android.groups;
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
@@ -0,0 +1,43 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.DialogFragment;
|
||||
|
||||
public class NoBlogsDialog extends DialogFragment {
|
||||
|
||||
private Listener listener = null;
|
||||
|
||||
void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle state) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setMessage(R.string.no_blogs);
|
||||
builder.setPositiveButton(R.string.create_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
listener.createGroupButtonClicked();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
listener.cancelButtonClicked();
|
||||
}
|
||||
});
|
||||
return builder.create();
|
||||
}
|
||||
|
||||
interface Listener {
|
||||
|
||||
void createGroupButtonClicked();
|
||||
|
||||
void cancelButtonClicked();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,375 @@
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.view.Gravity.CENTER;
|
||||
import static android.view.Gravity.CENTER_VERTICAL;
|
||||
import static android.view.View.INVISIBLE;
|
||||
import static android.view.View.VISIBLE;
|
||||
import static android.widget.LinearLayout.HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.text.DateFormat.SHORT;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.WRAP_WRAP_1;
|
||||
import static net.sf.briar.api.messaging.Rating.BAD;
|
||||
import static net.sf.briar.api.messaging.Rating.GOOD;
|
||||
import static net.sf.briar.api.messaging.Rating.UNRATED;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.widgets.HorizontalBorder;
|
||||
import net.sf.briar.android.widgets.HorizontalSpace;
|
||||
import net.sf.briar.api.AuthorId;
|
||||
import net.sf.briar.api.android.BundleEncrypter;
|
||||
import net.sf.briar.api.android.DatabaseUiExecutor;
|
||||
import net.sf.briar.api.db.DatabaseComponent;
|
||||
import net.sf.briar.api.db.DbException;
|
||||
import net.sf.briar.api.db.NoSuchMessageException;
|
||||
import net.sf.briar.api.messaging.GroupId;
|
||||
import net.sf.briar.api.messaging.MessageId;
|
||||
import net.sf.briar.api.messaging.Rating;
|
||||
import android.content.Intent;
|
||||
import android.content.res.Resources;
|
||||
import android.os.Bundle;
|
||||
import android.text.format.DateUtils;
|
||||
import android.view.View;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ImageButton;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.ScrollView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class ReadBlogPostActivity extends BriarActivity
|
||||
implements OnClickListener {
|
||||
|
||||
static final int RESULT_REPLY = RESULT_FIRST_USER;
|
||||
static final int RESULT_PREV = RESULT_FIRST_USER + 1;
|
||||
static final int RESULT_NEXT = RESULT_FIRST_USER + 2;
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ReadBlogPostActivity.class.getName());
|
||||
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
@Inject private BundleEncrypter bundleEncrypter;
|
||||
private GroupId groupId = null;
|
||||
private Rating rating = UNRATED;
|
||||
private boolean read;
|
||||
private ImageView thumb = null;
|
||||
private ImageButton goodButton = null, badButton = null, readButton = null;
|
||||
private ImageButton prevButton = null, nextButton = null;
|
||||
private ImageButton replyButton = null;
|
||||
private TextView content = null;
|
||||
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject private volatile DatabaseComponent db;
|
||||
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
|
||||
private volatile MessageId messageId = null;
|
||||
private volatile AuthorId authorId = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
super.onCreate(null);
|
||||
|
||||
Intent i = getIntent();
|
||||
byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
String groupName = i.getStringExtra("net.sf.briar.GROUP_NAME");
|
||||
if(groupName == null) throw new IllegalStateException();
|
||||
setTitle(groupName);
|
||||
b = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
messageId = new MessageId(b);
|
||||
String authorName = null;
|
||||
b = i.getByteArrayExtra("net.sf.briar.AUTHOR_ID");
|
||||
if(b != null) {
|
||||
authorId = new AuthorId(b);
|
||||
authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME");
|
||||
if(authorName == null) throw new IllegalStateException();
|
||||
String r = i.getStringExtra("net.sf.briar.RATING");
|
||||
if(r != null) rating = Rating.valueOf(r);
|
||||
}
|
||||
String contentType = i.getStringExtra("net.sf.briar.CONTENT_TYPE");
|
||||
if(contentType == null) throw new IllegalStateException();
|
||||
long timestamp = i.getLongExtra("net.sf.briar.TIMESTAMP", -1);
|
||||
if(timestamp == -1) throw new IllegalStateException();
|
||||
|
||||
if(state != null && bundleEncrypter.decrypt(state)) {
|
||||
read = state.getBoolean("net.sf.briar.READ");
|
||||
} else {
|
||||
read = false;
|
||||
setReadInDatabase(true);
|
||||
}
|
||||
|
||||
LinearLayout layout = new LinearLayout(this);
|
||||
layout.setLayoutParams(MATCH_WRAP);
|
||||
layout.setOrientation(VERTICAL);
|
||||
|
||||
ScrollView scrollView = new ScrollView(this);
|
||||
// Give me all the width and all the unused height
|
||||
scrollView.setLayoutParams(MATCH_WRAP_1);
|
||||
|
||||
LinearLayout message = new LinearLayout(this);
|
||||
message.setOrientation(VERTICAL);
|
||||
Resources res = getResources();
|
||||
message.setBackgroundColor(res.getColor(R.color.content_background));
|
||||
|
||||
LinearLayout header = new LinearLayout(this);
|
||||
header.setLayoutParams(MATCH_WRAP);
|
||||
header.setOrientation(HORIZONTAL);
|
||||
header.setGravity(CENTER_VERTICAL);
|
||||
|
||||
thumb = new ImageView(this);
|
||||
thumb.setPadding(0, 10, 10, 10);
|
||||
if(rating == GOOD) thumb.setImageResource(R.drawable.rating_good);
|
||||
else thumb.setImageResource(R.drawable.rating_bad);
|
||||
if(rating == UNRATED) thumb.setVisibility(INVISIBLE);
|
||||
header.addView(thumb);
|
||||
|
||||
TextView author = new TextView(this);
|
||||
// Give me all the unused width
|
||||
author.setLayoutParams(WRAP_WRAP_1);
|
||||
author.setTextSize(18);
|
||||
author.setMaxLines(1);
|
||||
author.setPadding(10, 10, 10, 10);
|
||||
if(authorName == null) {
|
||||
author.setTextColor(res.getColor(R.color.anonymous_author));
|
||||
author.setText(R.string.anonymous);
|
||||
} else {
|
||||
author.setText(authorName);
|
||||
}
|
||||
header.addView(author);
|
||||
|
||||
TextView date = new TextView(this);
|
||||
date.setTextSize(14);
|
||||
date.setPadding(0, 10, 10, 10);
|
||||
long now = System.currentTimeMillis();
|
||||
date.setText(DateUtils.formatSameDayTime(timestamp, now, SHORT, SHORT));
|
||||
header.addView(date);
|
||||
message.addView(header);
|
||||
|
||||
if(contentType.equals("text/plain")) {
|
||||
// Load and display the message body
|
||||
content = new TextView(this);
|
||||
content.setPadding(10, 0, 10, 10);
|
||||
message.addView(content);
|
||||
loadMessageBody();
|
||||
}
|
||||
scrollView.addView(message);
|
||||
layout.addView(scrollView);
|
||||
|
||||
layout.addView(new HorizontalBorder(this));
|
||||
|
||||
LinearLayout footer = new LinearLayout(this);
|
||||
footer.setLayoutParams(MATCH_WRAP);
|
||||
footer.setOrientation(HORIZONTAL);
|
||||
footer.setGravity(CENTER);
|
||||
|
||||
goodButton = new ImageButton(this);
|
||||
goodButton.setBackgroundResource(0);
|
||||
goodButton.setImageResource(R.drawable.rating_good);
|
||||
if(authorName == null) goodButton.setEnabled(false);
|
||||
else goodButton.setOnClickListener(this);
|
||||
footer.addView(goodButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
badButton = new ImageButton(this);
|
||||
badButton.setBackgroundResource(0);
|
||||
badButton.setImageResource(R.drawable.rating_bad);
|
||||
badButton.setOnClickListener(this);
|
||||
if(authorName == null) badButton.setEnabled(false);
|
||||
else badButton.setOnClickListener(this);
|
||||
footer.addView(badButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
readButton = new ImageButton(this);
|
||||
readButton.setBackgroundResource(0);
|
||||
if(read) readButton.setImageResource(R.drawable.content_unread);
|
||||
else readButton.setImageResource(R.drawable.content_read);
|
||||
readButton.setOnClickListener(this);
|
||||
footer.addView(readButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
prevButton = new ImageButton(this);
|
||||
prevButton.setBackgroundResource(0);
|
||||
prevButton.setImageResource(R.drawable.navigation_previous_item);
|
||||
prevButton.setOnClickListener(this);
|
||||
footer.addView(prevButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
nextButton = new ImageButton(this);
|
||||
nextButton.setBackgroundResource(0);
|
||||
nextButton.setImageResource(R.drawable.navigation_next_item);
|
||||
nextButton.setOnClickListener(this);
|
||||
footer.addView(nextButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
|
||||
replyButton = new ImageButton(this);
|
||||
replyButton.setBackgroundResource(0);
|
||||
replyButton.setImageResource(R.drawable.social_reply_all);
|
||||
replyButton.setOnClickListener(this);
|
||||
footer.addView(replyButton);
|
||||
layout.addView(footer);
|
||||
|
||||
setContentView(layout);
|
||||
|
||||
// Bind to the service so we can wait for it to start
|
||||
bindService(new Intent(BriarService.class.getName()),
|
||||
serviceConnection, 0);
|
||||
}
|
||||
|
||||
private void setReadInDatabase(final boolean read) {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
db.setReadFlag(messageId, read);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Setting flag took " + duration + " ms");
|
||||
setReadInUi(read);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setReadInUi(final boolean read) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
ReadBlogPostActivity.this.read = read;
|
||||
if(read) readButton.setImageResource(R.drawable.content_unread);
|
||||
else readButton.setImageResource(R.drawable.content_read);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void loadMessageBody() {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
byte[] body = db.getMessageBody(messageId);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Loading message took " + duration + " ms");
|
||||
final String text = new String(body, "UTF-8");
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
content.setText(text);
|
||||
}
|
||||
});
|
||||
} catch(NoSuchMessageException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message removed");
|
||||
finishOnUiThread();
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
} catch(UnsupportedEncodingException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle state) {
|
||||
state.putBoolean("net.sf.briar.READ", read);
|
||||
bundleEncrypter.encrypt(state);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDestroy() {
|
||||
super.onDestroy();
|
||||
unbindService(serviceConnection);
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if(view == goodButton) {
|
||||
if(rating == BAD) setRatingInDatabase(UNRATED);
|
||||
else if(rating == UNRATED) setRatingInDatabase(GOOD);
|
||||
} else if(view == badButton) {
|
||||
if(rating == GOOD) setRatingInDatabase(UNRATED);
|
||||
else if(rating == UNRATED) setRatingInDatabase(BAD);
|
||||
} else if(view == readButton) {
|
||||
setReadInDatabase(!read);
|
||||
} else if(view == prevButton) {
|
||||
setResult(RESULT_PREV);
|
||||
finish();
|
||||
} else if(view == nextButton) {
|
||||
setResult(RESULT_NEXT);
|
||||
finish();
|
||||
} else if(view == replyButton) {
|
||||
Intent i = new Intent(this, WriteBlogPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes());
|
||||
startActivity(i);
|
||||
setResult(RESULT_REPLY);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
private void setRatingInDatabase(final Rating r) {
|
||||
dbUiExecutor.execute(new Runnable() {
|
||||
public void run() {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
db.setRating(authorId, r);
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Setting rating took " + duration + " ms");
|
||||
setRatingInUi(r);
|
||||
} catch(DbException e) {
|
||||
if(LOG.isLoggable(WARNING))
|
||||
LOG.log(WARNING, e.toString(), e);
|
||||
} catch(InterruptedException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Interrupted while waiting for service");
|
||||
Thread.currentThread().interrupt();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void setRatingInUi(final Rating r) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
rating = r;
|
||||
if(r == GOOD) {
|
||||
thumb.setImageResource(R.drawable.rating_good);
|
||||
thumb.setVisibility(VISIBLE);
|
||||
} else if(r == BAD) {
|
||||
thumb.setImageResource(R.drawable.rating_bad);
|
||||
thumb.setVisibility(VISIBLE);
|
||||
} else {
|
||||
thumb.setVisibility(INVISIBLE);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
package net.sf.briar.android.groups;
|
||||
package net.sf.briar.android.blogs;
|
||||
|
||||
import static android.text.InputType.TYPE_CLASS_TEXT;
|
||||
import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES;
|
||||
@@ -22,6 +22,7 @@ import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.GroupNameComparator;
|
||||
import net.sf.briar.android.identity.CreateIdentityActivity;
|
||||
import net.sf.briar.android.identity.LocalAuthorItem;
|
||||
import net.sf.briar.android.identity.LocalAuthorItemComparator;
|
||||
@@ -4,8 +4,8 @@ import static android.view.Gravity.CENTER_HORIZONTAL;
|
||||
import static android.widget.LinearLayout.VERTICAL;
|
||||
import static java.util.logging.Level.INFO;
|
||||
import static java.util.logging.Level.WARNING;
|
||||
import static net.sf.briar.android.groups.ReadGroupMessageActivity.RESULT_NEXT;
|
||||
import static net.sf.briar.android.groups.ReadGroupMessageActivity.RESULT_PREV;
|
||||
import static net.sf.briar.android.groups.ReadGroupPostActivity.RESULT_NEXT;
|
||||
import static net.sf.briar.android.groups.ReadGroupPostActivity.RESULT_PREV;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_MATCH;
|
||||
import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
|
||||
|
||||
@@ -53,7 +53,6 @@ OnClickListener, OnItemClickListener {
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
private boolean restricted = false;
|
||||
private String groupName = null;
|
||||
private GroupAdapter adapter = null;
|
||||
private ListView list = null;
|
||||
@@ -68,7 +67,6 @@ OnClickListener, OnItemClickListener {
|
||||
super.onCreate(null);
|
||||
|
||||
Intent i = getIntent();
|
||||
restricted = i.getBooleanExtra("net.sf.briar.RESTRICTED", false);
|
||||
byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
@@ -210,15 +208,9 @@ OnClickListener, OnItemClickListener {
|
||||
}
|
||||
|
||||
public void onClick(View view) {
|
||||
if(restricted) {
|
||||
Intent i = new Intent(this, WriteBlogPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
startActivity(i);
|
||||
} else {
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
|
||||
public void onItemClick(AdapterView<?> parent, View view, int position,
|
||||
@@ -228,8 +220,7 @@ OnClickListener, OnItemClickListener {
|
||||
|
||||
private void displayMessage(int position) {
|
||||
GroupMessageHeader item = adapter.getItem(position);
|
||||
Intent i = new Intent(this, ReadGroupMessageActivity.class);
|
||||
i.putExtra("net.sf.briar.RESTRICTED", restricted);
|
||||
Intent i = new Intent(this, ReadGroupPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.GROUP_NAME", groupName);
|
||||
i.putExtra("net.sf.briar.MESSAGE_ID", item.getId().getBytes());
|
||||
|
||||
@@ -12,8 +12,6 @@ import static net.sf.briar.android.widgets.CommonLayoutParams.MATCH_WRAP_1;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.logging.Logger;
|
||||
|
||||
@@ -61,7 +59,6 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
// Fields that are accessed from background threads must be volatile
|
||||
@Inject private volatile DatabaseComponent db;
|
||||
@Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor;
|
||||
private volatile boolean restricted = false;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle state) {
|
||||
@@ -71,12 +68,6 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
layout.setOrientation(VERTICAL);
|
||||
layout.setGravity(CENTER_HORIZONTAL);
|
||||
|
||||
Intent i = getIntent();
|
||||
restricted = i.getBooleanExtra("net.sf.briar.RESTRICTED", false);
|
||||
String title = i.getStringExtra("net.sf.briar.TITLE");
|
||||
if(title == null) throw new IllegalStateException();
|
||||
setTitle(title);
|
||||
|
||||
adapter = new GroupListAdapter(this);
|
||||
list = new ListView(this);
|
||||
// Give me all the width and all the unused height
|
||||
@@ -95,9 +86,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
|
||||
newGroupButton = new ImageButton(this);
|
||||
newGroupButton.setBackgroundResource(0);
|
||||
if(restricted)
|
||||
newGroupButton.setImageResource(R.drawable.social_new_blog);
|
||||
else newGroupButton.setImageResource(R.drawable.social_new_chat);
|
||||
newGroupButton.setImageResource(R.drawable.social_new_chat);
|
||||
newGroupButton.setOnClickListener(this);
|
||||
footer.addView(newGroupButton);
|
||||
footer.addView(new HorizontalSpace(this));
|
||||
@@ -131,33 +120,15 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
Collection<Group> subs = db.getSubscriptions();
|
||||
if(restricted) {
|
||||
Set<GroupId> local = new HashSet<GroupId>();
|
||||
for(Group g : db.getLocalGroups()) local.add(g.getId());
|
||||
for(Group g : subs) {
|
||||
if(!g.isRestricted()) continue;
|
||||
boolean postable = local.contains(g.getId());
|
||||
try {
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
displayHeaders(g, postable, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Subscription removed");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for(Group g : subs) {
|
||||
if(g.isRestricted()) continue;
|
||||
try {
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
displayHeaders(g, true, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Subscription removed");
|
||||
}
|
||||
for(Group g : db.getSubscriptions()) {
|
||||
if(g.isRestricted()) continue;
|
||||
try {
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
displayHeaders(g, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Subscription removed");
|
||||
}
|
||||
}
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
@@ -183,7 +154,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
});
|
||||
}
|
||||
|
||||
private void displayHeaders(final Group g, final boolean postable,
|
||||
private void displayHeaders(final Group g,
|
||||
final Collection<GroupMessageHeader> headers) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
@@ -191,7 +162,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
GroupListItem item = findGroup(g.getId());
|
||||
if(item != null) adapter.remove(item);
|
||||
// Add a new item
|
||||
adapter.add(new GroupListItem(g, postable, headers));
|
||||
adapter.add(new GroupListItem(g, headers));
|
||||
adapter.sort(GroupComparator.INSTANCE);
|
||||
adapter.notifyDataSetChanged();
|
||||
selectFirstUnread();
|
||||
@@ -234,34 +205,22 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
|
||||
public void onClick(View view) {
|
||||
if(view == newGroupButton) {
|
||||
if(restricted)
|
||||
startActivity(new Intent(this, CreateBlogActivity.class));
|
||||
else startActivity(new Intent(this, CreateGroupActivity.class));
|
||||
startActivity(new Intent(this, CreateGroupActivity.class));
|
||||
} else if(view == composeButton) {
|
||||
if(countPostableGroups() == 0) {
|
||||
if(adapter.isEmpty()) {
|
||||
NoGroupsDialog dialog = new NoGroupsDialog();
|
||||
dialog.setListener(this);
|
||||
dialog.setRestricted(restricted);
|
||||
dialog.show(getSupportFragmentManager(), "NoGroupsDialog");
|
||||
} else if(restricted) {
|
||||
startActivity(new Intent(this, WriteBlogPostActivity.class));
|
||||
} else {
|
||||
startActivity(new Intent(this, WriteGroupPostActivity.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private int countPostableGroups() {
|
||||
int postable = 0, count = adapter.getCount();
|
||||
for(int i = 0; i < count; i++)
|
||||
if(adapter.getItem(i).isPostable()) postable++;
|
||||
return postable;
|
||||
}
|
||||
|
||||
public void eventOccurred(DatabaseEvent e) {
|
||||
if(e instanceof GroupMessageAddedEvent) {
|
||||
Group g = ((GroupMessageAddedEvent) e).getGroup();
|
||||
if(g.isRestricted() == restricted) {
|
||||
if(!g.isRestricted()) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Message added, reloading");
|
||||
loadHeaders(g);
|
||||
}
|
||||
@@ -270,7 +229,7 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
loadHeaders();
|
||||
} else if(e instanceof SubscriptionRemovedEvent) {
|
||||
Group g = ((SubscriptionRemovedEvent) e).getGroup();
|
||||
if(g.isRestricted() == restricted) {
|
||||
if(!g.isRestricted()) {
|
||||
// Reload the group, expecting NoSuchSubscriptionException
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading");
|
||||
loadHeaders(g);
|
||||
@@ -284,15 +243,12 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
try {
|
||||
serviceConnection.waitForStartup();
|
||||
long now = System.currentTimeMillis();
|
||||
boolean postable;
|
||||
if(restricted) postable = db.getLocalGroups().contains(g);
|
||||
else postable = true;
|
||||
Collection<GroupMessageHeader> headers =
|
||||
db.getMessageHeaders(g.getId());
|
||||
long duration = System.currentTimeMillis() - now;
|
||||
if(LOG.isLoggable(INFO))
|
||||
LOG.info("Partial load took " + duration + " ms");
|
||||
displayHeaders(g, postable, headers);
|
||||
displayHeaders(g, headers);
|
||||
} catch(NoSuchSubscriptionException e) {
|
||||
if(LOG.isLoggable(INFO)) LOG.info("Subscription removed");
|
||||
removeGroup(g.getId());
|
||||
@@ -320,10 +276,8 @@ implements OnClickListener, DatabaseListener, NoGroupsDialog.Listener {
|
||||
});
|
||||
}
|
||||
|
||||
public void createGroupButtonClicked() {
|
||||
if(restricted)
|
||||
startActivity(new Intent(this, CreateBlogActivity.class));
|
||||
else startActivity(new Intent(this, CreateGroupActivity.class));
|
||||
public void createButtonClicked() {
|
||||
startActivity(new Intent(this, CreateGroupActivity.class));
|
||||
}
|
||||
|
||||
public void cancelButtonClicked() {
|
||||
|
||||
@@ -101,7 +101,6 @@ implements OnItemClickListener {
|
||||
long id) {
|
||||
GroupListItem item = getItem(position);
|
||||
Intent i = new Intent(getContext(), GroupActivity.class);
|
||||
i.putExtra("net.sf.briar.RESTRICTED", item.isRestricted());
|
||||
i.putExtra("net.sf.briar.GROUP_ID", item.getGroupId().getBytes());
|
||||
i.putExtra("net.sf.briar.GROUP_NAME", item.getGroupName());
|
||||
getContext().startActivity(i);
|
||||
|
||||
@@ -14,15 +14,13 @@ import net.sf.briar.api.messaging.GroupId;
|
||||
class GroupListItem {
|
||||
|
||||
private final Group group;
|
||||
private final boolean postable, empty;
|
||||
private final boolean empty;
|
||||
private final String authorName, contentType, subject;
|
||||
private final long timestamp;
|
||||
private final int unread;
|
||||
|
||||
GroupListItem(Group group, boolean postable,
|
||||
Collection<GroupMessageHeader> headers) {
|
||||
GroupListItem(Group group, Collection<GroupMessageHeader> headers) {
|
||||
this.group = group;
|
||||
this.postable = postable;
|
||||
empty = headers.isEmpty();
|
||||
if(empty) {
|
||||
authorName = null;
|
||||
@@ -55,14 +53,6 @@ class GroupListItem {
|
||||
return group.getName();
|
||||
}
|
||||
|
||||
boolean isRestricted() {
|
||||
return group.isRestricted();
|
||||
}
|
||||
|
||||
boolean isPostable() {
|
||||
return postable;
|
||||
}
|
||||
|
||||
boolean isEmpty() {
|
||||
return empty;
|
||||
}
|
||||
|
||||
@@ -10,24 +10,19 @@ import android.support.v4.app.DialogFragment;
|
||||
public class NoGroupsDialog extends DialogFragment {
|
||||
|
||||
private Listener listener = null;
|
||||
private boolean restricted = false;
|
||||
|
||||
void setListener(Listener listener) {
|
||||
this.listener = listener;
|
||||
}
|
||||
|
||||
void setRestricted(boolean restricted) {
|
||||
this.restricted = restricted;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Dialog onCreateDialog(Bundle state) {
|
||||
AlertDialog.Builder builder = new AlertDialog.Builder(getActivity());
|
||||
builder.setMessage(restricted ? R.string.no_blogs : R.string.no_groups);
|
||||
builder.setMessage(R.string.no_groups);
|
||||
builder.setPositiveButton(R.string.create_button,
|
||||
new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
listener.createGroupButtonClicked();
|
||||
listener.createButtonClicked();
|
||||
}
|
||||
});
|
||||
builder.setNegativeButton(R.string.cancel_button,
|
||||
@@ -41,7 +36,7 @@ public class NoGroupsDialog extends DialogFragment {
|
||||
|
||||
interface Listener {
|
||||
|
||||
void createGroupButtonClicked();
|
||||
void createButtonClicked();
|
||||
|
||||
void cancelButtonClicked();
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ import android.widget.TextView;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
|
||||
public class ReadGroupMessageActivity extends BriarActivity
|
||||
public class ReadGroupPostActivity extends BriarActivity
|
||||
implements OnClickListener {
|
||||
|
||||
static final int RESULT_REPLY = RESULT_FIRST_USER;
|
||||
@@ -57,13 +57,12 @@ implements OnClickListener {
|
||||
static final int RESULT_NEXT = RESULT_FIRST_USER + 2;
|
||||
|
||||
private static final Logger LOG =
|
||||
Logger.getLogger(ReadGroupMessageActivity.class.getName());
|
||||
Logger.getLogger(ReadGroupPostActivity.class.getName());
|
||||
|
||||
private final BriarServiceConnection serviceConnection =
|
||||
new BriarServiceConnection();
|
||||
|
||||
@Inject private BundleEncrypter bundleEncrypter;
|
||||
private boolean restricted = false;
|
||||
private GroupId groupId = null;
|
||||
private Rating rating = UNRATED;
|
||||
private boolean read;
|
||||
@@ -84,7 +83,6 @@ implements OnClickListener {
|
||||
super.onCreate(null);
|
||||
|
||||
Intent i = getIntent();
|
||||
restricted = i.getBooleanExtra("net.sf.briar.RESTRICTED", false);
|
||||
byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID");
|
||||
if(b == null) throw new IllegalStateException();
|
||||
groupId = new GroupId(b);
|
||||
@@ -258,7 +256,7 @@ implements OnClickListener {
|
||||
private void setReadInUi(final boolean read) {
|
||||
runOnUiThread(new Runnable() {
|
||||
public void run() {
|
||||
ReadGroupMessageActivity.this.read = read;
|
||||
ReadGroupPostActivity.this.read = read;
|
||||
if(read) readButton.setImageResource(R.drawable.content_unread);
|
||||
else readButton.setImageResource(R.drawable.content_read);
|
||||
}
|
||||
@@ -326,17 +324,10 @@ implements OnClickListener {
|
||||
setResult(RESULT_NEXT);
|
||||
finish();
|
||||
} else if(view == replyButton) {
|
||||
if(restricted) {
|
||||
Intent i = new Intent(this, WriteBlogPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes());
|
||||
startActivity(i);
|
||||
} else {
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes());
|
||||
startActivity(i);
|
||||
}
|
||||
Intent i = new Intent(this, WriteGroupPostActivity.class);
|
||||
i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes());
|
||||
i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes());
|
||||
startActivity(i);
|
||||
setResult(RESULT_REPLY);
|
||||
finish();
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import java.util.logging.Logger;
|
||||
import net.sf.briar.R;
|
||||
import net.sf.briar.android.BriarActivity;
|
||||
import net.sf.briar.android.BriarService;
|
||||
import net.sf.briar.android.GroupNameComparator;
|
||||
import net.sf.briar.android.BriarService.BriarServiceConnection;
|
||||
import net.sf.briar.android.identity.CreateIdentityActivity;
|
||||
import net.sf.briar.android.identity.LocalAuthorItem;
|
||||
|
||||
Reference in New Issue
Block a user