Implement Nextcloud folder creation, update and deletion APIs

This commit is contained in:
Shinokuni 2019-07-14 21:24:59 +02:00
parent 9097c1d660
commit 5970b18203
11 changed files with 139 additions and 20 deletions

View File

@ -50,7 +50,7 @@ public abstract class ARepository {
public abstract Completable updateFolder(Folder folder, Account account);
public abstract Completable deleteFolder(Folder folder);
public abstract Completable deleteFolder(Folder folder, Account account);
public abstract Completable changeFeedFolder(Feed feed, Folder newFolder);

View File

@ -178,7 +178,7 @@ public class LocalFeedRepository extends ARepository {
}
@Override
public Completable deleteFolder(Folder folder) {
public Completable deleteFolder(Folder folder, Account account) {
return Completable.create(emitter -> {
database.folderDao().delete(folder);
emitter.onComplete();

View File

@ -21,6 +21,7 @@ import com.readrops.readropslibrary.services.nextcloudnews.SyncResult;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeed;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItem;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser;
import com.readrops.readropslibrary.utils.UnknownFormatException;
@ -169,30 +170,62 @@ public class NextNewsRepository extends ARepository {
@Override
public Completable addFolder(Folder folder, Account account) {
return Completable.create(emitter -> {
database.folderDao().insert(folder);
emitter.onComplete();
NextNewsAPI api = new NextNewsAPI();
//TODO : remote insert
try {
Credentials credentials = new Credentials(account.getLogin(), account.getPassword(), account.getUrl());
NextNewsFolders folders = api.createFolder(credentials, new NextNewsFolder(folder.getId(), folder.getName()));
if (folders != null)
insertFolders(folders.getFolders(), account);
else
emitter.onError(new Exception());
} catch (Exception e) {
emitter.onError(e);
}
emitter.onComplete();
});
}
@Override
public Completable updateFolder(Folder folder, Account account) {
return Completable.create(emitter -> {
database.folderDao().update(folder);
emitter.onComplete();
NextNewsAPI api = new NextNewsAPI();
//TODO : remote update
try {
Credentials credentials = new Credentials(account.getLogin(), account.getPassword(), account.getUrl());
if (api.renameFolder(credentials, new NextNewsFolder(folder.getId(), folder.getName())))
emitter.onComplete();
else
emitter.onError(new Exception());
} catch (Exception e) {
emitter.onError(e);
}
emitter.onComplete();
});
}
@Override
public Completable deleteFolder(Folder folder) {
public Completable deleteFolder(Folder folder, Account account) {
return Completable.create(emitter -> {
database.folderDao().delete(folder);
emitter.onComplete();
NextNewsAPI api = new NextNewsAPI();
//TODO : remote update
try {
Credentials credentials = new Credentials(account.getLogin(), account.getPassword(), account.getUrl());
if (api.deleteFolder(credentials, new NextNewsFolder(folder.getId(), folder.getName())))
emitter.onComplete();
else
emitter.onError(new Exception());
} catch (Exception e) {
emitter.onError(e);
}
emitter.onComplete();
});
}

View File

@ -76,7 +76,7 @@ public class ManageFeedsFoldersViewModel extends AndroidViewModel {
}
public Completable deleteFolder(Folder folder) {
return repository.deleteFolder(folder);
return repository.deleteFolder(folder, account);
}
public Completable deleteFeed(int feedId) {

View File

@ -87,7 +87,7 @@ public class FeedsAdapter extends ListAdapter<FeedWithFolder, FeedsAdapter.ViewH
if (feedWithFolder.getFolder() != null)
viewHolder.folderName.setText(feedWithFolder.getFolder().getName());
else
viewHolder.folderName.setText(viewHolder.itemView.getResources().getString(R.string.no_folder));
viewHolder.folderName.setText(R.string.no_folder);
viewHolder.itemView.setOnClickListener(v -> listener.onEdit(getItem(i)));
viewHolder.itemView.setOnLongClickListener(v -> {
@ -107,7 +107,7 @@ public class FeedsAdapter extends ListAdapter<FeedWithFolder, FeedsAdapter.ViewH
if (feedWithFolder.getFolder() != null)
holder.folderName.setText(feedWithFolder.getFolder().getName());
else
holder.folderName.setText(holder.itemView.getContext().getString(R.string.no_folder));
holder.folderName.setText(R.string.no_folder);
} else
onBindViewHolder(holder, position);

View File

@ -153,16 +153,16 @@ public class MainItemListAdapter extends PagedListAdapter<ItemWithFeed, MainItem
int minutes = (int) Math.round(itemWithFeed.getItem().getReadTime());
if (minutes < 1)
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time_lower_than_1));
viewHolder.itemReadTime.setText(R.string.read_time_lower_than_1);
else if (minutes > 1)
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time, String.valueOf(minutes)));
else
viewHolder.itemReadTime.setText(resources.getString(R.string.read_time_one_minute));
viewHolder.itemReadTime.setText(R.string.read_time_one_minute);
if (itemWithFeed.getFolder() != null)
viewHolder.itemFolderName.setText(itemWithFeed.getFolder().getName());
else
viewHolder.itemFolderName.setText(resources.getString(R.string.no_folder));
viewHolder.itemFolderName.setText(R.string.no_folder);
viewHolder.setReadState(itemWithFeed.getItem().isRead());
viewHolder.setSelected(selection.contains(viewHolder.getAdapterPosition()));

View File

@ -1,6 +1,7 @@
package com.readrops.readropslibrary.services;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFeeds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolder;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItemIds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
@ -39,4 +40,13 @@ public interface NextNewsService {
@POST("feeds")
Call<NextNewsFeeds> createFeed(@Query("url") String url, @Query("folderId") int folderId);
@POST("folders")
Call<NextNewsFolders> createFolder(@Body NextNewsFolder folder);
@POST("folders/{folderId}")
Call<ResponseBody> deleteFolder(@Path("folderId") int folderId);
@PUT("folders/{folderId}")
Call<ResponseBody> renameFolder(@Path("folderId") int folderId, @Body NextNewsFolder folder);
}

View File

@ -1,14 +1,18 @@
package com.readrops.readropslibrary.services.nextcloudnews;
import android.content.res.Resources;
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.NextNewsFolder;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsFolders;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItemIds;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsItems;
import com.readrops.readropslibrary.services.nextcloudnews.json.NextNewsUser;
import com.readrops.readropslibrary.utils.ConflictException;
import com.readrops.readropslibrary.utils.HttpManager;
import com.readrops.readropslibrary.utils.LibUtils;
import com.readrops.readropslibrary.utils.UnknownFormatException;
@ -62,7 +66,7 @@ public class NextNewsAPI {
Response<NextNewsFeeds> response = api.createFeed(url, folderId).execute();
if (!response.isSuccessful()) {
if (response.code() == LibUtils.UNPROCESSABLE_CODE)
if (response.code() == LibUtils.HTTP_UNPROCESSABLE)
throw new UnknownFormatException();
else
return null;
@ -152,6 +156,55 @@ public class NextNewsAPI {
syncResult.setError(true);
}
public @Nullable NextNewsFolders createFolder(Credentials credentials, NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException {
api = createAPI(credentials);
Response<NextNewsFolders> foldersResponse = api.createFolder(folder).execute();
if (foldersResponse.isSuccessful())
return foldersResponse.body();
else if (foldersResponse.code() == LibUtils.HTTP_UNPROCESSABLE)
throw new UnknownFormatException();
else if (foldersResponse.code() == LibUtils.HTTP_CONFLICT)
throw new ConflictException();
else
return null;
}
public boolean deleteFolder(Credentials credentials, NextNewsFolder folder) throws IOException {
api = createAPI(credentials);
Response response = api.deleteFolder(folder.getId()).execute();
if (response.isSuccessful())
return true;
else if (response.code() == LibUtils.HTTP_NOT_FOUND)
throw new Resources.NotFoundException();
else
return false;
}
public boolean renameFolder(Credentials credentials, NextNewsFolder folder) throws IOException, UnknownFormatException, ConflictException {
api = createAPI(credentials);
Response response = api.renameFolder(folder.getId(), folder).execute();
if (response.isSuccessful())
return true;
else {
switch (response.code()) {
case LibUtils.HTTP_NOT_FOUND:
throw new Resources.NotFoundException();
case LibUtils.HTTP_UNPROCESSABLE:
throw new UnknownFormatException();
case LibUtils.HTTP_CONFLICT:
throw new ConflictException();
default:
return false;
}
}
}
public enum SyncType {
INITIAL_SYNC,
CLASSIC_SYNC

View File

@ -10,6 +10,14 @@ public class NextNewsFolder {
@SerializedName("name")
private String name;
public NextNewsFolder() {
}
public NextNewsFolder(int id, String name) {
this.id = id;
this.name = name;
}
public int getId() {
return id;
}

View File

@ -0,0 +1,12 @@
package com.readrops.readropslibrary.utils;
public class ConflictException extends Exception {
public ConflictException() {
}
public ConflictException(String message) {
super(message);
}
}

View File

@ -18,7 +18,10 @@ public final class LibUtils {
public static final String LAST_MODIFIED_HEADER = "Last-Modified";
public static final String IF_MODIFIED_HEADER = "If-Modified-Since";
public static final int UNPROCESSABLE_CODE = 422;
public static final int HTTP_UNPROCESSABLE = 422;
public static final int HTTP_NOT_FOUND = 404;
public static final int HTTP_CONFLICT = 409;
public static String inputStreamToString(InputStream input) {
Scanner scanner = new Scanner(input).useDelimiter("\\A");