diff --git a/briar-android/AndroidManifest.xml b/briar-android/AndroidManifest.xml index 18b68762941190ca4fd64fa65ec023047cd0a2b3..476229541dce9930b1f0b791d91df133d86c4b6c 100644 --- a/briar-android/AndroidManifest.xml +++ b/briar-android/AndroidManifest.xml @@ -105,25 +105,6 @@ android:value=".android.contact.ContactListActivity" /> </activity> - <activity - android:name=".android.contact.ReadPrivateMessageActivity" - android:label="@string/app_name" - android:parentActivityName=".android.contact.ContactListActivity" > - <meta-data - android:name="android.support.PARENT_ACTIVITY" - android:value=".android.contact.ContactListActivity" - /> - </activity> - <activity - android:name=".android.contact.WritePrivateMessageActivity" - android:label="@string/app_name" - android:windowSoftInputMode="stateVisible" - android:parentActivityName=".android.contact.ContactListActivity" > - <meta-data - android:name="android.support.PARENT_ACTIVITY" - android:value=".android.contact.ContactListActivity" - /> - </activity> <activity android:name=".android.forum.AvailableForumsActivity" android:label="@string/available_forums_title" diff --git a/briar-android/res/layout/activity_password.xml b/briar-android/res/layout/activity_password.xml index bda170a9432446c6bf6394e5c19a5f1650ffac6a..d69ff185fa6a1a84911fe800b6a9f45891e1706a 100644 --- a/briar-android/res/layout/activity_password.xml +++ b/briar-android/res/layout/activity_password.xml @@ -40,7 +40,6 @@ android:imeOptions="actionDone" android:inputType="textPassword" android:maxLines="1" /> - </android.support.design.widget.TextInputLayout> <Button @@ -61,7 +60,6 @@ android:layout_alignTop="@id/btn_sign_in" android:layout_alignBottom="@id/btn_sign_in" android:layout_centerHorizontal="true" - android:gravity="center" android:visibility="invisible" /> <TextView diff --git a/briar-android/res/layout/activity_setup.xml b/briar-android/res/layout/activity_setup.xml index d5ec69ba6828ffcc77f2c5a7d0a309e364300743..ec3678cef4d35c70df522a72c548999af4c5c4c4 100644 --- a/briar-android/res/layout/activity_setup.xml +++ b/briar-android/res/layout/activity_setup.xml @@ -5,10 +5,9 @@ android:layout_width="match_parent" android:layout_height="match_parent"> - <LinearLayout + <RelativeLayout android:layout_width="match_parent" android:layout_height="wrap_content" - android:gravity="center_horizontal" android:orientation="vertical" android:paddingBottom="@dimen/margin_activity_vertical" android:paddingEnd="@dimen/margin_activity_horizontal" @@ -18,9 +17,11 @@ android:paddingTop="@dimen/margin_activity_vertical"> <TextView + android:id="@+id/nickname_title" + style="@style/BriarTextTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="center" + android:layout_centerHorizontal="true" android:text="@string/choose_nickname" android:textSize="@dimen/text_size_medium"/> @@ -28,6 +29,8 @@ android:id="@+id/nickname_entry_wrapper" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_below="@id/nickname_title" app:errorEnabled="true"> <EditText @@ -39,9 +42,12 @@ </android.support.design.widget.TextInputLayout> <TextView + android:id="@+id/password_title" + style="@style/BriarTextTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="center" + android:layout_centerHorizontal="true" + android:layout_below="@id/nickname_entry_wrapper" android:text="@string/choose_password" android:textSize="@dimen/text_size_medium"/> @@ -49,6 +55,8 @@ android:id="@+id/password_entry_wrapper" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_below="@id/password_title" app:errorEnabled="true"> <EditText @@ -60,9 +68,12 @@ </android.support.design.widget.TextInputLayout> <TextView + android:id="@+id/password_confirm_title" + style="@style/BriarTextTitle" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:gravity="center" + android:layout_centerHorizontal="true" + android:layout_below="@id/password_entry_wrapper" android:text="@string/confirm_password" android:textSize="@dimen/text_size_medium"/> @@ -70,6 +81,8 @@ android:id="@+id/password_confirm_wrapper" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_below="@id/password_confirm_title" app:errorEnabled="true"> <EditText @@ -85,20 +98,31 @@ android:id="@+id/strength_meter" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_below="@id/password_confirm_wrapper" android:visibility="invisible"/> <Button android:id="@+id/create_account" + style="@style/BriarButton.Default" android:layout_width="match_parent" android:layout_height="wrap_content" + android:layout_centerHorizontal="true" + android:layout_below="@id/strength_meter" + android:layout_marginTop="@dimen/margin_medium" android:enabled="false" android:text="@string/create_account_button"/> <ProgressBar android:id="@+id/progress_wheel" + style="?android:attr/progressBarStyleInverse" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:indeterminate="true" - android:visibility="gone"/> - </LinearLayout> + android:layout_alignTop="@id/create_account" + android:layout_alignBottom="@id/create_account" + android:layout_centerHorizontal="true" + android:visibility="invisible" /> + + </RelativeLayout> + </ScrollView> \ No newline at end of file diff --git a/briar-android/src/org/briarproject/android/BaseActivity.java b/briar-android/src/org/briarproject/android/BaseActivity.java index a36252747158257bfb15dc3144089c7b878c2fbe..138d3447ad744eacb2bd36b3424d56dcbc70fc4a 100644 --- a/briar-android/src/org/briarproject/android/BaseActivity.java +++ b/briar-android/src/org/briarproject/android/BaseActivity.java @@ -4,6 +4,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.content.res.Configuration; import android.os.Bundle; +import android.os.IBinder; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.view.inputmethod.InputMethodManager; @@ -31,7 +32,6 @@ import roboguice.inject.RoboInjector; import roboguice.util.RoboContext; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; -import static android.view.inputmethod.InputMethodManager.HIDE_IMPLICIT_ONLY; import static android.view.inputmethod.InputMethodManager.SHOW_IMPLICIT; import static org.briarproject.android.TestingConstants.PREVENT_SCREENSHOTS; @@ -39,7 +39,7 @@ public abstract class BaseActivity extends AppCompatActivity implements RoboContext { private final static String PREFS_DB = "db"; - private final static String KEY_DB_KEY = "key"; + private final static String PREFS_KEY = "key"; private final HashMap<Key<?>, Object> scopedObjects = new HashMap<Key<?>, Object>(); @@ -128,38 +128,24 @@ public abstract class BaseActivity extends AppCompatActivity return scopedObjects; } - private SharedPreferences getBriarPrefs(String prefsName) { - return getSharedPreferences(prefsName, MODE_PRIVATE); + private SharedPreferences getSharedPrefs() { + return getSharedPreferences(PREFS_DB, MODE_PRIVATE); } - protected String getDbKeyInHex() { - return getBriarPrefs(PREFS_DB).getString(KEY_DB_KEY, null); + protected String getEncryptedDatabaseKey() { + return getSharedPrefs().getString(PREFS_KEY, null); } - private void clearPrefs(String prefsName) { - SharedPreferences.Editor editor = getBriarPrefs(prefsName).edit(); - editor.clear(); + protected void storeEncryptedDatabaseKey(final String hex) { + SharedPreferences.Editor editor = getSharedPrefs().edit(); + editor.putString(PREFS_KEY, hex); editor.apply(); } - protected void clearDbPrefs() { - clearPrefs(PREFS_DB); - } - - protected void gotoAndFinish(Class classInstance, int resultCode) { - if (resultCode != Integer.MIN_VALUE) - setResult(resultCode); - startActivity(new Intent(this, classInstance)); - finish(); - } - - protected void gotoAndFinish(Class classInstance) { - gotoAndFinish(classInstance, Integer.MIN_VALUE); - } - - protected void toggleSoftKeyboard() { - Object o = getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).toggleSoftInput(HIDE_IMPLICIT_ONLY, 0); + protected void clearSharedPrefs() { + SharedPreferences.Editor editor = getSharedPrefs().edit(); + editor.clear(); + editor.apply(); } protected void showSoftKeyboard(View view) { @@ -168,8 +154,8 @@ public abstract class BaseActivity extends AppCompatActivity } protected void hideSoftKeyboard(View view) { + IBinder token = view.getWindowToken(); Object o = getSystemService(INPUT_METHOD_SERVICE); - ((InputMethodManager) o).hideSoftInputFromWindow(view.getWindowToken(), - 0); + ((InputMethodManager) o).hideSoftInputFromWindow(token, 0); } } diff --git a/briar-android/src/org/briarproject/android/PasswordActivity.java b/briar-android/src/org/briarproject/android/PasswordActivity.java index 353cb0953623da46f5e70557db19c9b60c0c191d..a1f06a3ea4201bd60bf5637d16ef95f021afe314 100644 --- a/briar-android/src/org/briarproject/android/PasswordActivity.java +++ b/briar-android/src/org/briarproject/android/PasswordActivity.java @@ -38,7 +38,6 @@ public class PasswordActivity extends BaseActivity { @Inject @CryptoExecutor private Executor cryptoExecutor; private Button signInButton; private ProgressBar progress; - private TextView title; private TextInputLayout input; private EditText password; @@ -52,9 +51,9 @@ public class PasswordActivity extends BaseActivity { public void onCreate(Bundle state) { super.onCreate(state); - String hex = getDbKeyInHex(); + String hex = getEncryptedDatabaseKey(); if (hex == null || !databaseConfig.databaseExists()) { - clearDbPrefs(); + clearSharedPrefsAndDeleteDatabase(); return; } encrypted = StringUtils.fromHexString(hex); @@ -62,7 +61,6 @@ public class PasswordActivity extends BaseActivity { setContentView(R.layout.activity_password); signInButton = (Button) findViewById(R.id.btn_sign_in); progress = (ProgressBar) findViewById(R.id.progress_wheel); - title = (TextView) findViewById(R.id.title_password); input = (TextInputLayout) findViewById(R.id.password_layout); password = (EditText) findViewById(R.id.edit_password); password.setOnEditorActionListener(new OnEditorActionListener() { @@ -98,11 +96,12 @@ public class PasswordActivity extends BaseActivity { startActivity(intent); } - @Override - protected void clearDbPrefs() { - super.clearDbPrefs(); + private void clearSharedPrefsAndDeleteDatabase() { + clearSharedPrefs(); FileUtils.deleteFileOrDir(databaseConfig.getDatabaseDirectory()); - gotoAndFinish(SetupActivity.class, RESULT_CANCELED); + setResult(RESULT_CANCELED); + startActivity(new Intent(this, SetupActivity.class)); + finish(); } public void onSignInClick(View v) { @@ -115,12 +114,13 @@ public class PasswordActivity extends BaseActivity { builder.setTitle(R.string.dialog_title_lost_password); builder.setMessage(R.string.dialog_message_lost_password); builder.setNegativeButton(R.string.no, null); - builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - clearDbPrefs(); - } - }); + builder.setPositiveButton(R.string.yes, + new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + clearSharedPrefsAndDeleteDatabase(); + } + }); AlertDialog dialog = builder.create(); dialog.show(); } diff --git a/briar-android/src/org/briarproject/android/SetupActivity.java b/briar-android/src/org/briarproject/android/SetupActivity.java index 380792bf187b7c92294b2aca0d01e7a9d97bd0eb..237dca1f8f5fc9b059838718caa56c6469b314b2 100644 --- a/briar-android/src/org/briarproject/android/SetupActivity.java +++ b/briar-android/src/org/briarproject/android/SetupActivity.java @@ -1,8 +1,6 @@ package org.briarproject.android; import android.content.Intent; -import android.content.SharedPreferences; -import android.content.SharedPreferences.Editor; import android.os.Bundle; import android.support.design.widget.TextInputLayout; import android.text.Editable; @@ -38,7 +36,6 @@ import javax.inject.Inject; import roboguice.inject.InjectView; import static android.content.Intent.FLAG_ACTIVITY_NEW_TASK; -import static android.view.View.GONE; import static android.view.View.INVISIBLE; import static android.view.View.VISIBLE; import static android.view.WindowManager.LayoutParams.FLAG_SECURE; @@ -134,8 +131,8 @@ public class SetupActivity extends BaseActivity implements OnClickListener, } public void onClick(View view) { - // Replace the feedback text and button with a progress bar - createAccountButton.setVisibility(GONE); + // Replace the button with a progress bar + createAccountButton.setVisibility(INVISIBLE); progress.setVisibility(VISIBLE); final String nickname = nicknameEntry.getText().toString(); final String password = passwordEntry.getText().toString(); @@ -144,8 +141,8 @@ public class SetupActivity extends BaseActivity implements OnClickListener, public void run() { SecretKey key = crypto.generateSecretKey(); databaseConfig.setEncryptionKey(key); - byte[] encrypted = encryptDatabaseKey(key, password); - storeEncryptedDatabaseKey(encrypted); + String hex = encryptDatabaseKey(key, password); + storeEncryptedDatabaseKey(hex); LocalAuthor localAuthor = createLocalAuthor(nickname); showDashboard(referenceManager.putReference(localAuthor, LocalAuthor.class)); @@ -153,24 +150,13 @@ public class SetupActivity extends BaseActivity implements OnClickListener, }); } - private void storeEncryptedDatabaseKey(final byte[] encrypted) { - long now = System.currentTimeMillis(); - SharedPreferences prefs = getSharedPreferences("db", MODE_PRIVATE); - Editor editor = prefs.edit(); - editor.putString("key", StringUtils.toHexString(encrypted)); - editor.commit(); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Key storage took " + duration + " ms"); - } - - private byte[] encryptDatabaseKey(SecretKey key, String password) { + private String encryptDatabaseKey(SecretKey key, String password) { long now = System.currentTimeMillis(); byte[] encrypted = crypto.encryptWithPassword(key.getBytes(), password); long duration = System.currentTimeMillis() - now; if (LOG.isLoggable(INFO)) LOG.info("Key derivation took " + duration + " ms"); - return encrypted; + return StringUtils.toHexString(encrypted); } private LocalAuthor createLocalAuthor(String nickname) { diff --git a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java index e50540bc2982039a166cd8eb11c5f41608d46c6d..4b79ce4389c2e29951ba8b05f10b055fcab7c2f7 100644 --- a/briar-android/src/org/briarproject/android/contact/ConversationActivity.java +++ b/briar-android/src/org/briarproject/android/contact/ConversationActivity.java @@ -37,7 +37,6 @@ import org.briarproject.api.event.EventListener; import org.briarproject.api.event.MessageAddedEvent; import org.briarproject.api.event.MessagesAckedEvent; import org.briarproject.api.event.MessagesSentEvent; -import org.briarproject.api.identity.AuthorId; import org.briarproject.api.messaging.MessagingManager; import org.briarproject.api.messaging.PrivateConversation; import org.briarproject.api.messaging.PrivateMessageFactory; @@ -67,14 +66,12 @@ import javax.inject.Inject; import static android.widget.Toast.LENGTH_SHORT; import static java.util.logging.Level.INFO; import static java.util.logging.Level.WARNING; -import static org.briarproject.android.contact.ReadPrivateMessageActivity.RESULT_PREV_NEXT; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.DELIVERED; import static org.briarproject.api.messaging.PrivateMessageHeader.Status.SENT; public class ConversationActivity extends BriarActivity implements EventListener, OnClickListener { - private static final int REQUEST_READ = 2; private static final Logger LOG = Logger.getLogger(ConversationActivity.class.getName()); @@ -96,7 +93,6 @@ public class ConversationActivity extends BriarActivity private volatile String contactName = null; private volatile GroupId groupId = null; private volatile PrivateConversation conversation = null; - private volatile AuthorId localAuthorId = null; private volatile boolean connected; @Override @@ -108,10 +104,6 @@ public class ConversationActivity extends BriarActivity if (id == -1) throw new IllegalStateException(); contactId = new ContactId(id); - Intent data = new Intent(); - data.putExtra("briar.CONTACT_ID", id); - setResult(RESULT_OK, data); - setContentView(R.layout.activity_conversation); adapter = new ConversationAdapter(this); @@ -141,23 +133,13 @@ public class ConversationActivity extends BriarActivity if (isFinishing()) markMessagesRead(); } - @Override - protected void onActivityResult(int request, int result, Intent data) { - super.onActivityResult(request, result, data); - if (request == REQUEST_READ && result == RESULT_PREV_NEXT) { - int position = data.getIntExtra("briar.POSITION", -1); - if (position >= 0 && position < adapter.getItemCount()) - displayMessage(position); - } - } - @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu items for use in the action bar MenuInflater inflater = getMenuInflater(); inflater.inflate(R.menu.contact_actions, menu); - // adapt icon color to dark action bar + // Adapt icon color to dark action bar menu.findItem(R.id.action_social_remove_person).getIcon().setColorFilter( getResources().getColor(R.color.action_bar_text), PorterDuff.Mode.SRC_IN); @@ -171,7 +153,6 @@ public class ConversationActivity extends BriarActivity switch (item.getItemId()) { case R.id.action_social_remove_person: askToRemoveContact(); - return true; default: return super.onOptionsItemSelected(item); @@ -185,7 +166,6 @@ public class ConversationActivity extends BriarActivity long now = System.currentTimeMillis(); Contact contact = contactManager.getContact(contactId); contactName = contact.getAuthor().getName(); - localAuthorId = contact.getLocalAuthorId(); groupId = messagingManager.getConversationId(contactId); conversation = messagingManager.getConversation(groupId); connected = connectionRegistry.isConnected(contactId); @@ -458,23 +438,6 @@ public class ConversationActivity extends BriarActivity }); } - private void displayMessage(int position) { - ConversationItem item = adapter.getItem(position); - PrivateMessageHeader header = item.getHeader(); - Intent i = new Intent(this, ReadPrivateMessageActivity.class); - i.putExtra("briar.CONTACT_ID", contactId.getInt()); - i.putExtra("briar.CONTACT_NAME", contactName); - i.putExtra("briar.GROUP_ID", groupId.getBytes()); - i.putExtra("briar.LOCAL_AUTHOR_ID", localAuthorId.getBytes()); - i.putExtra("briar.AUTHOR_NAME", header.getAuthor().getName()); - i.putExtra("briar.MESSAGE_ID", header.getId().getBytes()); - i.putExtra("briar.CONTENT_TYPE", header.getContentType()); - i.putExtra("briar.TIMESTAMP", header.getTimestamp()); - i.putExtra("briar.MIN_TIMESTAMP", getMinTimestampForNewMessage()); - i.putExtra("briar.POSITION", position); - startActivityForResult(i, REQUEST_READ); - } - private void askToRemoveContact() { runOnUiThread(new Runnable() { @Override @@ -523,10 +486,8 @@ public class ConversationActivity extends BriarActivity String deleted = getString(R.string.contact_deleted_toast); Toast.makeText(ConversationActivity.this, deleted, LENGTH_SHORT) .show(); - finish(); } }); } - } diff --git a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java deleted file mode 100644 index 01ba0030336eb2ae066eca735caa921fe5b447bf..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/contact/ReadPrivateMessageActivity.java +++ /dev/null @@ -1,240 +0,0 @@ -package org.briarproject.android.contact; - -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.LinearLayout; -import android.widget.ScrollView; -import android.widget.TextView; - -import org.briarproject.R; -import org.briarproject.android.BriarActivity; -import org.briarproject.android.util.AuthorView; -import org.briarproject.android.util.ElasticHorizontalSpace; -import org.briarproject.android.util.HorizontalBorder; -import org.briarproject.android.util.LayoutUtils; -import org.briarproject.api.db.DbException; -import org.briarproject.api.db.NoSuchMessageException; -import org.briarproject.api.identity.AuthorId; -import org.briarproject.api.messaging.MessagingManager; -import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.MessageId; -import org.briarproject.util.StringUtils; - -import java.util.logging.Logger; - -import javax.inject.Inject; - -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.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP_1; -import static org.briarproject.android.util.CommonLayoutParams.WRAP_WRAP_1; -import static org.briarproject.api.identity.Author.Status.VERIFIED; - -@Deprecated -public class ReadPrivateMessageActivity extends BriarActivity -implements OnClickListener { - - static final int RESULT_REPLY = RESULT_FIRST_USER; - static final int RESULT_PREV_NEXT = RESULT_FIRST_USER + 1; - - private static final Logger LOG = - Logger.getLogger(ReadPrivateMessageActivity.class.getName()); - - private String contactName = null; - private AuthorId localAuthorId = null; - private long timestamp = -1, minTimestamp = -1; - private ImageButton prevButton = null, nextButton = null; - private ImageButton replyButton = null; - private TextView content = null; - private int position = -1; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile MessagingManager messagingManager; - private volatile MessageId messageId = null; - private volatile GroupId groupId = null; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - Intent i = getIntent(); - contactName = i.getStringExtra("briar.CONTACT_NAME"); - if (contactName == null) throw new IllegalStateException(); - setTitle(contactName); - byte[] b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID"); - if (b == null) throw new IllegalStateException(); - localAuthorId = new AuthorId(b); - String authorName = i.getStringExtra("briar.AUTHOR_NAME"); - if (authorName == null) throw new IllegalStateException(); - b = i.getByteArrayExtra("briar.MESSAGE_ID"); - if (b == null) throw new IllegalStateException(); - messageId = new MessageId(b); - b = i.getByteArrayExtra("briar.GROUP_ID"); - if (b == null) throw new IllegalStateException(); - groupId = new GroupId(b); - String contentType = i.getStringExtra("briar.CONTENT_TYPE"); - if (contentType == null) throw new IllegalStateException(); - timestamp = i.getLongExtra("briar.TIMESTAMP", -1); - if (timestamp == -1) throw new IllegalStateException(); - minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); - if (minTimestamp == -1) throw new IllegalStateException(); - position = i.getIntExtra("briar.POSITION", -1); - if (position == -1) throw new IllegalStateException(); - - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_WRAP); - layout.setOrientation(VERTICAL); - - ScrollView scrollView = new ScrollView(this); - scrollView.setLayoutParams(MATCH_WRAP_1); - - LinearLayout message = new LinearLayout(this); - message.setOrientation(VERTICAL); - - LinearLayout header = new LinearLayout(this); - header.setLayoutParams(MATCH_WRAP); - header.setOrientation(HORIZONTAL); - header.setGravity(CENTER_VERTICAL); - - AuthorView author = new AuthorView(this); - author.setLayoutParams(WRAP_WRAP_1); - author.init(authorName, VERIFIED); - header.addView(author); - - int pad = LayoutUtils.getPadding(this); - - TextView date = new TextView(this); - date.setPadding(0, pad, pad, pad); - date.setText(DateUtils.getRelativeTimeSpanString(this, timestamp)); - header.addView(date); - message.addView(header); - - if (contentType.equals("text/plain")) { - // Load and display the message body - content = new TextView(this); - content.setPadding(pad, 0, pad, pad); - 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); - Resources res = getResources(); - footer.setBackgroundColor(res.getColor(R.color.button_bar_background)); - - prevButton = new ImageButton(this); - prevButton.setBackgroundResource(0); - prevButton.setImageResource(R.drawable.navigation_previous_item); - prevButton.setOnClickListener(this); - footer.addView(prevButton); - footer.addView(new ElasticHorizontalSpace(this)); - - nextButton = new ImageButton(this); - nextButton.setBackgroundResource(0); - nextButton.setImageResource(R.drawable.navigation_next_item); - nextButton.setOnClickListener(this); - footer.addView(nextButton); - footer.addView(new ElasticHorizontalSpace(this)); - - replyButton = new ImageButton(this); - replyButton.setBackgroundResource(0); - replyButton.setImageResource(R.drawable.social_reply); - replyButton.setOnClickListener(this); - footer.addView(replyButton); - layout.addView(footer); - - setContentView(layout); - } - - @Override - public void onPause() { - super.onPause(); - if (isFinishing()) markMessageRead(); - } - - private void markMessageRead() { - runOnDbThread(new Runnable() { - public void run() { - try { - long now = System.currentTimeMillis(); - messagingManager.setReadFlag(messageId, true); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Marking read took " + duration + " ms"); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } - } - }); - } - - private void loadMessageBody() { - runOnDbThread(new Runnable() { - public void run() { - try { - long now = System.currentTimeMillis(); - byte[] body = messagingManager.getMessageBody(messageId); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Loading message took " + duration + " ms"); - displayMessageBody(StringUtils.fromUtf8(body)); - } catch (NoSuchMessageException e) { - finishOnUiThread(); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } - } - }); - } - - private void displayMessageBody(final String body) { - runOnUiThread(new Runnable() { - public void run() { - content.setText(body); - } - }); - } - - public void onClick(View view) { - if (view == prevButton) { - Intent i = new Intent(); - i.putExtra("briar.POSITION", position - 1); - setResult(RESULT_PREV_NEXT, i); - finish(); - } else if (view == nextButton) { - Intent i = new Intent(); - i.putExtra("briar.POSITION", position + 1); - setResult(RESULT_PREV_NEXT, i); - finish(); - } else if (view == replyButton) { - Intent i = new Intent(this, WritePrivateMessageActivity.class); - i.putExtra("briar.CONTACT_NAME", contactName); - i.putExtra("briar.GROUP_ID", groupId.getBytes()); - i.putExtra("briar.LOCAL_AUTHOR_ID", - localAuthorId.getBytes()); - i.putExtra("briar.PARENT_ID", messageId.getBytes()); - i.putExtra("briar.MIN_TIMESTAMP", minTimestamp); - startActivity(i); - setResult(RESULT_REPLY); - finish(); - } - } -} diff --git a/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java b/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java deleted file mode 100644 index 74623463e43d026a5aa4d332bf6034d284eb6aba..0000000000000000000000000000000000000000 --- a/briar-android/src/org/briarproject/android/contact/WritePrivateMessageActivity.java +++ /dev/null @@ -1,224 +0,0 @@ -package org.briarproject.android.contact; - -import android.content.Intent; -import android.os.Bundle; -import android.text.InputType; -import android.view.View; -import android.view.View.OnClickListener; -import android.widget.EditText; -import android.widget.ImageButton; -import android.widget.LinearLayout; -import android.widget.RelativeLayout; -import android.widget.TextView; -import android.widget.Toast; - -import org.briarproject.R; -import org.briarproject.android.BriarActivity; -import org.briarproject.android.util.CommonLayoutParams; -import org.briarproject.android.util.LayoutUtils; -import org.briarproject.api.crypto.CryptoExecutor; -import org.briarproject.api.db.DbException; -import org.briarproject.api.db.NoSuchContactException; -import org.briarproject.api.db.NoSuchSubscriptionException; -import org.briarproject.api.identity.AuthorId; -import org.briarproject.api.identity.IdentityManager; -import org.briarproject.api.identity.LocalAuthor; -import org.briarproject.api.messaging.MessagingManager; -import org.briarproject.api.messaging.PrivateConversation; -import org.briarproject.api.messaging.PrivateMessageFactory; -import org.briarproject.api.sync.GroupId; -import org.briarproject.api.sync.Message; -import org.briarproject.api.sync.MessageId; -import org.briarproject.util.StringUtils; - -import java.io.IOException; -import java.security.GeneralSecurityException; -import java.util.concurrent.Executor; -import java.util.logging.Logger; - -import javax.inject.Inject; - -import static android.text.InputType.TYPE_CLASS_TEXT; -import static android.text.InputType.TYPE_TEXT_FLAG_CAP_SENTENCES; -import static android.text.TextUtils.TruncateAt.END; -import static android.widget.LinearLayout.VERTICAL; -import static android.widget.RelativeLayout.ALIGN_PARENT_LEFT; -import static android.widget.RelativeLayout.ALIGN_PARENT_RIGHT; -import static android.widget.RelativeLayout.CENTER_VERTICAL; -import static android.widget.RelativeLayout.LEFT_OF; -import static android.widget.Toast.LENGTH_LONG; -import static java.util.logging.Level.INFO; -import static java.util.logging.Level.WARNING; -import static org.briarproject.android.util.CommonLayoutParams.MATCH_WRAP; - -public class WritePrivateMessageActivity extends BriarActivity -implements OnClickListener { - - private static final Logger LOG = - Logger.getLogger(WritePrivateMessageActivity.class.getName()); - - @Inject @CryptoExecutor private Executor cryptoExecutor; - private TextView from = null; - private ImageButton sendButton = null; - private EditText content = null; - - // Fields that are accessed from background threads must be volatile - @Inject private volatile IdentityManager identityManager; - @Inject private volatile MessagingManager messagingManager; - @Inject private volatile PrivateMessageFactory privateMessageFactory; - private volatile GroupId groupId = null; - private volatile AuthorId localAuthorId = null; - private volatile MessageId parentId = null; - private volatile long minTimestamp = -1; - private volatile LocalAuthor localAuthor = null; - private volatile PrivateConversation conversation = null; - - @Override - public void onCreate(Bundle state) { - super.onCreate(state); - - Intent i = getIntent(); - String contactName = i.getStringExtra("briar.CONTACT_NAME"); - if (contactName == null) throw new IllegalStateException(); - setTitle(contactName); - byte[] b = i.getByteArrayExtra("briar.GROUP_ID"); - if (b == null) throw new IllegalStateException(); - groupId = new GroupId(b); - b = i.getByteArrayExtra("briar.LOCAL_AUTHOR_ID"); - if (b == null) throw new IllegalStateException(); - minTimestamp = i.getLongExtra("briar.MIN_TIMESTAMP", -1); - if (minTimestamp == -1) throw new IllegalStateException(); - localAuthorId = new AuthorId(b); - b = i.getByteArrayExtra("briar.PARENT_ID"); - if (b != null) parentId = new MessageId(b); - - LinearLayout layout = new LinearLayout(this); - layout.setLayoutParams(MATCH_WRAP); - layout.setOrientation(VERTICAL); - int pad = LayoutUtils.getPadding(this); - layout.setPadding(pad, 0, pad, pad); - - RelativeLayout header = new RelativeLayout(this); - - from = new TextView(this); - from.setId(1); - from.setTextSize(18); - from.setSingleLine(); - from.setEllipsize(END); - from.setPadding(0, 0, pad, 0); - from.setText(R.string.from); - RelativeLayout.LayoutParams leftOf = CommonLayoutParams.relative(); - leftOf.addRule(ALIGN_PARENT_LEFT); - leftOf.addRule(CENTER_VERTICAL); - leftOf.addRule(LEFT_OF, 2); - header.addView(from, leftOf); - - sendButton = new ImageButton(this); - sendButton.setId(2); - sendButton.setBackgroundResource(0); - sendButton.setImageResource(R.drawable.social_send_now); - sendButton.setEnabled(false); // Enabled after loading the conversation - sendButton.setOnClickListener(this); - RelativeLayout.LayoutParams right = CommonLayoutParams.relative(); - right.addRule(ALIGN_PARENT_RIGHT); - right.addRule(CENTER_VERTICAL); - header.addView(sendButton, right); - layout.addView(header); - - content = new EditText(this); - content.setId(3); - int inputType = TYPE_CLASS_TEXT | InputType.TYPE_TEXT_FLAG_MULTI_LINE - | TYPE_TEXT_FLAG_CAP_SENTENCES; - content.setInputType(inputType); - content.setHint(R.string.private_message_hint); - layout.addView(content); - - setContentView(layout); - } - - @Override - public void onResume() { - super.onResume(); - if (localAuthor == null || conversation == null) - loadAuthorAndConversation(); - } - - private void loadAuthorAndConversation() { - runOnDbThread(new Runnable() { - public void run() { - try { - long now = System.currentTimeMillis(); - localAuthor = identityManager.getLocalAuthor(localAuthorId); - conversation = messagingManager.getConversation(groupId); - long duration = System.currentTimeMillis() - now; - if (LOG.isLoggable(INFO)) - LOG.info("Load took " + duration + " ms"); - displayLocalAuthor(); - } catch (NoSuchContactException e) { - finishOnUiThread(); - } catch (NoSuchSubscriptionException e) { - finishOnUiThread(); - } catch (DbException e) { - if (LOG.isLoggable(WARNING)) - LOG.log(WARNING, e.toString(), e); - } - } - }); - } - - private void displayLocalAuthor() { - runOnUiThread(new Runnable() { - public void run() { - String format = getString(R.string.format_from); - String name = localAuthor.getName(); - from.setText(String.format(format, name)); - sendButton.setEnabled(true); - } - }); - } - - public void onClick(View view) { - String message = content.getText().toString(); - if (message.equals("")) return; - createMessage(StringUtils.toUtf8(message)); - Toast.makeText(this, R.string.message_sent_toast, LENGTH_LONG).show(); - finish(); - } - - private void createMessage(final byte[] body) { - cryptoExecutor.execute(new Runnable() { - public void run() { - // Don't use an earlier timestamp than the newest message - long timestamp = System.currentTimeMillis(); - timestamp = Math.max(timestamp, minTimestamp); - try { - Message m = privateMessageFactory.createPrivateMessage( - parentId, conversation, "text/plain", timestamp, - body); - storeMessage(m); - } catch (GeneralSecurityException e) { - throw new RuntimeException(e); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - }); - } - - private void storeMessage(final Message m) { - runOnDbThread(new Runnable() { - public void run() { - try { - long now = System.currentTimeMillis(); - messagingManager.addLocalMessage(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); - } - } - }); - } -}