Migrate settings to support-v4-preferencefragment, split out identities

This commit is contained in:
str4d
2015-05-28 11:01:57 +00:00
parent 1e090a3969
commit 29a0d02a84
26 changed files with 786 additions and 753 deletions

View File

@@ -60,6 +60,9 @@ dependencies {
compile 'com.google.zxing:android-integration:3.2.0'
compile 'com.androidplot:androidplot-core:0.6.1'
compile 'com.pnikosis:materialish-progress:1.4'
compile ('com.android.support:support-v4-preferencefragment:1.0.0@aar'){
exclude module: 'support-v4'
}
// Testing-only dependencies
androidTestCompile 'com.android.support.test.espresso:espresso-core:2.0'
@@ -80,7 +83,8 @@ dependencyVerification {
'com.google.zxing:core:7fe5a8ff437635a540e56317649937b768b454795ce999ed5f244f83373dee7b',
'com.google.zxing:android-integration:0de037a73138033c4a03cdbca5d5728ef65a026ffb89afce071105f43a98ee0e',
'com.androidplot:androidplot-core:777b54dd98b8dedc5f3fcc95018eece1188f6c692dcbd5b7744af175e15d70bd',
'com.pnikosis:materialish-progress:5dd770a78047d8dbf2690deb686675fe2b242a6d06bb52ef425c829454ca54b8'
'com.pnikosis:materialish-progress:5dd770a78047d8dbf2690deb686675fe2b242a6d06bb52ef425c829454ca54b8',
'com.android.support:support-v4-preferencefragment:5470f5872514a6226fa1fc6f4e000991f38805691c534cf0bd2778911fc773ad',
]
}

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<header
android:fragment="i2p.bote.android.config.SettingsActivity$SettingsFragment"
android:title="@string/pref_title_general"
android:summary="@string/pref_summ_general" >
<extra
android:name="settings"
android:value="general" />
</header>
<header android:title="@string/pref_title_change_password" >
<intent
android:targetClass="i2p.bote.android.config.SetPasswordActivity"
android:targetPackage="i2p.bote.android.debug" />
</header>
<header
android:id="@+id/identity_settings"
android:title="@string/pref_title_identities" />
<header
android:id="@+id/new_identity"
android:title="@string/new_identity" >
<intent
android:targetClass="i2p.bote.android.config.EditIdentityActivity"
android:targetPackage="i2p.bote.android.debug" />
</header>
</preference-headers>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference android:title="@string/pref_title_general" >
<intent
android:action="i2p.bote.PREFS_GENERAL"
android:targetClass="i2p.bote.android.config.SettingsActivity"
android:targetPackage="i2p.bote.android.debug" />
</Preference>
<Preference android:title="@string/pref_title_change_password" >
<intent
android:targetClass="i2p.bote.android.config.SetPasswordActivity"
android:targetPackage="i2p.bote.android.debug" />
</Preference>
<Preference android:title="@string/new_identity" >
<intent
android:targetClass="i2p.bote.android.config.EditIdentityActivity"
android:targetPackage="i2p.bote.android.debug" />
</Preference>
</PreferenceScreen>

View File

@@ -117,26 +117,34 @@
android:value="i2p.bote.android.config.SettingsActivity"/>
</activity>
<activity
android:name=".config.ViewIdentityActivity"
android:name=".identities.IdentityListActivity"
android:label="@string/pref_title_identities"
android:parentActivityName=".config.SettingsActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="i2p.bote.android.config.SettingsActivity"/>
</activity>
<activity
android:name=".config.EditIdentityActivity"
android:name=".identities.ViewIdentityActivity"
android:parentActivityName=".identities.IdentityListActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="i2p.bote.android.identities.IdentityListActivity"/>
</activity>
<activity
android:name=".identities.EditIdentityActivity"
android:label="@string/title_new_identity"
android:parentActivityName=".config.ViewIdentityActivity">
android:parentActivityName=".identities.ViewIdentityActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="i2p.bote.android.config.ViewIdentityActivity"/>
android:value=".identities.ViewIdentityActivity"/>
</activity>
<activity
android:name=".config.IdentityShipActivity"
android:parentActivityName=".config.SettingsActivity">
android:name=".identities.IdentityShipActivity"
android:parentActivityName=".identities.IdentityListActivity">
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="i2p.bote.android.config.SettingsActivity"/>
android:value="i2p.bote.android.identities.IdentityListActivity"/>
</activity>
<activity
android:name=".HelpActivity"

View File

@@ -0,0 +1,180 @@
package i2p.bote.android.config;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceManager;
import android.support.v4.preference.PreferenceFragment;
import java.util.Map;
import i2p.bote.Configuration;
import i2p.bote.I2PBote;
import i2p.bote.android.R;
import i2p.bote.android.widget.SummaryEditTextPreference;
public class GeneralPreferenceFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
addPreferencesFromResource(R.xml.settings_general);
setupGeneralSettings();
}
@Override
public void onResume() {
super.onResume();
((SettingsActivity) getActivity()).getSupportActionBar().setTitle(R.string.pref_title_general);
}
@Override
public void onPause() {
Configuration config = I2PBote.getInstance().getConfiguration();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
Map<String, ?> all = prefs.getAll();
for (String x : all.keySet()) {
if ("autoMailCheckEnabled".equals(x))
config.setAutoMailCheckEnabled(prefs.getBoolean(x, true));
else if ("mailCheckInterval".equals(x))
config.setMailCheckInterval(prefs.getInt(x, 30));
else if ("deliveryCheckEnabled".equals(x))
config.setDeliveryCheckEnabled(prefs.getBoolean(x, true));
else if ("hideLocale".equals(x))
config.setHideLocale(prefs.getBoolean(x, true));
else if ("includeSentTime".equals(x))
config.setIncludeSentTime(prefs.getBoolean(x, true));
else if ("numSendHops".equals(x))
config.setNumStoreHops(Integer.parseInt(prefs.getString(x, "0")));
else if ("relayMinDelay".equals(x))
config.setRelayMinDelay(prefs.getInt(x, 5));
else if ("relayMaxDelay".equals(x))
config.setRelayMaxDelay(prefs.getInt(x, 40));
}
config.save();
// Store the settings in Android
super.onPause();
}
private void setupGeneralSettings() {
addPreferencesFromResource(R.xml.settings_general);
ListPreference numSendHops = (ListPreference) findPreference("numSendHops");
int value = Integer.valueOf(numSendHops.getValue());
numSendHops.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
numSendHops.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int value = Integer.valueOf((String) newValue);
preference.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
return true;
}
});
final PreferenceCategory i2pCat = (PreferenceCategory) findPreference("i2pCategory");
CheckBoxPreference routerAuto = (CheckBoxPreference) findPreference("i2pbote.router.auto");
if (!routerAuto.isChecked()) {
setupI2PCategory(getActivity(), i2pCat);
}
routerAuto.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final Boolean checked = (Boolean) newValue;
if (!checked) {
setupI2PCategory(getActivity(), i2pCat);
} else {
Preference p1 = i2pCat.findPreference("i2pbote.router.use");
Preference p2 = i2pCat.findPreference("i2pbote.i2cp.tcp.host");
Preference p3 = i2pCat.findPreference("i2pbote.i2cp.tcp.port");
if (p1 != null)
i2pCat.removePreference(p1);
if (p2 != null)
i2pCat.removePreference(p2);
if (p3 != null)
i2pCat.removePreference(p3);
}
return true;
}
});
}
private static void setupI2PCategory(Context context, PreferenceCategory i2pCat) {
final ListPreference routerChoice = createRouterChoice(context);
final EditTextPreference hostField = createHostField(context);
final EditTextPreference portField = createPortField(context);
i2pCat.addPreference(routerChoice);
i2pCat.addPreference(hostField);
i2pCat.addPreference(portField);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
routerChoice.setSummary(routerChoice.getEntry());
if ("remote".equals(routerChoice.getValue())) {
hostField.setEnabled(true);
portField.setEnabled(true);
}
routerChoice.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String val = newValue.toString();
int index = routerChoice.findIndexOfValue(val);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
routerChoice.setSummary(routerChoice.getEntries()[index]);
if (index == 2) {
hostField.setEnabled(true);
hostField.setText("127.0.0.1");
portField.setEnabled(true);
portField.setText("7654");
} else {
hostField.setEnabled(false);
hostField.setText("internal");
portField.setEnabled(false);
portField.setText("internal");
}
return true;
}
});
}
private static ListPreference createRouterChoice(Context context) {
ListPreference routerChoice = new ListPreference(context);
routerChoice.setKey("i2pbote.router.use");
routerChoice.setEntries(R.array.routerOptionNames);
routerChoice.setEntryValues(R.array.routerOptions);
routerChoice.setTitle(R.string.pref_title_router);
routerChoice.setSummary("%s");
routerChoice.setDialogTitle(R.string.pref_dialog_title_router);
routerChoice.setDefaultValue("internal");
return routerChoice;
}
private static EditTextPreference createHostField(Context context) {
EditTextPreference p = new SummaryEditTextPreference(context);
p.setKey("i2pbote.i2cp.tcp.host");
p.setTitle(R.string.pref_title_i2cp_host);
p.setSummary("%s");
p.setDefaultValue("internal");
p.setEnabled(false);
return p;
}
private static EditTextPreference createPortField(Context context) {
EditTextPreference p = new SummaryEditTextPreference(context);
p.setKey("i2pbote.i2cp.tcp.port");
p.setTitle(R.string.pref_title_i2cp_port);
p.setSummary("%s");
p.setDefaultValue("internal");
p.setEnabled(false);
return p;
}
}

View File

@@ -1,61 +1,24 @@
package i2p.bote.android.config;
import android.annotation.TargetApi;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.preference.CheckBoxPreference;
import android.preference.EditTextPreference;
import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceCategory;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentManager;
import android.support.v4.preference.PreferenceFragment;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListAdapter;
import android.widget.TextView;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import i2p.bote.Configuration;
import i2p.bote.I2PBote;
import i2p.bote.android.EmailListActivity;
import i2p.bote.android.InitActivities;
import i2p.bote.android.R;
import i2p.bote.android.widget.SummaryEditTextPreference;
import i2p.bote.email.EmailIdentity;
import i2p.bote.fileencryption.PasswordException;
import i2p.bote.android.identities.IdentityListActivity;
public class SettingsActivity extends PreferenceActivity {
// Actions for legacy settings
private static final String ACTION_PREFS_GENERAL = "i2p.bote.PREFS_GENERAL";
static final int ALTER_IDENTITY_LIST = 1;
private Toolbar mToolbar;
// Preference Header vars
private Header[] mIdentityListHeaders;
private Preference[] mLegacyIdentityListHeaders;
private String mRequestedIdentityKey;
private String mDeletingIdentityKey;
// Async tasks
private LoadIdentityListTask mLoadIdentityListTask;
public class SettingsActivity extends AppCompatActivity {
public static final String PREFERENCE_CATEGORY = "preference_category";
public static final String PREFERENCE_CATEGORY_GENERAL = "preference_category_general";
public static final String PREFERENCE_CATEGORY_CHANGE_PASSWORD = "preference_category_change_password";
public static final String PREFERENCE_CATEGORY_IDENTITIES = "preference_category_identities";
//
@@ -65,166 +28,41 @@ public class SettingsActivity extends PreferenceActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar);
// Initialize I2P settings
InitActivities init = new InitActivities(this);
init.initialize();
String action = getIntent().getAction();
if (action != null) {
loadLegacySettings(action);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Load the legacy preferences headers
buildLegacyHeaders();
}
// Set the action bar
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
mToolbar.setTitle(getTitle());
Fragment fragment;
String category = getIntent().getStringExtra(PREFERENCE_CATEGORY);
if (category != null)
fragment = getFragmentForCategory(category);
else
fragment = new SettingsFragment();
getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.commit();
}
@Override
public void setContentView(int layoutResID) {
ViewGroup contentView = (ViewGroup) LayoutInflater.from(this).inflate(
R.layout.activity_settings,
(ViewGroup) getWindow().getDecorView().getRootView(), false);
mToolbar = (Toolbar) contentView.findViewById(R.id.main_toolbar);
mToolbar.setNavigationIcon(getResources().getDrawable(R.drawable.ic_arrow_back_white_24dp));
mToolbar.setNavigationOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
onBackPressed();
public boolean onSupportNavigateUp() {
FragmentManager fragmentManager = getSupportFragmentManager();
if (fragmentManager.getBackStackEntryCount() > 0) {
fragmentManager.popBackStack();
} else {
Intent intent = new Intent(this, EmailListActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
startActivity(intent);
finish();
}
});
ViewGroup contentWrapper = (ViewGroup) contentView.findViewById(R.id.content_wrapper);
LayoutInflater.from(this).inflate(layoutResID, contentWrapper, true);
getWindow().setContentView(contentView);
}
@Override
public void onResume() {
super.onResume();
updateIdentities();
}
@Override
protected void onPause() {
Configuration config = I2PBote.getInstance().getConfiguration();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
Map<String, ?> all = prefs.getAll();
for (String x : all.keySet()) {
if ("autoMailCheckEnabled".equals(x))
config.setAutoMailCheckEnabled(prefs.getBoolean(x, true));
else if ("mailCheckInterval".equals(x))
config.setMailCheckInterval(prefs.getInt(x, 30));
else if ("deliveryCheckEnabled".equals(x))
config.setDeliveryCheckEnabled(prefs.getBoolean(x, true));
else if ("hideLocale".equals(x))
config.setHideLocale(prefs.getBoolean(x, true));
else if ("includeSentTime".equals(x))
config.setIncludeSentTime(prefs.getBoolean(x, true));
else if ("numSendHops".equals(x))
config.setNumStoreHops(Integer.parseInt(prefs.getString(x, "0")));
else if ("relayMinDelay".equals(x))
config.setRelayMinDelay(prefs.getInt(x, 5));
else if ("relayMaxDelay".equals(x))
config.setRelayMaxDelay(prefs.getInt(x, 40));
}
config.save();
// Store the settings in Android
super.onPause();
}
@Override
protected boolean isValidFragment(String fragmentName) {
return SettingsFragment.class.getName().equals(fragmentName);
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.settings, menu);
return super.onCreateOptionsMenu(menu);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.export_identities:
Intent ei = new Intent(this, IdentityShipActivity.class);
ei.putExtra(IdentityShipActivity.EXPORTING, true);
startActivity(ei);
return true;
case R.id.import_identities:
Intent ii = new Intent(this, IdentityShipActivity.class);
ii.putExtra(IdentityShipActivity.EXPORTING, false);
startActivity(ii);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
//
// Building Headers
//
@SuppressWarnings("deprecation")
private void buildLegacyHeaders() {
// Always add general preferences as first header
addPreferencesFromResource(R.xml.settings_headers_legacy);
PreferenceCategory ic = new PreferenceCategory(this);
ic.setTitle(R.string.pref_title_identities);
// Then add zero or more identity headers as necessary
if (mLegacyIdentityListHeaders != null) {
getPreferenceScreen().addPreference(ic);
for (Preference header : mLegacyIdentityListHeaders) {
if (header != null) {
String key = header.getIntent().getExtras().getString(
ViewIdentityFragment.ADDRESS);
if (!key.equals(mDeletingIdentityKey)) {
ic.addPreference(header);
if (key.equals(mRequestedIdentityKey)) {
mRequestedIdentityKey = null;
}
}
}
}
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
@Override
public void onBuildHeaders(List<Header> target) {
// The resource com.android.internal.R.bool.preferences_prefer_dual_pane
// has different definitions based upon screen size. At present, it will
// be true for -sw720dp devices, false otherwise. For your curiosity, in
// Nexus 7 it is false.
// Always add general preferences as first header
target.clear();
loadHeadersFromResource(R.xml.settings_headers, target);
// Then add zero or more identity headers as necessary
if (mIdentityListHeaders != null) {
for (Header header : mIdentityListHeaders) {
if (header != null && header.id != HEADER_ID_UNDEFINED) {
String key = header.extras.getString(
ViewIdentityFragment.ADDRESS);
if (!key.equals(mDeletingIdentityKey)) {
target.add(header);
if (key.equals(mRequestedIdentityKey)) {
mRequestedIdentityKey = null;
}
}
}
}
}
}
@@ -232,454 +70,65 @@ public class SettingsActivity extends PreferenceActivity {
// Settings pages
//
@SuppressWarnings("deprecation")
private void loadLegacySettings(String action) {
if (ACTION_PREFS_GENERAL.equals(action)) {
addPreferencesFromResource(R.xml.settings_general);
ListPreference numSendHops = (ListPreference) findPreference("numSendHops");
int value = Integer.valueOf(numSendHops.getValue());
numSendHops.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
numSendHops.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int value = Integer.valueOf((String) newValue);
preference.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
return true;
}
});
final PreferenceCategory i2pCat = (PreferenceCategory) findPreference("i2pCategory");
CheckBoxPreference routerAuto = (CheckBoxPreference) findPreference("i2pbote.router.auto");
if (!routerAuto.isChecked()) {
setupI2PCategory(this, i2pCat);
}
routerAuto.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final Boolean checked = (Boolean) newValue;
if (!checked) {
setupI2PCategory(SettingsActivity.this, i2pCat);
} else {
Preference p1 = i2pCat.findPreference("i2pbote.router.use");
Preference p2 = i2pCat.findPreference("i2pbote.i2cp.tcp.host");
Preference p3 = i2pCat.findPreference("i2pbote.i2cp.tcp.port");
if (p1 != null)
i2pCat.removePreference(p1);
if (p2 != null)
i2pCat.removePreference(p2);
if (p3 != null)
i2pCat.removePreference(p3);
}
return true;
}
});
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
public static class SettingsFragment extends PreferenceFragment {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
addPreferencesFromResource(R.xml.settings);
String settings = getArguments().getString("settings");
if ("general".equals(settings)) {
addPreferencesFromResource(R.xml.settings_general);
ListPreference numSendHops = (ListPreference) findPreference("numSendHops");
int value = Integer.valueOf(numSendHops.getValue());
numSendHops.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
numSendHops.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
int value = Integer.valueOf((String) newValue);
preference.setSummary(getResources().getQuantityString(R.plurals.pref_summ_numHops,
value, value));
return true;
}
});
final PreferenceCategory i2pCat = (PreferenceCategory) findPreference("i2pCategory");
CheckBoxPreference routerAuto = (CheckBoxPreference) findPreference("i2pbote.router.auto");
if (!routerAuto.isChecked()) {
setupI2PCategory(getActivity(), i2pCat);
}
routerAuto.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final Boolean checked = (Boolean) newValue;
if (!checked) {
setupI2PCategory(getActivity(), i2pCat);
} else {
Preference p1 = i2pCat.findPreference("i2pbote.router.use");
Preference p2 = i2pCat.findPreference("i2pbote.i2cp.tcp.host");
Preference p3 = i2pCat.findPreference("i2pbote.i2cp.tcp.port");
if (p1 != null)
i2pCat.removePreference(p1);
if (p2 != null)
i2pCat.removePreference(p2);
if (p3 != null)
i2pCat.removePreference(p3);
}
return true;
}
});
}
}
}
private static void setupI2PCategory(Context context, PreferenceCategory i2pCat) {
final ListPreference routerChoice = createRouterChoice(context);
final EditTextPreference hostField = createHostField(context);
final EditTextPreference portField = createPortField(context);
i2pCat.addPreference(routerChoice);
i2pCat.addPreference(hostField);
i2pCat.addPreference(portField);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
routerChoice.setSummary(routerChoice.getEntry());
if ("remote".equals(routerChoice.getValue())) {
hostField.setEnabled(true);
portField.setEnabled(true);
}
routerChoice.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
public boolean onPreferenceChange(Preference preference, Object newValue) {
final String val = newValue.toString();
int index = routerChoice.findIndexOfValue(val);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
routerChoice.setSummary(routerChoice.getEntries()[index]);
if (index == 2) {
hostField.setEnabled(true);
hostField.setText("127.0.0.1");
portField.setEnabled(true);
portField.setText("7654");
} else {
hostField.setEnabled(false);
hostField.setText("internal");
portField.setEnabled(false);
portField.setText("internal");
}
return true;
}
});
}
private static ListPreference createRouterChoice(Context context) {
ListPreference routerChoice = new ListPreference(context);
routerChoice.setKey("i2pbote.router.use");
routerChoice.setEntries(R.array.routerOptionNames);
routerChoice.setEntryValues(R.array.routerOptions);
routerChoice.setTitle(R.string.pref_title_router);
routerChoice.setSummary("%s");
routerChoice.setDialogTitle(R.string.pref_dialog_title_router);
routerChoice.setDefaultValue("internal");
return routerChoice;
}
private static EditTextPreference createHostField(Context context) {
EditTextPreference p = new SummaryEditTextPreference(context);
p.setKey("i2pbote.i2cp.tcp.host");
p.setTitle(R.string.pref_title_i2cp_host);
p.setSummary("%s");
p.setDefaultValue("internal");
p.setEnabled(false);
return p;
}
private static EditTextPreference createPortField(Context context) {
EditTextPreference p = new SummaryEditTextPreference(context);
p.setKey("i2pbote.i2cp.tcp.port");
p.setTitle(R.string.pref_title_i2cp_port);
p.setSummary("%s");
p.setDefaultValue("internal");
p.setEnabled(false);
return p;
}
//
// Update list of identities in headers
//
/**
* Starts the async reload of the identities list
* (if the headers are being displayed)
*/
private void updateIdentities() {
if (shouldUpdateIdentities()) {
mLoadIdentityListTask = (LoadIdentityListTask)
new LoadIdentityListTask().execute();
}
}
private boolean shouldUpdateIdentities() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB)
return getIntent().getAction() == null;
else
return showingHeaders();
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private boolean showingHeaders() {
return hasHeaders();
}
//
// Load list of identities and convert
// into appropriate type of header
//
private class LoadIdentityListTask extends AsyncTask<String, Void, Object[]> {
protected Object[] doInBackground(String... params) {
try {
Collection<EmailIdentity> identities = I2PBote.getInstance().getIdentities().getAll();
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
// Return legacy headers
return loadLegacyHeaders(identities);
} else {
// Return list of Headers
return loadHeaders(identities);
}
} catch (PasswordException e) {
cancel(false);
return new Object[]{e};
} catch (IOException e) {
cancel(false);
return new Object[]{e};
} catch (GeneralSecurityException e) {
cancel(false);
return new Object[]{e};
}
}
private Object[] loadLegacyHeaders(Collection<EmailIdentity> identities) {
Preference[] result = new Preference[identities.size()];
int index = 0;
for (EmailIdentity identity : identities) {
final String name = identity.getPublicName();
final String desc = identity.getDescription();
final String key = identity.getKey();
final Intent intent = new Intent(
getApplicationContext(), ViewIdentityActivity.class);
final Bundle args = new Bundle();
args.putString(ViewIdentityFragment.ADDRESS, key);
intent.putExtras(args);
final Preference newHeader = new Preference(SettingsActivity.this);
newHeader.setTitle(name);
newHeader.setSummary(desc);
newHeader.setIntent(intent);
result[index++] = newHeader;
}
return new Object[]{result};
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private Object[] loadHeaders(Collection<EmailIdentity> identities) {
Header[] result = new Header[identities.size()];
int index = 0;
for (EmailIdentity identity : identities) {
final long id = identity.getHash().hashCode();
final String name = identity.getPublicName();
final String desc = identity.getDescription();
final String key = identity.getKey();
final Intent intent = new Intent(
getApplicationContext(), ViewIdentityActivity.class);
final Bundle args = new Bundle();
args.putString(ViewIdentityFragment.ADDRESS, key);
intent.putExtras(args);
final Header newHeader = new Header();
newHeader.id = id;
newHeader.title = name;
newHeader.summary = desc;
newHeader.intent = intent;
newHeader.extras = args;
result[index++] = newHeader;
}
return new Object[]{result};
findPreference(PREFERENCE_CATEGORY_GENERAL)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_GENERAL));
findPreference(PREFERENCE_CATEGORY_CHANGE_PASSWORD)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_CHANGE_PASSWORD));
findPreference(PREFERENCE_CATEGORY_IDENTITIES)
.setOnPreferenceClickListener(new CategoryClickListener(PREFERENCE_CATEGORY_IDENTITIES));
}
@Override
protected void onPostExecute(Object[] result) {
if (isCancelled()) return;
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
showLegacyHeaders(result);
} else {
showHeaders(result);
}
public void onResume() {
super.onResume();
((SettingsActivity) getActivity()).getSupportActionBar().setTitle(R.string.action_settings);
}
@SuppressWarnings("deprecation")
private void showLegacyHeaders(Object[] result) {
mLegacyIdentityListHeaders = (Preference[]) result[0];
getPreferenceScreen().removeAll();
buildLegacyHeaders();
}
private class CategoryClickListener implements Preference.OnPreferenceClickListener {
private String category;
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private void showHeaders(Object[] result) {
mIdentityListHeaders = (Header[]) result[0];
invalidateHeaders();
public CategoryClickListener(String category) {
this.category = category;
}
@Override
protected void onCancelled(Object[] result) {
}
}
//
// Styling for headers
//
@Override
public void setListAdapter(ListAdapter adapter) {
if (adapter == null) {
super.setListAdapter(null);
} else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
super.setListAdapter(adapter);
} else {
super.setListAdapter(new HeaderAdapter(this, adapter));
}
}
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
private static class HeaderAdapter extends ArrayAdapter<Header> {
static final int HEADER_TYPE_CATEGORY = 0;
static final int HEADER_TYPE_NORMAL = 1;
private static final int HEADER_TYPE_COUNT = HEADER_TYPE_NORMAL + 1;
private static class HeaderViewHolder {
TextView title;
TextView summary;
}
private ListAdapter mAdapter;
private LayoutInflater mInflater;
static int getHeaderType(Header header) {
if (header.fragment == null && header.intent == null) {
return HEADER_TYPE_CATEGORY;
} else {
return HEADER_TYPE_NORMAL;
}
}
@Override
public int getItemViewType(int position) {
Header header = getItem(position);
return getHeaderType(header);
}
@Override
public boolean areAllItemsEnabled() {
return false; // because of categories
}
@Override
public boolean isEnabled(int position) {
try {
return getItemViewType(position) != HEADER_TYPE_CATEGORY;
} catch (IndexOutOfBoundsException e) {
// Happens when deleting an identity
return false;
}
}
@Override
public int getViewTypeCount() {
return HEADER_TYPE_COUNT;
}
@Override
public boolean hasStableIds() {
return true;
}
public HeaderAdapter(Context context, ListAdapter adapter) {
super(context, 0);
mAdapter = adapter;
mInflater = (LayoutInflater) context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
}
@Override
public Header getItem(int position) {
return (Header) mAdapter.getItem(position);
}
@Override
public int getCount() {
return mAdapter.getCount();
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
HeaderViewHolder holder;
Header header = getItem(position);
int headerType = getHeaderType(header);
View view;
if (convertView == null) {
holder = new HeaderViewHolder();
switch (headerType) {
case HEADER_TYPE_CATEGORY:
view = new TextView(getContext(), null,
android.R.attr.listSeparatorTextViewStyle);
holder.title = (TextView) view;
public boolean onPreferenceClick(Preference preference) {
switch (category) {
case PREFERENCE_CATEGORY_CHANGE_PASSWORD:
Intent spi = new Intent(getActivity(), SetPasswordActivity.class);
startActivity(spi);
break;
case PREFERENCE_CATEGORY_IDENTITIES:
Intent ili = new Intent(getActivity(), IdentityListActivity.class);
startActivity(ili);
break;
case HEADER_TYPE_NORMAL:
default:
view = mInflater.inflate(
R.layout.preference_header_item, parent,
false);
holder.title = (TextView)
view.findViewById(android.R.id.title);
holder.summary = (TextView)
view.findViewById(android.R.id.summary);
break;
}
view.setTag(holder);
} else {
view = convertView;
holder = (HeaderViewHolder) view.getTag();
Fragment fragment = getFragmentForCategory(category);
getActivity().getSupportFragmentManager().beginTransaction()
.replace(R.id.container, fragment)
.addToBackStack(null)
.commit();
}
// All view fields must be updated every time, because the view may be recycled
switch (headerType) {
case HEADER_TYPE_CATEGORY:
holder.title.setText(header.getTitle(getContext().getResources()));
break;
case HEADER_TYPE_NORMAL:
updateCommonHeaderView(header, holder);
break;
return true;
}
}
}
return view;
}
private void updateCommonHeaderView(Header header, HeaderViewHolder holder) {
holder.title.setText(header.getTitle(getContext().getResources()));
CharSequence summary = header.getSummary(getContext().getResources());
if (summary != null && !summary.toString().isEmpty()) {
holder.summary.setVisibility(View.VISIBLE);
holder.summary.setText(summary);
} else {
holder.summary.setVisibility(View.GONE);
}
private static Fragment getFragmentForCategory(String category) {
switch (category) {
case PREFERENCE_CATEGORY_GENERAL:
return new GeneralPreferenceFragment();
default:
throw new AssertionError();
}
}
}

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import i2p.bote.android.InitActivities;
import i2p.bote.android.R;

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import android.app.Activity;
import android.content.Context;

View File

@@ -0,0 +1,134 @@
package i2p.bote.android.identities;
import android.content.Context;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import i2p.bote.android.R;
import i2p.bote.android.util.BoteHelper;
import i2p.bote.email.EmailIdentity;
public class IdentityAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private Context mCtx;
private List<EmailIdentity> mIdentities;
private IdentityListFragment.IdentityListListener mListener;
public static class SimpleViewHolder extends RecyclerView.ViewHolder {
public SimpleViewHolder(View itemView) {
super(itemView);
}
}
public static class IdentityViewHolder extends RecyclerView.ViewHolder {
public ImageView mPicture;
public TextView mName;
public IdentityViewHolder(View itemView) {
super(itemView);
mPicture = (ImageView) itemView.findViewById(R.id.identity_picture);
mName = (TextView) itemView.findViewById(R.id.identity_name);
}
}
public IdentityAdapter(Context context, IdentityListFragment.IdentityListListener listener) {
mCtx = context;
mListener = listener;
setHasStableIds(true);
}
public void setIdentities(Collection<EmailIdentity> identities) {
if (identities != null) {
mIdentities = new ArrayList<>();
mIdentities.addAll(identities);
} else
mIdentities = null;
notifyDataSetChanged();
}
@Override
public int getItemViewType(int position) {
if (position == 0)
return R.layout.listitem_text;
return R.layout.listitem_contact;
}
// Create new views (invoked by the layout manager)
@Override
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent,
int viewType) {
View v = LayoutInflater.from(parent.getContext())
.inflate(viewType, parent, false);
switch (viewType) {
case R.layout.listitem_identity:
return new IdentityViewHolder(v);
default:
return new SimpleViewHolder(v);
}
}
// Replace the contents of a view (invoked by the layout manager)
@Override
public void onBindViewHolder(RecyclerView.ViewHolder holder, int position) {
switch (holder.getItemViewType()) {
case R.layout.listitem_text:
((TextView) holder.itemView).setText(
mCtx.getResources().getString(R.string.new_identity));
holder.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onNewIdentity();
}
});
break;
case R.layout.listitem_identity:
final IdentityViewHolder cvh = (IdentityViewHolder) holder;
EmailIdentity identity = mIdentities.get(position - 1);
String pic = identity.getPictureBase64();
if (pic != null && !pic.isEmpty())
cvh.mPicture.setImageBitmap(BoteHelper.decodePicture(pic));
else {
ViewGroup.LayoutParams lp = cvh.mPicture.getLayoutParams();
cvh.mPicture.setImageBitmap(BoteHelper.getIdenticonForAddress(identity.getKey(), lp.width, lp.height));
}
cvh.mName.setText(identity.getPublicName());
cvh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
mListener.onIdentitySelected(mIdentities.get(cvh.getAdapterPosition() - 1));
}
});
break;
default:
break;
}
}
// Return the size of the dataset (invoked by the layout manager)
@Override
public int getItemCount() {
return mIdentities.size() + 1;
}
public long getItemId(int position) {
if (position == 0)
return 0;
EmailIdentity identity = mIdentities.get(position - 1);
return identity.getHash().hashCode();
}
}

View File

@@ -0,0 +1,64 @@
package i2p.bote.android.identities;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.support.v7.widget.Toolbar;
import i2p.bote.android.InitActivities;
import i2p.bote.android.R;
import i2p.bote.email.EmailIdentity;
public class IdentityListActivity extends AppCompatActivity implements
IdentityListFragment.IdentityListListener {
static final int ALTER_IDENTITY_LIST = 1;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_toolbar);
// Initialize I2P settings
InitActivities init = new InitActivities(this);
init.initialize();
// Set the action bar
Toolbar toolbar = (Toolbar) findViewById(R.id.main_toolbar);
setSupportActionBar(toolbar);
// Enable ActionBar app icon to behave as action to go back
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
if (savedInstanceState == null) {
IdentityListFragment f = new IdentityListFragment();
getSupportFragmentManager().beginTransaction()
.add(R.id.container, f).commit();
}
}
@Override
public void onNewIdentity() {
Intent i = new Intent(this, EditIdentityActivity.class);
startActivityForResult(i, ALTER_IDENTITY_LIST);
}
@Override
public void onIdentitySelected(EmailIdentity identity) {
Intent i = new Intent(this, ViewIdentityActivity.class);
i.putExtra(ViewIdentityFragment.ADDRESS, identity.getKey());
startActivityForResult(i, ALTER_IDENTITY_LIST);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ALTER_IDENTITY_LIST) {
if (resultCode == Activity.RESULT_OK) {
IdentityListFragment f = (IdentityListFragment) getSupportFragmentManager().findFragmentById(R.id.container);
f.updateContactList();
}
} else {
super.onActivityResult(requestCode, resultCode, data);
}
}
}

View File

@@ -0,0 +1,206 @@
package i2p.bote.android.identities;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.support.v4.app.LoaderManager;
import android.support.v4.content.Loader;
import android.support.v7.widget.LinearLayoutManager;
import android.support.v7.widget.RecyclerView;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import com.google.zxing.integration.android.IntentIntegrator;
import com.pnikosis.materialishprogress.ProgressWheel;
import java.io.IOException;
import java.security.GeneralSecurityException;
import java.util.Collection;
import i2p.bote.I2PBote;
import i2p.bote.android.R;
import i2p.bote.android.addressbook.EditContactActivity;
import i2p.bote.android.util.AuthenticatedFragment;
import i2p.bote.android.util.BetterAsyncTaskLoader;
import i2p.bote.android.widget.DividerItemDecoration;
import i2p.bote.android.widget.LoadingRecyclerView;
import i2p.bote.email.EmailIdentity;
import i2p.bote.fileencryption.PasswordException;
public class IdentityListFragment extends AuthenticatedFragment implements
LoaderManager.LoaderCallbacks<Collection<EmailIdentity>> {
IdentityListListener mCallback;
private LoadingRecyclerView mIdentitiesList;
private IdentityAdapter mAdapter;
// Container Activity must implement this interface
public interface IdentityListListener {
void onNewIdentity();
void onIdentitySelected(EmailIdentity identity);
}
@Override
public void onAttach(Activity activity) {
super.onAttach(activity);
// This makes sure that the container activity has implemented
// the callback interface. If not, it throws an exception
try {
mCallback = (IdentityListListener) activity;
} catch (ClassCastException e) {
throw new ClassCastException(activity.toString()
+ " must implement OnIdentitySelectedListener");
}
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Only so we can show/hide the FAM
setHasOptionsMenu(true);
}
@Override
public View onCreateAuthenticatedView(
LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View v = inflater.inflate(R.layout.fragment_list_identities, container, false);
mIdentitiesList = (LoadingRecyclerView) v.findViewById(R.id.identities_list);
View empty = v.findViewById(R.id.empty);
ProgressWheel loading = (ProgressWheel) v.findViewById(R.id.loading);
mIdentitiesList.setLoadingView(empty, loading);
return v;
}
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
mIdentitiesList.setHasFixedSize(true);
mIdentitiesList.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
// Use a linear layout manager
RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getActivity());
mIdentitiesList.setLayoutManager(mLayoutManager);
// Set the adapter for the list view
mAdapter = new IdentityAdapter(getActivity(), mCallback);
mIdentitiesList.setAdapter(mAdapter);
}
/**
* Start loading the address book.
* Only called when we have a password cached, or no
* password is required.
*/
protected void onInitializeFragment() {
getLoaderManager().initLoader(0, null, this);
}
protected void onDestroyFragment() {
getLoaderManager().destroyLoader(0);
}
@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
super.onCreateOptionsMenu(menu, inflater);
inflater.inflate(R.menu.settings, menu);
}
@Override
public void onPrepareOptionsMenu(Menu menu) {
super.onPrepareOptionsMenu(menu);
boolean passwordRequired = I2PBote.getInstance().isPasswordRequired();
menu.findItem(R.id.export_identities).setVisible(!passwordRequired);
menu.findItem(R.id.import_identities).setVisible(!passwordRequired);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case R.id.export_identities:
Intent ei = new Intent(getActivity(), IdentityShipActivity.class);
ei.putExtra(IdentityShipActivity.EXPORTING, true);
startActivity(ei);
return true;
case R.id.import_identities:
Intent ii = new Intent(getActivity(), IdentityShipActivity.class);
ii.putExtra(IdentityShipActivity.EXPORTING, false);
startActivity(ii);
return true;
default:
return super.onOptionsItemSelected(item);
}
}
private void startNewContact() {
Intent nci = new Intent(getActivity(), EditContactActivity.class);
getActivity().startActivityForResult(nci, IdentityListActivity.ALTER_IDENTITY_LIST);
}
private void startScanQrCode() {
IntentIntegrator integrator = new IntentIntegrator(getActivity());
integrator.initiateScan(IntentIntegrator.QR_CODE_TYPES);
}
protected void updateContactList() {
getLoaderManager().restartLoader(0, null, this);
}
// LoaderManager.LoaderCallbacks<SortedSet<EmailIdentity>>
public Loader<Collection<EmailIdentity>> onCreateLoader(int id, Bundle args) {
return new IdentityLoader(getActivity());
}
private static class IdentityLoader extends BetterAsyncTaskLoader<Collection<EmailIdentity>> {
public IdentityLoader(Context context) {
super(context);
}
@Override
public Collection<EmailIdentity> loadInBackground() {
Collection<EmailIdentity> identities = null;
try {
identities = I2PBote.getInstance().getIdentities().getAll();
} catch (PasswordException e) {
// TODO handle, but should not get here
e.printStackTrace();
} catch (GeneralSecurityException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return identities;
}
@Override
protected void onStartMonitoring() {
}
@Override
protected void onStopMonitoring() {
}
@Override
protected void releaseResources(Collection<EmailIdentity> data) {
}
}
@Override
public void onLoadFinished(Loader<Collection<EmailIdentity>> loader,
Collection<EmailIdentity> data) {
mAdapter.setIdentities(data);
}
@Override
public void onLoaderReset(Loader<Collection<EmailIdentity>> loader) {
mAdapter.setIdentities(null);
}
}

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import android.os.Bundle;
import android.support.v7.app.ActionBarActivity;

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import android.app.Activity;
import android.content.Intent;

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import android.annotation.SuppressLint;
import android.nfc.NdefMessage;

View File

@@ -1,4 +1,4 @@
package i2p.bote.android.config;
package i2p.bote.android.identities;
import android.app.Activity;
import android.content.Intent;

View File

@@ -11,7 +11,7 @@ import android.view.ViewGroup;
import android.widget.Toast;
import i2p.bote.android.R;
import i2p.bote.android.config.EditIdentityActivity;
import i2p.bote.android.identities.EditIdentityActivity;
import i2p.bote.android.config.SetPasswordActivity;
public class SetupActivity extends ActionBarActivity {

View File

@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<android.support.v7.widget.Toolbar xmlns:app="http://schemas.android.com/apk/res-auto"
<android.support.v7.widget.Toolbar
android:id="@+id/main_toolbar"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"

View File

@@ -8,7 +8,7 @@
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="i2p.bote.android.config.IdentityShipFragment$ExportIdentitiesFragment">
tools:context="i2p.bote.android.identities.IdentityShipFragment$ExportIdentitiesFragment">
<TextView
android:layout_width="wrap_content"

View File

@@ -8,7 +8,7 @@
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
android:paddingBottom="@dimen/activity_vertical_margin"
tools:context="i2p.bote.android.config.IdentityShipFragment$ImportIdentitiesFragment">
tools:context="i2p.bote.android.identities.IdentityShipFragment$ImportIdentitiesFragment">
<TextView
android:layout_width="wrap_content"

View File

@@ -0,0 +1,33 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<i2p.bote.android.widget.LoadingRecyclerView
android:id="@+id/identities_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:scrollbars="vertical"/>
<RelativeLayout
android:id="@+id/empty"
android:layout_width="match_parent"
android:layout_height="match_parent">
<com.pnikosis.materialishprogress.ProgressWheel
android:id="@+id/loading"
android:layout_width="80dp"
android:layout_height="80dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
app:matProg_barColor="@color/accent"
app:matProg_progressIndeterminate="true"/>
</RelativeLayout>
</FrameLayout>
</RelativeLayout>

View File

@@ -0,0 +1,32 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="@dimen/listitem_height_one_line_avatar">
<ImageView
android:id="@+id/identity_picture"
android:layout_width="@dimen/listitem_picture_size"
android:layout_height="@dimen/listitem_picture_size"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/listitem_horizontal_margin"
android:layout_marginStart="@dimen/listitem_horizontal_margin"
android:scaleType="centerCrop"
android:src="@drawable/ic_contact_picture"/>
<TextView
android:id="@+id/identity_name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:layout_alignParentStart="true"
android:layout_centerVertical="true"
android:layout_marginLeft="@dimen/listitem_text_left_margin"
android:layout_marginStart="@dimen/listitem_text_left_margin"
android:textAppearance="@style/TextAppearance.AppCompat.Primary"
tools:text="Identity name"/>
</RelativeLayout>

View File

@@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<TextView
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="@dimen/listitem_height_one_line"/>

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">
<Preference
android:key="preference_category_general"
android:title="@string/pref_title_general"/>
<Preference
android:key="preference_category_change_password"
android:title="@string/pref_title_change_password"/>
<Preference
android:key="preference_category_identities"
android:title="@string/pref_title_identities"/>
</PreferenceScreen>

View File

@@ -1,28 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<preference-headers xmlns:android="http://schemas.android.com/apk/res/android" >
<header
android:fragment="i2p.bote.android.config.SettingsActivity$SettingsFragment"
android:title="@string/pref_title_general"
android:summary="@string/pref_summ_general" >
<extra
android:name="settings"
android:value="general" />
</header>
<header android:title="@string/pref_title_change_password" >
<intent
android:targetClass="i2p.bote.android.config.SetPasswordActivity"
android:targetPackage="i2p.bote.android" />
</header>
<header
android:id="@+id/identity_settings"
android:title="@string/pref_title_identities" />
<header
android:id="@+id/new_identity"
android:title="@string/new_identity" >
<intent
android:targetClass="i2p.bote.android.config.EditIdentityActivity"
android:targetPackage="i2p.bote.android" />
</header>
</preference-headers>

View File

@@ -1,21 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android" >
<Preference android:title="@string/pref_title_general" >
<intent
android:action="i2p.bote.PREFS_GENERAL"
android:targetClass="i2p.bote.android.config.SettingsActivity"
android:targetPackage="i2p.bote.android" />
</Preference>
<Preference android:title="@string/pref_title_change_password" >
<intent
android:targetClass="i2p.bote.android.config.SetPasswordActivity"
android:targetPackage="i2p.bote.android" />
</Preference>
<Preference android:title="@string/new_identity" >
<intent
android:targetClass="i2p.bote.android.config.EditIdentityActivity"
android:targetPackage="i2p.bote.android" />
</Preference>
</PreferenceScreen>

View File

@@ -11,6 +11,9 @@ buildscript {
allprojects {
repositories {
mavenLocal()
maven {
url "https://raw.github.com/whispersystems/maven/master/preferencefragment/releases/"
}
mavenCentral()
}
}