fixed several issues, recyclerview now used in DisplayLogFragment, cosmetic changes
This commit is contained in:
@@ -140,10 +140,6 @@ public class KeyListFragment extends RecyclerFragment<KeySectionedListAdapter>
|
|||||||
case R.id.menu_key_list_multi_delete: {
|
case R.id.menu_key_list_multi_delete: {
|
||||||
long[] keyIds = getAdapter().getSelectedMasterKeyIds();
|
long[] keyIds = getAdapter().getSelectedMasterKeyIds();
|
||||||
boolean hasSecret = getAdapter().isAnySecretKeySelected();
|
boolean hasSecret = getAdapter().isAnySecretKeySelected();
|
||||||
|
|
||||||
System.out.println(Arrays.toString(keyIds));
|
|
||||||
System.out.println(hasSecret);
|
|
||||||
|
|
||||||
Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class);
|
Intent intent = new Intent(getActivity(), DeleteKeyDialogActivity.class);
|
||||||
intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, keyIds);
|
intent.putExtra(DeleteKeyDialogActivity.EXTRA_DELETE_MASTER_KEY_IDS, keyIds);
|
||||||
intent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, hasSecret);
|
intent.putExtra(DeleteKeyDialogActivity.EXTRA_HAS_SECRET, hasSecret);
|
||||||
|
|||||||
@@ -38,37 +38,35 @@ import android.widget.ArrayAdapter;
|
|||||||
import android.widget.ImageView;
|
import android.widget.ImageView;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.tonicartos.superslim.LayoutManager;
|
||||||
|
|
||||||
import org.sufficientlysecure.keychain.R;
|
import org.sufficientlysecure.keychain.R;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogEntryParcel;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.LogLevel;
|
||||||
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
|
import org.sufficientlysecure.keychain.operations.results.OperationResult.SubLogEntryParcel;
|
||||||
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
import org.sufficientlysecure.keychain.provider.TemporaryFileProvider;
|
||||||
|
import org.sufficientlysecure.keychain.ui.adapter.NestedLogAdapter;
|
||||||
import org.sufficientlysecure.keychain.ui.dialog.ShareLogDialogFragment;
|
import org.sufficientlysecure.keychain.ui.dialog.ShareLogDialogFragment;
|
||||||
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||||
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
import org.sufficientlysecure.keychain.ui.util.Notify.Style;
|
||||||
|
import org.sufficientlysecure.keychain.ui.util.recyclerview.RecyclerFragment;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
|
||||||
public class LogDisplayFragment extends ListFragment implements OnItemClickListener {
|
public class LogDisplayFragment extends RecyclerFragment<NestedLogAdapter>
|
||||||
|
implements NestedLogAdapter.LogActionListener {
|
||||||
LogAdapter mAdapter;
|
private OperationResult mResult;
|
||||||
|
|
||||||
OperationResult mResult;
|
|
||||||
|
|
||||||
public static final String EXTRA_RESULT = "log";
|
public static final String EXTRA_RESULT = "log";
|
||||||
protected int mTextColor;
|
|
||||||
|
|
||||||
private Uri mLogTempFile;
|
private Uri mLogTempFile;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
mTextColor = FormattingUtils.getColorFromAttr(getActivity(), R.attr.colorText);
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,14 +91,11 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
mAdapter = new LogAdapter(getActivity(), mResult.getLog());
|
NestedLogAdapter adapter = new NestedLogAdapter(getContext(), mResult.getLog());
|
||||||
setListAdapter(mAdapter);
|
adapter.setListener(this);
|
||||||
|
setAdapter(adapter);
|
||||||
getListView().setOnItemClickListener(this);
|
|
||||||
|
|
||||||
getListView().setFastScrollEnabled(true);
|
|
||||||
getListView().setDividerHeight(0);
|
|
||||||
|
|
||||||
|
setLayoutManager(new LayoutManager(getContext()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -130,7 +125,6 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void shareLog() {
|
private void shareLog() {
|
||||||
|
|
||||||
Activity activity = getActivity();
|
Activity activity = getActivity();
|
||||||
if (activity == null) {
|
if (activity == null) {
|
||||||
return;
|
return;
|
||||||
@@ -144,7 +138,7 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
|||||||
try {
|
try {
|
||||||
OutputStream outputStream = activity.getContentResolver().openOutputStream(mLogTempFile);
|
OutputStream outputStream = activity.getContentResolver().openOutputStream(mLogTempFile);
|
||||||
outputStream.write(log.getBytes());
|
outputStream.write(log.getBytes());
|
||||||
} catch (IOException e) {
|
} catch (IOException | NullPointerException e) {
|
||||||
Notify.create(activity, R.string.error_log_share_internal, Style.ERROR).show();
|
Notify.create(activity, R.string.error_log_share_internal, Style.ERROR).show();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -153,129 +147,12 @@ public class LogDisplayFragment extends ListFragment implements OnItemClickListe
|
|||||||
|
|
||||||
ShareLogDialogFragment shareLogDialog = ShareLogDialogFragment.newInstance(mLogTempFile);
|
ShareLogDialogFragment shareLogDialog = ShareLogDialogFragment.newInstance(mLogTempFile);
|
||||||
shareLogDialog.show(getActivity().getSupportFragmentManager(), "shareLogDialog");
|
shareLogDialog.show(getActivity().getSupportFragmentManager(), "shareLogDialog");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
|
public void onSubEntryClicked(SubLogEntryParcel subLogEntryParcel) {
|
||||||
LogEntryParcel parcel = mAdapter.getItem(position);
|
Intent intent = new Intent(getActivity(), LogDisplayActivity.class);
|
||||||
if ( ! (parcel instanceof SubLogEntryParcel)) {
|
intent.putExtra(LogDisplayFragment.EXTRA_RESULT, subLogEntryParcel.getSubResult());
|
||||||
return;
|
|
||||||
}
|
|
||||||
Intent intent = new Intent(
|
|
||||||
getActivity(), LogDisplayActivity.class);
|
|
||||||
intent.putExtra(LogDisplayFragment.EXTRA_RESULT, ((SubLogEntryParcel) parcel).getSubResult());
|
|
||||||
startActivity(intent);
|
startActivity(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class LogAdapter extends ArrayAdapter<LogEntryParcel> {
|
|
||||||
|
|
||||||
private LayoutInflater mInflater;
|
|
||||||
private int dipFactor;
|
|
||||||
|
|
||||||
public LogAdapter(Context context, OperationResult.OperationLog log) {
|
|
||||||
super(context, R.layout.log_display_item, log.toList());
|
|
||||||
mInflater = LayoutInflater.from(getContext());
|
|
||||||
dipFactor = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
|
||||||
(float) 8, getResources().getDisplayMetrics());
|
|
||||||
}
|
|
||||||
|
|
||||||
private class ItemHolder {
|
|
||||||
final View mSecond;
|
|
||||||
final TextView mText, mSecondText;
|
|
||||||
final ImageView mImg, mSecondImg, mSub;
|
|
||||||
public ItemHolder(TextView text, ImageView image, ImageView sub, View second, TextView secondText, ImageView secondImg) {
|
|
||||||
mText = text;
|
|
||||||
mImg = image;
|
|
||||||
mSub = sub;
|
|
||||||
mSecond = second;
|
|
||||||
mSecondText = secondText;
|
|
||||||
mSecondImg = secondImg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check if convertView.setPadding is redundant
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View convertView, ViewGroup parent) {
|
|
||||||
LogEntryParcel entry = getItem(position);
|
|
||||||
ItemHolder ih;
|
|
||||||
if (convertView == null) {
|
|
||||||
convertView = mInflater.inflate(R.layout.log_display_item, parent, false);
|
|
||||||
ih = new ItemHolder(
|
|
||||||
(TextView) convertView.findViewById(R.id.log_text),
|
|
||||||
(ImageView) convertView.findViewById(R.id.log_img),
|
|
||||||
(ImageView) convertView.findViewById(R.id.log_sub),
|
|
||||||
convertView.findViewById(R.id.log_second),
|
|
||||||
(TextView) convertView.findViewById(R.id.log_second_text),
|
|
||||||
(ImageView) convertView.findViewById(R.id.log_second_img)
|
|
||||||
);
|
|
||||||
convertView.setTag(ih);
|
|
||||||
} else {
|
|
||||||
ih = (ItemHolder) convertView.getTag();
|
|
||||||
}
|
|
||||||
|
|
||||||
if (entry instanceof SubLogEntryParcel) {
|
|
||||||
ih.mSub.setVisibility(View.VISIBLE);
|
|
||||||
convertView.setClickable(false);
|
|
||||||
convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0);
|
|
||||||
|
|
||||||
OperationResult result = ((SubLogEntryParcel) entry).getSubResult();
|
|
||||||
LogEntryParcel subEntry = result.getLog().getLast();
|
|
||||||
if (subEntry != null) {
|
|
||||||
ih.mSecond.setVisibility(View.VISIBLE);
|
|
||||||
// special case: first parameter may be a quantity
|
|
||||||
if (subEntry.mParameters != null && subEntry.mParameters.length > 0
|
|
||||||
&& subEntry.mParameters[0] instanceof Integer) {
|
|
||||||
ih.mSecondText.setText(getResources().getQuantityString(subEntry.mType.getMsgId(),
|
|
||||||
(Integer) subEntry.mParameters[0],
|
|
||||||
subEntry.mParameters));
|
|
||||||
} else {
|
|
||||||
ih.mSecondText.setText(getResources().getString(subEntry.mType.getMsgId(),
|
|
||||||
subEntry.mParameters));
|
|
||||||
}
|
|
||||||
ih.mSecondText.setTextColor(subEntry.mType.mLevel == LogLevel.DEBUG ? Color.GRAY : mTextColor);
|
|
||||||
switch (subEntry.mType.mLevel) {
|
|
||||||
case DEBUG: ih.mSecondImg.setBackgroundColor(Color.GRAY); break;
|
|
||||||
case INFO: ih.mSecondImg.setBackgroundColor(mTextColor); break;
|
|
||||||
case WARN: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); break;
|
|
||||||
case ERROR: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
|
|
||||||
case START: ih.mSecondImg.setBackgroundColor(mTextColor); break;
|
|
||||||
case OK: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_green_light)); break;
|
|
||||||
case CANCELLED: ih.mSecondImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ih.mSecond.setVisibility(View.GONE);
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
ih.mSub.setVisibility(View.GONE);
|
|
||||||
ih.mSecond.setVisibility(View.GONE);
|
|
||||||
convertView.setClickable(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// special case: first parameter may be a quantity
|
|
||||||
if (entry.mParameters != null && entry.mParameters.length > 0
|
|
||||||
&& entry.mParameters[0] instanceof Integer) {
|
|
||||||
ih.mText.setText(getResources().getQuantityString(entry.mType.getMsgId(),
|
|
||||||
(Integer) entry.mParameters[0],
|
|
||||||
entry.mParameters));
|
|
||||||
} else {
|
|
||||||
ih.mText.setText(getResources().getString(entry.mType.getMsgId(),
|
|
||||||
entry.mParameters));
|
|
||||||
}
|
|
||||||
convertView.setPadding((entry.mIndent) * dipFactor, 0, 0, 0);
|
|
||||||
ih.mText.setTextColor(entry.mType.mLevel == LogLevel.DEBUG ? Color.GRAY : mTextColor);
|
|
||||||
switch (entry.mType.mLevel) {
|
|
||||||
case DEBUG: ih.mImg.setBackgroundColor(Color.GRAY); break;
|
|
||||||
case INFO: ih.mImg.setBackgroundColor(mTextColor); break;
|
|
||||||
case WARN: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_orange_light)); break;
|
|
||||||
case ERROR: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
|
|
||||||
case START: ih.mImg.setBackgroundColor(mTextColor); break;
|
|
||||||
case OK: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_green_light)); break;
|
|
||||||
case CANCELLED: ih.mImg.setBackgroundColor(getResources().getColor(R.color.android_red_light)); break;
|
|
||||||
}
|
|
||||||
|
|
||||||
return convertView;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -190,7 +190,7 @@ public class KeySectionedListAdapter extends SectionCursorAdapter<KeySectionedLi
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected short getSectionItemViewType(int position) {
|
protected short getSectionItemViewType(int position) {
|
||||||
if(moveCursor(position)) {
|
if (moveCursor(position)) {
|
||||||
KeyCursor c = getCursor();
|
KeyCursor c = getCursor();
|
||||||
|
|
||||||
if (c.isSecret() && c.getKeyId() == 0L) {
|
if (c.isSecret() && c.getKeyId() == 0L) {
|
||||||
@@ -435,24 +435,24 @@ public class KeySectionedListAdapter extends SectionCursorAdapter<KeySectionedLi
|
|||||||
int pos = getAdapterPosition();
|
int pos = getAdapterPosition();
|
||||||
switch (v.getId()) {
|
switch (v.getId()) {
|
||||||
case R.id.key_list_item_slinger_button:
|
case R.id.key_list_item_slinger_button:
|
||||||
if(mListener != null) {
|
if (mListener != null) {
|
||||||
mListener.onSlingerButtonClicked(getItemId());
|
mListener.onSlingerButtonClicked(getItemId());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
if(getSelectedCount() == 0) {
|
if (getSelectedCount() == 0) {
|
||||||
if(mListener != null) {
|
if (mListener != null) {
|
||||||
mListener.onKeyItemClicked(getItemId());
|
mListener.onKeyItemClicked(getItemId());
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(isSelected(pos)) {
|
if (isSelected(pos)) {
|
||||||
deselectPosition(pos);
|
deselectPosition(pos);
|
||||||
} else {
|
} else {
|
||||||
selectPosition(pos);
|
selectPosition(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mListener != null) {
|
if (mListener != null) {
|
||||||
mListener.onSelectionStateChanged(getSelectedCount());
|
mListener.onSelectionStateChanged(getSelectedCount());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -464,10 +464,10 @@ public class KeySectionedListAdapter extends SectionCursorAdapter<KeySectionedLi
|
|||||||
@Override
|
@Override
|
||||||
public boolean onLongClick(View v) {
|
public boolean onLongClick(View v) {
|
||||||
System.out.println("Long Click!");
|
System.out.println("Long Click!");
|
||||||
if(getSelectedCount() == 0) {
|
if (getSelectedCount() == 0) {
|
||||||
selectPosition(getAdapterPosition());
|
selectPosition(getAdapterPosition());
|
||||||
|
|
||||||
if(mListener != null) {
|
if (mListener != null) {
|
||||||
mListener.onSelectionStateChanged(getSelectedCount());
|
mListener.onSelectionStateChanged(getSelectedCount());
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -0,0 +1,266 @@
|
|||||||
|
package org.sufficientlysecure.keychain.ui.adapter;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.graphics.Color;
|
||||||
|
import android.support.v4.content.ContextCompat;
|
||||||
|
import android.support.v7.widget.RecyclerView;
|
||||||
|
import android.util.Pair;
|
||||||
|
import android.util.TypedValue;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
import android.view.View;
|
||||||
|
import android.view.ViewGroup;
|
||||||
|
import android.widget.ImageView;
|
||||||
|
import android.widget.TextView;
|
||||||
|
|
||||||
|
import com.tonicartos.superslim.LayoutManager;
|
||||||
|
|
||||||
|
import org.sufficientlysecure.keychain.R;
|
||||||
|
import org.sufficientlysecure.keychain.operations.results.OperationResult;
|
||||||
|
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class NestedLogAdapter extends RecyclerView.Adapter<NestedLogAdapter.LogEntryViewHolder> {
|
||||||
|
private static final int ENTRY_TYPE_REGULAR = 0;
|
||||||
|
private static final int ENTRY_TYPE_SUBLOG = 1;
|
||||||
|
|
||||||
|
private final int mIndentFactor;
|
||||||
|
private LogActionListener mListener;
|
||||||
|
private List<Pair<OperationResult.LogEntryParcel, Integer>> mLogEntries;
|
||||||
|
|
||||||
|
public NestedLogAdapter(Context context) {
|
||||||
|
super();
|
||||||
|
|
||||||
|
mIndentFactor = (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP,
|
||||||
|
(float) 8, context.getResources().getDisplayMetrics());
|
||||||
|
}
|
||||||
|
|
||||||
|
public NestedLogAdapter(Context context, OperationResult.OperationLog log) {
|
||||||
|
this(context);
|
||||||
|
setLog(log);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setListener(LogActionListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLog(OperationResult.OperationLog log) {
|
||||||
|
List<OperationResult.LogEntryParcel> list = log.toList();
|
||||||
|
|
||||||
|
if (mLogEntries != null) {
|
||||||
|
mLogEntries.clear();
|
||||||
|
} else {
|
||||||
|
mLogEntries = new ArrayList<>(list.size());
|
||||||
|
}
|
||||||
|
|
||||||
|
int lastSection = 0;
|
||||||
|
for (int i = 0; i < list.size(); i++) {
|
||||||
|
OperationResult.LogEntryParcel parcel = list.get(i);
|
||||||
|
if(parcel.mIndent < 1) {
|
||||||
|
lastSection = i;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLogEntries.add(new Pair<>(parcel, lastSection));
|
||||||
|
}
|
||||||
|
|
||||||
|
notifyDataSetChanged();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemCount() {
|
||||||
|
return mLogEntries != null ? mLogEntries.size() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public long getItemId(int position) {
|
||||||
|
OperationResult.LogEntryParcel parcel = getItem(position);
|
||||||
|
return parcel != null ? parcel.hashCode() : -1L;
|
||||||
|
}
|
||||||
|
|
||||||
|
public OperationResult.LogEntryParcel getItem(int position) {
|
||||||
|
return mLogEntries != null ?
|
||||||
|
mLogEntries.get(position).first : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getFirstSectionPosition(int position) {
|
||||||
|
return mLogEntries != null ?
|
||||||
|
mLogEntries.get(position).second : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getItemViewType(int position) {
|
||||||
|
return (getItem(position) instanceof OperationResult.SubLogEntryParcel) ?
|
||||||
|
ENTRY_TYPE_SUBLOG : ENTRY_TYPE_REGULAR;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isSection(int position) {
|
||||||
|
return mLogEntries != null && mLogEntries.get(position).second == position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public LogEntryViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||||
|
switch (viewType) {
|
||||||
|
case ENTRY_TYPE_SUBLOG:
|
||||||
|
return new SublogEntryViewHolder(LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.log_display_sublog_item, parent, false));
|
||||||
|
|
||||||
|
case ENTRY_TYPE_REGULAR:
|
||||||
|
return new LogEntryViewHolder(LayoutInflater.from(parent.getContext())
|
||||||
|
.inflate(R.layout.log_display_regular_item, parent, false));
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onBindViewHolder(LogEntryViewHolder holder, int position) {
|
||||||
|
LayoutManager.LayoutParams layoutParams = LayoutManager.LayoutParams
|
||||||
|
.from(holder.itemView.getLayoutParams());
|
||||||
|
|
||||||
|
layoutParams.isHeader = isSection(position);
|
||||||
|
layoutParams.setFirstPosition(getFirstSectionPosition(position));
|
||||||
|
|
||||||
|
holder.bind(getItem(position), mIndentFactor);
|
||||||
|
holder.itemView.setLayoutParams(layoutParams);
|
||||||
|
}
|
||||||
|
|
||||||
|
class LogEntryViewHolder extends RecyclerView.ViewHolder {
|
||||||
|
private TextView mLogText;
|
||||||
|
private ImageView mLogImg;
|
||||||
|
|
||||||
|
public LogEntryViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
|
||||||
|
mLogText = (TextView) itemView.findViewById(R.id.log_text);
|
||||||
|
mLogImg = (ImageView) itemView.findViewById(R.id.log_img);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void bind(OperationResult.LogEntryParcel entry, int indentFactor) {
|
||||||
|
String logText;
|
||||||
|
if (entry.mParameters != null
|
||||||
|
&& entry.mParameters.length > 0
|
||||||
|
&& entry.mParameters[0] instanceof Integer) {
|
||||||
|
|
||||||
|
logText = itemView.getResources().getQuantityString(entry.mType.getMsgId(),
|
||||||
|
(int) entry.mParameters[0], entry.mParameters);
|
||||||
|
} else {
|
||||||
|
logText = itemView.getResources().getString(entry.mType.getMsgId(),
|
||||||
|
entry.mParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
int textColor, indicatorColor;
|
||||||
|
textColor = indicatorColor = FormattingUtils.getColorFromAttr(
|
||||||
|
itemView.getContext(), R.attr.colorText);
|
||||||
|
|
||||||
|
switch (entry.mType.mLevel) {
|
||||||
|
case DEBUG:
|
||||||
|
textColor = Color.GRAY;
|
||||||
|
indicatorColor = Color.GRAY;
|
||||||
|
break;
|
||||||
|
case WARN:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_orange_light);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_red_light);
|
||||||
|
break;
|
||||||
|
case OK:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_green_light);
|
||||||
|
break;
|
||||||
|
case CANCELLED:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_red_light);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mLogText.setText(logText);
|
||||||
|
mLogText.setTextColor(textColor);
|
||||||
|
mLogImg.setBackgroundColor(indicatorColor);
|
||||||
|
itemView.setPadding((entry.mIndent) * indentFactor, 0, 0, 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class SublogEntryViewHolder extends LogEntryViewHolder implements View.OnClickListener {
|
||||||
|
private TextView mSublogText;
|
||||||
|
private ImageView mSublogImg;
|
||||||
|
|
||||||
|
public SublogEntryViewHolder(View itemView) {
|
||||||
|
super(itemView);
|
||||||
|
|
||||||
|
itemView.setClickable(true);
|
||||||
|
itemView.setOnClickListener(this);
|
||||||
|
|
||||||
|
mSublogText = (TextView) itemView.findViewById(R.id.log_second_text);
|
||||||
|
mSublogImg = (ImageView) itemView.findViewById(R.id.log_second_img);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void bind(OperationResult.LogEntryParcel entry, int indentFactor) {
|
||||||
|
super.bind(entry, indentFactor);
|
||||||
|
|
||||||
|
OperationResult.LogEntryParcel sublogEntry = ((OperationResult.SubLogEntryParcel) entry)
|
||||||
|
.getSubResult().getLog().getLast();
|
||||||
|
|
||||||
|
String logText;
|
||||||
|
if (sublogEntry.mParameters != null
|
||||||
|
&& sublogEntry.mParameters.length > 0
|
||||||
|
&& sublogEntry.mParameters[0] instanceof Integer) {
|
||||||
|
|
||||||
|
logText = itemView.getResources().getQuantityString(sublogEntry.mType.getMsgId(),
|
||||||
|
(int) sublogEntry.mParameters[0], sublogEntry.mParameters);
|
||||||
|
} else {
|
||||||
|
logText = itemView.getResources().getString(sublogEntry.mType.getMsgId(),
|
||||||
|
sublogEntry.mParameters);
|
||||||
|
}
|
||||||
|
|
||||||
|
int textColor, indicatorColor;
|
||||||
|
textColor = indicatorColor = FormattingUtils.getColorFromAttr(
|
||||||
|
itemView.getContext(), R.attr.colorText);
|
||||||
|
|
||||||
|
switch (sublogEntry.mType.mLevel) {
|
||||||
|
case DEBUG:
|
||||||
|
textColor = Color.GRAY;
|
||||||
|
indicatorColor = Color.GRAY;
|
||||||
|
break;
|
||||||
|
case WARN:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_orange_light);
|
||||||
|
break;
|
||||||
|
case ERROR:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_red_light);
|
||||||
|
break;
|
||||||
|
case OK:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_green_light);
|
||||||
|
break;
|
||||||
|
case CANCELLED:
|
||||||
|
indicatorColor = ContextCompat.getColor(itemView.getContext(),
|
||||||
|
R.color.android_red_light);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
mSublogText.setText(logText);
|
||||||
|
mSublogText.setTextColor(textColor);
|
||||||
|
mSublogImg.setBackgroundColor(indicatorColor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(View v) {
|
||||||
|
if (mListener != null) {
|
||||||
|
OperationResult.LogEntryParcel parcel = getItem(getAdapterPosition());
|
||||||
|
if (parcel instanceof OperationResult.SubLogEntryParcel) {
|
||||||
|
mListener.onSubEntryClicked((OperationResult.SubLogEntryParcel) parcel);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface LogActionListener {
|
||||||
|
void onSubEntryClicked(OperationResult.SubLogEntryParcel subLogEntryParcel);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -10,6 +10,8 @@ import android.view.ViewGroup;
|
|||||||
import com.tonicartos.superslim.LayoutManager;
|
import com.tonicartos.superslim.LayoutManager;
|
||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param <T> section type.
|
* @param <T> section type.
|
||||||
* @param <VH> the view holder extending {@code BaseViewHolder<Cursor>} that is bound to the cursor data.
|
* @param <VH> the view holder extending {@code BaseViewHolder<Cursor>} that is bound to the cursor data.
|
||||||
@@ -71,7 +73,6 @@ public abstract class SectionCursorAdapter<C extends Cursor, T, VH extends Secti
|
|||||||
moveCursor(-1);
|
moveCursor(-1);
|
||||||
try {
|
try {
|
||||||
mSectionMap.clear();
|
mSectionMap.clear();
|
||||||
|
|
||||||
appendSections(getCursor());
|
appendSections(getCursor());
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
Log.e(TAG, "Couldn't build sections. Perhaps you're moving the cursor" +
|
Log.e(TAG, "Couldn't build sections. Perhaps you're moving the cursor" +
|
||||||
@@ -87,10 +88,12 @@ public abstract class SectionCursorAdapter<C extends Cursor, T, VH extends Secti
|
|||||||
int cursorPosition = 0;
|
int cursorPosition = 0;
|
||||||
while(hasValidData() && cursor.moveToNext()) {
|
while(hasValidData() && cursor.moveToNext()) {
|
||||||
T section = getSectionFromCursor(cursor);
|
T section = getSectionFromCursor(cursor);
|
||||||
if (cursor.getPosition() != cursorPosition)
|
if (cursor.getPosition() != cursorPosition) {
|
||||||
throw new IllegalStateException("Do not move the cursor's position in getSectionFromCursor.");
|
throw new IllegalStateException("Do not move the cursor's position in getSectionFromCursor.");
|
||||||
if (!hasSection(section))
|
}
|
||||||
|
if (!hasSection(section)) {
|
||||||
mSectionMap.append(cursorPosition + mSectionMap.size(), section);
|
mSectionMap.append(cursorPosition + mSectionMap.size(), section);
|
||||||
|
}
|
||||||
cursorPosition++;
|
cursorPosition++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -119,11 +122,13 @@ public abstract class SectionCursorAdapter<C extends Cursor, T, VH extends Secti
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final long getItemId(int listPosition) {
|
public final long getItemId(int listPosition) {
|
||||||
if (isSection(listPosition))
|
int index = mSectionMap.indexOfKey(listPosition);
|
||||||
return -1;
|
if (index < 0) {
|
||||||
else {
|
|
||||||
int cursorPosition = getCursorPositionWithoutSections(listPosition);
|
int cursorPosition = getCursorPositionWithoutSections(listPosition);
|
||||||
return super.getItemId(cursorPosition);
|
return super.getItemId(cursorPosition);
|
||||||
|
} else {
|
||||||
|
T section = mSectionMap.valueAt(index);
|
||||||
|
return section != null ? section.hashCode() : 0L;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -41,7 +41,6 @@ import android.widget.TextView;
|
|||||||
import org.sufficientlysecure.keychain.util.Log;
|
import org.sufficientlysecure.keychain.util.Log;
|
||||||
|
|
||||||
public class RecyclerFragment<A extends RecyclerView.Adapter> extends Fragment {
|
public class RecyclerFragment<A extends RecyclerView.Adapter> extends Fragment {
|
||||||
|
|
||||||
private static final int INTERNAL_LIST_VIEW_ID = android.R.id.list;
|
private static final int INTERNAL_LIST_VIEW_ID = android.R.id.list;
|
||||||
private static final int INTERNAL_EMPTY_VIEW_ID = android.R.id.empty;
|
private static final int INTERNAL_EMPTY_VIEW_ID = android.R.id.empty;
|
||||||
private static final int INTERNAL_LIST_CONTAINER_ID = android.R.id.widget_frame;
|
private static final int INTERNAL_LIST_CONTAINER_ID = android.R.id.widget_frame;
|
||||||
@@ -104,7 +103,7 @@ public class RecyclerFragment<A extends RecyclerView.Adapter> extends Fragment {
|
|||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup parent, Bundle savedInstanceState) {
|
||||||
|
|
||||||
final Context context = parent.getContext();
|
final Context context = getContext();
|
||||||
FrameLayout root = new FrameLayout(context);
|
FrameLayout root = new FrameLayout(context);
|
||||||
|
|
||||||
LinearLayout progressContainer = new LinearLayout(context);
|
LinearLayout progressContainer = new LinearLayout(context);
|
||||||
|
|||||||
@@ -40,9 +40,13 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="match_parent"
|
android:layout_height="match_parent"
|
||||||
android:paddingLeft="16dp"
|
android:paddingLeft="16dp"
|
||||||
|
android:paddingStart="16dp"
|
||||||
android:paddingRight="32dp"
|
android:paddingRight="32dp"
|
||||||
|
android:paddingEnd="32dp"
|
||||||
|
android:paddingBottom="72dp"
|
||||||
android:clipToPadding="false"
|
android:clipToPadding="false"
|
||||||
android:scrollbarStyle="outsideOverlay" />
|
android:scrollbars="vertical"
|
||||||
|
android:scrollbarStyle="outsideOverlay"/>
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:id="@android:id/empty"
|
android:id="@android:id/empty"
|
||||||
|
|||||||
@@ -0,0 +1,34 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:super="http://schemas.android.com/apk/lib-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?android:colorBackground"
|
||||||
|
|
||||||
|
super:slm_headerDisplay="sticky|inline"
|
||||||
|
super:slm_section_sectionManager="linear"
|
||||||
|
tools:ignore="ResAuto">
|
||||||
|
|
||||||
|
<ImageView
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:id="@+id/log_img"
|
||||||
|
android:minWidth="10dp"
|
||||||
|
android:background="?attr/colorLogBackground" />
|
||||||
|
|
||||||
|
<TextView
|
||||||
|
android:layout_width="0dp"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:id="@+id/log_text"
|
||||||
|
android:layout_marginTop="4dp"
|
||||||
|
android:layout_marginBottom="4dp"
|
||||||
|
android:layout_marginLeft="8dp"
|
||||||
|
android:layout_weight="1"
|
||||||
|
android:layout_gravity="center_vertical"
|
||||||
|
tools:text="Log Entry Text" />
|
||||||
|
</LinearLayout>
|
||||||
|
|
||||||
@@ -1,9 +1,18 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
|
||||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<LinearLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:super="http://schemas.android.com/apk/lib-auto"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:orientation="vertical"
|
android:orientation="vertical"
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content">
|
android:layout_height="wrap_content"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
|
|
||||||
|
super:slm_headerDisplay="sticky|inline"
|
||||||
|
super:slm_section_sectionManager="linear"
|
||||||
|
tools:ignore="ResAuto">
|
||||||
|
|
||||||
<LinearLayout
|
<LinearLayout
|
||||||
android:orientation="horizontal"
|
android:orientation="horizontal"
|
||||||
@@ -20,13 +29,13 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Log Entry Text"
|
|
||||||
android:id="@+id/log_text"
|
android:id="@+id/log_text"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_gravity="center_vertical"/>
|
android:layout_gravity="center_vertical"
|
||||||
|
tools:text="Log Entry Text" />
|
||||||
|
|
||||||
<ImageView
|
<ImageView
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
@@ -58,13 +67,13 @@
|
|||||||
<TextView
|
<TextView
|
||||||
android:layout_width="0dp"
|
android:layout_width="0dp"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="Log Entry Text"
|
|
||||||
android:id="@+id/log_second_text"
|
android:id="@+id/log_second_text"
|
||||||
android:layout_marginTop="4dp"
|
android:layout_marginTop="4dp"
|
||||||
android:layout_marginBottom="4dp"
|
android:layout_marginBottom="4dp"
|
||||||
android:layout_marginLeft="8dp"
|
android:layout_marginLeft="8dp"
|
||||||
android:layout_weight="1"
|
android:layout_weight="1"
|
||||||
android:layout_gravity="center_vertical"/>
|
android:layout_gravity="center_vertical"
|
||||||
|
tools:text="Log Entry Text" />
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
|
|
||||||
</LinearLayout>
|
</LinearLayout>
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content" >
|
android:layout_height="wrap_content" >
|
||||||
|
|
||||||
@@ -9,7 +12,7 @@
|
|||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:layout_gravity="start|left"
|
android:layout_gravity="start|left"
|
||||||
android:text="header text" />
|
tools:text="header text" />
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
<TextView
|
<TextView
|
||||||
|
|||||||
@@ -1,46 +1,52 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
<RelativeLayout
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
xmlns:tools="http://schemas.android.com/tools"
|
||||||
|
|
||||||
android:layout_width="match_parent"
|
android:layout_width="match_parent"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:minHeight="?android:attr/listPreferredItemHeight"
|
android:minHeight="?android:attr/listPreferredItemHeight"
|
||||||
android:gravity="center_vertical"
|
android:gravity="center_vertical"
|
||||||
android:paddingLeft="8dp"
|
android:paddingLeft="8dp"
|
||||||
|
android:paddingStart="8dp"
|
||||||
android:paddingTop="4dp"
|
android:paddingTop="4dp"
|
||||||
android:paddingBottom="4dp"
|
android:paddingBottom="4dp"
|
||||||
android:singleLine="true"
|
android:maxLines="1"
|
||||||
android:descendantFocusability="blocksDescendants"
|
android:descendantFocusability="blocksDescendants"
|
||||||
|
android:background="?attr/selectableItemBackground"
|
||||||
android:focusable="false">
|
android:focusable="false">
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/signerName"
|
android:id="@+id/signerName"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="signer name"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||||
android:layout_alignParentTop="true"
|
android:layout_alignParentTop="true"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true" />
|
android:layout_alignParentStart="true"
|
||||||
|
tools:text="signer name" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/signerKeyId"
|
android:id="@+id/signerKeyId"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:text="<user@example.com>"
|
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:layout_below="@+id/signerName"
|
android:layout_below="@+id/signerName"
|
||||||
android:layout_alignParentLeft="true"
|
android:layout_alignParentLeft="true"
|
||||||
android:layout_alignParentStart="true" />
|
android:layout_alignParentStart="true"
|
||||||
|
tools:text="<user@example.com>" />
|
||||||
|
|
||||||
<TextView
|
<TextView
|
||||||
android:id="@+id/signStatus"
|
android:id="@+id/signStatus"
|
||||||
android:layout_width="wrap_content"
|
android:layout_width="wrap_content"
|
||||||
android:layout_height="wrap_content"
|
android:layout_height="wrap_content"
|
||||||
android:textAppearance="?android:attr/textAppearanceSmall"
|
android:textAppearance="?android:attr/textAppearanceSmall"
|
||||||
android:text="status"
|
|
||||||
android:visibility="visible"
|
android:visibility="visible"
|
||||||
android:layout_above="@+id/signerKeyId"
|
android:layout_above="@+id/signerKeyId"
|
||||||
android:layout_alignParentRight="true"
|
android:layout_alignParentRight="true"
|
||||||
android:layout_alignParentEnd="true"
|
android:layout_alignParentEnd="true"
|
||||||
android:layout_marginRight="10dp" />
|
android:layout_marginRight="10dp"
|
||||||
|
android:layout_marginEnd="10dp"
|
||||||
|
tools:text="status" />
|
||||||
|
|
||||||
</RelativeLayout>
|
</RelativeLayout>
|
||||||
|
|||||||
Reference in New Issue
Block a user