Remove non-themed theme madness.

This commit is contained in:
Moxie Marlinspike 2012-07-16 19:56:10 -07:00
parent 647c41bf66
commit 44c221c9f1
4 changed files with 270 additions and 360 deletions

BIN
libs/android-support-v4.jar Normal file

Binary file not shown.

View File

@ -1,102 +1,51 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical">
<RelativeLayout android:id="@+id/title_bar_container"
android:layout_width="fill_parent"
android:layout_height="43dip"
android:background="@drawable/iphone_bar_top"
android:layout_alignParentTop="true">
<TextView
android:textSize="18.0dip"
android:textStyle="bold"
android:textColor="#ffffffff"
android:singleLine="true"
style="?android:windowTitleStyle"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="TextSecure"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:gravity="center" />
<EditText android:id="@+id/search_text"
android:layout_height="wrap_content"
android:capitalize="sentences"
android:autoText="true"
android:singleLine="true"
android:hint="Search"
android:paddingRight="50dip"
android:layout_margin="10dip"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true"
android:visibility="gone"/>
<!-- <ImageView-->
<!-- android:id="@+id/settings_button"-->
<!-- android:paddingLeft="2.0dip" -->
<!-- android:paddingRight="5.0dip" -->
<!-- android:layout_width="wrap_content" -->
<!-- android:layout_height="wrap_content" -->
<!-- android:src="@drawable/ic_settings_iphone" -->
<!-- android:adjustViewBounds="false" -->
<!-- android:layout_alignParentRight="true" -->
<!-- android:layout_centerVertical="true" />-->
</RelativeLayout>
<EditText android:id="@+id/search_text"
android:layout_height="wrap_content"
android:capitalize="sentences"
android:autoText="true"
android:singleLine="true"
android:hint="Search"
android:paddingRight="50dip"
android:layout_margin="10dip"
android:layout_width="fill_parent"
android:layout_alignParentBottom="true"
android:visibility="gone"/>
<ImageView android:id="@+id/search_close"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="16dip"
android:layout_marginBottom="20dip"
android:src="@android:drawable/btn_dialog"
android:visibility="gone"
/>
<ListView android:id="@android:id/list"
style="?android:attr/listViewWhiteStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:scrollbarStyle="insideOverlay"
android:fadingEdgeLength="16dip"
android:background="@android:color/white"
android:cacheColorHint="@android:color/white"
android:layout_below="@id/title_bar_container"
android:layout_above="@id/search_text" />
<ProgressBar android:id="@+id/search_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_centerInParent="true"
android:visibility="gone" />
<!-- <LinearLayout android:orientation="horizontal"-->
<!-- android:layout_width="fill_parent"-->
<!-- android:layout_height="wrap_content">-->
<!-- <TextView android:layout_width="wrap_content"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dip"-->
<!-- android:textAppearance="?android:attr/textAppearanceMedium"-->
<!-- android:singleLine="true" -->
<!-- android:text="Search:" />-->
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:layout_alignParentRight="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="16dip"
android:layout_marginBottom="20dip"
android:src="@android:drawable/btn_dialog"
android:visibility="gone"
/>
<ListView android:id="@android:id/list"
style="?android:attr/listViewWhiteStyle"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:drawSelectorOnTop="false"
android:scrollbarStyle="insideOverlay"
android:fadingEdgeLength="16dip"
android:background="@android:color/white"
android:cacheColorHint="@android:color/white"
android:layout_alignParentTop="true"
android:layout_above="@id/search_text" />
<ProgressBar android:id="@+id/search_progress"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:indeterminate="true"
android:layout_centerInParent="true"
android:visibility="gone" />
<!-- -->
<!-- <EditText android:layout_width="fill_parent"-->
<!-- android:layout_height="wrap_content"-->
<!-- android:layout_margin="10dip"-->
<!-- android:id="@+id/search_text" />-->
<!-- </LinearLayout>-->
</RelativeLayout>

View File

@ -1,6 +1,6 @@
/**
/**
* Copyright (C) 2011 Whisper Systems
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@ -10,17 +10,12 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import java.util.Set;
import org.thoughtcrime.securesms.database.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipients;
import android.content.Context;
import android.graphics.Color;
import android.preference.PreferenceManager;
@ -36,6 +31,11 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import org.thoughtcrime.securesms.database.MessageRecord;
import org.thoughtcrime.securesms.recipients.Recipients;
import java.util.Set;
/**
* A view that displays the element in a list of multiple conversation threads.
* Used by SecureSMS's ListActivity via a ConversationListAdapter.
@ -47,7 +47,7 @@ public class ConversationHeaderView extends RelativeLayout {
private final Context context;
private Set<Long> selectedThreads;
private Recipients recipients;
private long threadId;
private boolean first;
@ -58,21 +58,21 @@ public class ConversationHeaderView extends RelativeLayout {
private View keyIndicator;
private CheckBox checkbox;
private ImageView contactPhoto;
public ConversationHeaderView(Context context, boolean first) {
this(context, (Set<Long>)null);
this.first = true;
contactPhoto.setVisibility(View.GONE);
this.setBackgroundColor(Color.TRANSPARENT);
}
public ConversationHeaderView(Context context, Set<Long> selectedThreads) {
super(context);
LayoutInflater li = (LayoutInflater)context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
li.inflate(R.layout.conversation_header_view, this, true);
this.context = context;
this.selectedThreads = selectedThreads;
this.subjectView = (TextView)findViewById(R.id.subject);
@ -80,13 +80,12 @@ public class ConversationHeaderView extends RelativeLayout {
this.dateView = (TextView)findViewById(R.id.date);
this.unreadIndicator = findViewById(R.id.unread_indicator);
this.keyIndicator = findViewById(R.id.key_indicator);
this.contactPhoto = (ImageView)findViewById(R.id.contact_photo);
this.contactPhoto = (ImageView)findViewById(R.id.contact_photo);
this.checkbox = (CheckBox)findViewById(R.id.checkbox);
intializeListeners();
initializeColors();
}
public ConversationHeaderView(Context context, AttributeSet attrs) {
super(context, attrs);
this.context = context;
@ -96,78 +95,64 @@ public class ConversationHeaderView extends RelativeLayout {
this.recipients = message.getRecipients();
this.threadId = message.getThreadId();
this.fromView.setText(formatFrom(recipients, message.getCount()));
if (message.isKeyExchange())
this.subjectView.setText("Key exchange message...", TextView.BufferType.SPANNABLE);
else
this.subjectView.setText(message.getBody(), TextView.BufferType.SPANNABLE);
if (message.getEmphasis())
((Spannable)this.subjectView.getText()).setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 0, this.subjectView.getText().length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
if (message.getDate() > 0)
if (message.getDate() > 0)
this.dateView.setText(DateUtils.getRelativeTimeSpanString(getContext(), message.getDate(), false));
if (selectedThreads != null)
if (selectedThreads != null)
this.checkbox.setChecked(selectedThreads.contains(threadId));
clearIndicators();
setIndicators(message.getRead(), message.isKeyExchange());
setIndicators(message.getRead(), message.isKeyExchange());
if (!first) {
if (batchMode) checkbox.setVisibility(View.VISIBLE);
else checkbox.setVisibility(View.GONE);
else checkbox.setVisibility(View.GONE);
if (!PreferenceManager.getDefaultSharedPreferences(context).getBoolean(ApplicationPreferencesActivity.CONVERSATION_ICONS_LIST_PREF, ApplicationPreferencesActivity.showIcon())) {
contactPhoto.setVisibility(View.GONE);
} else {
} else {
contactPhoto.setImageBitmap(message.getRecipients().getPrimaryRecipient().getContactPhoto());
contactPhoto.setBackgroundResource(R.drawable.light_border_background);
contactPhoto.setVisibility(View.VISIBLE);
}
}
}
public void initializeColors() {
if (!PreferenceManager.getDefaultSharedPreferences(getContext()).getBoolean(ApplicationPreferencesActivity.DARK_THREADS_PREF, true)) {
this.setBackgroundDrawable(getResources().getDrawable(R.drawable.conversation_header_background_light));
this.subjectView.setTextColor(Color.BLACK);
this.fromView.setTextColor(Color.BLACK);
this.dateView.setTextColor(Color.LTGRAY);
} else {
this.setBackgroundColor(Color.TRANSPARENT);
this.subjectView.setTextColor(Color.LTGRAY);
this.fromView.setTextColor(Color.WHITE);
this.dateView.setTextColor(Color.LTGRAY);
}
}
private void intializeListeners() {
checkbox.setOnCheckedChangeListener(new CheckedChangedListener());
}
private void clearIndicators() {
this.keyIndicator.setVisibility(View.INVISIBLE);
this.unreadIndicator.setVisibility(View.INVISIBLE);
}
private void setIndicators(boolean read, boolean key) {
if (!read && key) this.keyIndicator.setVisibility(View.VISIBLE);
else if (!read) this.unreadIndicator.setVisibility(View.VISIBLE);
}
private String formatFrom(Recipients from, long count) {
return from.toShortString() + (count > 0 ? " (" + count + ")" : "");
}
public Recipients getRecipients() {
return recipients;
}
public long getThreadId() {
return threadId;
}
private class CheckedChangedListener implements CompoundButton.OnCheckedChangeListener {
public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
if (isChecked) selectedThreads.add(threadId);

View File

@ -1,6 +1,6 @@
/**
/**
* Copyright (C) 2011 Whisper Systems
*
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
@ -10,16 +10,49 @@
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.thoughtcrime.securesms;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import android.app.AlertDialog;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.View;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
import com.actionbarsherlock.app.SherlockListActivity;
import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuItem;
import com.actionbarsherlock.view.SubMenu;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.crypto.DecryptingQueue;
@ -41,57 +74,21 @@ import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.Eula;
import org.thoughtcrime.securesms.util.MemoryCleaner;
import android.app.AlertDialog;
import android.app.ListActivity;
import android.app.NotificationManager;
import android.app.ProgressDialog;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.ServiceConnection;
import android.content.SharedPreferences;
import android.database.ContentObserver;
import android.database.Cursor;
import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Parcelable;
import android.preference.PreferenceManager;
import android.text.Editable;
import android.text.TextWatcher;
import android.util.Log;
import android.view.ContextMenu;
import android.view.KeyCharacterMap;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SubMenu;
import android.view.View;
import android.view.Window;
import android.widget.AdapterView;
import android.widget.CursorAdapter;
import android.widget.EditText;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.ProgressBar;
import android.widget.Toast;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
/**
*
*
* The main Activity for TextSecure. Manages the conversation list, search
* access to the conversation list, and import/export handling.
*
*
* @author Moxie Marlinspike
*/
public class SecureSMS extends ListActivity {
public class SecureSMS extends SherlockListActivity {
private static final int MENU_SEND_KEY = 1;
private static final int MENU_PASSPHRASE_KEY = 2;
private static final int MENU_PREFERENCES_KEY = 3;
@ -101,16 +98,16 @@ public class SecureSMS extends ListActivity {
private static final int MENU_CLEAR_PASSPHRASE = 12;
private static final int MENU_DELETE_SELECTED_THREADS = 13;
private static final int MENU_BATCH_MODE = 14;
private static final int MENU_EXIT_BATCH = 15;
private static final int MENU_SELECT_ALL_THREADS = 16;
private static final int MENU_CLEAR_SELECTION = 17;
private static final int VIEW_THREAD_ID = 100;
private static final int VIEW_CONTACT_ID = 101;
private static final int DELETE_THREAD_ID = 102;
private static final int ADD_CONTACT_ID = 103;
private EditText searchBox;
private ConversationHeaderView headerView;
private MasterSecret masterSecret;
@ -119,53 +116,56 @@ public class SecureSMS extends ListActivity {
private boolean havePromptedForPassphrase = false;
private boolean batchMode = false;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
getWindow().requestFeature(Window.FEATURE_NO_TITLE);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle("TextSecure");
setContentView(R.layout.main);
initializeKillReceiver();
initializeSenderReceiverService();
initializeResources();
initializeSearchListener();
registerForContextMenu(getListView());
registerForContactsUpdates();
}
@Override
public void onPause() {
super.onPause();
if (receiver != null) {
Log.w("securesms", "Unregistering receiver...");
unregisterReceiver(receiver);
receiver = null;
}
}
}
@Override
public void onResume() {
super.onResume();
Log.w("securesms", "restart called...");
initializeColors();
Eula.showEula(this);
Eula.showDisclaimer(this);
}
@Override
public void onStart() {
super.onStart();
registerPassphraseActivityStarted();
}
@Override
public void onStop() {
super.onStop();
havePromptedForPassphrase = false;
registerPassphraseActivityStopped();
}
@Override
public void onDestroy() {
Log.w("SecureSMS", "onDestroy...");
@ -173,55 +173,55 @@ public class SecureSMS extends ListActivity {
MemoryCleaner.clean(masterSecret);
super.onDestroy();
}
@Override
public boolean onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
menu.clear();
if (!batchMode) prepareNormalMenu(menu);
else prepareBatchModeMenu(menu);
return true;
}
private void prepareNormalMenu(Menu menu) {
menu.add(0, MENU_BATCH_MODE, Menu.NONE, "Batch Mode").setIcon(android.R.drawable.ic_menu_share);
if (masterSecret != null) menu.add(0, MENU_SEND_KEY, Menu.NONE, "Secure Session").setIcon(R.drawable.ic_lock_message_sms);
else menu.add(0, MENU_PASSPHRASE_KEY, Menu.NONE, "Enter passphrase").setIcon(R.drawable.ic_lock_message_sms);
menu.add(0, MENU_SEARCH, Menu.NONE, "Search").setIcon(android.R.drawable.ic_menu_search);
menu.add(0, MENU_PREFERENCES_KEY, Menu.NONE, "Settings").setIcon(android.R.drawable.ic_menu_preferences);
menu.add(0, MENU_PREFERENCES_KEY, Menu.NONE, "Settings").setIcon(android.R.drawable.ic_menu_preferences);
SubMenu importExportMenu = menu.addSubMenu("Import/Export").setIcon(android.R.drawable.ic_menu_save);
importExportMenu.add(0, MENU_EXPORT, Menu.NONE, "Export To SD Card").setIcon(android.R.drawable.ic_menu_save);
importExportMenu.add(0, MENU_IMPORT, Menu.NONE, "Import From SD Card").setIcon(android.R.drawable.ic_menu_revert);
SubMenu moreMenu = menu.addSubMenu("More").setIcon(android.R.drawable.ic_menu_more);
if (masterSecret != null)
moreMenu.add(0, MENU_CLEAR_PASSPHRASE, Menu.NONE, "Clear Passphrase").setIcon(android.R.drawable.ic_menu_close_clear_cancel);
}
private void prepareBatchModeMenu(Menu menu) {
menu.add(0, MENU_EXIT_BATCH, Menu.NONE, "Normal Mode").setIcon(android.R.drawable.ic_menu_set_as);
menu.add(0, MENU_DELETE_SELECTED_THREADS, Menu.NONE, "Delete Selected").setIcon(android.R.drawable.ic_menu_delete);
menu.add(0, MENU_SELECT_ALL_THREADS, Menu.NONE, "Select All").setIcon(android.R.drawable.ic_menu_add);
menu.add(0, MENU_CLEAR_SELECTION, Menu.NONE, "Unselect All").setIcon(android.R.drawable.ic_menu_revert);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
switch (item.getItemId()) {
case MENU_SEND_KEY:
Intent intent = new Intent(this, SendKeyActivity.class);
intent.putExtra("master_secret", masterSecret);
startActivity(intent);
return true;
case MENU_PASSPHRASE_KEY:
@ -261,24 +261,24 @@ public class SecureSMS extends ListActivity {
// finish();
return true;
}
return false;
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
Log.w("SecureSMS", "Got onNewIntent...");
createConversationIfNecessary(intent);
}
public void eulaComplete() {
clearNotifications();
initializeReceivers();
checkCachingService();
}
}
@Override
public void onCreateContextMenu (ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
if (((AdapterView.AdapterContextMenuInfo)menuInfo).position > 0) {
@ -287,7 +287,7 @@ public class SecureSMS extends ListActivity {
Recipients recipients = RecipientFactory.getRecipientsForIds(this, recipientId);
menu.add(0, VIEW_THREAD_ID, Menu.NONE, "View thread");
if (recipients.isSingleRecipient()) {
if (recipients.getPrimaryRecipient().getName() != null) {
menu.add(0, VIEW_CONTACT_ID, Menu.NONE, "View contact");
@ -295,13 +295,13 @@ public class SecureSMS extends ListActivity {
menu.add(0, ADD_CONTACT_ID, Menu.NONE, "Add to contacts");
}
}
menu.add(0, DELETE_THREAD_ID, Menu.NONE, "Delete thread");
menu.add(0, DELETE_THREAD_ID, Menu.NONE, "Delete thread");
}
}
@Override
public boolean onContextItemSelected(MenuItem item) {
public boolean onContextItemSelected(android.view.MenuItem item) {
Cursor cursor = ((CursorAdapter)this.getListAdapter()).getCursor();
long threadId = cursor.getLong(cursor.getColumnIndexOrThrow(ThreadDatabase.ID));
String recipientId = cursor.getString(cursor.getColumnIndexOrThrow(ThreadDatabase.RECIPIENT_IDS));
@ -323,35 +323,35 @@ public class SecureSMS extends ListActivity {
}
return false;
}
private void initiateBatchMode() {
this.batchMode = true;
((ConversationListAdapter)this.getListAdapter()).initializeBatchMode(batchMode);
}
private void stopBatchMode() {
this.batchMode = false;
((ConversationListAdapter)this.getListAdapter()).initializeBatchMode(batchMode);
((ConversationListAdapter)this.getListAdapter()).initializeBatchMode(batchMode);
}
private void selectAllThreads() {
((ConversationListAdapter)this.getListAdapter()).selectAllThreads();
}
private void unselectAllThreads() {
((ConversationListAdapter)this.getListAdapter()).unselectAllThreads();
}
private void deleteSelectedThreads() {
AlertDialog.Builder alert = new AlertDialog.Builder(this);
alert.setIcon(android.R.drawable.ic_dialog_alert);
alert.setTitle("Delete threads?");
alert.setMessage("Are you sure you wish to delete ALL selected conversation threads?");
alert.setCancelable(true);
alert.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
alert.setPositiveButton("Delete", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
Set<Long> selectedConversations = ((ConversationListAdapter)getListAdapter()).getBatchSelections();
if (!selectedConversations.isEmpty())
DatabaseFactory.getThreadDatabase(SecureSMS.this).deleteConversations(selectedConversations);
}
@ -359,57 +359,52 @@ public class SecureSMS extends ListActivity {
alert.setNegativeButton("Cancel", null);
alert.show();
}
private void registerForContactsUpdates() {
Log.w("SecureSMS", "Registering for contacts update...");
getContentResolver().registerContentObserver(ContactAccessor.getInstance().getContactsUri(), true, new ContactUpdateObserver());
}
private void registerPassphraseActivityStarted() {
Intent intent = new Intent(this, KeyCachingService.class);
intent.setAction(KeyCachingService.ACTIVITY_START_EVENT);
startService(intent);
startService(intent);
}
private void registerPassphraseActivityStopped() {
Intent intent = new Intent(this, KeyCachingService.class);
intent.setAction(KeyCachingService.ACTIVITY_STOP_EVENT);
startService(intent);
}
private void addContact(Recipient recipient) {
RecipientFactory.getRecipientProvider().addContact(this, recipient);
}
private void viewContact(Recipient recipient) {
if (recipient.getPersonId() > 0) {
RecipientFactory.getRecipientProvider().viewContact(this, recipient);
}
}
private void clearNotifications() {
NotificationManager manager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
manager.cancel(KeyCachingService.NOTIFICATION_ID);
}
private void initializeResources() {
// ImageView settingsImage = (ImageView)findViewById(R.id.settings_button);
// settingsImage.setOnClickListener(new SettingsClickListener());
}
private void initializeKillReceiver() {
killActivityReceiver = new KillActivityReceiver();
registerReceiver(killActivityReceiver, new IntentFilter(KeyCachingService.PASSPHRASE_EXPIRED_EVENT),
registerReceiver(killActivityReceiver, new IntentFilter(KeyCachingService.PASSPHRASE_EXPIRED_EVENT),
KeyCachingService.KEY_PERMISSION, null);
}
private void initializeSenderReceiverService() {
Intent smsSenderIntent = new Intent(SendReceiveService.SEND_SMS_ACTION, null, this, SendReceiveService.class);
Intent mmsSenderIntent = new Intent(SendReceiveService.SEND_MMS_ACTION, null, this, SendReceiveService.class);
startService(smsSenderIntent);
startService(mmsSenderIntent);
}
private void checkCachingService() {
Log.w("securesms", "Checking caching service...");
Intent bindIntent = new Intent(this, KeyCachingService.class);
@ -420,46 +415,46 @@ public class SecureSMS extends ListActivity {
if (masterSecret != null)
DecryptingQueue.schedulePendingDecrypts(this, masterSecret);
}
private void migrateDatabase() {
MigrationHandler mh = new MigrationHandler();
mh.migrate();
}
private boolean isMigrated() {
return this.getSharedPreferences("SecureSMS", Context.MODE_PRIVATE).getBoolean("migrated", false);
}
private void initializeWithMasterSecret(MasterSecret masterSecret) {
this.masterSecret = masterSecret;
this.masterSecret = masterSecret;
if (masterSecret != null) {
if (!IdentityKeyUtil.hasIdentityKey(this)) initializeIdentityKeys();
if (!MasterSecretUtil.hasAsymmericMasterSecret(this)) initializeAsymmetricMasterSecret();
if (!isMigrated()) migrateDatabase();
else DecryptingQueue.schedulePendingDecrypts(this, masterSecret);
}
addNewMessageItem();
addConversationItems();
createConversationIfNecessary(this.getIntent());
}
private void initializeAsymmetricMasterSecret() {
new Thread(new AsymmetricMasteSecretInitializer()).start();
}
private void initializeIdentityKeys() {
new Thread(new IdentityKeyInitializer()).start();
}
private void initializeSearchListener() {
SearchTextListener listener = new SearchTextListener();
searchBox = (EditText)findViewById(R.id.search_text);
searchBox.addTextChangedListener(listener);
this.getListView().setOnKeyListener(listener);
}
private void initializeReceivers() {
Log.w("securesms", "Registering receiver...");
receiver = new NewKeyReceiver();
@ -468,25 +463,6 @@ public class SecureSMS extends ListActivity {
registerReceiver(receiver, filter, KeyCachingService.KEY_PERMISSION, null);
}
private void initializeColors() {
if (!PreferenceManager.getDefaultSharedPreferences(this).getBoolean(ApplicationPreferencesActivity.DARK_THREADS_PREF, true)) {
this.getListView().setBackgroundColor(Color.WHITE);
this.getListView().setCacheColorHint(Color.WHITE);
this.getListView().setDivider(new ColorDrawable(Color.parseColor("#cccccc")));
this.getListView().setDividerHeight(1);
} else {
this.getListView().setBackgroundColor(Color.BLACK);
this.getListView().setCacheColorHint(Color.BLACK);
this.getListView().setDivider(this.getResources().getDrawable(R.drawable.dark_divider));
this.getListView().setDividerHeight(1);
}
if (headerView != null) {
headerView.initializeColors();
headerView.setBackgroundColor(Color.TRANSPARENT);
}
}
@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
if (position == 0) {
@ -496,11 +472,11 @@ public class SecureSMS extends ListActivity {
createConversation(headerView.getThreadId(), headerView.getRecipients());
}
}
private void createConversationIfNecessary(Intent intent) {
long thread = intent.getLongExtra("thread_id", -1L);
Recipients recipients = null;
if (intent.getAction() != null && intent.getAction().equals("android.intent.action.SENDTO")) {
try {
recipients = RecipientFactory.getRecipientsFromString(this, intent.getData().getSchemeSpecificPart());
@ -511,7 +487,7 @@ public class SecureSMS extends ListActivity {
} else {
recipients = intent.getParcelableExtra("recipients");
}
if (recipients != null) {
createConversation(thread, recipients);
intent.putExtra("thread_id", -1L);
@ -519,41 +495,41 @@ public class SecureSMS extends ListActivity {
intent.setAction(null);
}
}
private void createConversation(long threadId, Recipients recipients) {
if (this.masterSecret == null) {
promptForPassphrase();
return;
}
Intent intent = new Intent(this, ComposeMessageActivity.class);
intent.putExtra("recipients", recipients);
intent.putExtra("thread_id", threadId);
intent.putExtra("master_secret", masterSecret);
startActivity(intent);
startActivity(intent);
}
private void addNewMessageItem() {
ListView listView = getListView();
if (listView.getHeaderViewsCount() > 0) return;
ArrayList<Recipient> dummyList = new ArrayList<Recipient>();
dummyList.add(new Recipient("New Message", null, null));
Recipients recipients = new Recipients(dummyList);
Recipients recipients = new Recipients(dummyList);
headerView = new ConversationHeaderView(this, true);
MessageRecord messageRecord = new MessageRecord(-1, recipients, 0, 0, true, -1);
messageRecord.setBody("Compose new message.");
headerView.set(messageRecord, false);
// headerView.setBackgroundColor(Color.TRANSPARENT);
listView.addHeaderView(headerView, null, true);
}
private void addConversationItems() {
Cursor cursor = DatabaseFactory.getThreadDatabase(this).getConversationList();
startManagingCursor(cursor);
if (masterSecret == null) setListAdapter(new ConversationListAdapter(this, cursor));
else setListAdapter(new DecryptingConversationListAdapter(this, cursor, masterSecret));
}
@ -568,18 +544,18 @@ public class SecureSMS extends ListActivity {
builder.setNegativeButton(R.string.no, null);
builder.show();
}
private void promptForPassphrase() {
havePromptedForPassphrase = true;
if (hasSelectedPassphrase()) startActivity(new Intent(this, PassphrasePromptActivity.class));
else startActivity(new Intent(this, PassphraseCreateActivity.class));
else startActivity(new Intent(this, PassphraseCreateActivity.class));
}
private boolean hasSelectedPassphrase() {
SharedPreferences settings = getSharedPreferences(KeyCachingService.PREFERENCES_NAME, 0);
return settings.getBoolean("passphrase_initialized", false);
}
private ServiceConnection serviceConnection = new ServiceConnection() {
public void onServiceConnected(ComponentName className, IBinder service) {
KeyCachingService keyCachingService = ((KeyCachingService.KeyCachingBinder)service).getService();
@ -587,14 +563,14 @@ public class SecureSMS extends ListActivity {
initializeWithMasterSecret(masterSecret);
if (masterSecret == null && !havePromptedForPassphrase)
promptForPassphrase();
Intent cachingIntent = new Intent(SecureSMS.this, KeyCachingService.class);
if (masterSecret == null && !havePromptedForPassphrase)
promptForPassphrase();
Intent cachingIntent = new Intent(SecureSMS.this, KeyCachingService.class);
startService(cachingIntent);
try {
SecureSMS.this.unbindService(this);
SecureSMS.this.unbindService(this);
} catch (IllegalArgumentException iae) {
Log.w("SecureSMS", iae);
}
@ -602,21 +578,21 @@ public class SecureSMS extends ListActivity {
public void onServiceDisconnected(ComponentName name) {}
};
private class DeleteThreadListener implements DialogInterface.OnClickListener {
private final long threadId;
public DeleteThreadListener(long threadId) {
this.threadId = threadId;
}
public void onClick(DialogInterface dialog, int which) {
if (threadId > 0) {
DatabaseFactory.getThreadDatabase(SecureSMS.this).deleteConversation(threadId);
}
}
}
}
};
private class NewKeyReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
@ -624,43 +600,43 @@ public class SecureSMS extends ListActivity {
initializeWithMasterSecret((MasterSecret)intent.getParcelableExtra("master_secret"));
}
}
private class KillActivityReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context arg0, Intent arg1) {
finish();
}
}
// private class SettingsClickListener implements View.OnClickListener {
// public void onClick(View v) {
// startActivity(new Intent(SecureSMS.this, ApplicationPreferencesActivity.class));
// }
// }
private class IdentityKeyInitializer implements Runnable {
public void run() {
IdentityKeyUtil.generateIdentityKeys(SecureSMS.this, masterSecret);
}
}
private class AsymmetricMasteSecretInitializer implements Runnable {
public void run() {
MasterSecretUtil.generateAsymmetricMasterSecret(SecureSMS.this, masterSecret);
}
}
private class ExportHandler extends Handler implements Runnable {
private static final int ERROR_NO_SD = 0;
private static final int ERROR_IO = 1;
private static final int COMPLETE = 2;
private static final int TASK_EXPORT = 0;
private static final int TASK_IMPORT = 1;
private int task;
private ProgressDialog progressDialog;
public void run() {
try {
switch (task) {
@ -676,11 +652,11 @@ public class SecureSMS extends ListActivity {
this.obtainMessage(ERROR_IO).sendToTarget();
return;
}
this.obtainMessage(COMPLETE).sendToTarget();
}
private void continueExport() {
private void continueExport() {
task = TASK_EXPORT;
progressDialog = new ProgressDialog(SecureSMS.this);
progressDialog.setTitle("Exporting Database and Keys");
@ -691,7 +667,7 @@ public class SecureSMS extends ListActivity {
progressDialog.show();
new Thread(this).start();
}
private void continueImport() {
task = TASK_IMPORT;
progressDialog = new ProgressDialog(SecureSMS.this);
@ -701,21 +677,21 @@ public class SecureSMS extends ListActivity {
progressDialog.setIndeterminate(true);
progressDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
progressDialog.show();
initializeWithMasterSecret(null);
Intent clearKeyIntent = new Intent(KeyCachingService.CLEAR_KEY_ACTION, null, SecureSMS.this, KeyCachingService.class);
startService(clearKeyIntent);
DatabaseFactory.getInstance(SecureSMS.this).close();
new Thread(this).start();
new Thread(this).start();
}
public void importFromSd() {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(SecureSMS.this);
alertBuilder.setTitle("Import Database and Settings?");
alertBuilder.setMessage("Import TextSecure database, keys, and settings from the SD Card?\n\nWARNING: This will clobber any existing messages, keys, and settings!");
alertBuilder.setCancelable(false);
alertBuilder.setPositiveButton("Import", new DialogInterface.OnClickListener() {
alertBuilder.setPositiveButton("Import", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
continueImport();
}
@ -724,15 +700,15 @@ public class SecureSMS extends ListActivity {
public void onClick(DialogInterface dialog, int which) {
}
});
alertBuilder.create().show();
alertBuilder.create().show();
}
public void export() {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(SecureSMS.this);
alertBuilder.setTitle("Export Database?");
alertBuilder.setMessage("Export TextSecure database, keys, and settings to the SD Card?");
alertBuilder.setCancelable(false);
alertBuilder.setPositiveButton("Export", new DialogInterface.OnClickListener() {
alertBuilder.setPositiveButton("Export", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
continueExport();
}
@ -743,7 +719,7 @@ public class SecureSMS extends ListActivity {
});
alertBuilder.create().show();
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
@ -766,68 +742,68 @@ public class SecureSMS extends ListActivity {
}
break;
}
progressDialog.dismiss();
}
}
private class SearchTextListener extends Handler implements TextWatcher, Runnable, View.OnClickListener, View.OnKeyListener {
private class SearchTextListener extends Handler implements TextWatcher, Runnable, View.OnClickListener, View.OnKeyListener {
private final ImageView closeButton;
private final ProgressBar progressDialog;
private final KeyCharacterMap keyMap;
private int outstandingThreads;
public SearchTextListener() {
closeButton = (ImageView)findViewById(R.id.search_close);
progressDialog = (ProgressBar)findViewById(R.id.search_progress);
keyMap = KeyCharacterMap.load(KeyCharacterMap.BUILT_IN_KEYBOARD);
outstandingThreads = 0;
closeButton.setOnClickListener(this);
}
private Cursor getCursorForFilter(String text) {
if (text.length() > 0) {
List<String> numbers = ContactAccessor.getInstance().getNumbersForThreadSearchFilter(text, getContentResolver());
return DatabaseFactory.getThreadDatabase(SecureSMS.this).getFilteredConversationList(numbers);
} else {
return DatabaseFactory.getThreadDatabase(SecureSMS.this).getConversationList();
}
}
}
public void afterTextChanged(Editable arg0) {
synchronized (this) {
if (outstandingThreads == 0)
progressDialog.setVisibility(View.VISIBLE);
outstandingThreads++;
}
new Thread(this).start();
}
@Override
public void handleMessage(Message message) {
Cursor cursor = (Cursor)message.obj;
if (cursor != null)
startManagingCursor(cursor);
if (getListAdapter() != null)
((CursorAdapter)getListAdapter()).changeCursor(cursor);
((CursorAdapter)getListAdapter()).changeCursor(cursor);
synchronized (this) {
outstandingThreads--;
if (outstandingThreads == 0)
progressDialog.setVisibility(View.GONE);
}
}
public void run() {
String text = searchBox.getText().toString();
Cursor cursor = getCursorForFilter(text);
Cursor cursor = getCursorForFilter(text);
this.obtainMessage(0, cursor).sendToTarget();
}
@ -849,11 +825,11 @@ public class SecureSMS extends ListActivity {
searchBox.requestFocus();
return true;
}
return false;
}
}
private class ContactUpdateObserver extends ContentObserver {
public ContactUpdateObserver() {
super(null);
@ -866,15 +842,15 @@ public class SecureSMS extends ListActivity {
RecipientFactory.clearCache();
}
}
private class MigrationHandler extends Handler implements Runnable {
private ProgressDialog progressDialog;
public void run() {
SmsMigrator.migrateDatabase(SecureSMS.this, masterSecret, this);
SmsMigrator.migrateDatabase(SecureSMS.this, masterSecret, this);
}
private void continueMigration() {
private void continueMigration() {
progressDialog = new ProgressDialog(SecureSMS.this);
progressDialog.setTitle("Migrating Database");
progressDialog.setMessage("Migrating your SMS database...");
@ -885,18 +861,18 @@ public class SecureSMS extends ListActivity {
progressDialog.show();
new Thread(this).start();
}
private void cancelMigration() {
SecureSMS.this.getSharedPreferences("SecureSMS", MODE_PRIVATE).edit().putBoolean("migrated", true).commit();
SecureSMS.this.migrateDatabaseComplete();
}
public void migrate() {
AlertDialog.Builder alertBuilder = new AlertDialog.Builder(SecureSMS.this);
alertBuilder.setTitle("Copy System Text Message Database?");
alertBuilder.setMessage("Current versions of TextSecure use an encrypted database that is separate from the default system database. Would you like to copy your existing text messages into TextSecure's encrypted database? Your default system database will be unaffected.");
alertBuilder.setCancelable(false);
alertBuilder.setPositiveButton("Copy", new DialogInterface.OnClickListener() {
alertBuilder.setPositiveButton("Copy", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int which) {
continueMigration();
}
@ -908,7 +884,7 @@ public class SecureSMS extends ListActivity {
});
alertBuilder.create().show();
}
@Override
public void handleMessage(Message message) {
switch (message.what) {
@ -927,5 +903,5 @@ public class SecureSMS extends ListActivity {
}
}
}