Add account settings activity to modify account informations and get account feeds and folder list

This commit is contained in:
Shinokuni 2019-07-11 13:49:34 +02:00
parent e1bf8b936e
commit 7ca509e8a9
15 changed files with 284 additions and 119 deletions

View File

@ -16,6 +16,9 @@
android:theme="@style/AppTheme"
android:usesCleartextTraffic="true"
tools:ignore="GoogleAppIndexingWarning">
<activity
android:name=".activities.AccountSettingsActivity"
android:parentActivityName=".activities.MainActivity" />
<activity
android:name=".activities.SplashActivity"
android:theme="@style/SplashTheme">

View File

@ -0,0 +1,59 @@
package com.readrops.app.activities;
import android.content.Intent;
import android.os.Bundle;
import android.view.MenuItem;
import androidx.appcompat.app.AppCompatActivity;
import androidx.databinding.DataBindingUtil;
import com.readrops.app.R;
import com.readrops.app.database.entities.Account;
import com.readrops.app.databinding.ActivityAccountSettingsBinding;
public class AccountSettingsActivity extends AppCompatActivity {
public static final String ACCOUNT = "ACCOUNT";
private ActivityAccountSettingsBinding binding;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
binding = DataBindingUtil.setContentView(this, R.layout.activity_account_settings);
Account account = getIntent().getParcelableExtra(ACCOUNT);
binding.accountSettingsFeeds.setOnClickListener(v -> {
Intent intent = new Intent(getApplication(), ManageFeedsActivity.class);
intent.putExtra(ManageFeedsActivity.ACCOUNT, account);
startActivity(intent);
});
binding.accountSettingsAccount.setOnClickListener(v -> {
if (account.getAccountType() != Account.AccountType.LOCAL) {
Intent intent = new Intent(getApplication(), AddAccountActivity.class);
intent.putExtra(AddAccountActivity.EDIT_ACCOUNT, account);
startActivity(intent);
}
});
}
@Override
public void onBackPressed() {
finish();
super.onBackPressed();
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
finish();
break;
}
return super.onOptionsItemSelected(item);
}
}

View File

@ -16,6 +16,7 @@ import com.readrops.app.databinding.ActivityAddAccountBinding;
import com.readrops.app.utils.SharedPreferencesManager;
import com.readrops.app.viewmodels.AccountViewModel;
import io.reactivex.CompletableObserver;
import io.reactivex.SingleObserver;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.disposables.Disposable;
@ -23,11 +24,15 @@ import io.reactivex.schedulers.Schedulers;
public class AddAccountActivity extends AppCompatActivity {
public static final String EDIT_ACCOUNT = "EDIT_ACCOUNT";
private ActivityAddAccountBinding binding;
private AccountViewModel viewModel;
private Account.AccountType accountType;
private boolean forwardResult;
private boolean forwardResult, editAccount;
private Account accountToEdit;
@Override
protected void onCreate(Bundle savedInstanceState) {
@ -41,17 +46,17 @@ public class AddAccountActivity extends AppCompatActivity {
int flag = getIntent().getFlags();
forwardResult = flag == Intent.FLAG_ACTIVITY_FORWARD_RESULT;
binding.providerImage.setImageResource(accountType.getIconRes());
binding.providerName.setText(accountType.getName());
accountToEdit = getIntent().getParcelableExtra(EDIT_ACCOUNT);
binding.addAccountSkip.setOnClickListener(v -> {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
startActivity(intent);
if (accountToEdit != null) {
editAccount = true;
fillFields();
} else {
binding.providerImage.setImageResource(accountType.getIconRes());
binding.providerName.setText(accountType.getName());
finish();
});
binding.addAccountName.setText(accountType.getName());
binding.addAccountName.setText(accountType.getName());
}
}
public void createAccount(View view) {
@ -61,55 +66,87 @@ public class AddAccountActivity extends AppCompatActivity {
String login = binding.addAccountLogin.getText().toString().trim();
String password = binding.addAccountPassword.getText().toString().trim();
Account account = new Account(url, name, accountType);
account.setLogin(login);
account.setPassword(password);
viewModel.login(account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Boolean>() {
if (editAccount) {
accountToEdit.setUrl(url);
accountToEdit.setAccountName(name);
accountToEdit.setLogin(login);
accountToEdit.setPassword(password);
@Override
public void onSubscribe(Disposable d) {
binding.addAccountLoading.setVisibility(View.VISIBLE);
binding.addAccountValidate.setEnabled(false);
}
@Override
public void onSuccess(Boolean success) {
binding.addAccountLoading.setVisibility(View.GONE);
if (success) {
saveLoginPassword(account);
if (forwardResult) {
Intent intent = new Intent();
intent.putExtra(MainActivity.ACCOUNT_KEY, account);
setResult(RESULT_OK, intent);
finish();
} else {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(MainActivity.ACCOUNT_KEY, account);
startActivity(intent);
}
finish();
} else {
binding.addAccountValidate.setEnabled(true);
Toast.makeText(AddAccountActivity.this, "Impossible to login",
Toast.LENGTH_LONG).show();
viewModel.update(accountToEdit)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new CompletableObserver() {
@Override
public void onSubscribe(Disposable d) {
binding.addAccountLoading.setVisibility(View.VISIBLE);
binding.addAccountValidate.setEnabled(false);
}
}
@Override
public void onError(Throwable e) {
binding.addAccountLoading.setVisibility(View.GONE);
binding.addAccountValidate.setEnabled(true);
Toast.makeText(AddAccountActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
});
@Override
public void onComplete() {
finish();
}
@Override
public void onError(Throwable e) {
binding.addAccountLoading.setVisibility(View.GONE);
binding.addAccountValidate.setEnabled(true);
Toast.makeText(AddAccountActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
});
} else {
Account account = new Account(url, name, accountType);
account.setLogin(login);
account.setPassword(password);
viewModel.login(account)
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new SingleObserver<Boolean>() {
@Override
public void onSubscribe(Disposable d) {
binding.addAccountLoading.setVisibility(View.VISIBLE);
binding.addAccountValidate.setEnabled(false);
}
@Override
public void onSuccess(Boolean success) {
binding.addAccountLoading.setVisibility(View.GONE);
if (success) {
saveLoginPassword(account);
if (forwardResult) {
Intent intent = new Intent();
intent.putExtra(MainActivity.ACCOUNT_KEY, account);
setResult(RESULT_OK, intent);
finish();
} else {
Intent intent = new Intent(getApplicationContext(), MainActivity.class);
intent.putExtra(MainActivity.ACCOUNT_KEY, account);
startActivity(intent);
}
finish();
} else {
binding.addAccountValidate.setEnabled(true);
Toast.makeText(AddAccountActivity.this, "Impossible to login",
Toast.LENGTH_LONG).show();
}
}
@Override
public void onError(Throwable e) {
binding.addAccountLoading.setVisibility(View.GONE);
binding.addAccountValidate.setEnabled(true);
Toast.makeText(AddAccountActivity.this, e.getMessage(), Toast.LENGTH_LONG).show();
}
});
}
}
}
@ -149,4 +186,14 @@ public class AddAccountActivity extends AppCompatActivity {
account.setLogin(null);
account.setPassword(null);
}
private void fillFields() {
binding.providerImage.setImageResource(accountToEdit.getAccountType().getIconRes());
binding.providerName.setText(accountToEdit.getAccountType().getName());
binding.addAccountUrl.setText(accountToEdit.getUrl());
binding.addAccountName.setText(accountToEdit.getAccountName());
binding.addAccountLogin.setText(SharedPreferencesManager.readString(this, accountToEdit.getLoginKey()));
binding.addAccountPassword.setText(SharedPreferencesManager.readString(this, accountToEdit.getPasswordKey()));
}
}

View File

@ -31,7 +31,6 @@ import com.afollestad.materialdialogs.MaterialDialog;
import com.bumptech.glide.Glide;
import com.bumptech.glide.integration.recyclerview.RecyclerViewPreloader;
import com.bumptech.glide.util.ViewPreloadSizeProvider;
import com.github.clans.fab.FloatingActionMenu;
import com.mikepenz.materialdrawer.Drawer;
import com.mikepenz.materialdrawer.model.PrimaryDrawerItem;
import com.mikepenz.materialdrawer.model.SecondaryDrawerItem;
@ -74,7 +73,6 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
private Toolbar toolbar;
private Drawer drawer;
private FloatingActionMenu actionMenu;
private PagedList<ItemWithFeed> allItems;
@ -110,8 +108,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
syncProgressLayout = findViewById(R.id.sync_progress_layout);
syncProgress = findViewById(R.id.sync_progress_text_view);
syncProgressBar = findViewById(R.id.sync_progress_bar);
actionMenu = findViewById(R.id.fab_menu);
syncProgressBar = findViewById(R.id.sync_progress_bar);
feedCount = 0;
initRecyclerView();
@ -158,6 +155,10 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
}
break;
}
} else {
Intent intent = new Intent(this, AccountSettingsActivity.class);
intent.putExtra(AccountSettingsActivity.ACCOUNT, viewModel.getCurrentAccount());
startActivity(intent);
}
return true;
@ -465,19 +466,10 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
}
public void openAddFeedActivity(View view) {
actionMenu.close(true);
Intent intent = new Intent(this, AddFeedActivity.class);
startActivityForResult(intent, ADD_FEED_REQUEST);
}
public void addFolder(View view) {
actionMenu.close(true);
Intent intent = new Intent(this, ManageFeedsActivity.class);
startActivityForResult(intent, MANAGE_FEEDS_REQUEST);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
if (requestCode == ADD_FEED_REQUEST && resultCode == RESULT_OK) {

View File

@ -11,13 +11,14 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.FragmentTransaction;
import androidx.lifecycle.ViewModelProvider;
import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.afollestad.materialdialogs.MaterialDialog;
import com.readrops.app.R;
import com.readrops.app.database.entities.Account;
import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.viewmodels.ManageFeedsViewModel;
@ -30,18 +31,27 @@ import io.reactivex.schedulers.Schedulers;
public class ManageFeedsActivity extends AppCompatActivity {
public static final String ACCOUNT = "ACCOUNT";
private RecyclerView recyclerView;
private FeedsAdapter adapter;
private ManageFeedsViewModel viewModel;
private Account account;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_manage_feeds);
account = getIntent().getParcelableExtra(ACCOUNT);
viewModel = ViewModelProviders.of(this).get(ManageFeedsViewModel.class);
viewModel.setAccount(account);
recyclerView = findViewById(R.id.feeds_recyclerview);
recyclerView.setLayoutManager(new LinearLayoutManager(getApplicationContext()));
recyclerView.setLayoutManager(new LinearLayoutManager(this));
adapter = new FeedsAdapter(new FeedsAdapter.ManageFeedsListener() {
@Override
@ -88,10 +98,7 @@ public class ManageFeedsActivity extends AppCompatActivity {
}).attachToRecyclerView(recyclerView);
viewModel = ViewModelProvider.AndroidViewModelFactory.getInstance(getApplication()).create(ManageFeedsViewModel.class);
viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> {
adapter.submitList(feedWithFolders);
});
viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> adapter.submitList(feedWithFolders));
}
private void deleteFolder(int feedId, int position) {

View File

@ -4,6 +4,7 @@ import androidx.lifecycle.LiveData;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.Update;
import com.readrops.app.database.entities.Account;
@ -24,6 +25,9 @@ public interface AccountDao {
@Insert
long insert(Account account);
@Update
void update(Account account);
@Query("Update Account set last_modified = :lastModified Where id = :accountId")
void updateLastModified(int accountId, long lastModified);

View File

@ -61,8 +61,8 @@ public interface FeedDao {
@Query("Select Feed.name as feed_name, Feed.id as feed_id, Folder.name as folder_name, Folder.id as folder_id," +
"Feed.description as feed_description, Feed.icon_url as feed_icon_url, Feed.url as feed_url, Feed.folder_id as feed_folder_id" +
", Feed.siteUrl as feed_siteUrl from Feed Left Join Folder on Feed.folder_id = Folder.id Order by Feed.name")
LiveData<List<FeedWithFolder>> getAllFeedsWithFolder();
", Feed.siteUrl as feed_siteUrl from Feed Left Join Folder on Feed.folder_id = Folder.id Where Feed.account_id = :accountId Order by Feed.name")
LiveData<List<FeedWithFolder>> getAllFeedsWithFolder(int accountId);
@Query("Select * From Feed Where id in (:ids)")
List<Feed> selectFromIdList(long[] ids);

View File

@ -13,8 +13,8 @@ import java.util.List;
@Dao
public interface FolderDao {
@Query("Select * from Folder Order By name ASC")
LiveData<List<Folder>> getAllFolders();
@Query("Select * from Folder Where account_id = :accountId Order By name ASC")
LiveData<List<Folder>> getAllFolders(int accountId);
@Query("Select * from Folder Where account_id = :accountId Order By name ASC")
List<Folder> getFolders(int accountId);

View File

@ -10,6 +10,7 @@ import com.readrops.app.database.entities.Account;
import com.readrops.app.repositories.ARepository;
import com.readrops.app.repositories.NextNewsRepository;
import io.reactivex.Completable;
import io.reactivex.Single;
public class AccountViewModel extends AndroidViewModel {
@ -36,6 +37,13 @@ public class AccountViewModel extends AndroidViewModel {
}
public Completable update(Account account) {
return Completable.create(emitter -> {
database.accountDao().update(account);
emitter.onComplete();
});
}
public Single<Integer> getAccountCountByAccountType(int accountTypeCode) {
return Single.create(emitter -> emitter.onSuccess(database.accountDao().getAccountCountByType(accountTypeCode)));
}

View File

@ -6,9 +6,12 @@ import androidx.lifecycle.LiveData;
import androidx.annotation.NonNull;
import com.readrops.app.database.Database;
import com.readrops.app.database.entities.Account;
import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.repositories.ARepository;
import com.readrops.app.repositories.LocalFeedRepository;
import com.readrops.app.repositories.NextNewsRepository;
import java.util.List;
@ -19,15 +22,28 @@ public class ManageFeedsViewModel extends AndroidViewModel {
private Database db;
private LiveData<List<FeedWithFolder>> feedsWithFolder;
private LiveData<List<Folder>> folders;
private LocalFeedRepository repository;
private ARepository repository;
private Account account;
public ManageFeedsViewModel(@NonNull Application application) {
super(application);
db = Database.getInstance(application);
repository = new LocalFeedRepository(application);
feedsWithFolder = db.feedDao().getAllFeedsWithFolder();
folders = db.folderDao().getAllFolders();
db = Database.getInstance(application);
}
private void setup() {
switch (account.getAccountType()) {
case LOCAL:
repository = new LocalFeedRepository(getApplication());
break;
case NEXTCLOUD_NEWS:
repository = new NextNewsRepository(getApplication());
break;
}
feedsWithFolder = db.feedDao().getAllFeedsWithFolder(account.getId());
folders = db.folderDao().getAllFolders(account.getId());
}
public LiveData<List<FeedWithFolder>> getFeedsWithFolder() {
@ -38,6 +54,15 @@ public class ManageFeedsViewModel extends AndroidViewModel {
repository.updateFeedWithFolder(feedWithFolder);
}
public Account getAccount() {
return account;
}
public void setAccount(Account account) {
this.account = account;
setup();
}
public LiveData<List<Folder>> getFolders() {
return folders;
}

View File

@ -0,0 +1,47 @@
<?xml version="1.0" encoding="utf-8"?>
<layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
tools:context=".activities.AccountSettingsActivity">
<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<RelativeLayout
android:id="@+id/account_settings_feeds"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:clickable="true"
android:focusable="true"
android:padding="10dp"
app:layout_constraintTop_toTopOf="parent">
<TextView
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="@string/feeds" />
</RelativeLayout>
<RelativeLayout
android:id="@+id/account_settings_account"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?android:attr/selectableItemBackground"
android:padding="10dp"
app:layout_constraintTop_toBottomOf="@id/account_settings_feeds">
<TextView
style="@style/TextAppearance.AppCompat.Subhead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_centerVertical="true"
android:text="@string/account" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>
</layout>

View File

@ -114,15 +114,6 @@
android:visibility="gone"
tools:visibility="visible" />
<TextView
android:id="@+id/add_account_skip"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@id/add_account_loading"
android:layout_centerInParent="true"
android:layout_marginTop="8dp"
android:text="Skip" />
</RelativeLayout>
</androidx.constraintlayout.widget.ConstraintLayout>

View File

@ -108,36 +108,14 @@
</RelativeLayout>
<com.github.clans.fab.FloatingActionMenu
android:id="@+id/fab_menu"
<com.google.android.material.floatingactionbutton.FloatingActionButton
android:id="@+id/add_feed_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="12dp"
app:menu_colorNormal="@color/colorPrimary"
app:menu_icon="@drawable/fab_add">
<com.github.clans.fab.FloatingActionButton
android:id="@+id/add_feed_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="openAddFeedActivity"
android:src="@drawable/ic_insert_link_white"
app:fab_colorNormal="@color/colorPrimary"
app:fab_label="@string/add_feed_item"
app:fab_size="mini" />
<com.github.clans.fab.FloatingActionButton
android:id="@+id/add_folder_fab"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:onClick="addFolder"
android:src="@drawable/ic_folder_white"
app:fab_colorNormal="@color/colorPrimary"
app:fab_label="@string/add_folder"
app:fab_size="mini" />
</com.github.clans.fab.FloatingActionMenu>
android:onClick="openAddFeedActivity"
android:src="@drawable/ic_add_white"
android:layout_margin="16dp"/>
</FrameLayout>

View File

@ -59,5 +59,7 @@
<string name="no_feed">Aucun flux</string>
<string name="choose_account">Choisir un compte</string>
<string name="local_account">Compte local</string>
<string name="feeds">Flux</string>
<string name="account">Compte</string>
</resources>

View File

@ -64,4 +64,6 @@
<string name="local_account">Local account</string>
<string name="freshrss" translatable="false">Freshrss</string>
<string name="feedly" translatable="false">Feedly</string>
<string name="feeds">Feeds</string>
<string name="account">Account</string>
</resources>