use LiveData to load data in TransferFragment
This commit is contained in:
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 Schürmann & Breitmoser GbR
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui.transfer.loader;
|
||||
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.ContentResolver;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.support.v4.content.AsyncTaskLoader;
|
||||
import android.util.Log;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract.KeyRings;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader.SecretKeyItem;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public class SecretKeyLoader extends AsyncTaskLoader<List<SecretKeyItem>> {
|
||||
public static final String[] PROJECTION = new String[] {
|
||||
KeyRings.MASTER_KEY_ID,
|
||||
KeyRings.CREATION,
|
||||
KeyRings.NAME,
|
||||
KeyRings.EMAIL,
|
||||
KeyRings.HAS_ANY_SECRET
|
||||
};
|
||||
private static final int INDEX_KEY_ID = 0;
|
||||
private static final int INDEX_CREATION = 1;
|
||||
private static final int INDEX_NAME = 2;
|
||||
private static final int INDEX_EMAIL = 3;
|
||||
|
||||
|
||||
private final ContentResolver contentResolver;
|
||||
|
||||
private List<SecretKeyItem> cachedResult;
|
||||
|
||||
|
||||
public SecretKeyLoader(Context context, ContentResolver contentResolver) {
|
||||
super(context);
|
||||
|
||||
this.contentResolver = contentResolver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SecretKeyItem> loadInBackground() {
|
||||
String where = KeyRings.HAS_ANY_SECRET + " = 1";
|
||||
Cursor cursor = contentResolver.query(KeyRings.buildUnifiedKeyRingsUri(), PROJECTION, where, null, null);
|
||||
if (cursor == null) {
|
||||
Timber.e("Error loading key items!");
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
ArrayList<SecretKeyItem> secretKeyItems = new ArrayList<>();
|
||||
while (cursor.moveToNext()) {
|
||||
SecretKeyItem secretKeyItem = new SecretKeyItem(cursor);
|
||||
secretKeyItems.add(secretKeyItem);
|
||||
}
|
||||
|
||||
return Collections.unmodifiableList(secretKeyItems);
|
||||
} finally {
|
||||
cursor.close();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deliverResult(List<SecretKeyItem> keySubkeyStatus) {
|
||||
cachedResult = keySubkeyStatus;
|
||||
|
||||
if (isStarted()) {
|
||||
super.deliverResult(keySubkeyStatus);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onStartLoading() {
|
||||
if (cachedResult != null) {
|
||||
deliverResult(cachedResult);
|
||||
}
|
||||
|
||||
if (takeContentChanged() || cachedResult == null) {
|
||||
forceLoad();
|
||||
}
|
||||
}
|
||||
|
||||
public static class SecretKeyItem {
|
||||
final int position;
|
||||
public final long masterKeyId;
|
||||
public final long creationMillis;
|
||||
public final String name;
|
||||
public final String email;
|
||||
|
||||
SecretKeyItem(Cursor cursor) {
|
||||
position = cursor.getPosition();
|
||||
|
||||
masterKeyId = cursor.getLong(INDEX_KEY_ID);
|
||||
creationMillis = cursor.getLong(INDEX_CREATION) * 1000;
|
||||
|
||||
name = cursor.getString(INDEX_NAME);
|
||||
email = cursor.getString(INDEX_EMAIL);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,8 @@ import java.io.IOException;
|
||||
import java.net.URISyntaxException;
|
||||
import java.util.List;
|
||||
|
||||
import android.arch.lifecycle.LifecycleOwner;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.content.Context;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.ConnectivityManager;
|
||||
@@ -30,19 +32,16 @@ import android.net.Uri;
|
||||
import android.net.wifi.WifiInfo;
|
||||
import android.net.wifi.WifiManager;
|
||||
import android.os.Build.VERSION_CODES;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Parcelable;
|
||||
import android.support.annotation.RequiresApi;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.app.LoaderManager.LoaderCallbacks;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.RecyclerView.Adapter;
|
||||
import android.view.LayoutInflater;
|
||||
|
||||
import org.openintents.openpgp.util.OpenPgpUtils;
|
||||
import org.openintents.openpgp.util.OpenPgpUtils.UserId;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.network.KeyTransferInteractor;
|
||||
import org.sufficientlysecure.keychain.network.KeyTransferInteractor.KeyTransferCallback;
|
||||
import org.sufficientlysecure.keychain.operations.results.ImportKeyResult;
|
||||
@@ -54,7 +53,7 @@ import org.sufficientlysecure.keychain.provider.KeyRepository.NotFoundException;
|
||||
import org.sufficientlysecure.keychain.service.ImportKeyringParcel;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper.Callback;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader.SecretKeyItem;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.GenericViewModel;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.view.ReceivedSecretKeyList.OnClickImportKeyListener;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.view.ReceivedSecretKeyList.ReceivedKeyAdapter;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.view.ReceivedSecretKeyList.ReceivedKeyItem;
|
||||
@@ -65,20 +64,19 @@ import timber.log.Timber;
|
||||
|
||||
|
||||
@RequiresApi(api = VERSION_CODES.LOLLIPOP)
|
||||
public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<List<SecretKeyItem>>,
|
||||
OnClickTransferKeyListener, OnClickImportKeyListener {
|
||||
public class TransferPresenter implements KeyTransferCallback, OnClickTransferKeyListener, OnClickImportKeyListener {
|
||||
private static final String DELIMITER_START = "-----BEGIN PGP PRIVATE KEY BLOCK-----";
|
||||
private static final String DELIMITER_END = "-----END PGP PRIVATE KEY BLOCK-----";
|
||||
private static final String BACKSTACK_TAG_TRANSFER = "transfer";
|
||||
|
||||
private final Context context;
|
||||
private final TransferMvpView view;
|
||||
private final LoaderManager loaderManager;
|
||||
private final int loaderId;
|
||||
private final KeyRepository databaseInteractor;
|
||||
private final KeyRepository keyRepository;
|
||||
|
||||
private final TransferKeyAdapter secretKeyAdapter;
|
||||
private final ReceivedKeyAdapter receivedKeyAdapter;
|
||||
private final LifecycleOwner lifecycleOwner;
|
||||
private final GenericViewModel viewModel;
|
||||
|
||||
|
||||
private KeyTransferInteractor keyTransferClientInteractor;
|
||||
@@ -90,12 +88,13 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
private Long confirmingMasterKeyId;
|
||||
|
||||
|
||||
public TransferPresenter(Context context, LoaderManager loaderManager, int loaderId, TransferMvpView view) {
|
||||
public TransferPresenter(Context context, LifecycleOwner lifecycleOwner,
|
||||
GenericViewModel viewModel, TransferMvpView view) {
|
||||
this.context = context;
|
||||
this.view = view;
|
||||
this.loaderManager = loaderManager;
|
||||
this.loaderId = loaderId;
|
||||
this.databaseInteractor = KeyRepository.create(context);
|
||||
this.lifecycleOwner = lifecycleOwner;
|
||||
this.viewModel = viewModel;
|
||||
this.keyRepository = KeyRepository.create(context);
|
||||
|
||||
secretKeyAdapter = new TransferKeyAdapter(context, LayoutInflater.from(context), this);
|
||||
view.setSecretKeyAdapter(secretKeyAdapter);
|
||||
@@ -110,13 +109,20 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
}
|
||||
|
||||
public void onUiStart() {
|
||||
loaderManager.restartLoader(loaderId, null, this);
|
||||
LiveData<List<UnifiedKeyInfo>> liveData =
|
||||
viewModel.getGenericLiveData(context, keyRepository::getAllUnifiedKeyInfoWithSecret);
|
||||
liveData.observe(lifecycleOwner, this::onLoadSecretUnifiedKeyInfo);
|
||||
|
||||
if (keyTransferServerInteractor == null && keyTransferClientInteractor == null && !wasConnected) {
|
||||
checkWifiResetAndStartListen();
|
||||
}
|
||||
}
|
||||
|
||||
private void onLoadSecretUnifiedKeyInfo(List<UnifiedKeyInfo> data) {
|
||||
secretKeyAdapter.setData(data);
|
||||
view.setShowSecretKeyEmptyView(data.isEmpty());
|
||||
}
|
||||
|
||||
public void onUiStop() {
|
||||
connectionClear();
|
||||
|
||||
@@ -288,12 +294,9 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
Timber.d("data sent ok!");
|
||||
final long masterKeyId = Long.parseLong(passthrough);
|
||||
|
||||
new Handler().postDelayed(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
secretKeyAdapter.focusItem(null);
|
||||
secretKeyAdapter.addToFinishedItems(masterKeyId);
|
||||
}
|
||||
new Handler().postDelayed(() -> {
|
||||
secretKeyAdapter.focusItem(null);
|
||||
secretKeyAdapter.addToFinishedItems(masterKeyId);
|
||||
}, 750);
|
||||
}
|
||||
|
||||
@@ -376,6 +379,10 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
|
||||
private boolean isWifiConnected() {
|
||||
ConnectivityManager connManager = (ConnectivityManager) context.getSystemService(Context.CONNECTIVITY_SERVICE);
|
||||
if (connManager == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
NetworkInfo wifiNetwork = connManager.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
|
||||
|
||||
return wifiNetwork.isConnected();
|
||||
@@ -411,7 +418,7 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
|
||||
private void prepareAndSendKey(long masterKeyId) {
|
||||
try {
|
||||
byte[] armoredSecretKey = databaseInteractor.getSecretKeyRingAsArmoredData(masterKeyId);
|
||||
byte[] armoredSecretKey = keyRepository.getSecretKeyRingAsArmoredData(masterKeyId);
|
||||
secretKeyAdapter.focusItem(masterKeyId);
|
||||
connectionSend(armoredSecretKey, Long.toString(masterKeyId));
|
||||
} catch (IOException | NotFoundException e) {
|
||||
@@ -429,24 +436,6 @@ public class TransferPresenter implements KeyTransferCallback, LoaderCallbacks<L
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Loader<List<SecretKeyItem>> onCreateLoader(int id, Bundle args) {
|
||||
return secretKeyAdapter.createLoader(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoadFinished(Loader<List<SecretKeyItem>> loader, List<SecretKeyItem> data) {
|
||||
secretKeyAdapter.setData(data);
|
||||
view.setShowSecretKeyEmptyView(data.isEmpty());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLoaderReset(Loader<List<SecretKeyItem>> loader) {
|
||||
secretKeyAdapter.setData(null);
|
||||
}
|
||||
|
||||
|
||||
public interface TransferMvpView {
|
||||
void showNotOnWifi();
|
||||
void showWaitingForConnection();
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.sufficientlysecure.keychain.ui.transfer.view;
|
||||
|
||||
|
||||
import android.app.Activity;
|
||||
import android.arch.lifecycle.ViewModelProviders;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
@@ -62,6 +63,7 @@ import org.sufficientlysecure.keychain.ui.MainActivity;
|
||||
import org.sufficientlysecure.keychain.ui.QrCodeCaptureActivity;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper;
|
||||
import org.sufficientlysecure.keychain.ui.base.CryptoOperationHelper.Callback;
|
||||
import org.sufficientlysecure.keychain.ui.keyview.GenericViewModel;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.presenter.TransferPresenter.TransferMvpView;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
@@ -140,7 +142,8 @@ public class TransferFragment extends Fragment implements TransferMvpView {
|
||||
}
|
||||
});
|
||||
|
||||
presenter = new TransferPresenter(getContext(), getLoaderManager(), LOADER_ID, this);
|
||||
GenericViewModel genericViewModel = ViewModelProviders.of(this).get(GenericViewModel.class);
|
||||
presenter = new TransferPresenter(getContext(), this, genericViewModel, this);
|
||||
|
||||
setHasOptionsMenu(true);
|
||||
|
||||
|
||||
@@ -22,8 +22,8 @@ import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.support.v4.content.Loader;
|
||||
import android.support.v7.widget.LinearLayoutManager;
|
||||
import android.support.v7.widget.RecyclerView;
|
||||
import android.text.format.DateUtils;
|
||||
@@ -35,8 +35,7 @@ import android.widget.TextView;
|
||||
import android.widget.ViewAnimator;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader;
|
||||
import org.sufficientlysecure.keychain.ui.transfer.loader.SecretKeyLoader.SecretKeyItem;
|
||||
import org.sufficientlysecure.keychain.model.SubKey.UnifiedKeyInfo;
|
||||
import org.sufficientlysecure.keychain.ui.util.recyclerview.DividerItemDecoration;
|
||||
|
||||
|
||||
@@ -75,7 +74,7 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
private final OnClickTransferKeyListener onClickTransferKeyListener;
|
||||
|
||||
private Long focusedMasterKeyId;
|
||||
private List<SecretKeyItem> data;
|
||||
private List<UnifiedKeyInfo> data;
|
||||
private ArrayList<Long> finishedItems = new ArrayList<>();
|
||||
private boolean allItemsDisabled;
|
||||
|
||||
@@ -87,15 +86,16 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
this.onClickTransferKeyListener = onClickTransferKeyListener;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public TransferKeyViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
|
||||
public TransferKeyViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
|
||||
return new TransferKeyViewHolder(layoutInflater.inflate(R.layout.key_transfer_item, parent, false));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBindViewHolder(TransferKeyViewHolder holder, int position) {
|
||||
SecretKeyItem item = data.get(position);
|
||||
boolean isFinished = finishedItems.contains(item.masterKeyId);
|
||||
public void onBindViewHolder(@NonNull TransferKeyViewHolder holder, int position) {
|
||||
UnifiedKeyInfo item = data.get(position);
|
||||
boolean isFinished = finishedItems.contains(item.master_key_id());
|
||||
holder.bind(context, item, onClickTransferKeyListener, focusedMasterKeyId, isFinished, allItemsDisabled);
|
||||
}
|
||||
|
||||
@@ -106,10 +106,10 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
|
||||
@Override
|
||||
public long getItemId(int position) {
|
||||
return data.get(position).masterKeyId;
|
||||
return data.get(position).master_key_id();
|
||||
}
|
||||
|
||||
public void setData(List<SecretKeyItem> data) {
|
||||
public void setData(List<UnifiedKeyInfo> data) {
|
||||
this.data = data;
|
||||
notifyDataSetChanged();
|
||||
}
|
||||
@@ -129,10 +129,6 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
notifyItemRangeChanged(0, getItemCount());
|
||||
}
|
||||
|
||||
public Loader<List<SecretKeyItem>> createLoader(Context context) {
|
||||
return new SecretKeyLoader(context, context.getContentResolver());
|
||||
}
|
||||
|
||||
public void setAllDisabled(boolean allItemsdisablde) {
|
||||
allItemsDisabled = allItemsdisablde;
|
||||
notifyItemRangeChanged(0, getItemCount());
|
||||
@@ -157,23 +153,23 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
vState = itemView.findViewById(R.id.transfer_state);
|
||||
}
|
||||
|
||||
private void bind(Context context, final SecretKeyItem item,
|
||||
private void bind(Context context, UnifiedKeyInfo item,
|
||||
final OnClickTransferKeyListener onClickTransferKeyListener, Long focusedMasterKeyId,
|
||||
boolean isFinished, boolean disableAll) {
|
||||
if (item.name != null) {
|
||||
vName.setText(item.name);
|
||||
if (item.name() != null) {
|
||||
vName.setText(item.name());
|
||||
vName.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vName.setVisibility(View.GONE);
|
||||
}
|
||||
if (item.email != null) {
|
||||
vEmail.setText(item.email);
|
||||
if (item.email() != null) {
|
||||
vEmail.setText(item.email());
|
||||
vEmail.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
vEmail.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
String dateTime = DateUtils.formatDateTime(context, item.creationMillis,
|
||||
String dateTime = DateUtils.formatDateTime(context, item.creation() * 1000,
|
||||
DateUtils.FORMAT_SHOW_DATE | DateUtils.FORMAT_SHOW_TIME |
|
||||
DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH);
|
||||
vCreation.setText(context.getString(R.string.label_key_created, dateTime));
|
||||
@@ -186,7 +182,7 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
}
|
||||
|
||||
if (focusedMasterKeyId != null) {
|
||||
if (focusedMasterKeyId != item.masterKeyId) {
|
||||
if (focusedMasterKeyId != item.master_key_id()) {
|
||||
itemView.animate().alpha(0.2f).start();
|
||||
vState.setDisplayedChild(isFinished ? STATE_TRANSFERRED : STATE_INVISIBLE);
|
||||
} else {
|
||||
@@ -199,12 +195,8 @@ public class TransferSecretKeyList extends RecyclerView {
|
||||
}
|
||||
|
||||
if (focusedMasterKeyId == null && onClickTransferKeyListener != null) {
|
||||
vSendButton.setOnClickListener(new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
onClickTransferKeyListener.onUiClickTransferKey(item.masterKeyId);
|
||||
}
|
||||
});
|
||||
vSendButton.setOnClickListener(
|
||||
v -> onClickTransferKeyListener.onUiClickTransferKey(item.master_key_id()));
|
||||
} else {
|
||||
vSendButton.setOnClickListener(null);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user