Add insertion results to the AddFeedActivity layout
This commit is contained in:
parent
594f3d1c5e
commit
0b389dd080
@ -13,11 +13,13 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.ProgressBar;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.fastadapter.FastAdapter;
|
||||
import com.mikepenz.fastadapter.adapters.ItemAdapter;
|
||||
import com.readrops.app.R;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.utils.FeedInsertionResult;
|
||||
import com.readrops.app.utils.Utils;
|
||||
import com.readrops.app.utils.ParsingResult;
|
||||
import com.readrops.app.viewmodels.AddFeedsViewModel;
|
||||
@ -36,9 +38,16 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
private Button load;
|
||||
private ProgressBar progressBar;
|
||||
private Button validate;
|
||||
private RecyclerView recyclerView;
|
||||
private RecyclerView parseResultsRecyclerView;
|
||||
private TextView resultsTextView;
|
||||
|
||||
private ProgressBar feedInsertionProgressBar;
|
||||
private RecyclerView insertionResultsRecyclerView;
|
||||
|
||||
private ItemAdapter<ParsingResult> parseItemsAdapter;
|
||||
private ItemAdapter<FeedInsertionResult> insertionResultsAdapter;
|
||||
|
||||
|
||||
private ItemAdapter<ParsingResult> itemAdapter;
|
||||
private AddFeedsViewModel viewModel;
|
||||
|
||||
private ArrayList<Feed> feedsToUpdate;
|
||||
@ -51,16 +60,20 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
feedInput = findViewById(R.id.add_feed_text_input);
|
||||
load = findViewById(R.id.add_feed_load);
|
||||
validate = findViewById(R.id.add_feed_ok);
|
||||
progressBar = findViewById(R.id.fadd_feed_loading);
|
||||
recyclerView = findViewById(R.id.add_feed_results);
|
||||
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);
|
||||
|
||||
load.setOnClickListener(this);
|
||||
validate.setOnClickListener(this);
|
||||
validate.setEnabled(false);
|
||||
|
||||
viewModel = ViewModelProviders.of(this).get(AddFeedsViewModel.class);
|
||||
|
||||
itemAdapter = new ItemAdapter<>();
|
||||
FastAdapter<ParsingResult> fastAdapter = FastAdapter.with(itemAdapter);
|
||||
parseItemsAdapter = new ItemAdapter<>();
|
||||
FastAdapter<ParsingResult> fastAdapter = FastAdapter.with(parseItemsAdapter);
|
||||
fastAdapter.withSelectable(true);
|
||||
fastAdapter.withOnClickListener((v, adapter, item, position) -> {
|
||||
if (item.isChecked()) {
|
||||
@ -74,11 +87,17 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
return true;
|
||||
});
|
||||
|
||||
recyclerView.setAdapter(fastAdapter);
|
||||
parseResultsRecyclerView.setAdapter(fastAdapter);
|
||||
RecyclerView.LayoutManager layoutManager = new LinearLayoutManager(this);
|
||||
recyclerView.setLayoutManager(layoutManager);
|
||||
parseResultsRecyclerView.setLayoutManager(layoutManager);
|
||||
DividerItemDecoration decoration = new DividerItemDecoration(this, ((LinearLayoutManager) layoutManager).getOrientation());
|
||||
recyclerView.addItemDecoration(decoration);
|
||||
//parseResultsRecyclerView.addItemDecoration(decoration);
|
||||
|
||||
insertionResultsAdapter = new ItemAdapter<>();
|
||||
RecyclerView.LayoutManager layoutManager1 = new LinearLayoutManager(this);
|
||||
insertionResultsRecyclerView.setAdapter(FastAdapter.with(insertionResultsAdapter));
|
||||
insertionResultsRecyclerView.setLayoutManager(layoutManager1);
|
||||
//insertionResultsRecyclerView.addItemDecoration(decoration);
|
||||
|
||||
feedsToUpdate = new ArrayList<>();
|
||||
}
|
||||
@ -112,8 +131,11 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
}
|
||||
|
||||
private void insertFeeds() {
|
||||
feedInsertionProgressBar.setVisibility(View.VISIBLE);
|
||||
validate.setEnabled(false);
|
||||
|
||||
List<ParsingResult> feedsToInsert = new ArrayList<>();
|
||||
for (ParsingResult result : itemAdapter.getAdapterItems()) {
|
||||
for (ParsingResult result : parseItemsAdapter.getAdapterItems()) {
|
||||
if (result.isChecked())
|
||||
feedsToInsert.add(result);
|
||||
}
|
||||
@ -121,15 +143,15 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
viewModel.addFeeds(feedsToInsert)
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
.subscribe(new SingleObserver<List<Feed>>() {
|
||||
.subscribe(new SingleObserver<List<FeedInsertionResult>>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(List<Feed> feeds) {
|
||||
feedsToUpdate.addAll(feeds);
|
||||
public void onSuccess(List<FeedInsertionResult> feedInsertionResults) {
|
||||
processResults(feedInsertionResults);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -139,6 +161,18 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
});
|
||||
}
|
||||
|
||||
private void processResults(List<FeedInsertionResult> feedInsertionResults) {
|
||||
feedInsertionProgressBar.setVisibility(View.GONE);
|
||||
insertionResultsRecyclerView.setVisibility(View.VISIBLE);
|
||||
|
||||
for (FeedInsertionResult feedInsertionResult : feedInsertionResults) {
|
||||
if (feedInsertionResult.getFeed() != null)
|
||||
feedsToUpdate.add(feedInsertionResult.getFeed());
|
||||
}
|
||||
|
||||
insertionResultsAdapter.add(feedInsertionResults);
|
||||
}
|
||||
|
||||
private void loadFeed() {
|
||||
String url = feedInput.getText().toString().trim();
|
||||
|
||||
@ -170,10 +204,14 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||
}
|
||||
|
||||
private void displayResults(List<ParsingResult> parsingResultList) {
|
||||
recyclerView.setVisibility(View.VISIBLE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
if (parsingResultList.size() > 0) {
|
||||
parseResultsRecyclerView.setVisibility(View.VISIBLE);
|
||||
progressBar.setVisibility(View.GONE);
|
||||
resultsTextView.setVisibility(View.VISIBLE);
|
||||
|
||||
itemAdapter.add(parsingResultList);
|
||||
parseItemsAdapter.add(parsingResultList);
|
||||
validate.setEnabled(true);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -236,44 +236,6 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
|
||||
public void onRefresh() {
|
||||
Log.d(TAG, "syncing started");
|
||||
|
||||
presync(null);
|
||||
}
|
||||
|
||||
public void displayAddFeedDialog(View view) {
|
||||
actionMenu.close(true);
|
||||
//Dialog dialog = new AddFeedDialog(this, R.layout.add_feed_layout);
|
||||
//dialog.show();
|
||||
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);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void insertNewFeed(ParsingResult result) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
viewModel.addFeed(result);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == ADD_FEED_REQUEST && resultCode == RESULT_OK) {
|
||||
ArrayList<Feed> feeds = data.getParcelableArrayListExtra("feedIds");
|
||||
|
||||
if (feeds != null && feeds.size() > 0) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
presync(feeds);
|
||||
}
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void presync(List<Feed> feeds) {
|
||||
viewModel.getFeedCount()
|
||||
.subscribeOn(Schedulers.io())
|
||||
.observeOn(AndroidSchedulers.mainThread())
|
||||
@ -281,14 +243,13 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
|
||||
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
syncProgressLayout.setVisibility(View.VISIBLE);
|
||||
syncProgressBar.setProgress(0);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSuccess(Integer integer) {
|
||||
feedNb = integer;
|
||||
sync(feeds);
|
||||
sync(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -298,6 +259,40 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
|
||||
});
|
||||
}
|
||||
|
||||
public void displayAddFeedDialog(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);
|
||||
startActivity(intent);
|
||||
}
|
||||
|
||||
public void insertNewFeed(ParsingResult result) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
viewModel.addFeed(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
|
||||
if (requestCode == ADD_FEED_REQUEST && resultCode == RESULT_OK) {
|
||||
ArrayList<Feed> feeds = data.getParcelableArrayListExtra("feedIds");
|
||||
|
||||
if (feeds != null && feeds.size() > 0) {
|
||||
refreshLayout.setRefreshing(true);
|
||||
feedNb = feeds.size();
|
||||
sync(feeds);
|
||||
}
|
||||
}
|
||||
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
}
|
||||
|
||||
private void sync(List<Feed> feeds) {
|
||||
viewModel.sync(feeds)
|
||||
.subscribeOn(Schedulers.io())
|
||||
@ -305,7 +300,8 @@ public class MainActivity extends AppCompatActivity implements SimpleCallback, S
|
||||
.subscribe(new Observer<Feed>() {
|
||||
@Override
|
||||
public void onSubscribe(Disposable d) {
|
||||
|
||||
syncProgressLayout.setVisibility(View.VISIBLE);
|
||||
syncProgressBar.setProgress(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -1,17 +1,23 @@
|
||||
package com.readrops.app.repositories;
|
||||
|
||||
import android.app.Application;
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Handler;
|
||||
import android.os.Looper;
|
||||
import android.support.v7.graphics.Palette;
|
||||
import android.util.Patterns;
|
||||
|
||||
import com.readrops.app.database.pojo.FeedWithFolder;
|
||||
import com.readrops.app.utils.SyncError;
|
||||
import com.readrops.app.utils.FeedInsertionResult;
|
||||
import com.readrops.app.utils.HtmlParser;
|
||||
import com.readrops.app.utils.Utils;
|
||||
import com.readrops.app.views.SimpleCallback;
|
||||
import com.readrops.app.database.Database;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.database.entities.Folder;
|
||||
import com.readrops.app.utils.ParsingResult;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.Executors;
|
||||
@ -40,7 +46,7 @@ public abstract class ARepository {
|
||||
|
||||
public abstract void addFeed(ParsingResult result);
|
||||
|
||||
public abstract Single<List<Feed>> addFeeds(List<ParsingResult> results);
|
||||
public abstract Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results);
|
||||
|
||||
public abstract void updateFeed(Feed feed);
|
||||
|
||||
@ -71,6 +77,24 @@ public abstract class ARepository {
|
||||
});
|
||||
}
|
||||
|
||||
protected void setFavIconUtils(Feed feed) throws IOException {
|
||||
String favUrl = HtmlParser.getFaviconLink(feed.getSiteUrl());
|
||||
if (favUrl != null && Patterns.WEB_URL.matcher(favUrl).matches()) {
|
||||
feed.setIconUrl(favUrl);
|
||||
setFeedColors(favUrl, feed);
|
||||
}
|
||||
}
|
||||
|
||||
protected void setFeedColors(String favUrl, Feed feed) throws IOException {
|
||||
Bitmap favicon = Utils.getImageFromUrl(favUrl);
|
||||
Palette palette = Palette.from(favicon).generate();
|
||||
|
||||
feed.setTextColor(palette.getDominantSwatch().getRgb());
|
||||
|
||||
if (palette.getMutedSwatch() != null)
|
||||
feed.setBackgroundColor(palette.getMutedSwatch().getRgb());
|
||||
}
|
||||
|
||||
protected void failureCallBackInMainThread(Exception e) {
|
||||
Handler handler = new Handler(Looper.getMainLooper());
|
||||
|
||||
|
@ -3,20 +3,16 @@ package com.readrops.app.repositories;
|
||||
import android.accounts.NetworkErrorException;
|
||||
import android.app.Application;
|
||||
import android.arch.lifecycle.LiveData;
|
||||
import android.graphics.Bitmap;
|
||||
import android.support.v7.graphics.Palette;
|
||||
import android.util.Patterns;
|
||||
|
||||
import com.readrops.app.database.entities.Folder;
|
||||
import com.readrops.app.database.pojo.FeedWithFolder;
|
||||
import com.readrops.app.database.pojo.ItemWithFeed;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.database.entities.Item;
|
||||
import com.readrops.app.utils.SyncError;
|
||||
import com.readrops.app.utils.FeedInsertionResult;
|
||||
import com.readrops.app.utils.Utils;
|
||||
import com.readrops.app.utils.HtmlParser;
|
||||
import com.readrops.app.utils.ParsingResult;
|
||||
import com.readrops.readropslibrary.QueryCallback;
|
||||
import com.readrops.readropslibrary.Utils.LibUtils;
|
||||
import com.readrops.readropslibrary.Utils.UnknownFormatException;
|
||||
import com.readrops.readropslibrary.localfeed.AFeed;
|
||||
@ -26,7 +22,6 @@ import com.readrops.readropslibrary.localfeed.atom.ATOMFeed;
|
||||
import com.readrops.readropslibrary.localfeed.json.JSONFeed;
|
||||
import com.readrops.readropslibrary.localfeed.rss.RSSFeed;
|
||||
|
||||
import org.joda.time.LocalDateTime;
|
||||
import org.jsoup.Jsoup;
|
||||
|
||||
import java.io.IOException;
|
||||
@ -36,13 +31,12 @@ import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
public class LocalFeedRepository extends ARepository {
|
||||
|
||||
private static final String TAG = LocalFeedRepository.class.getSimpleName();
|
||||
|
||||
@ -69,11 +63,11 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
feedList = new ArrayList<>(feeds);
|
||||
|
||||
RSSQuery rssQuery = new RSSQuery();
|
||||
List<SyncError> syncErrors = new ArrayList<>();
|
||||
List<FeedInsertionResult> syncErrors = new ArrayList<>();
|
||||
|
||||
for (Feed feed : feedList) {
|
||||
emitter.onNext(feed);
|
||||
SyncError syncError = new SyncError();
|
||||
FeedInsertionResult syncError = new FeedInsertionResult();
|
||||
|
||||
try {
|
||||
HashMap<String, String> headers = new HashMap<>();
|
||||
@ -89,18 +83,18 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
Exception e = queryResult.getException();
|
||||
|
||||
if (e instanceof UnknownFormatException)
|
||||
syncError.setInsertionError(SyncError.FeedInsertionError.FORMAT_ERROR);
|
||||
syncError.setInsertionError(FeedInsertionResult.FeedInsertionError.FORMAT_ERROR);
|
||||
else if (e instanceof NetworkErrorException)
|
||||
syncError.setInsertionError(SyncError.FeedInsertionError.NETWORK_ERROR);
|
||||
syncError.setInsertionError(FeedInsertionResult.FeedInsertionError.NETWORK_ERROR);
|
||||
|
||||
syncError.setFeed(feed);
|
||||
syncErrors.add(syncError);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof IOException)
|
||||
syncError.setInsertionError(SyncError.FeedInsertionError.NETWORK_ERROR);
|
||||
syncError.setInsertionError(FeedInsertionResult.FeedInsertionError.NETWORK_ERROR);
|
||||
else
|
||||
syncError.setInsertionError(SyncError.FeedInsertionError.PARSE_ERROR);
|
||||
syncError.setInsertionError(FeedInsertionResult.FeedInsertionError.PARSE_ERROR);
|
||||
|
||||
syncError.setFeed(feed);
|
||||
syncErrors.add(syncError);
|
||||
@ -130,22 +124,43 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Single<List<Feed>> addFeeds(List<ParsingResult> results) {
|
||||
public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results) {
|
||||
return Single.create(emitter -> {
|
||||
List<Feed> insertedFeeds = new ArrayList<>();
|
||||
List<FeedInsertionResult> insertionResults = new ArrayList<>();
|
||||
|
||||
for (ParsingResult result : results) {
|
||||
RSSQuery rssNet = new RSSQuery();
|
||||
RSSQueryResult queryResult = rssNet.queryUrl(result.getUrl(), new HashMap<>());
|
||||
for (ParsingResult parsingResult : results) {
|
||||
FeedInsertionResult insertionResult = new FeedInsertionResult();
|
||||
|
||||
if (queryResult != null && queryResult.getException() == null) {
|
||||
Feed feed = insertFeed(queryResult.getFeed(), queryResult.getRssType());
|
||||
if (feed != null)
|
||||
insertedFeeds.add(feed);
|
||||
}
|
||||
}
|
||||
try {
|
||||
RSSQuery rssNet = new RSSQuery();
|
||||
RSSQueryResult queryResult = rssNet.queryUrl(parsingResult.getUrl(), new HashMap<>());
|
||||
|
||||
emitter.onSuccess(insertedFeeds);
|
||||
if (queryResult != null && queryResult.getException() == null) {
|
||||
Feed feed = insertFeed(queryResult.getFeed(), queryResult.getRssType());
|
||||
if (feed != null) {
|
||||
insertionResult.setFeed(feed);
|
||||
insertionResults.add(insertionResult);
|
||||
}
|
||||
} else if (queryResult != null && queryResult.getException() != null) {
|
||||
insertionResult.setParsingResult(parsingResult);
|
||||
insertionResult.setInsertionError(getErrorFromException(queryResult.getException()));
|
||||
|
||||
insertionResults.add(insertionResult);
|
||||
} else {
|
||||
// error 304
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e instanceof IOException)
|
||||
insertionResult.setInsertionError(FeedInsertionResult.FeedInsertionError.NETWORK_ERROR);
|
||||
else
|
||||
insertionResult.setInsertionError(FeedInsertionResult.FeedInsertionError.PARSE_ERROR);
|
||||
|
||||
insertionResult.setParsingResult(parsingResult);
|
||||
insertionResults.add(insertionResult);
|
||||
}
|
||||
}
|
||||
|
||||
emitter.onSuccess(insertionResults);
|
||||
});
|
||||
}
|
||||
|
||||
@ -184,26 +199,6 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSyncSuccess(AFeed feed, RSSQuery.RSSType type) {
|
||||
switch (type) {
|
||||
case RSS_2:
|
||||
parseRSSItems(((RSSFeed) feed));
|
||||
break;
|
||||
case RSS_ATOM:
|
||||
parseATOMItems(((ATOMFeed) feed));
|
||||
break;
|
||||
case RSS_JSON:
|
||||
parseJSONItems(((JSONFeed) feed));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSyncFailure(Exception e) {
|
||||
failureCallBackInMainThread(e);
|
||||
}
|
||||
|
||||
private void insertNewItems(AFeed feed, RSSQuery.RSSType type) throws ParseException {
|
||||
Feed dbFeed = null;
|
||||
List<Item> items = null;
|
||||
@ -256,80 +251,6 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
return dbFeed;
|
||||
}
|
||||
|
||||
|
||||
private void parseRSSItems(RSSFeed rssFeed) {
|
||||
try {
|
||||
Feed dbFeed = database.feedDao().getFeedByUrl(rssFeed.getChannel().getFeedUrl());
|
||||
if (dbFeed == null) {
|
||||
dbFeed = Feed.feedFromRSS(rssFeed);
|
||||
|
||||
setFavIconUtils(dbFeed);
|
||||
dbFeed.setId((int)(database.feedDao().insert(dbFeed)));
|
||||
} else
|
||||
database.feedDao().updateHeaders(rssFeed.getEtag(), rssFeed.getLastModified(), dbFeed.getId());
|
||||
|
||||
List<Item> dbItems = Item.itemsFromRSS(rssFeed.getChannel().getItems(), dbFeed);
|
||||
TreeMap<LocalDateTime, Item> sortedItems = new TreeMap<>(LocalDateTime::compareTo);
|
||||
for (Item item : dbItems) {
|
||||
sortedItems.put(item.getPubDate(), item);
|
||||
}
|
||||
|
||||
insertItems(sortedItems.values(), dbFeed);
|
||||
|
||||
} catch (Exception e) {
|
||||
failureCallBackInMainThread(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void parseATOMItems(ATOMFeed feed) {
|
||||
try {
|
||||
Feed dbFeed = database.feedDao().getFeedByUrl(feed.getUrl());
|
||||
if (dbFeed == null) {
|
||||
dbFeed = Feed.feedFromATOM(feed);
|
||||
|
||||
setFavIconUtils(dbFeed);
|
||||
dbFeed.setId((int)(database.feedDao().insert(dbFeed)));
|
||||
} else
|
||||
database.feedDao().updateHeaders(feed.getEtag(), feed.getLastModified(), dbFeed.getId());
|
||||
|
||||
List<Item> dbItems = Item.itemsFromATOM(feed.getEntries(), dbFeed);
|
||||
TreeMap<LocalDateTime, Item> sortedItems = new TreeMap<>(LocalDateTime::compareTo);
|
||||
for (Item item : dbItems) {
|
||||
sortedItems.put(item.getPubDate(), item);
|
||||
}
|
||||
|
||||
insertItems(sortedItems.values(), dbFeed);
|
||||
|
||||
} catch (Exception e) {
|
||||
failureCallBackInMainThread(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseJSONItems(JSONFeed feed) {
|
||||
try {
|
||||
Feed dbFeed = database.feedDao().getFeedByUrl(feed.getFeedUrl());
|
||||
if (dbFeed == null) {
|
||||
dbFeed = Feed.feedFromJSON(feed);
|
||||
|
||||
setFavIconUtils(dbFeed);
|
||||
dbFeed.setId((int)(database.feedDao().insert(dbFeed)));
|
||||
} else
|
||||
database.feedDao().updateHeaders(feed.getEtag(), feed.getLastModified(), dbFeed.getId());
|
||||
|
||||
List<Item> dbItems = Item.itemsFromJSON(feed.getItems(), dbFeed);
|
||||
TreeMap<LocalDateTime, Item> sortedItems = new TreeMap<>(LocalDateTime::compareTo);
|
||||
for (Item item : dbItems) {
|
||||
sortedItems.put(item.getPubDate(), item);
|
||||
}
|
||||
|
||||
insertItems(sortedItems.values(), dbFeed);
|
||||
|
||||
} catch (Exception e) {
|
||||
failureCallBackInMainThread(e);
|
||||
}
|
||||
}
|
||||
|
||||
private void insertItems(Collection<Item> items, Feed feed) {
|
||||
for (Item dbItem : items) {
|
||||
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid()))) {
|
||||
@ -364,23 +285,16 @@ public class LocalFeedRepository extends ARepository implements QueryCallback {
|
||||
}
|
||||
}
|
||||
|
||||
private void setFavIconUtils(Feed feed) throws IOException {
|
||||
String favUrl = HtmlParser.getFaviconLink(feed.getSiteUrl());
|
||||
if (favUrl != null && Patterns.WEB_URL.matcher(favUrl).matches()) {
|
||||
feed.setIconUrl(favUrl);
|
||||
setFeedColors(favUrl, feed);
|
||||
}
|
||||
private FeedInsertionResult.FeedInsertionError getErrorFromException(Exception e) {
|
||||
if (e instanceof UnknownFormatException)
|
||||
return FeedInsertionResult.FeedInsertionError.FORMAT_ERROR;
|
||||
else if (e instanceof NetworkErrorException)
|
||||
return FeedInsertionResult.FeedInsertionError.NETWORK_ERROR;
|
||||
else
|
||||
return FeedInsertionResult.FeedInsertionError.UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
private void setFeedColors(String favUrl, Feed feed) throws IOException {
|
||||
Bitmap favicon = Utils.getImageFromUrl(favUrl);
|
||||
Palette palette = Palette.from(favicon).generate();
|
||||
|
||||
feed.setTextColor(palette.getDominantSwatch().getRgb());
|
||||
|
||||
if (palette.getMutedSwatch() != null)
|
||||
feed.setBackgroundColor(palette.getMutedSwatch().getRgb());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,134 @@
|
||||
package com.readrops.app.utils;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.StringRes;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import com.mikepenz.fastadapter.FastAdapter;
|
||||
import com.mikepenz.fastadapter.items.AbstractItem;
|
||||
import com.readrops.app.R;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FeedInsertionResult extends AbstractItem<FeedInsertionResult, FeedInsertionResult.ViewHolder> {
|
||||
|
||||
private Feed feed;
|
||||
|
||||
private ParsingResult parsingResult;
|
||||
|
||||
private FeedInsertionError insertionError;
|
||||
|
||||
public FeedInsertionResult() {
|
||||
|
||||
}
|
||||
|
||||
public Feed getFeed() {
|
||||
return feed;
|
||||
}
|
||||
|
||||
public void setFeed(Feed feed) {
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
public ParsingResult getParsingResult() {
|
||||
return parsingResult;
|
||||
}
|
||||
|
||||
public void setParsingResult(ParsingResult parsingResult) {
|
||||
this.parsingResult = parsingResult;
|
||||
}
|
||||
|
||||
public FeedInsertionError getInsertionError() {
|
||||
return insertionError;
|
||||
}
|
||||
|
||||
public void setInsertionError(FeedInsertionError insertionError) {
|
||||
this.insertionError = insertionError;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isSelectable() {
|
||||
return false;
|
||||
}
|
||||
|
||||
@NonNull
|
||||
@Override
|
||||
public ViewHolder getViewHolder(View v) {
|
||||
return new ViewHolder(v);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getType() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getLayoutRes() {
|
||||
return R.layout.feed_insertion_result;
|
||||
}
|
||||
|
||||
|
||||
public enum FeedInsertionError {
|
||||
NETWORK_ERROR,
|
||||
DB_ERROR,
|
||||
PARSE_ERROR,
|
||||
FORMAT_ERROR,
|
||||
UNKNOWN_ERROR
|
||||
}
|
||||
|
||||
class ViewHolder extends FastAdapter.ViewHolder<FeedInsertionResult> {
|
||||
|
||||
private TextView feedInsertionRes;
|
||||
private ImageView feedInsertionIcon;
|
||||
|
||||
public ViewHolder(View itemView) {
|
||||
super(itemView);
|
||||
|
||||
feedInsertionRes = itemView.findViewById(R.id.feed_insertion_result_text_view);
|
||||
feedInsertionIcon = itemView.findViewById(R.id.feed_insertion_result_icon);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void bindView(FeedInsertionResult item, List<Object> payloads) {
|
||||
if (item.getFeed() != null) {
|
||||
feedInsertionRes.setText(itemView.getContext().getString(R.string.feed_insertion_successfull, item.feed.getName()));
|
||||
feedInsertionIcon.setImageResource(R.drawable.ic_check_green);
|
||||
}
|
||||
else {
|
||||
switch (item.getInsertionError()) {
|
||||
case NETWORK_ERROR:
|
||||
setErrorText(R.string.feed_insertion_network_failed, item.parsingResult);
|
||||
break;
|
||||
case DB_ERROR:
|
||||
break;
|
||||
case PARSE_ERROR:
|
||||
setErrorText(R.string.feed_insertion_parse_failed, item.parsingResult);
|
||||
break;
|
||||
case FORMAT_ERROR:
|
||||
setErrorText(R.string.feed_insertion_wrong_format, item.parsingResult);
|
||||
break;
|
||||
case UNKNOWN_ERROR:
|
||||
setErrorText(R.string.feed_insertion_unknown_error, item.parsingResult);
|
||||
break;
|
||||
}
|
||||
|
||||
feedInsertionIcon.setImageResource(R.drawable.ic_warning_red);
|
||||
}
|
||||
}
|
||||
|
||||
private void setErrorText(@StringRes int stringRes, ParsingResult parsingResult) {
|
||||
feedInsertionRes.setText(itemView.getContext().getString(stringRes,
|
||||
parsingResult.getLabel() != null ? parsingResult.getLabel() :
|
||||
parsingResult.getUrl()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void unbindView(FeedInsertionResult item) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
package com.readrops.app.utils;
|
||||
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
|
||||
public class SyncError {
|
||||
|
||||
private Feed feed;
|
||||
|
||||
private FeedInsertionError insertionError;
|
||||
|
||||
public SyncError() {
|
||||
}
|
||||
|
||||
public SyncError(Feed feed, FeedInsertionError insertionError) {
|
||||
this.feed = feed;
|
||||
this.insertionError = insertionError;
|
||||
}
|
||||
|
||||
public Feed getFeed() {
|
||||
return feed;
|
||||
}
|
||||
|
||||
public void setFeed(Feed feed) {
|
||||
this.feed = feed;
|
||||
}
|
||||
|
||||
public FeedInsertionError getInsertionError() {
|
||||
return insertionError;
|
||||
}
|
||||
|
||||
public void setInsertionError(FeedInsertionError insertionError) {
|
||||
this.insertionError = insertionError;
|
||||
}
|
||||
|
||||
public enum FeedInsertionError {
|
||||
NETWORK_ERROR,
|
||||
DB_ERROR,
|
||||
PARSE_ERROR,
|
||||
FORMAT_ERROR
|
||||
}
|
||||
}
|
@ -6,6 +6,7 @@ import android.support.annotation.NonNull;
|
||||
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.repositories.LocalFeedRepository;
|
||||
import com.readrops.app.utils.FeedInsertionResult;
|
||||
import com.readrops.app.utils.HtmlParser;
|
||||
import com.readrops.app.utils.ParsingResult;
|
||||
import com.readrops.readropslibrary.localfeed.RSSQuery;
|
||||
@ -25,7 +26,7 @@ public class AddFeedsViewModel extends AndroidViewModel {
|
||||
repository = new LocalFeedRepository(application);
|
||||
}
|
||||
|
||||
public Single<List<Feed>> addFeeds(List<ParsingResult> results) {
|
||||
public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results) {
|
||||
return repository.addFeeds(results);
|
||||
}
|
||||
|
||||
|
@ -8,13 +8,11 @@ import android.support.annotation.NonNull;
|
||||
import com.readrops.app.database.entities.Feed;
|
||||
import com.readrops.app.database.pojo.ItemWithFeed;
|
||||
import com.readrops.app.repositories.LocalFeedRepository;
|
||||
import com.readrops.app.utils.SyncError;
|
||||
import com.readrops.app.views.SimpleCallback;
|
||||
import com.readrops.app.utils.ParsingResult;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import io.reactivex.Completable;
|
||||
import io.reactivex.Observable;
|
||||
import io.reactivex.Single;
|
||||
|
||||
|
5
app/src/main/res/drawable/ic_check_green.xml
Normal file
5
app/src/main/res/drawable/ic_check_green.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#11FF00"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M9,16.17L4.83,12l-1.42,1.41L9,19 21,7l-1.41,-1.41z"/>
|
||||
</vector>
|
5
app/src/main/res/drawable/ic_warning_red.xml
Normal file
5
app/src/main/res/drawable/ic_warning_red.xml
Normal file
@ -0,0 +1,5 @@
|
||||
<vector android:height="24dp" android:tint="#FF6200"
|
||||
android:viewportHeight="24.0" android:viewportWidth="24.0"
|
||||
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<path android:fillColor="#FF000000" android:pathData="M1,21h22L12,2 1,21zM13,18h-2v-2h2v2zM13,14h-2v-4h2v4z"/>
|
||||
</vector>
|
@ -1,77 +1,122 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<android.support.v4.widget.NestedScrollView 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"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:padding="20dp"
|
||||
tools:context=".activities.AddFeedActivity">
|
||||
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/add_feed_main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
android:layout_height="match_parent"
|
||||
android:animateLayoutChanges="true"
|
||||
android:padding="20dp">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/add_feed_input_layout"
|
||||
<android.support.constraint.ConstraintLayout
|
||||
android:id="@+id/add_feed_main_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/add_feed_text_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/feed_url" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_feed_load"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/load"
|
||||
android:animateLayoutChanges="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_input_layout" />
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputLayout
|
||||
android:id="@+id/add_feed_input_layout"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent">
|
||||
|
||||
<android.support.design.widget.TextInputEditText
|
||||
android:id="@+id/add_feed_text_input"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:hint="@string/feed_url" />
|
||||
|
||||
</android.support.design.widget.TextInputLayout>
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_feed_load"
|
||||
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_marginTop="8dp"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_load"
|
||||
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:text="@string/results"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/add_feed_loading"
|
||||
tools:visibility="visible" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/add_feed_results"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:visibility="gone"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_results_text_view"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_feed_ok"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:enabled="true"
|
||||
android:text="@string/validate"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_main_layout" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/fadd_feed_loading"
|
||||
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_load"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_ok"
|
||||
tools:visibility="gone" />
|
||||
|
||||
<android.support.v7.widget.RecyclerView
|
||||
android:id="@+id/add_feed_results"
|
||||
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/fadd_feed_loading"
|
||||
tools:visibility="gone" />
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_insert_progressbar"
|
||||
tools:visibility="visible" />
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
|
||||
<Button
|
||||
android:id="@+id/add_feed_ok"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="8dp"
|
||||
android:text="@string/validate"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/add_feed_main_layout"
|
||||
android:enabled="true"/>
|
||||
|
||||
|
||||
</android.support.constraint.ConstraintLayout>
|
||||
</android.support.v4.widget.NestedScrollView>
|
26
app/src/main/res/layout/feed_insertion_result.xml
Normal file
26
app/src/main/res/layout/feed_insertion_result.xml
Normal file
@ -0,0 +1,26 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:padding="6dp">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/feed_insertion_result_icon"
|
||||
android:layout_width="20dp"
|
||||
android:layout_height="20dp"
|
||||
android:layout_alignParentStart="true" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/feed_insertion_result_text_view"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_centerInParent="true"
|
||||
android:layout_marginStart="6dp"
|
||||
android:layout_toEndOf="@id/feed_insertion_result_icon"
|
||||
android:ellipsize="end"
|
||||
android:maxLines="2"
|
||||
android:minLines="1"
|
||||
tools:text="Inserting feed Nextinpact with success" />
|
||||
|
||||
</RelativeLayout>
|
@ -32,5 +32,11 @@
|
||||
<string name="delete_feed">Supprimer le flux ?</string>
|
||||
<string name="load">Charger</string>
|
||||
<string name="updating_feed">Mise à jour du flux : %1$s</string>
|
||||
<string name="results">Résultats</string>
|
||||
<string name="feed_insertion_successfull">Le flux %1$s a été ajouté</string>
|
||||
<string name="feed_insertion_network_failed">Erreur d\'accès au flux %1$s</string>
|
||||
<string name="feed_insertion_parse_failed">Erreur de traitement pour le flux %1$s</string>
|
||||
<string name="feed_insertion_wrong_format">Mauvais format pour le flux %1$s</string>
|
||||
<string name="feed_insertion_unknown_error">Erreur inconnue pour le flux %1$s</string>
|
||||
|
||||
</resources>
|
@ -34,4 +34,10 @@
|
||||
<string name="delete_feed">Delete feed ?</string>
|
||||
<string name="load">Load</string>
|
||||
<string name="updating_feed">Updating feed : %1$s</string>
|
||||
<string name="results">Results</string>
|
||||
<string name="feed_insertion_successfull">Feed %1$s added successfully</string>
|
||||
<string name="feed_insertion_network_failed">Network failure when accessing feed %1$s</string>
|
||||
<string name="feed_insertion_parse_failed">Failure when parsing feed %1$s</string>
|
||||
<string name="feed_insertion_wrong_format">Wrong format for feed %1$s</string>
|
||||
<string name="feed_insertion_unknown_error">Unknown error for feed %1$s</string>
|
||||
</resources>
|
||||
|
Loading…
x
Reference in New Issue
Block a user