diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index 70d79d2fa924a6fa2b4b08750d75154181da6985..393815fa3e4ba82b696b13c2f956bbdb7eefb837 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -45,34 +45,6 @@ android:name=".android.contact.ContactListActivity" android:label="@string/contact_list_title" > </activity> - <activity - 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.ConfigureBlogActivity" - android:label="@string/app_name" > - </activity> - <activity - android:name=".android.blogs.CreateBlogActivity" - android:label="@string/create_blog_title" > - </activity> - <activity - android:name=".android.blogs.ManageBlogsActivity" - android:label="@string/manage_subscriptions_title" > - </activity> - <activity - android:name=".android.blogs.ReadBlogPostActivity" - android:label="@string/app_name" > - </activity> - <activity - android:name=".android.blogs.WriteBlogPostActivity" - android:label="@string/new_post_title" > - </activity> <activity android:name=".android.groups.ConfigureGroupActivity" android:label="@string/app_name" > diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index eb4bc573682d7201a98bc407e6e4fab601988515..916e3674c75feac857c0b7c181515b2660ea7302 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -14,7 +14,6 @@ <string name="contact_list_button">Contacts</string> <string name="messages_button">Messages</string> <string name="groups_button">Groups</string> - <string name="blogs_button">Blogs</string> <string name="synchronize_button">Synchronize</string> <string name="quit_button">Quit</string> <string name="new_identity_item">New identity\u2026</string> @@ -74,23 +73,9 @@ <string name="new_group_item">New group\u2026</string> <string name="manage_subscriptions_title">Manage Subscriptions</string> <string name="no_groups_available">No groups available from contacts</string> - <string name="blogs_title">Blogs</string> - <plurals name="blogs_available"> - <item quantity="one">%1$d blog available from contacts</item> - <item quantity="other">%1$d blogs available from contacts</item> - </plurals> - <string name="no_blogs_available">No blogs available from contacts</string> <string name="subscribed_all">Subscribed, shared with all contacts</string> <string name="subscribed_some">Subscribed, shared with chosen contacts</string> <string name="not_subscribed">Not subscribed</string> - <string name="subscribe_to_this_blog">Subscribe to this blog</string> - <string name="create_blog_title">New Blog</string> - <string name="choose_blog_name">Choose a name for your blog:</string> - <string name="blog_visible_to_all">Share this blog with all contacts</string> - <string name="blog_visible_to_some">Share this blog with chosen contacts</string> - <string name="not_your_blog">Only the creator of this blog can write posts</string> - <string name="ok_button">OK</string> - <string name="new_blog_item">New blog\u2026</string> <string name="create_nickname_item">New nickname\u2026</string> <string name="create_identity_title">Create an Identity</string> <string name="create_button">Create</string> @@ -98,5 +83,4 @@ <string name="add_button">Add</string> <string name="cancel_button">Cancel</string> <string name="no_groups">You aren\'t subscribed to any groups. Create a group now?</string> - <string name="no_blogs">You don\'t have any blogs. Create a blog now?</string> </resources> diff --git a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java index 4f7303ec640eeb97069eb3b8f6d31a588490bca6..915f4b3d45513f6686f503cb4f897b663454e68a 100644 --- a/briar-android/src/net/sf/briar/android/HomeScreenActivity.java +++ b/briar-android/src/net/sf/briar/android/HomeScreenActivity.java @@ -23,7 +23,6 @@ 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; @@ -62,8 +61,8 @@ import com.google.inject.Inject; public class HomeScreenActivity extends RoboActivity { - // This build expires on 15 August 2013 - private static final long EXPIRY_DATE = 1376524800 * 1000L; + // This build expires on 30 September 2013 + private static final long EXPIRY_DATE = 1380499200 * 1000L; private static final Logger LOG = Logger.getLogger(HomeScreenActivity.class.getName()); @@ -346,20 +345,6 @@ public class HomeScreenActivity extends RoboActivity { }); buttons.add(groupsButton); - Button blogsButton = new Button(this); - blogsButton.setLayoutParams(matchMatch); - blogsButton.setBackgroundResource(0); - blogsButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.social_blog, 0, 0); - blogsButton.setText(R.string.blogs_button); - blogsButton.setOnClickListener(new OnClickListener() { - public void onClick(View view) { - startActivity(new Intent(HomeScreenActivity.this, - BlogListActivity.class)); - } - }); - buttons.add(blogsButton); - Button syncButton = new Button(this); syncButton.setLayoutParams(matchMatch); syncButton.setBackgroundResource(0); diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/BlogActivity.java deleted file mode 100644 index b3fa2cd92fc441e7f1478654fe78cfdc8d2c9812..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/BlogActivity.java +++ /dev/null @@ -1,250 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -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.util.CommonLayoutParams.MATCH_MATCH; -import static net.sf.briar.android.util.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.util.HorizontalBorder; -import net.sf.briar.android.util.ListLoadingProgressBar; -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.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.GroupId; -import roboguice.activity.RoboFragmentActivity; -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 RoboFragmentActivity -implements DatabaseListener, OnClickListener, OnItemClickListener { - - private static final Logger LOG = - Logger.getLogger(BlogActivity.class.getName()); - - private String groupName = null; - private boolean postable = false; - private BlogAdapter adapter = null; - private ListView list = null; - private ListLoadingProgressBar loading = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - private volatile GroupId groupId = null; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - 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); - postable = i.getBooleanExtra("net.sf.briar.POSTABLE", false); - - 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); - - // Show a progress bar while the list is loading - list.setVisibility(GONE); - loading = new ListLoadingProgressBar(this); - layout.addView(loading); - - 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); - } - - @Override - public void onResume() { - super.onResume(); - db.addListener(this); - loadHeaders(); - } - - private void loadHeaders() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<GroupMessageHeader> headers = - db.getGroupMessageHeaders(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"); - runOnUiThread(new Runnable() { - public void run() { - finish(); - } - }); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayHeaders(final Collection<GroupMessageHeader> headers) { - runOnUiThread(new Runnable() { - public void run() { - list.setVisibility(VISIBLE); - loading.setVisibility(GONE); - 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); - } - - 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"); - runOnUiThread(new Runnable() { - public void run() { - finish(); - } - }); - } - } - } - - public void onClick(View view) { - if(postable) { - Intent i = new Intent(this, WriteBlogPostActivity.class); - i.putExtra("net.sf.briar.GROUP_ID", groupId.getBytes()); - startActivity(i); - } else { - NotYourBlogDialog dialog = new NotYourBlogDialog(); - dialog.show(getSupportFragmentManager(), "NotYourBlogDialog"); - } - } - - 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.POSTABLE", postable); - i.putExtra("net.sf.briar.MESSAGE_ID", item.getId().getBytes()); - Author author = item.getAuthor(); - if(author != null) { - 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); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogAdapter.java b/briar-android/src/net/sf/briar/android/blogs/BlogAdapter.java deleted file mode 100644 index bd181bdedf0188429257a57655b9b9c350211624..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/BlogAdapter.java +++ /dev/null @@ -1,110 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.graphics.Typeface.BOLD; -import static android.view.Gravity.CENTER_VERTICAL; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import static java.text.DateFormat.SHORT; -import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP_1; -import static net.sf.briar.api.messaging.Rating.BAD; -import static net.sf.briar.api.messaging.Rating.GOOD; - -import java.util.ArrayList; - -import net.sf.briar.R; -import net.sf.briar.android.util.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(); - Resources res = ctx.getResources(); - - LinearLayout layout = new LinearLayout(ctx); - layout.setOrientation(HORIZONTAL); - if(!item.isRead()) - 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(5, 5, 5, 5); - Rating rating = item.getRating(); - if(rating == GOOD) thumb.setImageResource(R.drawable.rating_good); - else if(rating == BAD) thumb.setImageResource(R.drawable.rating_bad); - else thumb.setImageResource(R.drawable.rating_unrated); - 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(); - 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(5, 0, 5, 5); - 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; - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java b/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java deleted file mode 100644 index 0b16ce3423102b33c10c070283780ede0def27ca..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/BlogListActivity.java +++ /dev/null @@ -1,412 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -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.blogs.BlogListItem.MANAGE; -import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH; -import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP; -import static net.sf.briar.android.util.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.util.HorizontalBorder; -import net.sf.briar.android.util.HorizontalSpace; -import net.sf.briar.android.util.ListLoadingProgressBar; -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.RemoteSubscriptionsUpdatedEvent; -import net.sf.briar.api.db.event.SubscriptionAddedEvent; -import net.sf.briar.api.db.event.SubscriptionRemovedEvent; -import net.sf.briar.api.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.Group; -import net.sf.briar.api.messaging.GroupId; -import net.sf.briar.api.messaging.GroupStatus; -import roboguice.activity.RoboFragmentActivity; -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 BlogListActivity extends RoboFragmentActivity -implements DatabaseListener, OnClickListener, NoBlogsDialog.Listener, -OnItemClickListener { - - private static final Logger LOG = - Logger.getLogger(BlogListActivity.class.getName()); - - private BlogListAdapter adapter = null; - private ListView list = null; - private ListLoadingProgressBar loading = null; - private ImageButton newBlogButton = null, composeButton = null; - private ImageButton manageBlogsButton = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - 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(this); - layout.addView(list); - - // Show a progress bar while the list is loading - list.setVisibility(GONE); - loading = new ListLoadingProgressBar(this); - layout.addView(loading); - - 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)); - - manageBlogsButton = new ImageButton(this); - manageBlogsButton.setBackgroundResource(0); - manageBlogsButton.setImageResource(R.drawable.action_settings); - manageBlogsButton.setOnClickListener(this); - footer.addView(manageBlogsButton); - footer.addView(new HorizontalSpace(this)); - layout.addView(footer); - - setContentView(layout); - } - - @Override - public void onResume() { - super.onResume(); - db.addListener(this); - loadHeaders(); - } - - private void loadHeaders() { - clearHeaders(); - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Set<GroupId> local = new HashSet<GroupId>(); - for(Group g : db.getLocalGroups()) local.add(g.getId()); - int available = 0; - for(GroupStatus s : db.getAvailableGroups()) { - Group g = s.getGroup(); - if(!g.isRestricted()) continue; - if(s.isSubscribed()) { - boolean postable = local.contains(g.getId()); - try { - Collection<GroupMessageHeader> headers = - db.getGroupMessageHeaders(g.getId()); - displayHeaders(g, postable, headers); - } catch(NoSuchSubscriptionException e) { - if(LOG.isLoggable(INFO)) - LOG.info("Subscription removed"); - } - } else { - available++; - } - } - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Full load took " + duration + " ms"); - displayAvailable(available); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void clearHeaders() { - runOnUiThread(new Runnable() { - public void run() { - list.setVisibility(GONE); - loading.setVisibility(VISIBLE); - adapter.clear(); - adapter.notifyDataSetChanged(); - } - }); - } - - private void displayHeaders(final Group g, final boolean postable, - final Collection<GroupMessageHeader> headers) { - runOnUiThread(new Runnable() { - public void run() { - list.setVisibility(VISIBLE); - loading.setVisibility(GONE); - // 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(ItemComparator.INSTANCE); - adapter.notifyDataSetChanged(); - selectFirstUnread(); - } - }); - } - - private void displayAvailable(final int available) { - runOnUiThread(new Runnable() { - public void run() { - list.setVisibility(VISIBLE); - loading.setVisibility(GONE); - adapter.setAvailable(available); - adapter.notifyDataSetChanged(); - } - }); - } - - private BlogListItem findGroup(GroupId g) { - int count = adapter.getCount(); - for(int i = 0; i < count; i++) { - BlogListItem item = adapter.getItem(i); - if(item == MANAGE) continue; - if(item.getGroup().getId().equals(g)) return item; - } - return null; // Not found - } - - private void selectFirstUnread() { - int firstUnread = -1, count = adapter.getCount(); - for(int i = 0; i < count; i++) { - BlogListItem item = adapter.getItem(i); - if(item == MANAGE) continue; - if(item.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); - } - - 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 RemoteSubscriptionsUpdatedEvent) { - if(LOG.isLoggable(INFO)) - LOG.info("Remote subscriptions changed, reloading"); - loadAvailable(); - } else if(e instanceof SubscriptionAddedEvent) { - Group g = ((SubscriptionAddedEvent) e).getGroup(); - if(g.isRestricted()) { - if(LOG.isLoggable(INFO)) LOG.info("Group added, 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 { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<GroupMessageHeader> headers = - db.getGroupMessageHeaders(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 database"); - 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); - adapter.notifyDataSetChanged(); - selectFirstUnread(); - } - } - }); - } - - private void loadAvailable() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - int available = 0; - long now = System.currentTimeMillis(); - for(GroupStatus s : db.getAvailableGroups()) { - if(s.getGroup().isRestricted() && !s.isSubscribed()) - available++; - } - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Loading available took " + duration + " ms"); - displayAvailable(available); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - 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(), "NoBlogsDialog"); - } else { - startActivity(new Intent(this, WriteBlogPostActivity.class)); - } - } else if(view == manageBlogsButton) { - startActivity(new Intent(this, ManageBlogsActivity.class)); - } - } - - private int countPostableGroups() { - int postable = 0, count = adapter.getCount(); - for(int i = 0; i < count; i++) { - BlogListItem item = adapter.getItem(i); - if(item == MANAGE) continue; - if(item.isPostable()) postable++; - } - return postable; - } - - public void blogCreationSelected() { - startActivity(new Intent(this, CreateBlogActivity.class)); - } - - public void blogCreationCancelled() {} - - public void onItemClick(AdapterView<?> parent, View view, int position, - long id) { - BlogListItem item = adapter.getItem(position); - if(item == MANAGE) { - startActivity(new Intent(this, ManageBlogsActivity.class)); - } else { - Intent i = new Intent(this, BlogActivity.class); - i.putExtra("net.sf.briar.GROUP_ID", - item.getGroup().getId().getBytes()); - i.putExtra("net.sf.briar.GROUP_NAME", item.getGroup().getName()); - i.putExtra("net.sf.briar.POSTABLE", item.isPostable()); - startActivity(i); - } - } - - private static class ItemComparator implements Comparator<BlogListItem> { - - private static final ItemComparator INSTANCE = new ItemComparator(); - - public int compare(BlogListItem a, BlogListItem b) { - if(a == b) return 0; - // The manage blogs item comes last - if(a == MANAGE) return 1; - if(b == MANAGE) return -1; - // 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.getGroup().getName(); - String bName = b.getGroup().getName(); - return String.CASE_INSENSITIVE_ORDER.compare(aName, bName); - } - } -} \ No newline at end of file diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java b/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java deleted file mode 100644 index f99eb1a8a4088216c2bd92c436ab185014906043..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/BlogListAdapter.java +++ /dev/null @@ -1,150 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.graphics.Typeface.BOLD; -import static android.view.Gravity.CENTER; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import static java.text.DateFormat.SHORT; -import static net.sf.briar.android.blogs.BlogListItem.MANAGE; -import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP_1; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import net.sf.briar.R; -import net.sf.briar.android.util.HorizontalSpace; -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.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -class BlogListAdapter extends BaseAdapter { - - private final Context ctx; - private final List<BlogListItem> list = new ArrayList<BlogListItem>(); - private int available = 0; - - BlogListAdapter(Context ctx) { - this.ctx = ctx; - } - - public void setAvailable(int available) { - this.available = available; - } - - public void add(BlogListItem item) { - list.add(item); - } - - public void clear() { - list.clear(); - } - - public int getCount() { - return available == 0 ? list.size() : list.size() + 1; - } - - public BlogListItem getItem(int position) { - return position == list.size() ? MANAGE : list.get(position); - } - - public long getItemId(int position) { - return android.R.layout.simple_expandable_list_item_1; - } - - public View getView(int position, View convertView, ViewGroup parent) { - BlogListItem item = getItem(position); - Resources res = ctx.getResources(); - - if(item == MANAGE) { - TextView manage = new TextView(ctx); - manage.setGravity(CENTER); - manage.setTextSize(18); - manage.setPadding(10, 10, 10, 10); - String format = res.getQuantityString(R.plurals.blogs_available, - available); - manage.setText(String.format(format, available)); - return manage; - } - - 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(); - String groupName = item.getGroup().getName(); - if(unread > 0) name.setText(groupName + " (" + unread + ")"); - else name.setText(groupName); - 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(5, 0, 5, 5); - 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; - } - - @Override - public boolean isEmpty() { - return list.isEmpty() && available == 0; - } - - public void remove(BlogListItem item) { - list.remove(item); - } - - public void sort(Comparator<BlogListItem> comparator) { - Collections.sort(list, comparator); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/BlogListItem.java b/briar-android/src/net/sf/briar/android/blogs/BlogListItem.java deleted file mode 100644 index 72f3b1b8d5b2c6f7390ca49183ab942913cf7df2..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/BlogListItem.java +++ /dev/null @@ -1,83 +0,0 @@ -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; - -class BlogListItem { - - static final BlogListItem MANAGE = new BlogListItem(null, false, - Collections.<GroupMessageHeader>emptyList()); - - 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; - } - } - - Group getGroup() { - return group; - } - - 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; - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java deleted file mode 100644 index c34dc6e6ac0ef3ab8f6786f7310a9fc52d4dfe8d..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/ConfigureBlogActivity.java +++ /dev/null @@ -1,248 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -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.util.CommonLayoutParams.MATCH_MATCH; -import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP; - -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import net.sf.briar.R; -import net.sf.briar.android.contact.SelectContactsDialog; -import net.sf.briar.android.invitation.AddContactActivity; -import net.sf.briar.android.messages.NoContactsDialog; -import net.sf.briar.api.Contact; -import net.sf.briar.api.ContactId; -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.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.Group; -import net.sf.briar.api.messaging.GroupId; -import roboguice.activity.RoboFragmentActivity; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.Button; -import android.widget.CheckBox; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RadioButton; -import android.widget.RadioGroup; - -import com.google.inject.Inject; - -public class ConfigureBlogActivity extends RoboFragmentActivity -implements OnClickListener, NoContactsDialog.Listener, -SelectContactsDialog.Listener { - - private static final Logger LOG = - Logger.getLogger(ConfigureBlogActivity.class.getName()); - - private boolean subscribed = false; - private CheckBox subscribeCheckBox = null; - private RadioGroup radioGroup = null; - private RadioButton visibleToAll = null, visibleToSome = null; - private Button doneButton = null; - private ProgressBar progress = null; - private NoContactsDialog noContactsDialog = null; - private SelectContactsDialog selectContactsDialog = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - private volatile Group group = null; - private volatile Collection<ContactId> selected = Collections.emptyList(); - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - Intent i = getIntent(); - byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); - if(b == null) throw new IllegalStateException(); - GroupId id = new GroupId(b); - String name = i.getStringExtra("net.sf.briar.GROUP_NAME"); - if(name == null) throw new IllegalStateException(); - setTitle(name); - byte[] publicKey = i.getByteArrayExtra("net.sf.briar.PUBLIC_KEY"); - if(publicKey == null) throw new IllegalStateException(); - group = new Group(id, name, publicKey); - subscribed = i.getBooleanExtra("net.sf.briar.SUBSCRIBED", false); - boolean all = i.getBooleanExtra("net.sf.briar.VISIBLE_TO_ALL", false); - - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_MATCH); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - subscribeCheckBox = new CheckBox(this); - subscribeCheckBox.setId(1); - subscribeCheckBox.setText(R.string.subscribe_to_this_blog); - subscribeCheckBox.setChecked(subscribed); - subscribeCheckBox.setOnClickListener(this); - layout.addView(subscribeCheckBox); - - radioGroup = new RadioGroup(this); - radioGroup.setOrientation(VERTICAL); - - visibleToAll = new RadioButton(this); - visibleToAll.setId(2); - visibleToAll.setText(R.string.blog_visible_to_all); - visibleToAll.setEnabled(subscribed); - visibleToAll.setOnClickListener(this); - radioGroup.addView(visibleToAll); - - visibleToSome = new RadioButton(this); - visibleToSome.setId(3); - visibleToSome.setText(R.string.blog_visible_to_some); - visibleToSome.setEnabled(subscribed); - visibleToSome.setOnClickListener(this); - radioGroup.addView(visibleToSome); - - if(!subscribed || all) radioGroup.check(visibleToAll.getId()); - else radioGroup.check(visibleToSome.getId()); - layout.addView(radioGroup); - - doneButton = new Button(this); - doneButton.setLayoutParams(WRAP_WRAP); - doneButton.setText(R.string.done_button); - doneButton.setOnClickListener(this); - layout.addView(doneButton); - - progress = new ProgressBar(this); - progress.setLayoutParams(WRAP_WRAP); - progress.setIndeterminate(true); - progress.setVisibility(GONE); - layout.addView(progress); - - setContentView(layout); - - FragmentManager fm = getSupportFragmentManager(); - Fragment f = fm.findFragmentByTag("NoContactsDialog"); - if(f == null) noContactsDialog = new NoContactsDialog(); - else noContactsDialog = (NoContactsDialog) f; - noContactsDialog.setListener(this); - - f = fm.findFragmentByTag("SelectContactsDialog"); - if(f == null) selectContactsDialog = new SelectContactsDialog(); - else selectContactsDialog = (SelectContactsDialog) f; - selectContactsDialog.setListener(this); - } - - public void onClick(View view) { - if(view == subscribeCheckBox) { - boolean subscribe = subscribeCheckBox.isChecked(); - visibleToAll.setEnabled(subscribe); - visibleToSome.setEnabled(subscribe); - } else if(view == visibleToSome) { - loadContacts(); - } else if(view == doneButton) { - boolean subscribe = subscribeCheckBox.isChecked(); - boolean all = visibleToAll.isChecked(); - Collection<ContactId> visible = - Collections.unmodifiableCollection(selected); - // Replace the button with a progress bar - doneButton.setVisibility(GONE); - progress.setVisibility(VISIBLE); - // Update the blog in a background thread - if(subscribe || subscribed) - updateGroup(subscribe, subscribed, all, visible); - } - } - - private void loadContacts() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<Contact> contacts = db.getContacts(); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Load took " + duration + " ms"); - displayContacts(contacts); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayContacts(final Collection<Contact> contacts) { - runOnUiThread(new Runnable() { - public void run() { - FragmentManager fm = getSupportFragmentManager(); - if(contacts.isEmpty()) { - noContactsDialog.show(fm, "NoContactsDialog"); - } else { - selectContactsDialog.setContacts(contacts); - selectContactsDialog.show(fm, "SelectContactsDialog"); - } - } - }); - } - - private void updateGroup(final boolean subscribe, - final boolean wasSubscribed, final boolean all, - final Collection<ContactId> visible) { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - if(subscribe) { - if(!wasSubscribed) db.subscribe(group); - db.setVisibleToAll(group.getId(), all); - if(!all) db.setVisibility(group.getId(), visible); - } else if(wasSubscribed) { - db.unsubscribe(group); - } - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Update 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 database"); - Thread.currentThread().interrupt(); - } - runOnUiThread(new Runnable() { - public void run() { - finish(); - } - }); - } - }); - } - - public void contactCreationSelected() { - startActivity(new Intent(this, AddContactActivity.class)); - } - - public void contactCreationCancelled() {} - - public void contactsSelected(Collection<ContactId> selected) { - this.selected = selected; - } - - public void contactSelectionCancelled() {} -} diff --git a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java b/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java deleted file mode 100644 index 9f7cbeadeec7410980efbf288068f5c95c876cce..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/CreateBlogActivity.java +++ /dev/null @@ -1,290 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.text.InputType.TYPE_CLASS_TEXT; -import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_HORIZONTAL; -import static android.view.View.GONE; -import static android.view.View.VISIBLE; -import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; -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.util.CommonLayoutParams.MATCH_MATCH; -import static net.sf.briar.android.util.CommonLayoutParams.WRAP_WRAP; - -import java.io.IOException; -import java.util.Collection; -import java.util.Collections; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import net.sf.briar.R; -import net.sf.briar.android.contact.SelectContactsDialog; -import net.sf.briar.android.invitation.AddContactActivity; -import net.sf.briar.android.messages.NoContactsDialog; -import net.sf.briar.api.Contact; -import net.sf.briar.api.ContactId; -import net.sf.briar.api.android.DatabaseUiExecutor; -import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.CryptoExecutor; -import net.sf.briar.api.crypto.KeyPair; -import net.sf.briar.api.db.DatabaseComponent; -import net.sf.briar.api.db.DbException; -import net.sf.briar.api.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.GroupFactory; -import net.sf.briar.api.messaging.LocalGroup; -import roboguice.activity.RoboFragmentActivity; -import android.content.Intent; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentManager; -import android.view.KeyEvent; -import android.view.View; -import android.view.View.OnClickListener; -import android.view.inputmethod.InputMethodManager; -import android.widget.Button; -import android.widget.EditText; -import android.widget.LinearLayout; -import android.widget.ProgressBar; -import android.widget.RadioButton; -import android.widget.RadioGroup; -import android.widget.TextView; -import android.widget.TextView.OnEditorActionListener; - -import com.google.inject.Inject; - -public class CreateBlogActivity extends RoboFragmentActivity -implements OnEditorActionListener, OnClickListener, NoContactsDialog.Listener, -SelectContactsDialog.Listener { - - private static final Logger LOG = - Logger.getLogger(CreateBlogActivity.class.getName()); - - @Inject @CryptoExecutor private Executor cryptoExecutor; - private EditText nameEntry = null; - private RadioGroup radioGroup = null; - private RadioButton visibleToAll = null, visibleToSome = null; - private Button createButton = null; - private ProgressBar progress = null; - private NoContactsDialog noContactsDialog = null; - private SelectContactsDialog selectContactsDialog = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile CryptoComponent crypto; - @Inject private volatile GroupFactory groupFactory; - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - private volatile Collection<ContactId> selected = Collections.emptyList(); - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_MATCH); - layout.setOrientation(VERTICAL); - layout.setGravity(CENTER_HORIZONTAL); - - TextView chooseName = new TextView(this); - chooseName.setGravity(CENTER); - chooseName.setTextSize(18); - chooseName.setPadding(10, 10, 10, 0); - chooseName.setText(R.string.choose_blog_name); - layout.addView(chooseName); - - nameEntry = new EditText(this) { - @Override - protected void onTextChanged(CharSequence text, int start, - int lengthBefore, int lengthAfter) { - enableOrDisableCreateButton(); - } - }; - nameEntry.setId(1); - nameEntry.setMaxLines(1); - nameEntry.setInputType(TYPE_CLASS_TEXT | TYPE_TEXT_FLAG_CAP_SENTENCES); - nameEntry.setOnEditorActionListener(this); - layout.addView(nameEntry); - - radioGroup = new RadioGroup(this); - radioGroup.setOrientation(VERTICAL); - - visibleToAll = new RadioButton(this); - visibleToAll.setId(2); - visibleToAll.setText(R.string.blog_visible_to_all); - visibleToAll.setOnClickListener(this); - radioGroup.addView(visibleToAll); - - visibleToSome = new RadioButton(this); - visibleToSome.setId(3); - visibleToSome.setText(R.string.blog_visible_to_some); - visibleToSome.setOnClickListener(this); - radioGroup.addView(visibleToSome); - layout.addView(radioGroup); - - createButton = new Button(this); - createButton.setLayoutParams(WRAP_WRAP); - createButton.setText(R.string.create_button); - createButton.setEnabled(false); - createButton.setOnClickListener(this); - layout.addView(createButton); - - progress = new ProgressBar(this); - progress.setLayoutParams(WRAP_WRAP); - progress.setIndeterminate(true); - progress.setVisibility(GONE); - layout.addView(progress); - - setContentView(layout); - - FragmentManager fm = getSupportFragmentManager(); - Fragment f = fm.findFragmentByTag("NoContactsDialog"); - if(f == null) noContactsDialog = new NoContactsDialog(); - else noContactsDialog = (NoContactsDialog) f; - noContactsDialog.setListener(this); - - f = fm.findFragmentByTag("SelectContactsDialog"); - if(f == null) selectContactsDialog = new SelectContactsDialog(); - else selectContactsDialog = (SelectContactsDialog) f; - selectContactsDialog.setListener(this); - } - - private void enableOrDisableCreateButton() { - if(nameEntry == null || radioGroup == null || createButton == null) - return; // Activity not created yet - boolean nameNotEmpty = nameEntry.getText().length() > 0; - boolean visibilitySelected = radioGroup.getCheckedRadioButtonId() != -1; - createButton.setEnabled(nameNotEmpty && visibilitySelected); - } - - public boolean onEditorAction(TextView textView, int actionId, KeyEvent e) { - validateName(); - return true; - } - - public void onClick(View view) { - if(view == visibleToAll) { - enableOrDisableCreateButton(); - } else if(view == visibleToSome) { - loadContacts(); - } else if(view == createButton) { - if(!validateName()) return; - final String name = nameEntry.getText().toString(); - final boolean all = visibleToAll.isChecked(); - final Collection<ContactId> visible = - Collections.unmodifiableCollection(selected); - // Replace the button with a progress bar - createButton.setVisibility(GONE); - progress.setVisibility(VISIBLE); - // Create the blog in a background thread - cryptoExecutor.execute(new Runnable() { - public void run() { - KeyPair keyPair = crypto.generateSignatureKeyPair(); - final byte[] publicKey = keyPair.getPublic().getEncoded(); - final byte[] privateKey = keyPair.getPrivate().getEncoded(); - LocalGroup g; - try { - g = groupFactory.createLocalGroup(name, publicKey, - privateKey); - } catch(IOException e) { - throw new RuntimeException(e); - } - storeLocalGroup(g, all, visible); - } - }); - } - } - - private void loadContacts() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<Contact> contacts = db.getContacts(); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Load took " + duration + " ms"); - displayContacts(contacts); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayContacts(final Collection<Contact> contacts) { - runOnUiThread(new Runnable() { - public void run() { - FragmentManager fm = getSupportFragmentManager(); - if(contacts.isEmpty()) { - noContactsDialog.show(fm, "NoContactsDialog"); - } else { - selectContactsDialog.setContacts(contacts); - selectContactsDialog.show(fm, "SelectContactsDialog"); - } - } - }); - } - - private void storeLocalGroup(final LocalGroup g, final boolean all, - final Collection<ContactId> visible) { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - db.addLocalGroup(g); - db.subscribe(g); - if(all) db.setVisibleToAll(g.getId(), true); - else db.setVisibility(g.getId(), visible); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Storing group 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 database"); - Thread.currentThread().interrupt(); - } - runOnUiThread(new Runnable() { - public void run() { - finish(); - } - }); - } - }); - } - - private boolean validateName() { - if(nameEntry.getText().toString().equals("")) return false; - // Hide the soft keyboard - Object o = getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); - return true; - } - - public void contactCreationSelected() { - startActivity(new Intent(this, AddContactActivity.class)); - } - - public void contactCreationCancelled() { - enableOrDisableCreateButton(); - } - - public void contactsSelected(Collection<ContactId> selected) { - this.selected = selected; - enableOrDisableCreateButton(); - } - - public void contactSelectionCancelled() { - enableOrDisableCreateButton(); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/LocalGroupItem.java b/briar-android/src/net/sf/briar/android/blogs/LocalGroupItem.java deleted file mode 100644 index cd7f893556bbf80276adf621537a1522a003d517..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/LocalGroupItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.sf.briar.android.blogs; - -import net.sf.briar.api.messaging.LocalGroup; - -class LocalGroupItem { - - static final LocalGroupItem NEW = new LocalGroupItem(null); - - private final LocalGroup localGroup; - - LocalGroupItem(LocalGroup localGroup) { - this.localGroup = localGroup; - } - - LocalGroup getLocalGroup() { - return localGroup; - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/LocalGroupItemComparator.java b/briar-android/src/net/sf/briar/android/blogs/LocalGroupItemComparator.java deleted file mode 100644 index b6943000cefa54cf75743c3f15af55c55cef6136..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/LocalGroupItemComparator.java +++ /dev/null @@ -1,20 +0,0 @@ -package net.sf.briar.android.blogs; - -import static net.sf.briar.android.blogs.LocalGroupItem.NEW; - -import java.util.Comparator; - -class LocalGroupItemComparator implements Comparator<LocalGroupItem> { - - static final LocalGroupItemComparator INSTANCE = - new LocalGroupItemComparator(); - - public int compare(LocalGroupItem a, LocalGroupItem b) { - if(a == b) return 0; - if(a == NEW) return 1; - if(b == NEW) return -1; - String aName = a.getLocalGroup().getName(); - String bName = b.getLocalGroup().getName(); - return String.CASE_INSENSITIVE_ORDER.compare(aName, bName); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java b/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java deleted file mode 100644 index c0ee80065dcb0c67bd70ecb265249536e9ec4959..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/LocalGroupSpinnerAdapter.java +++ /dev/null @@ -1,76 +0,0 @@ -package net.sf.briar.android.blogs; - -import static net.sf.briar.android.blogs.LocalGroupItem.NEW; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import net.sf.briar.R; -import android.content.Context; -import android.content.res.Resources; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.SpinnerAdapter; -import android.widget.TextView; - -class LocalGroupSpinnerAdapter extends BaseAdapter implements SpinnerAdapter { - - private final Context ctx; - private final List<LocalGroupItem> list = new ArrayList<LocalGroupItem>(); - - LocalGroupSpinnerAdapter(Context ctx) { - this.ctx = ctx; - } - - public void add(LocalGroupItem item) { - list.add(item); - } - - public void clear() { - list.clear(); - } - - public int getCount() { - return list.isEmpty() ? 0 : list.size() + 1; - } - - @Override - public View getDropDownView(int position, View convertView, - ViewGroup parent) { - return getView(position, convertView, parent); - } - - public LocalGroupItem getItem(int position) { - if(position == list.size()) return NEW; - return list.get(position); - } - - public long getItemId(int position) { - return android.R.layout.simple_spinner_item; - } - - public View getView(int position, View convertView, ViewGroup parent) { - TextView name = new TextView(ctx); - name.setTextSize(18); - name.setMaxLines(1); - Resources res = ctx.getResources(); - int pad = res.getInteger(R.integer.spinner_padding); - name.setPadding(pad, pad, pad, pad); - LocalGroupItem item = getItem(position); - if(item == NEW) name.setText(R.string.new_blog_item); - else name.setText(item.getLocalGroup().getName()); - return name; - } - - @Override - public boolean isEmpty() { - return list.isEmpty(); - } - - public void sort(Comparator<LocalGroupItem> comparator) { - Collections.sort(list, comparator); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java deleted file mode 100644 index 430e40e7d182680d89118befd2778156366e3f2a..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsActivity.java +++ /dev/null @@ -1,169 +0,0 @@ -package net.sf.briar.android.blogs; - -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static net.sf.briar.android.blogs.ManageBlogsItem.NONE; -import static net.sf.briar.android.util.CommonLayoutParams.MATCH_MATCH; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import net.sf.briar.android.util.ListLoadingProgressBar; -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.event.DatabaseEvent; -import net.sf.briar.api.db.event.DatabaseListener; -import net.sf.briar.api.db.event.RemoteSubscriptionsUpdatedEvent; -import net.sf.briar.api.db.event.SubscriptionAddedEvent; -import net.sf.briar.api.db.event.SubscriptionRemovedEvent; -import net.sf.briar.api.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.Group; -import net.sf.briar.api.messaging.GroupStatus; -import roboguice.activity.RoboFragmentActivity; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemClickListener; -import android.widget.ListView; - -import com.google.inject.Inject; - -public class ManageBlogsActivity extends RoboFragmentActivity -implements DatabaseListener, OnItemClickListener { - - private static final Logger LOG = - Logger.getLogger(ManageBlogsActivity.class.getName()); - - private ManageBlogsAdapter adapter = null; - private ListView list = null; - private ListLoadingProgressBar loading = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - adapter = new ManageBlogsAdapter(this); - list = new ListView(this); - list.setLayoutParams(MATCH_MATCH); - list.setAdapter(adapter); - list.setOnItemClickListener(this); - - // Show a progress bar while the list is loading - loading = new ListLoadingProgressBar(this); - setContentView(loading); - } - - @Override - public void onResume() { - super.onResume(); - db.addListener(this); - loadAvailableGroups(); - } - - private void loadAvailableGroups() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - List<GroupStatus> available = new ArrayList<GroupStatus>(); - for(GroupStatus s : db.getAvailableGroups()) - if(s.getGroup().isRestricted()) available.add(s); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Load took " + duration + " ms"); - available = Collections.unmodifiableList(available); - displayAvailableGroups(available); - } 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayAvailableGroups( - final Collection<GroupStatus> available) { - runOnUiThread(new Runnable() { - public void run() { - setContentView(list); - adapter.clear(); - for(GroupStatus g : available) - adapter.add(new ManageBlogsItem(g)); - adapter.sort(ItemComparator.INSTANCE); - adapter.notifyDataSetChanged(); - } - }); - } - - @Override - public void onPause() { - super.onPause(); - db.removeListener(this); - } - - public void eventOccurred(DatabaseEvent e) { - if(e instanceof RemoteSubscriptionsUpdatedEvent) { - if(LOG.isLoggable(INFO)) - LOG.info("Remote subscriptions changed, reloading"); - loadAvailableGroups(); - } else if(e instanceof SubscriptionAddedEvent) { - Group g = ((SubscriptionAddedEvent) e).getGroup(); - if(g.isRestricted()) { - if(LOG.isLoggable(INFO)) LOG.info("Group added, reloading"); - loadAvailableGroups(); - } - } else if(e instanceof SubscriptionRemovedEvent) { - Group g = ((SubscriptionRemovedEvent) e).getGroup(); - if(g.isRestricted()) { - if(LOG.isLoggable(INFO)) LOG.info("Group removed, reloading"); - loadAvailableGroups(); - } - } - } - - public void onItemClick(AdapterView<?> parent, View view, int position, - long id) { - ManageBlogsItem item = adapter.getItem(position); - if(item == NONE) return; - GroupStatus s = item.getGroupStatus(); - Group g = s.getGroup(); - Intent i = new Intent(this, ConfigureBlogActivity.class); - i.putExtra("net.sf.briar.GROUP_ID", g.getId().getBytes()); - i.putExtra("net.sf.briar.GROUP_NAME", g.getName()); - i.putExtra("net.sf.briar.PUBLIC_KEY", g.getPublicKey()); - i.putExtra("net.sf.briar.SUBSCRIBED", s.isSubscribed()); - i.putExtra("net.sf.briar.VISIBLE_TO_ALL", s.isVisibleToAll()); - startActivity(i); - } - - private static class ItemComparator implements Comparator<ManageBlogsItem> { - - private static final ItemComparator INSTANCE = new ItemComparator(); - - public int compare(ManageBlogsItem a, ManageBlogsItem b) { - if(a == b) return 0; - if(a == NONE) return 1; - if(b == NONE) return -1; - String aName = a.getGroupStatus().getGroup().getName(); - String bName = b.getGroupStatus().getGroup().getName(); - return String.CASE_INSENSITIVE_ORDER.compare(aName, bName); - } - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java deleted file mode 100644 index 6afe109f1774b0edb1f196d8f5ef386375840510..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsAdapter.java +++ /dev/null @@ -1,112 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.view.Gravity.CENTER; -import static android.view.View.INVISIBLE; -import static android.widget.LinearLayout.HORIZONTAL; -import static android.widget.LinearLayout.VERTICAL; -import static net.sf.briar.android.blogs.ManageBlogsItem.NONE; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -import net.sf.briar.R; -import net.sf.briar.api.messaging.GroupStatus; -import android.content.Context; -import android.view.View; -import android.view.ViewGroup; -import android.widget.BaseAdapter; -import android.widget.ImageView; -import android.widget.LinearLayout; -import android.widget.TextView; - -class ManageBlogsAdapter extends BaseAdapter { - - private final Context ctx; - private final List<ManageBlogsItem> list = new ArrayList<ManageBlogsItem>(); - - ManageBlogsAdapter(Context ctx) { - this.ctx = ctx; - } - - public void add(ManageBlogsItem item) { - list.add(item); - } - - public void clear() { - list.clear(); - } - - public int getCount() { - return list.isEmpty() ? 1 : list.size(); - } - - public ManageBlogsItem getItem(int position) { - return list.isEmpty() ? NONE : list.get(position); - } - - public long getItemId(int position) { - return android.R.layout.simple_expandable_list_item_1; - } - - public View getView(int position, View convertView, ViewGroup parent) { - ManageBlogsItem item = getItem(position); - - if(item == NONE) { - TextView none = new TextView(ctx); - none.setGravity(CENTER); - none.setTextSize(18); - none.setPadding(10, 10, 10, 10); - none.setText(R.string.no_blogs_available); - return none; - } - - GroupStatus s = item.getGroupStatus(); - LinearLayout layout = new LinearLayout(ctx); - layout.setOrientation(HORIZONTAL); - - ImageView subscribed = new ImageView(ctx); - subscribed.setPadding(5, 5, 5, 5); - subscribed.setImageResource(R.drawable.navigation_accept); - if(!s.isSubscribed()) subscribed.setVisibility(INVISIBLE); - layout.addView(subscribed); - - LinearLayout innerLayout = new LinearLayout(ctx); - innerLayout.setOrientation(VERTICAL); - - TextView name = new TextView(ctx); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(0, 10, 10, 10); - name.setText(s.getGroup().getName()); - innerLayout.addView(name); - - TextView status = new TextView(ctx); - status.setTextSize(14); - status.setPadding(0, 0, 10, 10); - if(s.isSubscribed()) { - if(s.isVisibleToAll()) status.setText(R.string.subscribed_all); - else status.setText(R.string.subscribed_some); - } else { - status.setText(R.string.not_subscribed); - } - innerLayout.addView(status); - layout.addView(innerLayout); - - return layout; - } - - @Override - public boolean isEmpty() { - return false; - } - - public void remove(ManageBlogsItem item) { - list.remove(item); - } - - public void sort(Comparator<ManageBlogsItem> comparator) { - Collections.sort(list, comparator); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java b/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java deleted file mode 100644 index dfa61ea77db41184339d4b5e82cf4b0d95372084..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/ManageBlogsItem.java +++ /dev/null @@ -1,18 +0,0 @@ -package net.sf.briar.android.blogs; - -import net.sf.briar.api.messaging.GroupStatus; - -class ManageBlogsItem { - - static final ManageBlogsItem NONE = new ManageBlogsItem(null); - - private final GroupStatus status; - - ManageBlogsItem(GroupStatus status) { - this.status = status; - } - - GroupStatus getGroupStatus() { - return status; - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java b/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java deleted file mode 100644 index b835960ae9e768a9627552c37abf89fd1cc2f2ef..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/NoBlogsDialog.java +++ /dev/null @@ -1,43 +0,0 @@ -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.blogCreationSelected(); - } - }); - builder.setNegativeButton(R.string.cancel_button, - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int id) { - listener.blogCreationCancelled(); - } - }); - return builder.create(); - } - - interface Listener { - - void blogCreationSelected(); - - void blogCreationCancelled(); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/NotYourBlogDialog.java b/briar-android/src/net/sf/briar/android/blogs/NotYourBlogDialog.java deleted file mode 100644 index c306339de1000db054b84d75f985a1e5fa0206dc..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/NotYourBlogDialog.java +++ /dev/null @@ -1,24 +0,0 @@ -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 NotYourBlogDialog extends DialogFragment { - - private static final DialogInterface.OnClickListener IGNORE = - new DialogInterface.OnClickListener() { - public void onClick(DialogInterface dialog, int which) {} - }; - - @Override - public Dialog onCreateDialog(Bundle state) { - AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); - builder.setMessage(R.string.not_your_blog); - builder.setPositiveButton(R.string.ok_button, IGNORE); - return builder.create(); - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/ReadBlogPostActivity.java b/briar-android/src/net/sf/briar/android/blogs/ReadBlogPostActivity.java deleted file mode 100644 index f243acb1f9aeff4553aa0c52789bfa97f472c979..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/ReadBlogPostActivity.java +++ /dev/null @@ -1,297 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.view.Gravity.CENTER; -import static android.view.Gravity.CENTER_VERTICAL; -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.util.CommonLayoutParams.MATCH_WRAP; -import static net.sf.briar.android.util.CommonLayoutParams.MATCH_WRAP_1; -import static net.sf.briar.android.util.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.util.HorizontalBorder; -import net.sf.briar.android.util.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.NoSuchMessageException; -import net.sf.briar.api.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.GroupId; -import net.sf.briar.api.messaging.MessageId; -import net.sf.briar.api.messaging.Rating; -import roboguice.activity.RoboFragmentActivity; -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 RoboFragmentActivity -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 GroupId groupId = null; - private boolean postable = false; - private Rating rating = UNRATED; - private boolean read; - private ImageView thumb = null; - private ImageButton readButton = null, 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; - @Inject private volatile LifecycleManager lifecycleManager; - private volatile MessageId messageId = null; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - 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); - postable = i.getBooleanExtra("net.sf.briar.POSTABLE", false); - b = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); - if(b == null) throw new IllegalStateException(); - messageId = new MessageId(b); - String authorName = i.getStringExtra("net.sf.briar.AUTHOR_NAME"); - 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) { - read = false; - setReadInDatabase(true); - } else { - read = state.getBoolean("net.sf.briar.READ"); - } - - 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(5, 5, 5, 5); - if(rating == GOOD) thumb.setImageResource(R.drawable.rating_good); - else if(rating == BAD) thumb.setImageResource(R.drawable.rating_bad); - else thumb.setImageResource(R.drawable.rating_unrated); - header.addView(thumb); - - TextView name = new TextView(this); - // Give me all the unused width - name.setLayoutParams(WRAP_WRAP_1); - name.setTextSize(18); - name.setMaxLines(1); - name.setPadding(0, 10, 10, 10); - if(authorName == null) { - name.setTextColor(res.getColor(R.color.anonymous_author)); - name.setText(R.string.anonymous); - } else { - name.setText(authorName); - } - header.addView(name); - - 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); - - 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); - } - - private void setReadInDatabase(final boolean read) { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - 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 database"); - 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 { - lifecycleManager.waitForDatabase(); - 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"); - runOnUiThread(new Runnable() { - public void run() { - finish(); - } - }); - } 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 database"); - Thread.currentThread().interrupt(); - } catch(UnsupportedEncodingException e) { - throw new RuntimeException(e); - } - } - }); - } - - @Override - public void onSaveInstanceState(Bundle state) { - super.onSaveInstanceState(state); - state.putBoolean("net.sf.briar.READ", read); - } - - public void onClick(View view) { - 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) { - if(postable) { - 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(); - } else { - NotYourBlogDialog dialog = new NotYourBlogDialog(); - dialog.show(getSupportFragmentManager(), "NotYourBlogDialog"); - } - } - } -} diff --git a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java b/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java deleted file mode 100644 index d28262c042c801d0fa1d30ecfecbe34e94189117..0000000000000000000000000000000000000000 --- a/briar-android/src/net/sf/briar/android/blogs/WriteBlogPostActivity.java +++ /dev/null @@ -1,357 +0,0 @@ -package net.sf.briar.android.blogs; - -import static android.text.InputType.TYPE_CLASS_TEXT; -import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; -import static android.view.Gravity.CENTER_VERTICAL; -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.util.CommonLayoutParams.MATCH_WRAP; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.Collection; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import net.sf.briar.R; -import net.sf.briar.android.identity.CreateIdentityActivity; -import net.sf.briar.android.identity.LocalAuthorItem; -import net.sf.briar.android.identity.LocalAuthorItemComparator; -import net.sf.briar.android.identity.LocalAuthorSpinnerAdapter; -import net.sf.briar.android.util.HorizontalSpace; -import net.sf.briar.api.AuthorId; -import net.sf.briar.api.LocalAuthor; -import net.sf.briar.api.android.DatabaseUiExecutor; -import net.sf.briar.api.crypto.CryptoComponent; -import net.sf.briar.api.crypto.KeyParser; -import net.sf.briar.api.crypto.PrivateKey; -import net.sf.briar.api.db.DatabaseComponent; -import net.sf.briar.api.db.DbException; -import net.sf.briar.api.lifecycle.LifecycleManager; -import net.sf.briar.api.messaging.GroupId; -import net.sf.briar.api.messaging.LocalGroup; -import net.sf.briar.api.messaging.Message; -import net.sf.briar.api.messaging.MessageFactory; -import net.sf.briar.api.messaging.MessageId; -import roboguice.activity.RoboActivity; -import android.content.Intent; -import android.os.Bundle; -import android.text.InputType; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.AdapterView; -import android.widget.AdapterView.OnItemSelectedListener; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.Spinner; -import android.widget.TextView; - -import com.google.inject.Inject; - -public class WriteBlogPostActivity extends RoboActivity -implements OnItemSelectedListener, OnClickListener { - - private static final Logger LOG = - Logger.getLogger(WriteBlogPostActivity.class.getName()); - - @Inject private CryptoComponent crypto; - @Inject private MessageFactory messageFactory; - private LocalAuthorSpinnerAdapter fromAdapter = null; - private LocalGroupSpinnerAdapter toAdapter = null; - private Spinner fromSpinner = null, toSpinner = null; - private ImageButton sendButton = null; - private EditText content = null; - private AuthorId localAuthorId = null; - private GroupId localGroupId = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile DatabaseComponent db; - @Inject @DatabaseUiExecutor private volatile Executor dbUiExecutor; - @Inject private volatile LifecycleManager lifecycleManager; - private volatile LocalAuthor localAuthor = null; - private volatile LocalGroup localGroup = null; - private volatile MessageId parentId = null; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - Intent i = getIntent(); - byte[] b = i.getByteArrayExtra("net.sf.briar.GROUP_ID"); - if(b != null) localGroupId = new GroupId(b); - b = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); - if(b != null) parentId = new MessageId(b); - - if(state != null) { - b = state.getByteArray("net.sf.briar.LOCAL_AUTHOR_ID"); - if(b != null) localAuthorId = new AuthorId(b); - b = state.getByteArray("net.sf.briar.LOCAL_GROUP_ID"); - if(b != null) localGroupId = new GroupId(b); - } - - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_WRAP); - layout.setOrientation(VERTICAL); - - LinearLayout header = new LinearLayout(this); - header.setLayoutParams(MATCH_WRAP); - header.setOrientation(HORIZONTAL); - header.setGravity(CENTER_VERTICAL); - - TextView from = new TextView(this); - from.setTextSize(18); - from.setPadding(10, 10, 0, 10); - from.setText(R.string.from); - header.addView(from); - - fromAdapter = new LocalAuthorSpinnerAdapter(this, true); - fromSpinner = new Spinner(this); - fromSpinner.setAdapter(fromAdapter); - fromSpinner.setOnItemSelectedListener(this); - header.addView(fromSpinner); - - header.addView(new HorizontalSpace(this)); - - sendButton = new ImageButton(this); - sendButton.setBackgroundResource(0); - sendButton.setImageResource(R.drawable.social_send_now); - sendButton.setEnabled(false); // Enabled when a group is selected - sendButton.setOnClickListener(this); - header.addView(sendButton); - layout.addView(header); - - header = new LinearLayout(this); - header.setLayoutParams(MATCH_WRAP); - header.setOrientation(HORIZONTAL); - header.setGravity(CENTER_VERTICAL); - - TextView to = new TextView(this); - to.setTextSize(18); - to.setPadding(10, 0, 0, 10); - to.setText(R.string.to); - header.addView(to); - - toAdapter = new LocalGroupSpinnerAdapter(this); - toSpinner = new Spinner(this); - toSpinner.setAdapter(toAdapter); - toSpinner.setOnItemSelectedListener(this); - header.addView(toSpinner); - layout.addView(header); - - content = new EditText(this); - content.setId(1); - int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE - | TYPE_TEXT_FLAG_CAP_SENTENCES; - content.setInputType(inputType); - layout.addView(content); - - setContentView(layout); - } - - @Override - public void onResume() { - super.onResume(); - loadLocalAuthors(); - loadLocalGroups(); - } - - private void loadLocalAuthors() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<LocalAuthor> localAuthors = db.getLocalAuthors(); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Loading authors took " + duration + " ms"); - displayLocalAuthors(localAuthors); - } catch(DbException e) { - if(LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } catch(InterruptedException e) { - LOG.info("Interrupted while waiting for database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayLocalAuthors( - final Collection<LocalAuthor> localAuthors) { - runOnUiThread(new Runnable() { - public void run() { - if(localAuthors.isEmpty()) throw new IllegalStateException(); - fromAdapter.clear(); - for(LocalAuthor a : localAuthors) - fromAdapter.add(new LocalAuthorItem(a)); - fromAdapter.sort(LocalAuthorItemComparator.INSTANCE); - fromAdapter.notifyDataSetChanged(); - int count = fromAdapter.getCount(); - for(int i = 0; i < count; i++) { - LocalAuthorItem item = fromAdapter.getItem(i); - if(item == LocalAuthorItem.ANONYMOUS) continue; - if(item == LocalAuthorItem.NEW) continue; - if(item.getLocalAuthor().getId().equals(localAuthorId)) { - localAuthor = item.getLocalAuthor(); - fromSpinner.setSelection(i); - break; - } - } - } - }); - } - - private void loadLocalGroups() { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - Collection<LocalGroup> groups = db.getLocalGroups(); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Loading groups took " + duration + " ms"); - displayLocalGroups(groups); - } catch(DbException e) { - if(LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } catch(InterruptedException e) { - LOG.info("Interrupted while waiting for database"); - Thread.currentThread().interrupt(); - } - } - }); - } - - private void displayLocalGroups(final Collection<LocalGroup> groups) { - runOnUiThread(new Runnable() { - public void run() { - if(groups.isEmpty()) finish(); - toAdapter.clear(); - for(LocalGroup g : groups) toAdapter.add(new LocalGroupItem(g)); - toAdapter.sort(LocalGroupItemComparator.INSTANCE); - toAdapter.notifyDataSetChanged(); - int count = toAdapter.getCount(); - for(int i = 0; i < count; i++) { - LocalGroupItem item = toAdapter.getItem(i); - if(item == LocalGroupItem.NEW) continue; - if(item.getLocalGroup().getId().equals(localGroupId)) { - localGroup = item.getLocalGroup(); - toSpinner.setSelection(i); - break; - } - } - } - }); - } - - @Override - public void onSaveInstanceState(Bundle state) { - super.onSaveInstanceState(state); - if(localAuthorId != null) { - byte[] b = localAuthorId.getBytes(); - state.putByteArray("net.sf.briar.LOCAL_AUTHOR_ID", b); - } - if(localGroupId != null) { - byte[] b = localGroupId.getBytes(); - state.putByteArray("net.sf.briar.LOCAL_GROUP_ID", b); - } - } - - public void onItemSelected(AdapterView<?> parent, View view, int position, - long id) { - if(parent == fromSpinner) { - LocalAuthorItem item = fromAdapter.getItem(position); - if(item == LocalAuthorItem.ANONYMOUS) { - localAuthor = null; - localAuthorId = null; - } else if(item == LocalAuthorItem.NEW) { - localAuthor = null; - localAuthorId = null; - startActivity(new Intent(this, CreateIdentityActivity.class)); - } else { - localAuthor = item.getLocalAuthor(); - localAuthorId = localAuthor.getId(); - } - } else if(parent == toSpinner) { - LocalGroupItem item = toAdapter.getItem(position); - if(item == LocalGroupItem.NEW) { - localGroup = null; - localGroupId = null; - startActivity(new Intent(this, CreateBlogActivity.class)); - } else { - localGroup = item.getLocalGroup(); - localGroupId = localGroup.getId(); - sendButton.setEnabled(true); - } - } - } - - public void onNothingSelected(AdapterView<?> parent) { - if(parent == fromSpinner) { - localAuthor = null; - localAuthorId = null; - } else if(parent == toSpinner) { - localGroup = null; - localGroupId = null; - sendButton.setEnabled(false); - } - } - - public void onClick(View view) { - if(localGroup == null) throw new IllegalStateException(); - try { - byte[] b = content.getText().toString().getBytes("UTF-8"); - storeMessage(createMessage(b)); - } catch(GeneralSecurityException e) { - throw new RuntimeException(e); - } catch(IOException e) { - throw new RuntimeException(e); - } - finish(); - } - - // FIXME: This should happen on a CryptoExecutor thread - private Message createMessage(byte[] body) throws IOException, - GeneralSecurityException { - KeyParser keyParser = crypto.getSignatureKeyParser(); - byte[] groupKeyBytes = localGroup.getPrivateKey(); - PrivateKey groupKey = keyParser.parsePrivateKey(groupKeyBytes); - if(localAuthor == null) { - return messageFactory.createAnonymousMessage(parentId, localGroup, - groupKey, "text/plain", body); - } else { - byte[] authorKeyBytes = localAuthor.getPrivateKey(); - PrivateKey authorKey = keyParser.parsePrivateKey(authorKeyBytes); - return messageFactory.createPseudonymousMessage(parentId, - localGroup, groupKey, localAuthor, authorKey, "text/plain", - body); - } - } - - private void storeMessage(final Message m) { - dbUiExecutor.execute(new Runnable() { - public void run() { - try { - lifecycleManager.waitForDatabase(); - long now = System.currentTimeMillis(); - db.addLocalGroupMessage(m); - long duration = System.currentTimeMillis() - now; - if(LOG.isLoggable(INFO)) - LOG.info("Storing message 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 database"); - Thread.currentThread().interrupt(); - } - } - }); - } -}