extend-uid: add option icon for edit action mode
This commit is contained in:
committed by
Dominik Schürmann
parent
50248bd570
commit
5b6bc24a0c
@@ -26,6 +26,10 @@ import android.support.v4.app.LoaderManager;
|
|||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
import android.support.v4.view.ViewPager;
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.support.v7.view.ActionMode;
|
||||||
|
import android.support.v7.view.ActionMode.Callback;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,16 @@ package org.sufficientlysecure.keychain.ui;
|
|||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
import android.support.v4.app.FragmentActivity;
|
||||||
import android.support.v4.app.LoaderManager;
|
import android.support.v4.app.LoaderManager;
|
||||||
import android.support.v4.content.CursorLoader;
|
import android.support.v4.content.CursorLoader;
|
||||||
import android.support.v4.content.Loader;
|
import android.support.v4.content.Loader;
|
||||||
|
import android.view.ActionMode;
|
||||||
|
import android.view.ActionMode.Callback;
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.Menu;
|
||||||
|
import android.view.MenuInflater;
|
||||||
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
@@ -33,8 +39,8 @@ import android.widget.ListView;
|
|||||||
import org.sufficientlysecure.keychain.Constants;
|
import org.sufficientlysecure.keychain.Constants;
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
import org.sufficientlysecure.keychain.compatibility.DialogFragmentWorkaround;
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
|
||||||
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
import org.sufficientlysecure.keychain.provider.KeychainContract.UserPackets;
|
||||||
|
import org.sufficientlysecure.keychain.service.SaveKeyringParcel;
|
||||||
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
import org.sufficientlysecure.keychain.ui.adapter.UserIdsAdapter;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.UserIdInfoDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
@@ -95,54 +101,44 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
|||||||
getActivity().finish();
|
getActivity().finish();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
boolean hasSecret = getArguments().getBoolean(ARG_HAS_SECRET);
|
||||||
|
|
||||||
loadData(dataUri);
|
loadData(dataUri, hasSecret);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void loadData(Uri dataUri) {
|
private void loadData(Uri dataUri, boolean hasSecret) {
|
||||||
mDataUri = dataUri;
|
mDataUri = dataUri;
|
||||||
|
mHasSecret = hasSecret;
|
||||||
|
|
||||||
Log.i(Constants.TAG, "mDataUri: " + mDataUri.toString());
|
Log.i(Constants.TAG, "mDataUri: " + mDataUri);
|
||||||
|
|
||||||
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
|
mUserIdsAdapter = new UserIdsAdapter(getActivity(), null, 0);
|
||||||
mUserIds.setAdapter(mUserIdsAdapter);
|
mUserIds.setAdapter(mUserIdsAdapter);
|
||||||
|
|
||||||
|
setHasOptionsMenu(hasSecret);
|
||||||
|
|
||||||
// Prepare the loaders. Either re-connect with an existing ones,
|
// Prepare the loaders. Either re-connect with an existing ones,
|
||||||
// or start new ones.
|
// or start new ones.
|
||||||
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
|
|
||||||
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
|
getLoaderManager().initLoader(LOADER_ID_USER_IDS, null, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
static final String[] UNIFIED_PROJECTION = new String[]{
|
|
||||||
KeyRings._ID, KeyRings.MASTER_KEY_ID,
|
|
||||||
KeyRings.HAS_ANY_SECRET, KeyRings.IS_REVOKED, KeyRings.IS_EXPIRED, KeyRings.HAS_ENCRYPT
|
|
||||||
};
|
|
||||||
static final int INDEX_UNIFIED_MASTER_KEY_ID = 1;
|
|
||||||
static final int INDEX_UNIFIED_HAS_ANY_SECRET = 2;
|
|
||||||
static final int INDEX_UNIFIED_IS_REVOKED = 3;
|
|
||||||
static final int INDEX_UNIFIED_IS_EXPIRED = 4;
|
|
||||||
static final int INDEX_UNIFIED_HAS_ENCRYPT = 5;
|
|
||||||
|
|
||||||
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
public Loader<Cursor> onCreateLoader(int id, Bundle args) {
|
||||||
setContentShown(false);
|
setContentShown(false);
|
||||||
|
|
||||||
switch (id) {
|
if (id != LOADER_ID_USER_IDS) {
|
||||||
case LOADER_ID_UNIFIED: {
|
return null;
|
||||||
Uri baseUri = KeyRings.buildUnifiedKeyRingUri(mDataUri);
|
|
||||||
return new CursorLoader(getActivity(), baseUri, UNIFIED_PROJECTION, null, null, null);
|
|
||||||
}
|
|
||||||
case LOADER_ID_USER_IDS: {
|
|
||||||
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
|
|
||||||
return new CursorLoader(getActivity(), baseUri,
|
|
||||||
UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null);
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Uri baseUri = UserPackets.buildUserIdsUri(mDataUri);
|
||||||
|
return new CursorLoader(getActivity(), baseUri,
|
||||||
|
UserIdsAdapter.USER_PACKETS_PROJECTION, null, null, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
public void onLoadFinished(Loader<Cursor> loader, Cursor data) {
|
||||||
|
if (loader.getId() != LOADER_ID_USER_IDS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
/* TODO better error handling? May cause problems when a key is deleted,
|
/* TODO better error handling? May cause problems when a key is deleted,
|
||||||
* because the notification triggers faster than the activity closes.
|
* because the notification triggers faster than the activity closes.
|
||||||
*/
|
*/
|
||||||
@@ -150,23 +146,8 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
|||||||
if (data.getCount() == 0) {
|
if (data.getCount() == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
// Swap the new cursor in. (The framework will take care of closing the
|
|
||||||
// old cursor once we return.)
|
|
||||||
switch (loader.getId()) {
|
|
||||||
case LOADER_ID_UNIFIED: {
|
|
||||||
if (data.moveToFirst()) {
|
|
||||||
|
|
||||||
|
mUserIdsAdapter.swapCursor(data);
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
case LOADER_ID_USER_IDS: {
|
|
||||||
mUserIdsAdapter.swapCursor(data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
setContentShown(true);
|
setContentShown(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -175,11 +156,61 @@ public class ViewKeyAdvUserIdsFragment extends LoaderFragment implements
|
|||||||
* We need to make sure we are no longer using it.
|
* We need to make sure we are no longer using it.
|
||||||
*/
|
*/
|
||||||
public void onLoaderReset(Loader<Cursor> loader) {
|
public void onLoaderReset(Loader<Cursor> loader) {
|
||||||
switch (loader.getId()) {
|
if (loader.getId() != LOADER_ID_USER_IDS) {
|
||||||
case LOADER_ID_USER_IDS:
|
return;
|
||||||
mUserIdsAdapter.swapCursor(null);
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
mUserIdsAdapter.swapCursor(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
|
||||||
|
super.onCreateOptionsMenu(menu, inflater);
|
||||||
|
inflater.inflate(R.menu.edit_user_id, menu);
|
||||||
|
MenuItem vEditUserIds = menu.findItem(R.id.menu_edit_user_ids);
|
||||||
|
vEditUserIds.setVisible(mHasSecret);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void enterEditMode() {
|
||||||
|
FragmentActivity activity = getActivity();
|
||||||
|
activity.startActionMode(new Callback() {
|
||||||
|
@Override
|
||||||
|
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
|
||||||
|
mUserIdsAdapter.setEditMode(new SaveKeyringParcel(0L, new byte[0]));
|
||||||
|
getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this);
|
||||||
|
|
||||||
|
mode.setTitle("Edit User Ids");
|
||||||
|
mode.getMenuInflater().inflate(R.menu.action_edit_uids, menu);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
|
||||||
|
mode.finish();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroyActionMode(ActionMode mode) {
|
||||||
|
mUserIdsAdapter.setEditMode(null);
|
||||||
|
getLoaderManager().restartLoader(LOADER_ID_USER_IDS, null, ViewKeyAdvUserIdsFragment.this);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean onOptionsItemSelected(MenuItem item) {
|
||||||
|
switch (item.getItemId()) {
|
||||||
|
case R.id.menu_edit_user_ids:
|
||||||
|
enterEditMode();
|
||||||
|
return true;
|
||||||
|
default:
|
||||||
|
return super.onOptionsItemSelected(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -29,6 +29,7 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
import android.widget.ViewAnimator;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||||
@@ -66,7 +67,7 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
|||||||
TextView vAddress = (TextView) view.findViewById(R.id.user_id_item_address);
|
TextView vAddress = (TextView) view.findViewById(R.id.user_id_item_address);
|
||||||
TextView vComment = (TextView) view.findViewById(R.id.user_id_item_comment);
|
TextView vComment = (TextView) view.findViewById(R.id.user_id_item_comment);
|
||||||
ImageView vVerified = (ImageView) view.findViewById(R.id.user_id_item_certified);
|
ImageView vVerified = (ImageView) view.findViewById(R.id.user_id_item_certified);
|
||||||
View vVerifiedLayout = view.findViewById(R.id.user_id_item_certified_layout);
|
ViewAnimator vVerifiedLayout = (ViewAnimator) view.findViewById(R.id.user_id_icon_animator);
|
||||||
ImageView vEditImage = (ImageView) view.findViewById(R.id.user_id_item_edit_image);
|
ImageView vEditImage = (ImageView) view.findViewById(R.id.user_id_item_edit_image);
|
||||||
ImageView vDeleteButton = (ImageView) view.findViewById(R.id.user_id_item_delete_button);
|
ImageView vDeleteButton = (ImageView) view.findViewById(R.id.user_id_item_delete_button);
|
||||||
vDeleteButton.setVisibility(View.GONE); // not used
|
vDeleteButton.setVisibility(View.GONE); // not used
|
||||||
@@ -114,16 +115,9 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
vEditImage.setVisibility(View.VISIBLE);
|
vVerifiedLayout.setDisplayedChild(2);
|
||||||
vVerifiedLayout.setVisibility(View.GONE);
|
|
||||||
} else {
|
} else {
|
||||||
vEditImage.setVisibility(View.GONE);
|
vVerifiedLayout.setDisplayedChild(mShowStatusImages ? 1 : 0);
|
||||||
|
|
||||||
if (mShowStatusImages) {
|
|
||||||
vVerifiedLayout.setVisibility(View.VISIBLE);
|
|
||||||
} else {
|
|
||||||
vVerifiedLayout.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isRevoked) {
|
if (isRevoked) {
|
||||||
@@ -177,6 +171,10 @@ public class UserIdsAdapter extends UserAttributesAdapter {
|
|||||||
return isRevokedPending;
|
return isRevokedPending;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setEditMode(SaveKeyringParcel saveKeyringParcel) {
|
||||||
|
mSaveKeyringParcel = saveKeyringParcel;
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
public View newView(Context context, Cursor cursor, ViewGroup parent) {
|
||||||
return mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
|
return mInflater.inflate(R.layout.view_key_adv_user_id_item, null);
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public class UserIdsAddedAdapter extends ArrayAdapter<String> {
|
|||||||
holder.vDelete.setVisibility(View.VISIBLE); // always visible
|
holder.vDelete.setVisibility(View.VISIBLE); // always visible
|
||||||
|
|
||||||
// not used:
|
// not used:
|
||||||
View certifiedLayout = convertView.findViewById(R.id.user_id_item_certified_layout);
|
View certifiedLayout = convertView.findViewById(R.id.user_id_icon_animator);
|
||||||
ImageView editImage = (ImageView) convertView.findViewById(R.id.user_id_item_edit_image);
|
ImageView editImage = (ImageView) convertView.findViewById(R.id.user_id_item_edit_image);
|
||||||
certifiedLayout.setVisibility(View.GONE);
|
certifiedLayout.setVisibility(View.GONE);
|
||||||
editImage.setVisibility(View.GONE);
|
editImage.setVisibility(View.GONE);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
|
xmlns:custom="http://schemas.android.com/apk/res-auto"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
android:singleLine="true">
|
android:singleLine="true">
|
||||||
@@ -40,16 +41,19 @@
|
|||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
|
<org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator
|
||||||
<LinearLayout
|
android:id="@+id/user_id_icon_animator"
|
||||||
android:id="@+id/user_id_item_certified_layout"
|
|
||||||
android:layout_width="22dp"
|
android:layout_width="22dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_marginLeft="16dp"
|
android:layout_marginLeft="16dp"
|
||||||
android:layout_marginRight="16dp"
|
android:layout_marginRight="16dp"
|
||||||
|
|
||||||
android:layout_gravity="center_vertical"
|
android:layout_gravity="center_vertical"
|
||||||
android:orientation="vertical">
|
android:orientation="vertical"
|
||||||
|
custom:initialView="1">
|
||||||
|
|
||||||
|
<Space
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:id="@+id/user_id_item_certified"
|
android:id="@+id/user_id_item_certified"
|
||||||
@@ -58,15 +62,14 @@
|
|||||||
android:src="@drawable/status_signature_unverified_cutout_24dp"
|
android:src="@drawable/status_signature_unverified_cutout_24dp"
|
||||||
android:layout_gravity="center_horizontal" />
|
android:layout_gravity="center_horizontal" />
|
||||||
|
|
||||||
</LinearLayout>
|
<ImageView
|
||||||
|
android:id="@+id/user_id_item_edit_image"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:src="@drawable/ic_mode_edit_grey_24dp"
|
||||||
|
android:layout_gravity="center_vertical" />
|
||||||
|
|
||||||
<ImageView
|
</org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
|
||||||
android:id="@+id/user_id_item_edit_image"
|
|
||||||
android:layout_width="wrap_content"
|
|
||||||
android:layout_height="match_parent"
|
|
||||||
android:src="@drawable/ic_mode_edit_grey_24dp"
|
|
||||||
android:padding="8dp"
|
|
||||||
android:layout_gravity="center_vertical" />
|
|
||||||
|
|
||||||
<ImageButton
|
<ImageButton
|
||||||
android:id="@+id/user_id_item_delete_button"
|
android:id="@+id/user_id_item_delete_button"
|
||||||
|
|||||||
10
OpenKeychain/src/main/res/menu/action_edit_uids.xml
Normal file
10
OpenKeychain/src/main/res/menu/action_edit_uids.xml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_uids_save"
|
||||||
|
android:title="@string/menu_uids_save"
|
||||||
|
app:showAsAction="always" />
|
||||||
|
|
||||||
|
</menu>
|
||||||
12
OpenKeychain/src/main/res/menu/edit_user_id.xml
Normal file
12
OpenKeychain/src/main/res/menu/edit_user_id.xml
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<menu xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:app="http://schemas.android.com/apk/res-auto">
|
||||||
|
|
||||||
|
<item
|
||||||
|
android:id="@+id/menu_edit_user_ids"
|
||||||
|
android:icon="@drawable/ic_mode_edit_white_24dp"
|
||||||
|
android:title="@string/key_view_action_edit"
|
||||||
|
app:showAsAction="always"
|
||||||
|
/>
|
||||||
|
|
||||||
|
</menu>
|
||||||
@@ -1704,5 +1704,6 @@
|
|||||||
<string name="toast_wrong_mimetype">"Wrong data type, text was expected!"</string>
|
<string name="toast_wrong_mimetype">"Wrong data type, text was expected!"</string>
|
||||||
<string name="toast_no_text">"No text in shared data!"</string>
|
<string name="toast_no_text">"No text in shared data!"</string>
|
||||||
<string name="btn_search_for_query">"Search for\n'%s'"</string>
|
<string name="btn_search_for_query">"Search for\n'%s'"</string>
|
||||||
|
<string name="menu_uids_save">Save</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
|||||||
Reference in New Issue
Block a user