diff --git a/briar-android/res/drawable-hdpi/content_read.png b/briar-android/res/drawable-hdpi/content_read.png new file mode 100644 index 0000000000000000000000000000000000000000..5fc1132225399d9dd7dc9511295b7d923cfad0c7 Binary files /dev/null and b/briar-android/res/drawable-hdpi/content_read.png differ diff --git a/briar-android/res/drawable-hdpi/content_unread.png b/briar-android/res/drawable-hdpi/content_unread.png new file mode 100644 index 0000000000000000000000000000000000000000..e5f368257d32b4b7be5d2a2cb6fccc9643783a5e Binary files /dev/null and b/briar-android/res/drawable-hdpi/content_unread.png differ diff --git a/briar-android/res/drawable-mdpi/content_read.png b/briar-android/res/drawable-mdpi/content_read.png new file mode 100644 index 0000000000000000000000000000000000000000..3d61dc5e35867d190dd452c5b86910a8ce349890 Binary files /dev/null and b/briar-android/res/drawable-mdpi/content_read.png differ diff --git a/briar-android/res/drawable-mdpi/content_unread.png b/briar-android/res/drawable-mdpi/content_unread.png new file mode 100644 index 0000000000000000000000000000000000000000..72956c4456bea7d7e6c678b30ebf1304ea9795b6 Binary files /dev/null and b/briar-android/res/drawable-mdpi/content_unread.png differ diff --git a/briar-android/res/drawable-xhdpi/content_read.png b/briar-android/res/drawable-xhdpi/content_read.png new file mode 100644 index 0000000000000000000000000000000000000000..99a826a8d43aad459ddff4f7fd496a022493b0a1 Binary files /dev/null and b/briar-android/res/drawable-xhdpi/content_read.png differ diff --git a/briar-android/res/drawable-xhdpi/content_unread.png b/briar-android/res/drawable-xhdpi/content_unread.png new file mode 100644 index 0000000000000000000000000000000000000000..2e4ddddbd1f576701b7bcebb959c6142a487bbc6 Binary files /dev/null and b/briar-android/res/drawable-xhdpi/content_unread.png differ diff --git a/briar-android/res/values-v11/styles.xml b/briar-android/res/values-v11/styles.xml index f5476f167a1086f597cbf7495a8624d65fac2cc1..aa2dc3fa70a3b32da60868c1d46af2fb811024ce 100644 --- a/briar-android/res/values-v11/styles.xml +++ b/briar-android/res/values-v11/styles.xml @@ -1,4 +1,6 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <style name="LightTheme" parent="android:Theme.Holo.Light" /> + <style name="LightThemeNoActionBar" + parent="android:Theme.Holo.Light.NoActionBar" /> </resources> \ No newline at end of file diff --git a/briar-android/res/values/strings.xml b/briar-android/res/values/strings.xml index df2deb07c7a3308841e6488e1982b9e7a19ae1b0..bb5a5d51d6ccaa962e6b300465f54f4925fb3d63 100644 --- a/briar-android/res/values/strings.xml +++ b/briar-android/res/values/strings.xml @@ -12,7 +12,6 @@ <string name="contact_list_title">Contacts</string> <string name="contact_connected">Connected</string> <string name="contact_last_connected">Last connected <br /> %1$s</string> - <string name="add_contact_button">New Contact</string> <string name="search_button">Search</string> <string name="add_contact_title">Add a Contact</string> <string name="same_network">Briar can add contacts via Wi-Fi or Bluetooth. For security reasons, you must be face-to-face to add someone as a contact. To use Wi-Fi you must both be connected to the same network.</string> @@ -42,6 +41,7 @@ <string name="enter_nickname">Please enter a nickname for this contact:</string> <string name="done_button">Done</string> <string name="messages_title">Messages</string> - <string name="compose_button">New Message</string> + <string name="message_from">From: %1$s</string> <string name="compose_title">New Message</string> + <string name="message_to">To: %1$s</string> </resources> diff --git a/briar-android/res/values/styles.xml b/briar-android/res/values/styles.xml index 7974ea7455171c48a1223c3dde5625189631448a..0b92145119f1cb308ddc3816dfbb03209d899049 100644 --- a/briar-android/res/values/styles.xml +++ b/briar-android/res/values/styles.xml @@ -1,4 +1,5 @@ <?xml version="1.0" encoding="utf-8"?> <resources> <style name="LightTheme" parent="android:Theme.Light" /> + <style name="LightThemeNoActionBar" parent="android:Theme.Light" /> </resources> \ No newline at end of file diff --git a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java index d0d7ace2fd4ff981747460c4ba862834f7c43c0a..6fcea7483b7993b861d794c228cf078c7d9c933b 100644 --- a/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java +++ b/briar-android/src/net/sf/briar/android/contact/ContactListActivity.java @@ -31,7 +31,7 @@ import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; -import android.widget.Button; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; @@ -69,13 +69,10 @@ implements OnClickListener, DatabaseListener, ConnectionListener { list.setOnItemClickListener(adapter); layout.addView(list); - Button addContactButton = new Button(this); + ImageButton addContactButton = new ImageButton(this); + addContactButton.setPadding(5, 5, 5, 5); addContactButton.setBackgroundResource(0); - addContactButton.setLayoutParams(new LayoutParams(MATCH_PARENT, - WRAP_CONTENT)); - addContactButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.social_add_person, 0, 0); - addContactButton.setText(R.string.add_contact_button); + addContactButton.setImageResource(R.drawable.social_add_person); addContactButton.setOnClickListener(this); layout.addView(addContactButton); diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java index f178060fda377a80bceb642c1237064da6f22fe7..f290dbc2d8d1697243dfd3a5604774951fba22bf 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationActivity.java @@ -7,7 +7,10 @@ import static android.widget.LinearLayout.VERTICAL; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; +import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -30,7 +33,7 @@ import android.view.View; import android.view.View.OnClickListener; import android.widget.AdapterView; import android.widget.AdapterView.OnItemClickListener; -import android.widget.Button; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; @@ -49,22 +52,21 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { @Inject private DatabaseComponent db; @Inject @DatabaseExecutor private Executor dbExecutor; + private ContactId contactId = null; + private String contactName = null; private ConversationAdapter adapter = null; private ListView list = null; - private String contactName = null; - private volatile ContactId contactId = null; @Override public void onCreate(Bundle state) { super.onCreate(null); Intent i = getIntent(); - contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); - if(contactName == null) throw new IllegalStateException(); - setTitle(contactName); int id = i.getIntExtra("net.sf.briar.CONTACT_ID", -1); if(id == -1) throw new IllegalStateException(); contactId = new ContactId(id); + contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); + if(contactName == null) throw new IllegalStateException(); LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(new LayoutParams(MATCH_PARENT, MATCH_PARENT)); @@ -79,13 +81,10 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { list.setOnItemClickListener(this); layout.addView(list); - Button composeButton = new Button(this); + ImageButton composeButton = new ImageButton(this); + composeButton.setPadding(5, 5, 5, 5); composeButton.setBackgroundResource(0); - composeButton.setLayoutParams(new LayoutParams(MATCH_PARENT, - WRAP_CONTENT)); - composeButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.content_new_email, 0, 0); - composeButton.setText(R.string.compose_button); + composeButton.setImageResource(R.drawable.content_new_email); composeButton.setOnClickListener(this); layout.addView(composeButton); @@ -122,6 +121,7 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { } private void reloadMessageHeaders() { + final ContactId contactId = this.contactId; dbExecutor.execute(new Runnable() { public void run() { try { @@ -146,18 +146,19 @@ implements DatabaseListener, OnClickListener, OnItemClickListener { }); } - private void updateConversation( - final Collection<PrivateMessageHeader> headers) { + private void updateConversation(Collection<PrivateMessageHeader> headers) { + final List<PrivateMessageHeader> sort = + new ArrayList<PrivateMessageHeader>(headers); + Collections.sort(sort, AscendingHeaderComparator.INSTANCE); runOnUiThread(new Runnable() { public void run() { int firstUnread = -1; adapter.clear(); - for(PrivateMessageHeader h : headers) { + for(PrivateMessageHeader h : sort) { if(firstUnread == -1 && !h.isRead()) firstUnread = adapter.getCount(); adapter.add(h); } - adapter.sort(AscendingHeaderComparator.INSTANCE); if(firstUnread == -1) list.setSelection(adapter.getCount() - 1); else list.setSelection(firstUnread); } diff --git a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java index ba5b3c661d25d82aff2b1b738777732c423e14db..32b8e73b17048f6a3961310c63e8e069d3057f47 100644 --- a/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ConversationListActivity.java @@ -37,7 +37,7 @@ import android.content.Intent; import android.os.Bundle; import android.view.View; import android.view.View.OnClickListener; -import android.widget.Button; +import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; import android.widget.ListView; @@ -75,13 +75,10 @@ implements OnClickListener, DatabaseListener { list.setOnItemClickListener(adapter); layout.addView(list); - Button composeButton = new Button(this); + ImageButton composeButton = new ImageButton(this); + composeButton.setPadding(5, 5, 5, 5); composeButton.setBackgroundResource(0); - composeButton.setLayoutParams(new LayoutParams(MATCH_PARENT, - WRAP_CONTENT)); - composeButton.setCompoundDrawablesWithIntrinsicBounds(0, - R.drawable.content_new_email, 0, 0); - composeButton.setText(R.string.compose_button); + composeButton.setImageResource(R.drawable.content_new_email); composeButton.setOnClickListener(this); layout.addView(composeButton); @@ -110,7 +107,14 @@ implements OnClickListener, DatabaseListener { ContactId contactId = db.addContact("Carol"); // Insert some text messages to and from the contact for(int i = 0; i < 20; i++) { - String body = "Message " + i + " is short"; + String body; + if(i % 3 == 0) { + body = "Message " + i + " is short."; + } else { + body = "Message " + i + " is long enough to" + + " wrap onto a second line on some" + + " screens."; + } Message m = messageFactory.createPrivateMessage( null, "text/plain", body.getBytes("UTF-8")); if(Math.random() < 0.5) diff --git a/briar-android/src/net/sf/briar/android/messages/ReadMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/ReadMessageActivity.java index e998249754d8205e6b36c5911852e6e8cd951298..c862c978c082586a366fdb374a65413660901bb8 100644 --- a/briar-android/src/net/sf/briar/android/messages/ReadMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/ReadMessageActivity.java @@ -1,7 +1,7 @@ package net.sf.briar.android.messages; +import static android.view.Gravity.CENTER; import static android.view.Gravity.CENTER_VERTICAL; -import static android.view.Gravity.RIGHT; import static android.view.ViewGroup.LayoutParams.MATCH_PARENT; import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT; import static android.widget.LinearLayout.HORIZONTAL; @@ -19,6 +19,7 @@ import net.sf.briar.android.BriarActivity; import net.sf.briar.android.BriarService; import net.sf.briar.android.BriarService.BriarServiceConnection; import net.sf.briar.api.ContactId; +import net.sf.briar.api.android.BundleEncrypter; import net.sf.briar.api.db.DatabaseComponent; import net.sf.briar.api.db.DatabaseExecutor; import net.sf.briar.api.db.DbException; @@ -45,14 +46,16 @@ implements OnClickListener { private final BriarServiceConnection serviceConnection = new BriarServiceConnection(); + @Inject private BundleEncrypter bundleEncrypter; @Inject private DatabaseComponent db; @Inject @DatabaseExecutor private Executor dbExecutor; private ContactId contactId = null; private String contactName = null; private MessageId messageId = null; - private boolean starred = false; - private ImageButton starButton = null, replyButton = null; + private boolean starred, read; + private ImageButton replyButton = null, starButton = null; + private ImageButton readButton = null; private TextView content = null; @Override @@ -65,7 +68,6 @@ implements OnClickListener { contactId = new ContactId(cid); contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); if(contactName == null) throw new IllegalStateException(); - setTitle(contactName); byte[] mid = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); if(mid == null) throw new IllegalStateException(); messageId = new MessageId(mid); @@ -73,52 +75,108 @@ implements OnClickListener { if(contentType == null) throw new IllegalStateException(); long timestamp = i.getLongExtra("net.sf.briar.TIMESTAMP", -1); if(timestamp == -1) throw new IllegalStateException(); - starred = i.getBooleanExtra("net.sf.briar.STARRED", false); + + if(state != null && bundleEncrypter.decrypt(state)) { + starred = state.getBoolean("net.sf.briar.STARRED"); + read = state.getBoolean("net.sf.briar.READ"); + } else { + starred = i.getBooleanExtra("net.sf.briar.STARRED", false); + read = false; + final MessageId id = messageId; + dbExecutor.execute(new Runnable() { + public void run() { + try { + serviceConnection.waitForStartup(); + db.setReadFlag(id, true); + runOnUiThread(new Runnable() { + public void run() { + setRead(true); + } + }); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); + } + } + }); + } LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); layout.setOrientation(VERTICAL); + ScrollView scrollView = new ScrollView(this); + // Give me all the width and all the unused height + scrollView.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT, + 1)); + + LinearLayout message = new LinearLayout(this); + message.setOrientation(VERTICAL); + LinearLayout header = new LinearLayout(this); header.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); header.setOrientation(HORIZONTAL); header.setGravity(CENTER_VERTICAL); - starButton = new ImageButton(this); - starButton.setPadding(5, 5, 5, 5); - starButton.setBackgroundResource(0); - if(starred) starButton.setImageResource(R.drawable.rating_important); - else starButton.setImageResource(R.drawable.rating_not_important); - starButton.setOnClickListener(this); - header.addView(starButton); - - replyButton = new ImageButton(this); - replyButton.setPadding(5, 5, 5, 5); - replyButton.setBackgroundResource(0); - replyButton.setImageResource(R.drawable.social_reply); - replyButton.setOnClickListener(this); - header.addView(replyButton); + TextView name = new TextView(this); + // Give me all the unused width + name.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1)); + name.setTextSize(18); + name.setPadding(10, 0, 0, 0); + String format = getResources().getString(R.string.message_from); + name.setText(String.format(format, contactName)); + header.addView(name); TextView date = new TextView(this); - // Give me all the unused width - date.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1)); date.setTextSize(14); - date.setPadding(10, 0, 10, 0); - date.setGravity(RIGHT); + date.setPadding(0, 0, 10, 0); long now = System.currentTimeMillis(); date.setText(DateUtils.formatSameDayTime(timestamp, now, SHORT, SHORT)); header.addView(date); - layout.addView(header); + message.addView(header); if(contentType.equals("text/plain")) { // Load and display the message body - ScrollView scrollView = new ScrollView(this); content = new TextView(this); content.setPadding(10, 10, 10, 10); - scrollView.addView(content); - layout.addView(scrollView); + message.addView(content); loadMessageBody(); } + scrollView.addView(message); + layout.addView(scrollView); + + LinearLayout footer = new LinearLayout(this); + footer.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + footer.setOrientation(HORIZONTAL); + footer.setGravity(CENTER); + + replyButton = new ImageButton(this); + replyButton.setPadding(5, 5, 5, 5); + replyButton.setBackgroundResource(0); + replyButton.setImageResource(R.drawable.social_reply); + replyButton.setOnClickListener(this); + footer.addView(replyButton); + layout.addView(footer); + + starButton = new ImageButton(this); + starButton.setPadding(5, 5, 5, 5); + starButton.setBackgroundResource(0); + if(starred) starButton.setImageResource(R.drawable.rating_important); + else starButton.setImageResource(R.drawable.rating_not_important); + starButton.setOnClickListener(this); + footer.addView(starButton); + + readButton = new ImageButton(this); + readButton.setPadding(5, 5, 5, 5); + readButton.setBackgroundResource(0); + if(read) readButton.setImageResource(R.drawable.content_unread); + else readButton.setImageResource(R.drawable.content_read); + readButton.setOnClickListener(this); + footer.addView(readButton); setContentView(layout); @@ -133,12 +191,9 @@ implements OnClickListener { dbExecutor.execute(new Runnable() { public void run() { try { - // Wait for the service to be bound and started serviceConnection.waitForStartup(); - // Load the message body from the database byte[] body = db.getMessageBody(messageId); final String text = new String(body, "UTF-8"); - // Display the message body runOnUiThread(new Runnable() { public void run() { content.setText(text); @@ -159,26 +214,10 @@ implements OnClickListener { } @Override - public void onResume() { - super.onResume(); - final MessageId id = messageId; - dbExecutor.execute(new Runnable() { - public void run() { - try { - // Wait for the service to be bound and started - serviceConnection.waitForStartup(); - // Mark the message as read - db.setReadFlag(id, true); - } catch(DbException e) { - if(LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } catch(InterruptedException e) { - if(LOG.isLoggable(INFO)) - LOG.info("Interrupted while waiting for service"); - Thread.currentThread().interrupt(); - } - } - }); + public void onSaveInstanceState(Bundle state) { + state.putBoolean("net.sf.briar.STARRED", starred); + state.putBoolean("net.sf.briar.READ", read); + bundleEncrypter.encrypt(state); } @Override @@ -188,29 +227,71 @@ implements OnClickListener { } public void onClick(View view) { - if(view == starButton) { - final MessageId id = messageId; - final boolean starredNow = !starred; + if(view == replyButton) { + Intent i = new Intent(this, WriteMessageActivity.class); + i.putExtra("net.sf.briar.CONTACT_ID", contactId.getInt()); + i.putExtra("net.sf.briar.CONTACT_NAME", contactName); + i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes()); + startActivity(i); + finish(); + } else if(view == starButton) { + final MessageId messageId = this.messageId; + final boolean starred = !this.starred; dbExecutor.execute(new Runnable() { public void run() { try { - db.setStarredFlag(id, starredNow); + serviceConnection.waitForStartup(); + db.setStarredFlag(messageId, starred); + runOnUiThread(new Runnable() { + public void run() { + setStarred(starred); + } + }); } catch(DbException e) { if(LOG.isLoggable(WARNING)) LOG.log(WARNING, e.toString(), e); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); + } + } + }); + } else if(view == readButton) { + final MessageId messageId = this.messageId; + final boolean read = !this.read; + dbExecutor.execute(new Runnable() { + public void run() { + try { + serviceConnection.waitForStartup(); + db.setReadFlag(messageId, read); + runOnUiThread(new Runnable() { + public void run() { + setRead(read); + } + }); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); } } }); - starred = starredNow; - if(starred) - starButton.setImageResource(R.drawable.rating_important); - else starButton.setImageResource(R.drawable.rating_not_important); - } else if(view == replyButton) { - Intent i = new Intent(this, WriteMessageActivity.class); - i.putExtra("net.sf.briar.CONTACT_ID", contactId.getInt()); - i.putExtra("net.sf.briar.CONTACT_NAME", contactName); - i.putExtra("net.sf.briar.PARENT_ID", messageId.getBytes()); - startActivity(i); } } + + private void setStarred(boolean starred) { + this.starred = starred; + if(starred) starButton.setImageResource(R.drawable.rating_important); + else starButton.setImageResource(R.drawable.rating_not_important); + } + + private void setRead(boolean read) { + this.read = read; + if(read) readButton.setImageResource(R.drawable.content_unread); + else readButton.setImageResource(R.drawable.content_read); + } } diff --git a/briar-android/src/net/sf/briar/android/messages/WriteMessageActivity.java b/briar-android/src/net/sf/briar/android/messages/WriteMessageActivity.java index 92d0dbfdfffb19e1845e226a7f3ee7246bf14767..078541da89c12bf41449eec57febc506d9a9dd8d 100644 --- a/briar-android/src/net/sf/briar/android/messages/WriteMessageActivity.java +++ b/briar-android/src/net/sf/briar/android/messages/WriteMessageActivity.java @@ -9,7 +9,6 @@ import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; import java.io.IOException; -import java.io.UnsupportedEncodingException; import java.security.GeneralSecurityException; import java.util.concurrent.Executor; import java.util.logging.Logger; @@ -35,7 +34,7 @@ import android.widget.EditText; import android.widget.ImageButton; import android.widget.LinearLayout; import android.widget.LinearLayout.LayoutParams; -import android.widget.ScrollView; +import android.widget.TextView; import com.google.inject.Inject; @@ -56,7 +55,6 @@ implements OnClickListener { private ContactId contactId = null; private String contactName = null; private MessageId parentId = null; - private ImageButton cancelButton = null, sendButton = null; private EditText content = null; @Override @@ -69,42 +67,42 @@ implements OnClickListener { contactId = new ContactId(cid); contactName = i.getStringExtra("net.sf.briar.CONTACT_NAME"); if(contactName == null) throw new IllegalStateException(); - byte[] pid = i.getByteArrayExtra("net.sf.briar.MESSAGE_ID"); + byte[] pid = i.getByteArrayExtra("net.sf.briar.PARENT_ID"); if(pid != null) parentId = new MessageId(pid); LinearLayout layout = new LinearLayout(this); layout.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); layout.setOrientation(VERTICAL); - LinearLayout header = new LinearLayout(this); - header.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); - header.setOrientation(HORIZONTAL); - header.setGravity(CENTER_VERTICAL); - - cancelButton = new ImageButton(this); - cancelButton.setPadding(5, 5, 5, 5); - cancelButton.setBackgroundResource(0); - cancelButton.setImageResource(R.drawable.navigation_cancel); - cancelButton.setOnClickListener(this); - header.addView(cancelButton); - - sendButton = new ImageButton(this); + LinearLayout actionBar = new LinearLayout(this); + actionBar.setLayoutParams(new LayoutParams(MATCH_PARENT, WRAP_CONTENT)); + actionBar.setOrientation(HORIZONTAL); + actionBar.setGravity(CENTER_VERTICAL); + + TextView to = new TextView(this); + // Give me all the unused width + to.setLayoutParams(new LayoutParams(WRAP_CONTENT, WRAP_CONTENT, 1)); + to.setPadding(10, 0, 0, 0); + to.setTextSize(18); + String format = getResources().getString(R.string.message_to); + to.setText(String.format(format, contactName)); + actionBar.addView(to); + + ImageButton sendButton = new ImageButton(this); sendButton.setPadding(5, 5, 5, 5); sendButton.setBackgroundResource(0); sendButton.setImageResource(R.drawable.social_send_now); sendButton.setOnClickListener(this); - header.addView(sendButton); - layout.addView(header); + actionBar.addView(sendButton); + layout.addView(actionBar); - ScrollView scrollView = new ScrollView(this); content = new EditText(this); content.setPadding(10, 10, 10, 10); if(state != null && bundleEncrypter.decrypt(state)) { Parcelable p = state.getParcelable("net.sf.briar.CONTENT"); if(p != null) content.onRestoreInstanceState(p); } - scrollView.addView(content); - layout.addView(scrollView); + layout.addView(content); setContentView(layout); @@ -127,38 +125,32 @@ implements OnClickListener { } public void onClick(View view) { - if(view == cancelButton) { - finish(); - } else if(view == sendButton) { - final Message m; - try { - byte[] body = content.getText().toString().getBytes("UTF-8"); - m = messageFactory.createPrivateMessage(parentId, - "text/plain", body); - } catch(UnsupportedEncodingException e) { - throw new RuntimeException(e); - } catch(IOException e) { - throw new RuntimeException(e); - } catch(GeneralSecurityException e) { - throw new RuntimeException(e); - } - final ContactId contactId = this.contactId; - dbExecutor.execute(new Runnable() { - public void run() { - try { - serviceConnection.waitForStartup(); - db.addLocalPrivateMessage(m, contactId); - } catch(DbException e) { - if(LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } catch(InterruptedException e) { - if(LOG.isLoggable(INFO)) - LOG.info("Interrupted while waiting for service"); - Thread.currentThread().interrupt(); - } - } - }); - finish(); + final Message m; + try { + byte[] body = content.getText().toString().getBytes("UTF-8"); + m = messageFactory.createPrivateMessage(parentId, "text/plain", + body); + } catch(IOException e) { + throw new RuntimeException(e); + } catch(GeneralSecurityException e) { + throw new RuntimeException(e); } + final ContactId contactId = this.contactId; + dbExecutor.execute(new Runnable() { + public void run() { + try { + serviceConnection.waitForStartup(); + db.addLocalPrivateMessage(m, contactId); + } catch(DbException e) { + if(LOG.isLoggable(WARNING)) + LOG.log(WARNING, e.toString(), e); + } catch(InterruptedException e) { + if(LOG.isLoggable(INFO)) + LOG.info("Interrupted while waiting for service"); + Thread.currentThread().interrupt(); + } + } + }); + finish(); } }