Add OPML import to the account type list activity

This commit is contained in:
Shinokuni 2019-11-11 15:22:47 +01:00
parent 1f41cb974a
commit e9448c6dde
6 changed files with 144 additions and 49 deletions

View File

@ -1,36 +1,45 @@
package com.readrops.app.activities;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.view.MenuItem;
import android.view.View;
import android.widget.LinearLayout;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import com.afollestad.materialdialogs.MaterialDialog;
import com.readrops.app.R;
import com.readrops.app.adapters.AccountTypeListAdapter;
import com.readrops.app.database.entities.account.Account;
import com.readrops.app.database.entities.account.AccountType;
import com.readrops.app.databinding.ActivityAccountTypeListBinding;
import com.readrops.app.utils.Utils;
import com.readrops.app.viewmodels.AccountViewModel;
import com.readrops.app.adapters.AccountTypeListAdapter;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.observers.DisposableCompletableObserver;
import io.reactivex.observers.DisposableSingleObserver;
import io.reactivex.schedulers.Schedulers;
import static com.readrops.app.fragments.settings.AccountSettingsFragment.OPEN_OPML_FILE_REQUEST;
import static com.readrops.app.utils.ReadropsKeys.ACCOUNT;
public class AccountTypeListActivity extends AppCompatActivity {
private static final String TAG = AccountTypeListActivity.class.getSimpleName();
private ActivityAccountTypeListBinding binding;
private AccountTypeListAdapter adapter;
private AccountViewModel viewModel;
@ -55,7 +64,7 @@ public class AccountTypeListActivity extends AppCompatActivity {
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
adapter = new AccountTypeListAdapter(accountType -> {
if (!(accountType == AccountType.LOCAL)) {
if (accountType != AccountType.LOCAL) {
Intent intent = new Intent(getApplicationContext(), AddAccountActivity.class);
if (fromMainActivity)
@ -65,8 +74,27 @@ public class AccountTypeListActivity extends AppCompatActivity {
startActivity(intent);
finish();
} else
createNewLocalAccount(accountType);
} else {
Account account = new Account(null, getString(AccountType.LOCAL.getName()), AccountType.LOCAL);
account.setCurrentAccount(true);
viewModel.insert(account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableSingleObserver<Long>() {
@Override
public void onSuccess(Long id) {
account.setId(id.intValue());
goToNextActivity(account);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.getMessage());
Utils.showSnackbar(binding.accountTypeListRoot, e.getMessage());
}
});
}
});
@ -84,39 +112,6 @@ public class AccountTypeListActivity extends AppCompatActivity {
return accountTypes;
}
private void createNewLocalAccount(AccountType accountType) {
Account account = new Account(null, getString(accountType.getName()), accountType);
account.setCurrentAccount(true);
viewModel.insert(account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableSingleObserver<Long>() {
@Override
public void onSuccess(Long id) {
account.setId(id.intValue());
if (fromMainActivity) {
Intent intent = new Intent();
intent.putExtra(ACCOUNT, account);
setResult(RESULT_OK, intent);
} else {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(ACCOUNT, account);
startActivity(intent);
}
finish();
}
@Override
public void onError(Throwable e) {
Utils.showSnackbar(binding.accountTypeListRoot, e.getMessage());
}
});
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
@ -127,4 +122,75 @@ public class AccountTypeListActivity extends AppCompatActivity {
return super.onOptionsItemSelected(item);
}
public void openOPMLFile(View view) {
Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
intent.addCategory(Intent.CATEGORY_OPENABLE);
intent.setType("application/*");
startActivityForResult(intent, OPEN_OPML_FILE_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == OPEN_OPML_FILE_REQUEST && resultCode == RESULT_OK && data != null) {
Uri uri = data.getData();
MaterialDialog dialog = new MaterialDialog.Builder(this)
.title(R.string.opml_processing)
.content(R.string.operation_takes_time)
.progress(true, 100)
.cancelable(false)
.show();
parseOPMLFile(uri, dialog);
}
super.onActivityResult(requestCode, resultCode, data);
}
private void parseOPMLFile(Uri uri, MaterialDialog dialog) {
Account account = new Account(null, getString(AccountType.LOCAL.getName()), AccountType.LOCAL);
account.setCurrentAccount(true);
viewModel.insert(account)
.flatMapCompletable(id -> {
account.setId(id.intValue());
viewModel.setAccount(account);
return viewModel.parseOPMLFile(uri);
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableCompletableObserver() {
@Override
public void onComplete() {
dialog.dismiss();
goToNextActivity(account);
}
@Override
public void onError(Throwable e) {
Log.e(TAG, e.getMessage());
dialog.dismiss();
Utils.showSnackbar(binding.accountTypeListRoot, e.getMessage());
}
});
}
private void goToNextActivity(Account account) {
if (fromMainActivity) {
Intent intent = new Intent();
intent.putExtra(ACCOUNT, account);
setResult(RESULT_OK, intent);
} else {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(ACCOUNT, account);
startActivity(intent);
}
finish();
}
}

View File

@ -24,13 +24,13 @@ import androidx.preference.PreferenceFragmentCompat;
import com.afollestad.materialdialogs.MaterialDialog;
import com.readrops.app.R;
import com.readrops.app.ReadropsApp;
import com.readrops.app.activities.AddAccountActivity;
import com.readrops.app.activities.ManageFeedsFoldersActivity;
import com.readrops.app.database.entities.account.Account;
import com.readrops.app.database.entities.account.AccountType;
import com.readrops.app.utils.matchers.OPMLMatcher;
import com.readrops.app.ReadropsApp;
import com.readrops.app.utils.Utils;
import com.readrops.app.utils.matchers.OPMLMatcher;
import com.readrops.app.viewmodels.AccountViewModel;
import com.readrops.readropslibrary.opml.OPMLParser;
import com.readrops.readropslibrary.opml.model.OPML;
@ -55,7 +55,7 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
private static final String TAG = AccountSettingsFragment.class.getSimpleName();
private static final int OPEN_OPML_FILE_REQUEST = 1;
public static final int OPEN_OPML_FILE_REQUEST = 1;
private static final int WRITE_EXTERNAL_STORAGE_REQUEST = 1;
private Account account;
@ -192,8 +192,7 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
}
private void parseOPMLFile(Uri uri, MaterialDialog dialog) {
OPMLParser.read(uri, getContext())
.flatMapCompletable(opml -> viewModel.insertOPMLFoldersAndFeeds(opml))
viewModel.parseOPMLFile(uri)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new DisposableCompletableObserver() {

View File

@ -1,6 +1,7 @@
package com.readrops.app.viewmodels;
import android.app.Application;
import android.net.Uri;
import android.util.Log;
import androidx.annotation.NonNull;
@ -13,7 +14,7 @@ import com.readrops.app.database.entities.account.Account;
import com.readrops.app.database.entities.account.AccountType;
import com.readrops.app.repositories.ARepository;
import com.readrops.app.utils.matchers.OPMLMatcher;
import com.readrops.readropslibrary.opml.model.OPML;
import com.readrops.readropslibrary.opml.OPMLParser;
import java.util.List;
import java.util.Map;
@ -66,13 +67,16 @@ public class AccountViewModel extends AndroidViewModel {
return database.accountDao().getAccountCount();
}
public Completable insertOPMLFoldersAndFeeds(OPML opml) {
Map<Folder, List<Feed>> foldersAndFeeds = OPMLMatcher.INSTANCE.opmltoFoldersAndFeeds(opml);
return repository.insertOPMLFoldersAndFeeds(foldersAndFeeds);
}
public Single<Map<Folder, List<Feed>>> getFoldersWithFeeds() {
return repository.getFoldersWithFeeds();
}
public Completable parseOPMLFile(Uri uri) {
return OPMLParser.read(uri, getApplication())
.flatMapCompletable(opml -> {
Map<Folder, List<Feed>> foldersAndFeeds = OPMLMatcher.INSTANCE.opmltoFoldersAndFeeds(opml);
return repository.insertOPMLFoldersAndFeeds(foldersAndFeeds);
});
}
}

View File

@ -49,6 +49,30 @@
app:layout_constraintTop_toBottomOf="@+id/account_type_list_choose"
tools:itemCount="4"
tools:listitem="@layout/account_type_item" />
<TextView
android:id="@+id/account_type_or"
style="@style/TextAppearance.AppCompat.Large"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/or"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/account_type_recyclerview" />
<Button
android:id="@+id/account_type_opml_import"
style="@style/GenericButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/opml_import"
android:onClick="openOPMLFile"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/account_type_or" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>

View File

@ -102,5 +102,6 @@
<string name="external_storage_opml_export">L\'export des soubscriptions nécessite l\'accès au stockage</string>
<string name="try_again">Réessayer</string>
<string name="permissions">Permissions</string>
<string name="or">Ou</string>
</resources>

View File

@ -111,4 +111,5 @@
<string name="external_storage_opml_export">Subscriptions export needs external storage permission</string>
<string name="try_again">Try again</string>
<string name="permissions">Permissions</string>
<string name="or">Or</string>
</resources>