Requesting folders, feeds and items from Nextcloud News now works

This commit is contained in:
Shinokuni 2019-05-12 16:16:27 +02:00
parent 3903bb6eb1
commit 92ce491771
23 changed files with 409 additions and 118 deletions

View File

@ -5,7 +5,6 @@ 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.Feed;
import com.readrops.app.database.pojo.FeedWithFolder;
@ -21,8 +20,8 @@ public interface FeedDao {
@Insert
long insert(Feed feed);
@Update
void update(Feed feed);
@Insert
long[] insert(List<Feed> feeds);
@Query("Delete From Feed Where id = :feedId")
void delete(int feedId);
@ -30,12 +29,18 @@ public interface FeedDao {
@Query("Select case When :feedUrl In (Select url from Feed) Then 'true' else 'false' end")
String feedExists(String feedUrl);
@Query("Select case When :remoteId In (Select remoteId from Feed) Then 1 else 0 end")
boolean remoteFeedExists(int remoteId);
@Query("Select count(*) from Feed")
int getFeedCount();
@Query("Select * from Feed Where url = :feedUrl")
Feed getFeedByUrl(String feedUrl);
@Query("Select * from Feed Where remoteId = :remoteId")
Feed getFeedByRemoteId(int remoteId);
@Query("Select * from Feed Where folder_id = :folderId")
List<Feed> getFeedsByFolder(int folderId);
@ -48,9 +53,15 @@ public interface FeedDao {
@Query("Update Feed set name = :feedName, url = :feedUrl, folder_id = :folderId Where id = :feedId")
void updateFeedFields(int feedId, String feedName, String feedUrl, int folderId);
@Query("Update Feed set text_color = :textColor, background_color = :bgColor Where id = :feedId")
void updateColors(int feedId, int textColor, int bgColor);
@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 Inner Join Folder on Feed.folder_id = Folder.id Order by Feed.name")
LiveData<List<FeedWithFolder>> getAllFeedsWithFolder();
@Query("Select * From Feed Where id in (:ids)")
List<Feed> selectFromIdList(long[] ids);
}

View File

@ -22,6 +22,15 @@ public interface FolderDao {
@Insert
long insert(Folder folder);
@Insert
long[] insert(List<Folder> folders);
@Delete
void delete(Folder folder);
@Query("Select id From Folder Where remoteId = :remoteId")
int getRemoteFolderLocalId(int remoteId);
@Query("Select case When :remoteId In (Select remoteId from Folder) Then 1 else 0 end")
boolean remoteFolderExists(int remoteId);
}

View File

@ -2,18 +2,19 @@ package com.readrops.app.database.dao;
import androidx.lifecycle.LiveData;
import androidx.paging.DataSource;
import androidx.paging.PageKeyedDataSource;
import androidx.sqlite.db.SupportSQLiteQuery;
import androidx.room.Dao;
import androidx.room.Insert;
import androidx.room.Query;
import androidx.room.RawQuery;
import androidx.sqlite.db.SupportSQLiteQuery;
import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.ItemWithFeed;
import com.readrops.app.database.entities.Item;
import com.readrops.app.database.pojo.ItemWithFeed;
import java.util.List;
@Dao
public interface ItemDao {
@ -24,9 +25,15 @@ public interface ItemDao {
@Query("Select case When :guid In (Select guid from Item) Then 'true' else 'false' end")
String guidExist(String guid);
@Query("Select case When :remoteId In (Select remoteId from Item) Then 1 else 0 end")
boolean remoteItemExists(int remoteId);
@Insert
long insert(Item item);
@Insert
long[] insert(List<Item> items);
/**
* Set an item read or unread
* @param itemId id of the item to update

View File

@ -1,11 +1,15 @@
package com.readrops.app.database.entities;
import androidx.room.*;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.annotation.ColorInt;
import androidx.annotation.Nullable;
import androidx.room.ColumnInfo;
import androidx.room.Entity;
import androidx.room.ForeignKey;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import com.readrops.readropslibrary.localfeed.atom.ATOMFeed;
import com.readrops.readropslibrary.localfeed.json.JSONFeed;
@ -14,8 +18,6 @@ import com.readrops.readropslibrary.localfeed.rss.RSSFeed;
import org.jsoup.Jsoup;
import static androidx.room.ForeignKey.NO_ACTION;
@Entity(foreignKeys = @ForeignKey(entity = Folder.class, parentColumns = "id", childColumns = "folder_id", onDelete = ForeignKey.SET_NULL))
public class Feed implements Parcelable {
@ -46,9 +48,11 @@ public class Feed implements Parcelable {
@ColumnInfo(name = "last_modified")
private String lastModified;
@ColumnInfo(name = "folder_id")
@ColumnInfo(name = "folder_id", index = true)
private int folderId;
private int remoteId;
@Ignore
private int unreadCount;
@ -76,6 +80,7 @@ public class Feed implements Parcelable {
etag = in.readString();
lastModified = in.readString();
folderId = in.readInt();
remoteId = in.readInt();
}
public static final Creator<Feed> CREATOR = new Creator<Feed>() {
@ -194,6 +199,14 @@ public class Feed implements Parcelable {
this.unreadCount = unreadCount;
}
public int getRemoteId() {
return remoteId;
}
public void setRemoteId(int remoteId) {
this.remoteId = remoteId;
}
public static Feed feedFromRSS(RSSFeed rssFeed) {
Feed feed = new Feed();
RSSChannel channel = rssFeed.getChannel();
@ -270,5 +283,6 @@ public class Feed implements Parcelable {
dest.writeString(etag);
dest.writeString(lastModified);
dest.writeInt(folderId);
dest.writeInt(remoteId);
}
}

View File

@ -1,10 +1,11 @@
package com.readrops.app.database.entities;
import android.os.Parcel;
import android.os.Parcelable;
import androidx.room.Entity;
import androidx.room.Ignore;
import androidx.room.PrimaryKey;
import android.os.Parcel;
import android.os.Parcelable;
@Entity
public class Folder implements Parcelable, Comparable<Folder> {
@ -14,6 +15,8 @@ public class Folder implements Parcelable, Comparable<Folder> {
private String name;
private int remoteId;
public Folder() {
}
@ -46,6 +49,14 @@ public class Folder implements Parcelable, Comparable<Folder> {
this.name = name;
}
public int getRemoteId() {
return remoteId;
}
public void setRemoteId(int remoteId) {
this.remoteId = remoteId;
}
public static final Creator<Folder> CREATOR = new Creator<Folder>() {
@Override
public Folder createFromParcel(Parcel in) {

View File

@ -47,7 +47,7 @@ public class Item implements Comparable<Item> {
private String content;
@ColumnInfo(name = "feed_id")
@ColumnInfo(name = "feed_id", index = true)
private int feedId;
@ColumnInfo(index = true)
@ -61,6 +61,8 @@ public class Item implements Comparable<Item> {
@ColumnInfo(name = "read_it_later")
private boolean readItLater;
private int remoteId;
public int getId() {
return id;
}
@ -184,6 +186,14 @@ public class Item implements Comparable<Item> {
this.readItLater = readItLater;
}
public int getRemoteId() {
return remoteId;
}
public void setRemoteId(int remoteId) {
this.remoteId = remoteId;
}
public static List<Item> itemsFromRSS(List<RSSItem> items, Feed feed) throws ParseException {
List<Item> dbItems = new ArrayList<>();

View File

@ -2,17 +2,18 @@ package com.readrops.app.repositories;
import android.app.Application;
import android.graphics.Bitmap;
import androidx.palette.graphics.Palette;
import android.util.Patterns;
import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.HtmlParser;
import com.readrops.app.utils.Utils;
import androidx.palette.graphics.Palette;
import com.readrops.app.database.Database;
import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.HtmlParser;
import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils;
import java.io.IOException;
import java.util.List;
@ -79,8 +80,10 @@ public abstract class ARepository {
}
}
protected void setFeedColors(String favUrl, Feed feed) throws IOException {
protected void setFeedColors(String favUrl, Feed feed) {
Bitmap favicon = Utils.getImageFromUrl(favUrl);
if (favicon != null) {
Palette palette = Palette.from(favicon).generate();
feed.setTextColor(palette.getDominantSwatch().getRgb());
@ -88,4 +91,5 @@ public abstract class ARepository {
if (palette.getMutedSwatch() != null)
feed.setBackgroundColor(palette.getMutedSwatch().getRgb());
}
}
}

View File

@ -219,6 +219,8 @@ public class LocalFeedRepository extends ARepository {
}
private void insertItems(Collection<Item> items, Feed feed) {
List<Item> itemsToInsert = new ArrayList<>();
for (Item dbItem : items) {
if (!Boolean.valueOf(database.itemDao().guidExist(dbItem.getGuid()))) {
if (dbItem.getDescription() != null) {
@ -247,9 +249,11 @@ public class LocalFeedRepository extends ARepository {
else if (dbItem.getDescription() != null)
dbItem.setReadTime(Utils.readTimeFromString(dbItem.getCleanDescription()));
database.itemDao().insert(dbItem);
itemsToInsert.add(dbItem);
}
}
database.itemDao().insert(itemsToInsert);
}
private FeedInsertionResult.FeedInsertionError getErrorFromException(Exception e) {

View File

@ -1,25 +1,38 @@
package com.readrops.app.repositories;
import android.app.Application;
import android.util.TimingLogger;
import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.Folder;
import com.readrops.app.database.entities.Item;
import com.readrops.app.database.pojo.FeedWithFolder;
import com.readrops.app.utils.FeedInsertionResult;
import com.readrops.app.utils.FeedMatcher;
import com.readrops.app.utils.ItemMatcher;
import com.readrops.app.utils.ParsingResult;
import com.readrops.app.utils.Utils;
import com.readrops.readropslibrary.services.nextcloudnews.Credentials;
import com.readrops.readropslibrary.services.nextcloudnews.NextNewsAPI;
import com.readrops.readropslibrary.services.nextcloudnews.SyncResults;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
import com.readrops.readropslibrary.utils.LibUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import io.reactivex.Completable;
import io.reactivex.Observable;
import io.reactivex.Single;
import io.reactivex.schedulers.Schedulers;
public class NextNewsRepository extends ARepository {
private static final String TAG = NextNewsRepository.class.getSimpleName();
public NextNewsRepository(Application application) {
super(application);
}
@ -31,7 +44,18 @@ public class NextNewsRepository extends ARepository {
NextNewsAPI newsAPI = new NextNewsAPI();
Credentials credentials = new Credentials("", LibUtils.NEXTCLOUD_PASSWORD, "");
newsAPI.sync(credentials, NextNewsAPI.SyncType.INITIAL_SYNC, null);
SyncResults results = newsAPI.sync(credentials, NextNewsAPI.SyncType.INITIAL_SYNC, null);
TimingLogger timings = new TimingLogger(TAG, "sync");
insertFolders(results.getFolders());
timings.addSplit("insert folders");
insertFeeds(results.getFeeds());
timings.addSplit("insert feeds");
insertItems(results.getItems());
timings.addSplit("insert items");
timings.dumpToLog();
emitter.onComplete();
} catch (IOException e) {
@ -60,4 +84,77 @@ public class NextNewsRepository extends ARepository {
public Completable addFolder(Folder folder) {
return null;
}
private void insertFeeds(List<NextNewsFeed> feeds) {
List<Feed> newFeeds = new ArrayList<>();
for (NextNewsFeed nextNewsFeed : feeds) {
if (!database.feedDao().remoteFeedExists(nextNewsFeed.getId())) {
Feed feed = FeedMatcher.nextNewsFeedToFeed(nextNewsFeed);
// if the Nextcloud feed has a folder, it is already inserted, so we have to get its local id
if (nextNewsFeed.getFolderId() != 0) {
int folderId = database.folderDao().getRemoteFolderLocalId(nextNewsFeed.getFolderId());
if (folderId != 0)
feed.setFolderId(folderId);
}
newFeeds.add(feed);
}
}
long[] ids = database.feedDao().insert(newFeeds);
List<Feed> insertedFeeds = database.feedDao().selectFromIdList(ids);
Observable.<Feed>create(emitter -> {
for (Feed feed : insertedFeeds) {
setFavIconUtils(feed);
emitter.onNext(feed);
}
}).subscribeOn(Schedulers.computation())
.observeOn(Schedulers.io())
.doOnNext(feed1 -> database.feedDao().updateColors(feed1.getId(),
feed1.getTextColor(), feed1.getBackgroundColor()))
.subscribe();
}
private void insertFolders(List<NextNewsFolder> folders) {
List<Folder> newFolders = new ArrayList<>();
for (NextNewsFolder nextNewsFolder : folders) {
if (!database.folderDao().remoteFolderExists(nextNewsFolder.getId())) {
Folder folder = new Folder(nextNewsFolder.getName());
folder.setRemoteId(nextNewsFolder.getId());
newFolders.add(folder);
}
}
database.folderDao().insert(newFolders);
}
private void insertItems(List<NextNewsItem> items) {
List<Item> newItems = new ArrayList<>();
for (NextNewsItem nextNewsItem : items) {
if (!database.itemDao().remoteItemExists(nextNewsItem.getId())) {
try {
Feed feed = database.feedDao().getFeedByRemoteId(nextNewsItem.getFeedId());
Item item = ItemMatcher.nextNewsItemToItem(nextNewsItem, feed);
item.setReadTime(Utils.readTimeFromString(item.getContent()));
newItems.add(item);
} catch (Exception e) {
e.printStackTrace();
}
}
}
database.itemDao().insert(newItems);
}
}

View File

@ -0,0 +1,24 @@
package com.readrops.app.utils;
import com.readrops.app.database.entities.Feed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
public final class FeedMatcher {
public static Feed nextNewsFeedToFeed(NextNewsFeed feed) {
Feed newFeed = new Feed();
newFeed.setName(feed.getTitle());
newFeed.setUrl(feed.getUrl());
newFeed.setSiteUrl(feed.getLink());
newFeed.setUnreadCount(feed.getUnreadCount());
newFeed.setFolderId(feed.getFolderId());
newFeed.setIconUrl(feed.getFaviconLink());
newFeed.setRemoteId(feed.getId());
return newFeed;
}
}

View File

@ -100,7 +100,7 @@ public final class HtmlParser {
String head = body.substring(body.indexOf("<head>"), body.indexOf("</head>"));
long end = System.currentTimeMillis();
Log.d(TAG, "parsing time : " + String.valueOf(end - start));
Log.d(TAG, "parsing time : " + (end - start));
return head;
}

View File

@ -0,0 +1,34 @@
package com.readrops.app.utils;
import com.readrops.app.database.entities.Feed;
import com.readrops.app.database.entities.Item;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
public final class ItemMatcher {
public static Item nextNewsItemToItem(NextNewsItem nextNewsItem, Feed feed) {
Item item = new Item();
item.setRemoteId(nextNewsItem.getId());
item.setTitle(nextNewsItem.getTitle());
if (!nextNewsItem.getAuthor().isEmpty())
item.setAuthor(nextNewsItem.getAuthor());
item.setPubDate(new LocalDateTime(nextNewsItem.getPubDate() * 1000L,
DateTimeZone.getDefault()));
item.setContent(nextNewsItem.getBody());
item.setLink(nextNewsItem.getUrl());
item.setGuid(nextNewsItem.getGuid());
item.setRead(!nextNewsItem.isUnread());
item.setFeedId(feed.getId());
return item;
}
}

View File

@ -12,14 +12,15 @@ import android.graphics.drawable.ShapeDrawable;
import android.graphics.drawable.shapes.OvalShape;
import android.os.Handler;
import android.os.Looper;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import android.util.DisplayMetrics;
import android.widget.Toast;
import java.io.IOException;
import androidx.annotation.ColorInt;
import androidx.annotation.NonNull;
import java.io.InputStream;
import java.util.Locale;
import java.util.concurrent.TimeUnit;
import okhttp3.OkHttpClient;
import okhttp3.Request;
@ -45,8 +46,11 @@ public final class Utils {
}
public static Bitmap getImageFromUrl(String url) throws IOException {
OkHttpClient okHttpClient = new OkHttpClient();
public static Bitmap getImageFromUrl(String url) {
try {
OkHttpClient okHttpClient = new OkHttpClient.Builder()
.callTimeout(5, TimeUnit.SECONDS)
.build();
Request request = new Request.Builder().url(url).build();
Response response = okHttpClient.newCall(request).execute();
@ -56,6 +60,9 @@ public final class Utils {
return BitmapFactory.decodeStream(inputStream);
} else
return null;
} catch (Exception e) {
return null; // no way to get the favicon
}
}
public static int getDeviceWidth(Activity activity) {

View File

@ -1,17 +1,9 @@
package com.readrops.app.views;
import androidx.paging.PagedListAdapter;
import android.content.Context;
import android.content.res.Resources;
import android.graphics.drawable.ColorDrawable;
import android.graphics.drawable.Drawable;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.appcompat.content.res.AppCompatResources;
import androidx.recyclerview.widget.ListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
@ -20,6 +12,13 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.core.content.ContextCompat;
import androidx.paging.PagedListAdapter;
import androidx.recyclerview.widget.DiffUtil;
import androidx.recyclerview.widget.RecyclerView;
import com.bumptech.glide.ListPreloader;
import com.bumptech.glide.RequestBuilder;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
@ -30,8 +29,8 @@ import com.bumptech.glide.request.RequestOptions;
import com.bumptech.glide.request.transition.DrawableCrossFadeFactory;
import com.bumptech.glide.util.ViewPreloadSizeProvider;
import com.readrops.app.R;
import com.readrops.app.database.pojo.ItemWithFeed;
import com.readrops.app.database.entities.Item;
import com.readrops.app.database.pojo.ItemWithFeed;
import com.readrops.app.utils.DateUtils;
import com.readrops.app.utils.GlideRequests;
import com.readrops.app.utils.Utils;
@ -40,8 +39,6 @@ import java.util.Collections;
import java.util.LinkedHashSet;
import java.util.List;
import static com.bumptech.glide.load.resource.bitmap.BitmapTransitionOptions.withCrossFade;
public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItemListAdapter.ItemViewHolder> implements ListPreloader.PreloadModelProvider<String> {
private GlideRequests glideRequests;
@ -73,7 +70,9 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
itemWithFeed.getFeedName().equals(t1.getFeedName()) &&
itemWithFeed.getFolder().getName().equals(t1.getFolder().getName()) &&
item.isRead() == item1.isRead() &&
item.isReadItLater() == item1.isReadItLater();
item.isReadItLater() == item1.isReadItLater() &&
itemWithFeed.getColor() == t1.getColor() &&
itemWithFeed.getBgColor() == t1.getBgColor();
}
};
@ -123,7 +122,8 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
viewHolder.itemImage.setVisibility(View.GONE);
if (itemWithFeed.getFeedIconUrl() != null) {
glideRequests.load(itemWithFeed.getFeedIconUrl())
glideRequests.
load(itemWithFeed.getFeedIconUrl())
.diskCacheStrategy(DiskCacheStrategy.ALL)
.placeholder(R.drawable.ic_rss_feed)
.into(viewHolder.feedIcon);
@ -222,6 +222,7 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
public RequestBuilder<Drawable> getPreloadRequestBuilder(@NonNull String url) {
return glideRequests
.load(url)
.centerCrop()
.apply(requestOptions)
.diskCacheStrategy(DiskCacheStrategy.ALL)
.transition(DrawableTransitionOptions.withCrossFade(FADE_FACTORY));

View File

@ -2,12 +2,13 @@ package com.readrops.app;
import com.readrops.app.utils.DateUtils;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDateTime;
import org.junit.Test;
import java.text.ParseException;
import static org.junit.Assert.*;
import static org.junit.Assert.assertEquals;
/**
* Example local unit test, which will execute on the development machine (host).
@ -39,4 +40,11 @@ public class ExampleUnitTest {
e.printStackTrace();
}
}
@Test
public void timeStamptoDateTest() {
LocalDateTime localDateTime = new LocalDateTime(1367270544 * 1000L, DateTimeZone.getDefault());
assertEquals(0, localDateTime.compareTo(new LocalDateTime(2013, 4, 29, 21, 22, 24)));
}
}

View File

@ -1,8 +1,5 @@
package com.readrops.readropslibrary.services;
import androidx.annotation.CallSuper;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
@ -11,9 +8,11 @@ import java.util.List;
import okhttp3.ResponseBody;
import retrofit2.Call;
import retrofit2.http.Body;
import retrofit2.http.GET;
import retrofit2.http.PUT;
import retrofit2.http.Path;
import retrofit2.http.Query;
public interface NextNewsService {
@ -25,21 +24,24 @@ public interface NextNewsService {
@GET("feeds")
Call<NextNewsFeeds> getFeeds();
@GET("items?type={type}&getRead={read}&batchSize={batchSize}")
Call<NextNewsItems> getItems(@Path("type") int type, @Path("read") boolean read, @Path("batchSize") int batchSize);
@GET("items")
Call<NextNewsItems> getItems(@Query("type") int type, @Query("getRead") boolean read, @Query("batchSize") int batchSize);
@GET("items/updated?lastModified={lastModified}&type=3")
Call<NextNewsItems> getNewItems(@Path("lastModified") long lastModified);
@GET("items/updated?type=3")
Call<NextNewsItems> getNewItems(@Query("lastModified") long lastModified);
@PUT("items/read/multiple")
Call<ResponseBody> setReadArticles();
Call<ResponseBody> setReadArticles(@Body List<Integer> itemsIds);
@PUT("items/unread/multiple")
Call<ResponseBody> setUnreadArticles();
Call<ResponseBody> setUnreadArticles(@Body List<Integer> itemsIds);
@PUT("items/starred/multiple")
Call<ResponseBody> setStarredArticles();
Call<ResponseBody> setStarredArticles(@Body List<Integer> itemsIds);
@PUT("items/unstarred/multiple")
Call<ResponseBody> setUnstarredArticles();
Call<ResponseBody> setUnstarredArticles(@Body List<Integer> itemsIds);
@PUT("items/{stateType}/multiple")
Call<ResponseBody> setArticlesState(@Path("stateType") String stateType, @Body List<Integer> items);
}

View File

@ -2,36 +2,17 @@ package com.readrops.readropslibrary.services.nextcloudnews;
public class Credentials {
private String login;
private String password;
private String base64;
private String url;
public Credentials(String login, String password, String url) {
this.login = login;
this.password = password;
this.base64 = okhttp3.Credentials.basic(login, password);
this.url = url;
}
public String toBase64() {
return okhttp3.Credentials.basic(login, password);
}
public String getLogin() {
return login;
}
public void setLogin(String login) {
this.login = login;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
public String getBase64() {
return base64;
}
public String getUrl() {

View File

@ -1,21 +1,25 @@
package com.readrops.readropslibrary.services.nextcloudnews;
import android.util.TimingLogger;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.readrops.readropslibrary.services.NextNewsService;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
import com.readrops.readropslibrary.utils.HttpManager;
import java.io.IOException;
import retrofit2.Response;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
public class NextNewsAPI {
private static final String TAG = NextNewsAPI.class.getSimpleName();
public NextNewsAPI() {
}
@ -28,15 +32,41 @@ public class NextNewsAPI {
.build();
}
public void sync(@NonNull Credentials credentials, @NonNull SyncType syncType, @Nullable SyncData data) throws IOException {
public SyncResults sync(@NonNull Credentials credentials, @NonNull SyncType syncType, @Nullable SyncData data) throws IOException {
HttpManager httpManager = new HttpManager(credentials);
Retrofit retrofit = getConfiguredRetrofitInstance(httpManager);
NextNewsService api = retrofit.create(NextNewsService.class);
TimingLogger timings = new TimingLogger(TAG, "sync");
NextNewsFeeds feedList = api.getFeeds().execute().body();
timings.addSplit("get feeds");
NextNewsFolders folderList = api.getFolders().execute().body();
timings.addSplit("get folders");
NextNewsItems itemList = api.getItems(3, false, 300).execute().body();
timings.addSplit("get items");
timings.dumpToLog();
SyncResults results = new SyncResults();
results.setFeeds(feedList.getFeeds());
results.setFolders(folderList.getFolders());
results.setItems(itemList.getItems());
return results;
}
public enum SyncType {
INITIAL_SYNC,
CLASSIC_SYNC
}
public enum StateType {
READ,
UNREAD,
STARRED,
UNSTARRED
}
}

View File

@ -0,0 +1,43 @@
package com.readrops.readropslibrary.services.nextcloudnews;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
import java.util.List;
public class SyncResults {
private List<NextNewsFolder> folders;
private List<NextNewsFeed> feeds;
private List<NextNewsItem> items;
public SyncResults() {
}
public List<NextNewsFolder> getFolders() {
return folders;
}
public void setFolders(List<NextNewsFolder> folders) {
this.folders = folders;
}
public List<NextNewsFeed> getFeeds() {
return feeds;
}
public void setFeeds(List<NextNewsFeed> feeds) {
this.feeds = feeds;
}
public List<NextNewsItem> getItems() {
return items;
}
public void setItems(List<NextNewsItem> items) {
this.items = items;
}
}

View File

@ -10,13 +10,13 @@ public class NextNewsFeed {
private String faviconLink;
private float added;
private long added;
private float folderId;
private int folderId;
private float unreadCount;
private int unreadCount;
private float ordering;
private int ordering;
private String link;
@ -54,35 +54,35 @@ public class NextNewsFeed {
this.faviconLink = faviconLink;
}
public float getAdded() {
public long getAdded() {
return added;
}
public void setAdded(float added) {
public void setAdded(long added) {
this.added = added;
}
public float getFolderId() {
public int getFolderId() {
return folderId;
}
public void setFolderId(float folderId) {
public void setFolderId(int folderId) {
this.folderId = folderId;
}
public float getUnreadCount() {
public int getUnreadCount() {
return unreadCount;
}
public void setUnreadCount(float unreadCount) {
public void setUnreadCount(int unreadCount) {
this.unreadCount = unreadCount;
}
public float getOrdering() {
public int getOrdering() {
return ordering;
}
public void setOrdering(float ordering) {
public void setOrdering(int ordering) {
this.ordering = ordering;
}

View File

@ -14,7 +14,7 @@ public class NextNewsItem {
private String author;
private float pubDate;
private long pubDate;
private String body;
@ -22,13 +22,13 @@ public class NextNewsItem {
private String enclosureLink;
private float feedId;
private int feedId;
private boolean unread;
private boolean starred;
private float lastModified;
private long lastModified;
private String fingerprint;
@ -80,11 +80,11 @@ public class NextNewsItem {
this.author = author;
}
public float getPubDate() {
public long getPubDate() {
return pubDate;
}
public void setPubDate(float pubDate) {
public void setPubDate(long pubDate) {
this.pubDate = pubDate;
}
@ -112,11 +112,11 @@ public class NextNewsItem {
this.enclosureLink = enclosureLink;
}
public float getFeedId() {
public int getFeedId() {
return feedId;
}
public void setFeedId(float feedId) {
public void setFeedId(int feedId) {
this.feedId = feedId;
}
@ -136,11 +136,11 @@ public class NextNewsItem {
this.starred = starred;
}
public float getLastModified() {
public long getLastModified() {
return lastModified;
}
public void setLastModified(float lastModified) {
public void setLastModified(long lastModified) {
this.lastModified = lastModified;
}

View File

@ -1,6 +0,0 @@
package com.readrops.readropslibrary.services.nextcloudnews.json;
public class SyncResults {
}

View File

@ -40,7 +40,7 @@ public class HttpManager {
Request request = chain.request();
request = request.newBuilder()
.addHeader("Authorization", credentials.toBase64())
.addHeader("Authorization", credentials.getBase64())
.build();
return chain.proceed(request);