Merge remote-tracking branch 'origin/master'

This commit is contained in:
Shinokuni 2019-10-08 21:18:59 +02:00
commit fded33596f
4 changed files with 262 additions and 245 deletions

View File

@ -2,38 +2,38 @@ package com.readrops.app.activities;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.content.Intent; import android.content.Intent;
import android.graphics.Color;
import android.os.Bundle; import android.os.Bundle;
import android.util.Patterns; import android.util.Patterns;
import android.view.KeyEvent; import android.view.KeyEvent;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent; import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.AdapterView;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.Spinner;
import android.widget.TextView;
import androidx.annotation.NonNull; import androidx.annotation.Nullable;
import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.app.AppCompatActivity;
import androidx.core.widget.NestedScrollView; import androidx.databinding.DataBindingUtil;
import androidx.lifecycle.ViewModelProviders; import androidx.lifecycle.ViewModelProviders;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.ItemTouchHelper; import androidx.recyclerview.widget.ItemTouchHelper;
import androidx.recyclerview.widget.LinearLayoutManager; import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView; import androidx.recyclerview.widget.RecyclerView;
import com.google.android.material.textfield.TextInputEditText;
import com.mikepenz.fastadapter.FastAdapter; import com.mikepenz.fastadapter.FastAdapter;
import com.mikepenz.fastadapter.adapters.ItemAdapter; import com.mikepenz.fastadapter.adapters.ItemAdapter;
import com.mikepenz.fastadapter.commons.utils.DiffCallback;
import com.mikepenz.fastadapter.commons.utils.FastAdapterDiffUtil;
import com.readrops.app.R; import com.readrops.app.R;
import com.readrops.app.database.entities.account.Account; import com.readrops.app.adapters.AccountArrayAdapter;
import com.readrops.app.database.entities.Feed; import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.account.Account;
import com.readrops.app.databinding.ActivityAddFeedBinding;
import com.readrops.app.utils.FeedInsertionResult; import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.ParsingResult; import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.ReadropsItemTouchCallback;
import com.readrops.app.utils.SharedPreferencesManager; import com.readrops.app.utils.SharedPreferencesManager;
import com.readrops.app.utils.Utils; import com.readrops.app.utils.Utils;
import com.readrops.app.viewmodels.AddFeedsViewModel; import com.readrops.app.viewmodels.AddFeedsViewModel;
import com.readrops.app.adapters.AccountArrayAdapter;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@ -44,57 +44,35 @@ import io.reactivex.schedulers.Schedulers;
public class AddFeedActivity extends AppCompatActivity implements View.OnClickListener { public class AddFeedActivity extends AppCompatActivity implements View.OnClickListener {
private TextInputEditText feedInput;
private Button load;
private ProgressBar progressBar;
private Button validate;
private RecyclerView parseResultsRecyclerView;
private TextView resultsTextView;
private NestedScrollView rootLayout;
private ProgressBar feedInsertionProgressBar;
private RecyclerView insertionResultsRecyclerView;
private Spinner accountSpinner;
private AccountArrayAdapter arrayAdapter; private AccountArrayAdapter arrayAdapter;
private ItemAdapter<ParsingResult> parseItemsAdapter; private ItemAdapter<ParsingResult> parseItemsAdapter;
private ItemAdapter<FeedInsertionResult> insertionResultsAdapter; private ItemAdapter<FeedInsertionResult> insertionResultsAdapter;
FastAdapter<ParsingResult> fastAdapter;
private AddFeedsViewModel viewModel; private AddFeedsViewModel viewModel;
private ArrayList<Feed> feedsToUpdate; private ArrayList<Feed> feedsToUpdate;
private ActivityAddFeedBinding binding;
@SuppressLint("ClickableViewAccessibility") @SuppressLint("ClickableViewAccessibility")
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
setContentView(R.layout.activity_add_feed); binding = DataBindingUtil.setContentView(this, R.layout.activity_add_feed);
feedInput = findViewById(R.id.add_feed_text_input); binding.addFeedLoad.setOnClickListener(this);
load = findViewById(R.id.add_feed_load); binding.addFeedOk.setOnClickListener(this);
validate = findViewById(R.id.add_feed_ok); binding.addFeedOk.setEnabled(false);
progressBar = findViewById(R.id.add_feed_loading);
parseResultsRecyclerView = findViewById(R.id.add_feed_results);
resultsTextView = findViewById(R.id.add_feed_results_text_view);
feedInsertionProgressBar = findViewById(R.id.add_feed_insert_progressbar);
insertionResultsRecyclerView = findViewById(R.id.add_feed_inserted_results_recyclerview);
accountSpinner = findViewById(R.id.add_feed_account_spinner);
rootLayout = findViewById(R.id.add_feed_root); binding.addFeedTextInput.setOnTouchListener((v, event) -> {
load.setOnClickListener(this);
validate.setOnClickListener(this);
validate.setEnabled(false);
feedInput.setOnTouchListener((v, event) -> {
final int DRAWABLE_RIGHT = 2; final int DRAWABLE_RIGHT = 2;
if(event.getAction() == MotionEvent.ACTION_UP) { int drawablePos = (binding.addFeedTextInput.getRight() -
if(event.getRawX() >= (feedInput.getRight() - feedInput.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width())) { binding.addFeedTextInput.getCompoundDrawables()[DRAWABLE_RIGHT].getBounds().width());
feedInput.setText(""); if (event.getAction() == MotionEvent.ACTION_UP && event.getRawX() >= drawablePos) {
return true; binding.addFeedTextInput.setText("");
} return true;
} }
return false; return false;
@ -103,7 +81,7 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
viewModel = ViewModelProviders.of(this).get(AddFeedsViewModel.class); viewModel = ViewModelProviders.of(this).get(AddFeedsViewModel.class);
parseItemsAdapter = new ItemAdapter<>(); parseItemsAdapter = new ItemAdapter<>();
FastAdapter<ParsingResult> fastAdapter = FastAdapter.with(parseItemsAdapter); fastAdapter = FastAdapter.with(parseItemsAdapter);
fastAdapter.withSelectable(true); fastAdapter.withSelectable(true);
fastAdapter.withOnClickListener((v, adapter, item, position) -> { fastAdapter.withOnClickListener((v, adapter, item, position) -> {
if (item.isChecked()) { if (item.isChecked()) {
@ -114,67 +92,41 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
fastAdapter.notifyAdapterItemChanged(position); fastAdapter.notifyAdapterItemChanged(position);
} }
validate.setEnabled(recyclerViewHasCheckedItems()); binding.addFeedOk.setEnabled(recyclerViewHasCheckedItems());
return true; return true;
}); });
parseResultsRecyclerView.setAdapter(fastAdapter); binding.addFeedResults.setAdapter(fastAdapter);
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this); RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
parseResultsRecyclerView.setLayoutManager(layoutManager); binding.addFeedResults.setLayoutManager(layoutManager);
new ItemTouchHelper(new ItemTouchHelper.SimpleCallback(0, ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT) { new ItemTouchHelper(new ReadropsItemTouchCallback(this,
@Override new ReadropsItemTouchCallback.Config.Builder()
public int getMovementFlags(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder) { .swipeDirs(ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT)
int swipeFlags = ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT; .leftDraw(Color.RED, R.drawable.ic_delete)
.rightDraw(Color.RED, R.drawable.ic_delete)
.swipeCallback((viewHolder, direction) -> {
parseItemsAdapter.remove(viewHolder.getAdapterPosition());
return makeMovementFlags(0, swipeFlags); if (parseItemsAdapter.getAdapterItemCount() == 0) {
} binding.addFeedResultsTextView.setVisibility(View.GONE);
binding.addFeedResults.setVisibility(View.GONE);
@Override }
public boolean onMove(@NonNull RecyclerView recyclerView, @NonNull RecyclerView.ViewHolder viewHolder, @NonNull RecyclerView.ViewHolder viewHolder1) { })
return false; .build()))
} .attachToRecyclerView(binding.addFeedResults);
@Override
public void onSwiped(@NonNull RecyclerView.ViewHolder viewHolder, int i) {
parseItemsAdapter.remove(viewHolder.getAdapterPosition());
if (parseItemsAdapter.getAdapterItemCount() == 0) {
resultsTextView.setVisibility(View.GONE);
parseResultsRecyclerView.setVisibility(View.GONE);
}
}
@Override
public boolean isItemViewSwipeEnabled() {
return true;
}
}).attachToRecyclerView(parseResultsRecyclerView);
insertionResultsAdapter = new ItemAdapter<>(); insertionResultsAdapter = new ItemAdapter<>();
RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(this); RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(this);
insertionResultsRecyclerView.setAdapter(FastAdapter.with(insertionResultsAdapter)); binding.addFeedInsertedResultsRecyclerview.setAdapter(FastAdapter.with(insertionResultsAdapter));
insertionResultsRecyclerView.setLayoutManager(layoutManager1); binding.addFeedInsertedResultsRecyclerview.setLayoutManager(layoutManager1);
viewModel.getAccounts().observe(this, accounts -> { viewModel.getAccounts().observe(this, accounts -> {
arrayAdapter = new AccountArrayAdapter(this, accounts); arrayAdapter = new AccountArrayAdapter(this, accounts);
arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); arrayAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
accountSpinner.setAdapter(arrayAdapter); binding.addFeedAccountSpinner.setAdapter(arrayAdapter);
accountSpinner.setOnItemSelectedListener(new AdapterView.OnItemSelectedListener() {
@Override
public void onItemSelected(AdapterView<?> parent, View view, int position, long id) {
}
@Override
public void onNothingSelected(AdapterView<?> parent) {
}
});
}); });
feedsToUpdate = new ArrayList<>(); feedsToUpdate = new ArrayList<>();
@ -185,24 +137,25 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
switch (v.getId()) { switch (v.getId()) {
case R.id.add_feed_load: case R.id.add_feed_load:
if (isValidUrl()) { if (isValidUrl()) {
progressBar.setVisibility(View.VISIBLE); binding.addFeedLoading.setVisibility(View.VISIBLE);
loadFeed(); loadFeed();
} }
break; break;
case R.id.add_feed_ok: case R.id.add_feed_ok:
insertionResultsAdapter.clear();
insertFeeds(); insertFeeds();
break; break;
} }
} }
private boolean isValidUrl() { private boolean isValidUrl() {
String url = feedInput.getText().toString().trim(); String url = binding.addFeedTextInput.getText().toString().trim();
if (url.isEmpty()) { if (url.isEmpty()) {
feedInput.setError(getString(R.string.empty_field)); binding.addFeedTextInput.setError(getString(R.string.empty_field));
return false; return false;
} else if (!Patterns.WEB_URL.matcher(url).matches()) { } else if (!Patterns.WEB_URL.matcher(url).matches()) {
feedInput.setError(getString(R.string.wrong_url)); binding.addFeedTextInput.setError(getString(R.string.wrong_url));
return false; return false;
} else } else
return true; return true;
@ -217,8 +170,17 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
return false; return false;
} }
private void disableParsingResult(ParsingResult parsingResult) {
for (ParsingResult result : parseItemsAdapter.getAdapterItems()) {
if (result.getUrl().equals(parsingResult.getUrl())) {
result.setChecked(false);
fastAdapter.notifyAdapterItemChanged(parseItemsAdapter.getAdapterPosition(result));
}
}
}
private void loadFeed() { private void loadFeed() {
String url = feedInput.getText().toString().trim(); String url = binding.addFeedTextInput.getText().toString().trim();
final String finalUrl; final String finalUrl;
if (!(url.contains(Utils.HTTP_PREFIX) || url.contains(Utils.HTTPS_PREFIX))) if (!(url.contains(Utils.HTTP_PREFIX) || url.contains(Utils.HTTPS_PREFIX)))
@ -237,27 +199,47 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
Utils.showSnackbar(rootLayout, e.getMessage()); Utils.showSnackbar(binding.addFeedRoot, e.getMessage());
progressBar.setVisibility(View.GONE); binding.addFeedLoading.setVisibility(View.GONE);
} }
}); });
} }
private void displayParseResults(List<ParsingResult> parsingResultList) { private void displayParseResults(List<ParsingResult> parsingResultList) {
if (parsingResultList.size() > 0) { binding.addFeedLoading.setVisibility(View.GONE);
parseResultsRecyclerView.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
resultsTextView.setVisibility(View.VISIBLE);
parseItemsAdapter.add(parsingResultList); if (!parsingResultList.isEmpty()) {
validate.setEnabled(recyclerViewHasCheckedItems()); binding.addFeedResultsTextView.setVisibility(View.VISIBLE);
} else binding.addFeedResults.setVisibility(View.VISIBLE);
progressBar.setVisibility(View.GONE);
DiffUtil.DiffResult diffResult = FastAdapterDiffUtil.calculateDiff(parseItemsAdapter, parsingResultList, new DiffCallback<ParsingResult>() {
@Override
public boolean areItemsTheSame(ParsingResult oldItem, ParsingResult newItem) {
return oldItem.getUrl().equals(newItem.getUrl());
}
@Override
public boolean areContentsTheSame(ParsingResult oldItem, ParsingResult newItem) {
return oldItem.getUrl().equals(newItem.getUrl()) &&
oldItem.isChecked() == newItem.isChecked();
}
@Nullable
@Override
public Object getChangePayload(ParsingResult oldItem, int oldItemPosition, ParsingResult newItem, int newItemPosition) {
newItem.setChecked(oldItem.isChecked());
return newItem;
}
}, false);
FastAdapterDiffUtil.set(parseItemsAdapter, diffResult);
binding.addFeedOk.setEnabled(recyclerViewHasCheckedItems());
}
} }
private void insertFeeds() { private void insertFeeds() {
feedInsertionProgressBar.setVisibility(View.VISIBLE); binding.addFeedInsertProgressbar.setVisibility(View.VISIBLE);
validate.setEnabled(false); binding.addFeedOk.setEnabled(false);
List<ParsingResult> feedsToInsert = new ArrayList<>(); List<ParsingResult> feedsToInsert = new ArrayList<>();
for (ParsingResult result : parseItemsAdapter.getAdapterItems()) { for (ParsingResult result : parseItemsAdapter.getAdapterItems()) {
@ -265,7 +247,7 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
feedsToInsert.add(result); feedsToInsert.add(result);
} }
Account account = (Account) accountSpinner.getSelectedItem(); Account account = (Account) binding.addFeedAccountSpinner.getSelectedItem();
account.setLogin(SharedPreferencesManager.readString(this, account.getLoginKey())); account.setLogin(SharedPreferencesManager.readString(this, account.getLoginKey()));
account.setPassword(SharedPreferencesManager.readString(this, account.getPasswordKey())); account.setPassword(SharedPreferencesManager.readString(this, account.getPasswordKey()));
@ -281,29 +263,29 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
@Override @Override
public void onError(Throwable e) { public void onError(Throwable e) {
feedInsertionProgressBar.setVisibility(View.GONE); binding.addFeedInsertProgressbar.setVisibility(View.GONE);
validate.setEnabled(true); binding.addFeedOk.setEnabled(true);
Utils.showSnackbar(rootLayout, e.getMessage()); Utils.showSnackbar(binding.addFeedRoot, e.getMessage());
} }
}); });
} }
private void displayInsertionResults(List<FeedInsertionResult> feedInsertionResults) { private void displayInsertionResults(List<FeedInsertionResult> feedInsertionResults) {
feedInsertionProgressBar.setVisibility(View.GONE); binding.addFeedInsertProgressbar.setVisibility(View.GONE);
insertionResultsRecyclerView.setVisibility(View.VISIBLE); binding.addFeedInsertedResultsRecyclerview.setVisibility(View.VISIBLE);
for (FeedInsertionResult feedInsertionResult : feedInsertionResults) { for (FeedInsertionResult feedInsertionResult : feedInsertionResults) {
if (feedInsertionResult.getFeed() != null) if (feedInsertionResult.getFeed() != null)
feedsToUpdate.add(feedInsertionResult.getFeed()); feedsToUpdate.add(feedInsertionResult.getFeed());
disableParsingResult(feedInsertionResult.getParsingResult());
} }
insertionResultsAdapter.add(feedInsertionResults); insertionResultsAdapter.add(feedInsertionResults);
validate.setEnabled(recyclerViewHasCheckedItems()); binding.addFeedOk.setEnabled(recyclerViewHasCheckedItems());
} }
@Override @Override
public void onBackPressed() { public void onBackPressed() {
finish(); finish();
@ -323,7 +305,7 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
@Override @Override
public void finish() { public void finish() {
if (feedsToUpdate.size() > 0) { if (!feedsToUpdate.isEmpty()) {
Intent intent = new Intent(); Intent intent = new Intent();
intent.putParcelableArrayListExtra("feedIds", feedsToUpdate); intent.putParcelableArrayListExtra("feedIds", feedsToUpdate);
@ -337,10 +319,10 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
public boolean onKeyUp(int keyCode, KeyEvent event) { public boolean onKeyUp(int keyCode, KeyEvent event) {
switch (keyCode) { switch (keyCode) {
case KeyEvent.KEYCODE_ENTER: case KeyEvent.KEYCODE_ENTER:
onClick(load); onClick(binding.addFeedLoad);
return true; return true;
default:
return super.onKeyUp(keyCode, event);
} }
return super.onKeyUp(keyCode, event);
} }
} }

View File

@ -1,14 +1,17 @@
package com.readrops.app.utils; package com.readrops.app.utils;
import androidx.annotation.NonNull;
import android.view.View; import android.view.View;
import android.widget.CheckBox; import android.widget.CheckBox;
import android.widget.TextView; import android.widget.TextView;
import androidx.annotation.NonNull;
import com.mikepenz.fastadapter.FastAdapter; import com.mikepenz.fastadapter.FastAdapter;
import com.mikepenz.fastadapter.items.AbstractItem; import com.mikepenz.fastadapter.items.AbstractItem;
import com.readrops.app.R; import com.readrops.app.R;
import org.jetbrains.annotations.NotNull;
import java.util.List; import java.util.List;
public class ParsingResult extends AbstractItem<ParsingResult, ParsingResult.ParsingResultViewHolder> { public class ParsingResult extends AbstractItem<ParsingResult, ParsingResult.ParsingResultViewHolder> {
@ -89,21 +92,31 @@ public class ParsingResult extends AbstractItem<ParsingResult, ParsingResult.Par
} }
@Override @Override
public void bindView(ParsingResult item, List<Object> payloads) { public void bindView(@NotNull ParsingResult item, List<Object> payloads) {
if (item.getLabel() != null && !item.getLabel().isEmpty()) if (!payloads.isEmpty()) {
feedLabel.setText(item.getLabel()); ParsingResult newItem = (ParsingResult) payloads.get(0);
else
feedLabel.setVisibility(View.GONE); checkBox.setChecked(newItem.isChecked());
} else {
if (item.getLabel() != null && !item.getLabel().isEmpty())
feedLabel.setText(item.getLabel());
else
feedLabel.setVisibility(View.GONE);
feedUrl.setText(item.getUrl());
checkBox.setChecked(item.isChecked());
checkBox.setClickable(false);
}
feedUrl.setText(item.getUrl());
checkBox.setChecked(item.isChecked());
checkBox.setClickable(false);
} }
@Override @Override
public void unbindView(ParsingResult item) { public void unbindView(@NotNull ParsingResult item) {
// not useful
} }
} }
} }

View File

@ -1,6 +1,7 @@
package com.readrops.app.viewmodels; package com.readrops.app.viewmodels;
import android.app.Application; import android.app.Application;
import android.util.Log;
import androidx.annotation.NonNull; import androidx.annotation.NonNull;
import androidx.lifecycle.AndroidViewModel; import androidx.lifecycle.AndroidViewModel;
@ -21,6 +22,8 @@ import io.reactivex.Single;
public class AddFeedsViewModel extends AndroidViewModel { public class AddFeedsViewModel extends AndroidViewModel {
private static final String TAG = AddFeedsViewModel.class.getSimpleName();
private ARepository repository; private ARepository repository;
private Database database; private Database database;
@ -36,7 +39,7 @@ public class AddFeedsViewModel extends AndroidViewModel {
return repository.addFeeds(results); return repository.addFeeds(results);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); Log.d(TAG, e.getMessage());
} }
return null; return null;

View File

@ -1,135 +1,154 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<androidx.core.widget.NestedScrollView xmlns:android="http://schemas.android.com/apk/res/android" <layout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools" xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/add_feed_root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".activities.AddFeedActivity"> tools:context=".activities.AddFeedActivity">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.core.widget.NestedScrollView
android:id="@+id/add_feed_root"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="match_parent" android:layout_height="match_parent">
android:animateLayoutChanges="true"
android:padding="20dp">
<androidx.constraintlayout.widget.ConstraintLayout <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/add_feed_main_layout"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:animateLayoutChanges="true" android:animateLayoutChanges="true">
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent">
<com.google.android.material.textfield.TextInputLayout <Spinner
android:id="@+id/add_feed_input_layout" android:id="@+id/add_feed_account_spinner"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
app:layout_constraintEnd_toEndOf="parent" app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent" app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"> app:layout_constraintTop_toTopOf="parent"
tools:listitem="@layout/account_type_item" />
<com.google.android.material.textfield.TextInputEditText <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/add_feed_text_input" android:id="@+id/add_feed_main_layout"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/add_feed_account_spinner"
android:padding="16dp">
<com.google.android.material.textfield.TextInputLayout
android:id="@+id/add_feed_input_layout"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toStartOf="@id/add_feed_load">
<com.google.android.material.textfield.TextInputEditText
android:id="@+id/add_feed_text_input"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:drawableEnd="@drawable/ic_cancel_grey"
android:hint="@string/feed_url"
android:inputType="text"/>
</com.google.android.material.textfield.TextInputLayout>
<Button
android:id="@+id/add_feed_load"
style="@style/GenericButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
android:layout_marginStart="6dp"
android:text="@string/load"
app:layout_constraintStart_toEndOf="@id/add_feed_input_layout"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent" />
<ProgressBar
android:id="@+id/add_feed_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_input_layout"
tools:visibility="gone" />
<TextView
android:id="@+id/add_feed_results_text_view"
style="@style/TextAppearance.Design.Hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:text="@string/results"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_loading"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/add_feed_results"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:drawableEnd="@drawable/ic_cancel_grey" android:visibility="gone"
android:hint="@string/feed_url" app:layout_constraintEnd_toEndOf="parent"
android:inputType="text"/> app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_results_text_view"
tools:visibility="visible"
tools:listitem="@layout/add_feed_item"
tools:itemCount="2"/>
</com.google.android.material.textfield.TextInputLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<Button <androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/add_feed_load"
style="@style/GenericButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:text="@string/load"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_input_layout" />
<ProgressBar
android:id="@+id/add_feed_loading"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintStart_toEndOf="@+id/add_feed_load"
app:layout_constraintTop_toBottomOf="@+id/add_feed_input_layout"
tools:visibility="visible" />
<TextView
android:id="@+id/add_feed_results_text_view"
style="@style/TextAppearance.Design.Hint"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/results"
android:visibility="gone"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_load"
tools:visibility="visible" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/add_feed_results"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="match_parent"
android:visibility="gone" app:layout_constraintTop_toBottomOf="@id/add_feed_main_layout"
app:layout_constraintEnd_toEndOf="parent" android:paddingStart="16dp"
app:layout_constraintStart_toStartOf="parent" android:paddingEnd="16dp">
app:layout_constraintTop_toBottomOf="@+id/add_feed_results_text_view"
tools:visibility="visible" /> <Button
android:id="@+id/add_feed_ok"
style="@style/GenericButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="true"
android:text="@string/validate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<ProgressBar
android:id="@+id/add_feed_insert_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_ok"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/add_feed_inserted_results_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_insert_progressbar"
tools:visibility="visible"
tools:listitem="@layout/feed_insertion_result"
tools:itemCount="2"/>
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.constraintlayout.widget.ConstraintLayout> </androidx.constraintlayout.widget.ConstraintLayout>
<Spinner </androidx.core.widget.NestedScrollView>
android:id="@+id/add_feed_account_spinner"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_main_layout" />
<Button </layout>
android:id="@+id/add_feed_ok"
style="@style/GenericButton"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:enabled="true"
android:text="@string/validate"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/add_feed_account_spinner" />
<ProgressBar
android:id="@+id/add_feed_insert_progressbar"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_ok"
tools:visibility="gone" />
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/add_feed_inserted_results_recyclerview"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="8dp"
android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.6"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/add_feed_insert_progressbar"
tools:visibility="visible" />
</androidx.constraintlayout.widget.ConstraintLayout>
</androidx.core.widget.NestedScrollView>