Basic navigation drawer support.

This commit is contained in:
Moxie Marlinspike 2013-06-22 21:44:12 -07:00
parent 5263ac1f1a
commit 903ab92f5f
36 changed files with 194 additions and 27 deletions

Binary file not shown.

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 171 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 182 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@ -1,13 +1,21 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" <android.support.v4.widget.DrawerLayout
android:layout_width="fill_parent" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="fill_parent" android:id="@+id/drawer_layout"
android:orientation="vertical" > android:layout_width="match_parent"
android:layout_height="match_parent">
<fragment <fragment
android:id="@+id/fragment_content" android:id="@+id/fragment_content"
android:name="org.thoughtcrime.securesms.ConversationListFragment" android:name="org.thoughtcrime.securesms.ConversationListFragment"
android:layout_width="fill_parent" android:layout_width="match_parent"
android:layout_height="fill_parent" /> android:layout_height="match_parent"/>
</LinearLayout> <ListView android:id="@+id/left_drawer"
android:layout_width="240dp"
android:layout_height="match_parent"
android:layout_gravity="start"
android:choiceMode="singleChoice"
android:dividerHeight="1dp"
android:background="?navigation_drawer_background"/>
</android.support.v4.widget.DrawerLayout>

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_vertical"
android:minHeight="48dp">
<ImageView android:id="@+id/navigation_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginRight="12dip"
android:layout_marginLeft="16dip"
android:contentDescription="Navigation Image"/>
<TextView android:id="@+id/navigation_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:layout_marginRight="26dp"
android:textColor="?navigation_drawer_text_color"/>
</LinearLayout>

View File

@ -41,12 +41,35 @@
<item>@string/preferences__slow</item> <item>@string/preferences__slow</item>
<item>@string/preferences__custom</item> <item>@string/preferences__custom</item>
</string-array> </string-array>
<string-array name="pref_led_blink_pattern_values"
translatable="false"> <string-array name="pref_led_blink_pattern_values" translatable="false">
<item>300,300</item> <item>300,300</item>
<item>500,2000</item> <item>500,2000</item>
<item>3000,3000</item> <item>3000,3000</item>
<item>custom</item> <item>custom</item>
</string-array> </string-array>
<string-array name="navigation_drawer_text">
<item>@string/arrays__import_export</item>
<item>@string/arrays__my_identity_key</item>
<item>@string/arrays__contact_keys</item>
</string-array>
<string-array name="navigation_drawer_values" translatable="false">
<item>import_export</item>
<item>my_identity_key</item>
<item>contact_identity_keys</item>
</string-array>
<string-array name="navigation_drawer_icons_light">
<item>@drawable/import_export_light</item>
<item>@drawable/my_identity_light</item>
<item>@drawable/contacts_identities_light</item>
</string-array>
<string-array name="navigation_drawer_icons_dark">
<item>@drawable/import_export_dark</item>
<item>@drawable/my_identity_dark</item>
<item>@drawable/contacts_identities_dark</item>
</string-array>
</resources> </resources>

View File

@ -16,4 +16,9 @@
<attr name="conversation_send_button" format="reference"/> <attr name="conversation_send_button" format="reference"/>
<attr name="conversation_send_secure_button" format="reference"/> <attr name="conversation_send_secure_button" format="reference"/>
<attr name="conversation_delivered_indicator" format="reference"/> <attr name="conversation_delivered_indicator" format="reference"/>
<attr name="navigation_drawer_background" format="reference|color"/>
<attr name="navigation_drawer_text_color" format="color"/>
<attr name="navigation_drawer_icons" format="reference"/>
<attr name="navigation_drawer_shadow" format="reference"/>
</resources> </resources>

View File

@ -84,7 +84,7 @@
<string name="ConversationActivity_invalid_recipient">Invalid recipient!</string> <string name="ConversationActivity_invalid_recipient">Invalid recipient!</string>
<string name="ConversationActivity_calls_not_supported">Calls Not Supported</string> <string name="ConversationActivity_calls_not_supported">Calls Not Supported</string>
<string name="ConversationActivity_this_device_does_not_appear_to_support_dial_actions">This device does not appear to support dial actions.</string> <string name="ConversationActivity_this_device_does_not_appear_to_support_dial_actions">This device does not appear to support dial actions.</string>
<!-- ConversationFragment --> <!-- ConversationFragment -->
<string name="ConversationFragment_message_details">Message details</string> <string name="ConversationFragment_message_details">Message details</string>
<string name="ConversationFragment_sender_s_transport_s_sent_received_s">Sender: %1$s\nTransport: %2$s\nSent/Received:%3$s</string> <string name="ConversationFragment_sender_s_transport_s_sent_received_s">Sender: %1$s\nTransport: %2$s\nSent/Received:%3$s</string>
@ -379,7 +379,12 @@
<string name="AndroidManifest__manage_identity_keys">Manage Identity Keys</string> <string name="AndroidManifest__manage_identity_keys">Manage Identity Keys</string>
<string name="AndroidManifest__complete_key_exchange">Complete Key Exchange</string> <string name="AndroidManifest__complete_key_exchange">Complete Key Exchange</string>
<string name="AndroidManifest__verify_imported_identity">Verify Imported Identity</string> <string name="AndroidManifest__verify_imported_identity">Verify Imported Identity</string>
<!-- arrays.xml -->
<string name="arrays__import_export">Import / Export</string>
<string name="arrays__my_identity_key">My Identity Key</string>
<string name="arrays__contact_keys">Contact Keys</string>
<!-- preferences.xml --> <!-- preferences.xml -->
<string name="preferences__general">General</string> <string name="preferences__general">General</string>
<string name="preferences__use_settings">Use Settings</string> <string name="preferences__use_settings">Use Settings</string>
@ -459,6 +464,8 @@
<string name="preferences__scan_through_all_conversation_threads_and_enforce_conversation_length_limits">Scan through all conversation threads and enforce conversation length limits</string> <string name="preferences__scan_through_all_conversation_threads_and_enforce_conversation_length_limits">Scan through all conversation threads and enforce conversation length limits</string>
<string name="preferences__light_theme">Light Theme</string> <string name="preferences__light_theme">Light Theme</string>
<string name="preferences__dark_theme">Dark Theme</string> <string name="preferences__dark_theme">Dark Theme</string>
<string name="preferences__appearance">Appearance</string>
<string name="preferences__theme">Theme</string>
<!-- **************************************** --> <!-- **************************************** -->
<!-- menus --> <!-- menus -->
@ -528,8 +535,6 @@
<!-- verify_keys --> <!-- verify_keys -->
<string name="verify_keys__menu_verified">Verified</string> <string name="verify_keys__menu_verified">Verified</string>
<string name="preferences__appearance">Appearance</string>
<string name="preferences__theme">Theme</string>
<!-- EOF --> <!-- EOF -->
</resources> </resources>

View File

@ -19,6 +19,15 @@
<item name="conversation_delivered_indicator">@drawable/ic_sms_mms_delivered_light</item> <item name="conversation_delivered_indicator">@drawable/ic_sms_mms_delivered_light</item>
</style> </style>
<style name="TextSecure.LightTheme.NavigationDrawer" parent="@style/TextSecure.LightTheme">
<item name="homeAsUpIndicator">@drawable/ic_drawer</item>
<item name="navigation_drawer_background">@color/abs__background_holo_light</item>
<item name="navigation_drawer_text_color">#ff333333</item>
<item name="navigation_drawer_icons">@array/navigation_drawer_icons_light</item>
<item name="navigation_drawer_shadow">@drawable/drawer_shadow_light</item>
</style>
<style name="TextSecure.DarkTheme" parent="@style/Theme.Sherlock"> <style name="TextSecure.DarkTheme" parent="@style/Theme.Sherlock">
<item name="conversation_list_item_background_read">@drawable/conversation_list_item_background_read_dark</item> <item name="conversation_list_item_background_read">@drawable/conversation_list_item_background_read_dark</item>
<item name="conversation_list_item_background_unread">@drawable/conversation_list_item_background_unread_dark</item> <item name="conversation_list_item_background_unread">@drawable/conversation_list_item_background_unread_dark</item>
@ -36,6 +45,15 @@
<item name="conversation_send_button">@drawable/ic_send_holo_dark</item> <item name="conversation_send_button">@drawable/ic_send_holo_dark</item>
<item name="conversation_send_secure_button">@drawable/ic_send_holo_dark_encrypted</item> <item name="conversation_send_secure_button">@drawable/ic_send_holo_dark_encrypted</item>
<item name="conversation_delivered_indicator">@drawable/ic_sms_mms_delivered_dark</item> <item name="conversation_delivered_indicator">@drawable/ic_sms_mms_delivered_dark</item>
</style>
<style name="TextSecure.DarkTheme.NavigationDrawer" parent="@style/TextSecure.DarkTheme">
<item name="homeAsUpIndicator">@drawable/ic_drawer</item>
<item name="navigation_drawer_background">#ff333333</item>
<item name="navigation_drawer_text_color">#ffdddddd</item>
<item name="navigation_drawer_icons">@array/navigation_drawer_icons_dark</item>
<item name="navigation_drawer_shadow">@drawable/drawer_shadow_dark</item>
</style> </style>
</resources> </resources>

View File

@ -1,18 +1,26 @@
package org.thoughtcrime.securesms; package org.thoughtcrime.securesms;
import android.content.Intent; import android.content.Intent;
import android.content.res.TypedArray;
import android.database.ContentObserver; import android.database.ContentObserver;
import android.os.AsyncTask; import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.provider.ContactsContract; import android.provider.ContactsContract;
import android.support.v4.view.GravityCompat;
import android.support.v4.widget.DrawerLayout;
import android.util.Log; import android.util.Log;
import android.view.View;
import android.view.WindowManager; import android.view.WindowManager;
import android.widget.AdapterView;
import android.widget.ListView;
import android.widget.SimpleAdapter;
import com.actionbarsherlock.view.Menu; import com.actionbarsherlock.view.Menu;
import com.actionbarsherlock.view.MenuInflater; import com.actionbarsherlock.view.MenuInflater;
import com.actionbarsherlock.view.MenuItem; import com.actionbarsherlock.view.MenuItem;
import org.thoughtcrime.securesms.ApplicationExportManager.ApplicationExportListener; import org.thoughtcrime.securesms.ApplicationExportManager.ApplicationExportListener;
import org.thoughtcrime.securesms.crypto.IdentityKeyUtil;
import org.thoughtcrime.securesms.crypto.MasterSecret; import org.thoughtcrime.securesms.crypto.MasterSecret;
import org.thoughtcrime.securesms.database.DatabaseFactory; import org.thoughtcrime.securesms.database.DatabaseFactory;
import org.thoughtcrime.securesms.database.ThreadDatabase; import org.thoughtcrime.securesms.database.ThreadDatabase;
@ -24,13 +32,20 @@ import org.thoughtcrime.securesms.service.SendReceiveService;
import org.thoughtcrime.securesms.util.DynamicTheme; import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MemoryCleaner; import org.thoughtcrime.securesms.util.MemoryCleaner;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
public class ConversationListActivity extends PassphraseRequiredSherlockFragmentActivity public class ConversationListActivity extends PassphraseRequiredSherlockFragmentActivity
implements ConversationListFragment.ConversationSelectedListener implements ConversationListFragment.ConversationSelectedListener,
ListView.OnItemClickListener
{ {
private final DynamicTheme dynamicTheme = new DynamicTheme(); private final DynamicTheme dynamicTheme = new DynamicTheme();
private ConversationListFragment fragment; private ConversationListFragment fragment;
private MasterSecret masterSecret; private MasterSecret masterSecret;
private DrawerLayout drawerLayout;
private ListView drawerList;
@Override @Override
public void onCreate(Bundle icicle) { public void onCreate(Bundle icicle) {
@ -40,6 +55,7 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
setContentView(R.layout.conversation_list_activity); setContentView(R.layout.conversation_list_activity);
getSupportActionBar().setTitle("TextSecure"); getSupportActionBar().setTitle("TextSecure");
initializeNavigationDrawer();
initializeSenderReceiverService(); initializeSenderReceiverService();
initializeResources(); initializeResources();
initializeContactUpdatesReceiver(); initializeContactUpdatesReceiver();
@ -76,6 +92,31 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
return true; return true;
} }
@Override
public void onItemClick(AdapterView parent, View view, int position, long id) {
String[] values = getResources().getStringArray(R.array.navigation_drawer_values);
String selected = values[position];
Intent intent;
if (selected.equals("import_export")) {
intent = new Intent();
} else if (selected.equals("my_identity_key")) {
intent = new Intent(this, ViewIdentityActivity.class);
intent.putExtra("identity_key", IdentityKeyUtil.getIdentityKey(this));
intent.putExtra("title", getString(R.string.ApplicationPreferencesActivity_my) + " " +
getString(R.string.ViewIdentityActivity_identity_fingerprint));
} else if (selected.equals("contact_identity_keys")) {
intent = new Intent(this, ReviewIdentitiesActivity.class);
intent.putExtra("master_secret", masterSecret);
} else {
return;
}
drawerLayout.closeDrawers();
startActivity(intent);
}
@Override @Override
public boolean onOptionsItemSelected(MenuItem item) { public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item); super.onOptionsItemSelected(item);
@ -89,6 +130,7 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
case R.id.menu_import: handleImportDatabase(); return true; case R.id.menu_import: handleImportDatabase(); return true;
case R.id.menu_clear_passphrase: handleClearPassphrase(); return true; case R.id.menu_clear_passphrase: handleClearPassphrase(); return true;
case R.id.menu_mark_all_read: handleMarkAllRead(); return true; case R.id.menu_mark_all_read: handleMarkAllRead(); return true;
case android.R.id.home: handleNavigationDrawerToggle(); return true;
} }
return false; return false;
@ -109,6 +151,14 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
startActivity(intent); startActivity(intent);
} }
private void handleNavigationDrawerToggle() {
if (drawerLayout.isDrawerOpen(drawerList)) {
drawerLayout.closeDrawer(drawerList);
} else {
drawerLayout.openDrawer(drawerList);
}
}
private void handleDisplaySettings() { private void handleDisplaySettings() {
Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class); Intent preferencesIntent = new Intent(this, ApplicationPreferencesActivity.class);
preferencesIntent.putExtra("master_secret", masterSecret); preferencesIntent.putExtra("master_secret", masterSecret);
@ -151,6 +201,40 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
}.execute(); }.execute();
} }
private void initializeNavigationDrawer() {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeButtonEnabled(true);
int[] attributes = new int[] {R.attr.navigation_drawer_icons, R.attr.navigation_drawer_shadow};
String[] from = new String[]{"navigation_icon", "navigation_text" };
int[] to = new int[] {R.id.navigation_icon, R.id.navigation_text};
TypedArray iconArray = obtainStyledAttributes(attributes);
int iconArrayResource = iconArray.getResourceId(0, -1);
TypedArray icons = getResources().obtainTypedArray(iconArrayResource);
String[] text = getResources().getStringArray(R.array.navigation_drawer_text);
List<HashMap<String, String>> items = new ArrayList<HashMap<String, String>>();
for(int i = 0; i < text.length; i++){
HashMap<String, String> item = new HashMap<String, String>();
item.put("navigation_icon", Integer.toString(icons.getResourceId(i, -1)));
item.put("navigation_text", text[i]);
items.add(item);
}
DrawerLayout drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
ListView drawer = (ListView)findViewById(R.id.left_drawer);
SimpleAdapter adapter = new SimpleAdapter(this, items, R.layout.navigation_drawer_item, from, to);
drawerLayout.setDrawerShadow(iconArray.getDrawable(1), GravityCompat.START);
drawer.setAdapter(adapter);
drawer.setOnItemClickListener(this);
iconArray.recycle();
icons.recycle();
}
private void initializeContactUpdatesReceiver() { private void initializeContactUpdatesReceiver() {
ContentObserver observer = new ContentObserver(null) { ContentObserver observer = new ContentObserver(null) {
@Override @Override
@ -179,6 +263,8 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
WindowManager.LayoutParams.FLAG_SECURE); WindowManager.LayoutParams.FLAG_SECURE);
} }
this.drawerLayout = (DrawerLayout)findViewById(R.id.drawer_layout);
this.drawerList = (ListView)findViewById(R.id.left_drawer);
this.masterSecret = (MasterSecret)getIntent().getParcelableExtra("master_secret"); this.masterSecret = (MasterSecret)getIntent().getParcelableExtra("master_secret");
this.fragment = (ConversationListFragment)this.getSupportFragmentManager() this.fragment = (ConversationListFragment)this.getSupportFragmentManager()
@ -186,4 +272,5 @@ public class ConversationListActivity extends PassphraseRequiredSherlockFragment
this.fragment.setMasterSecret(masterSecret); this.fragment.setMasterSecret(masterSecret);
} }
}
}

View File

@ -1,12 +1,12 @@
package org.thoughtcrime.securesms.util; package org.thoughtcrime.securesms.util;
import android.app.Activity; import android.app.Activity;
import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.os.Build; import android.os.Build;
import android.preference.PreferenceManager; import android.preference.PreferenceManager;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity; import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.R; import org.thoughtcrime.securesms.R;
public class DynamicTheme { public class DynamicTheme {
@ -36,18 +36,16 @@ public class DynamicTheme {
} }
} }
public static int getSelectedTheme(Context context) { private static int getSelectedTheme(Activity activity) {
String theme = PreferenceManager.getDefaultSharedPreferences(context) String theme = PreferenceManager.getDefaultSharedPreferences(activity)
.getString(ApplicationPreferencesActivity.THEME_PREF, "light"); .getString(ApplicationPreferencesActivity.THEME_PREF, "light");
return getSelectedTheme(theme);
}
public static int getSelectedTheme(String theme) {
if (theme.equals("light")) { if (theme.equals("light")) {
return R.style.TextSecure_LightTheme; if (activity instanceof ConversationListActivity) return R.style.TextSecure_LightTheme_NavigationDrawer;
else return R.style.TextSecure_LightTheme;
} else if (theme.equals("dark")) { } else if (theme.equals("dark")) {
return R.style.TextSecure_DarkTheme; if (activity instanceof ConversationListActivity) return R.style.TextSecure_DarkTheme_NavigationDrawer;
else return R.style.TextSecure_DarkTheme;
} }
return R.style.TextSecure_LightTheme; return R.style.TextSecure_LightTheme;