use ocs-api for user info as news-api user endpoint is deprecated

Signed-off-by: David Luhmer <david-dev@live.de>
This commit is contained in:
David-Development 2020-11-11 17:32:53 +01:00 committed by David Luhmer
parent 1057bd540e
commit 38682bb87c
19 changed files with 244 additions and 183 deletions

View file

@ -19,7 +19,7 @@ import java.io.OutputStream;
import de.luhmer.owncloudnewsreader.NewsReaderListFragment;
import de.luhmer.owncloudnewsreader.SettingsActivity;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import de.luhmer.owncloudnewsreader.model.OcsUser;
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
import static com.nextcloud.android.sso.Constants.ACCOUNT_TYPE_PROD;
@ -49,11 +49,7 @@ public class TestApiModule extends ApiModule {
ACCOUNT_TYPE_PROD
);
UserInfo userInfo = new UserInfo.Builder()
.setUserId("1")
.setDisplayName(DUMMY_ACCOUNT_username)
.setAvatar(null)
.build();
OcsUser userInfo = new OcsUser("1", DUMMY_ACCOUNT_username);
//SharedPreferences sharedPrefs = new MockSharedPreference();
SharedPreferences sharedPrefs = application.getSharedPreferences(providesSharedPreferencesFileName(), Context.MODE_PRIVATE);

View file

@ -20,7 +20,7 @@ import java.nio.charset.Charset;
import java.util.ArrayList;
import de.luhmer.owncloudnewsreader.helper.GsonConfig;
import de.luhmer.owncloudnewsreader.reader.nextcloud.API;
import de.luhmer.owncloudnewsreader.reader.nextcloud.NewsAPI;
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
import retrofit2.NextcloudRetrofitApiBuilder;
@ -59,7 +59,7 @@ public class TestApiProvider extends ApiProvider {
}
NextcloudAPI nextcloudAPI = new NextcloudAPI(GsonConfig.GetGson(), networkRequestSpy);
mApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, API.mApiEndpoint).create(API.class);
mNewsApi = new NextcloudRetrofitApiBuilder(nextcloudAPI, NewsAPI.mApiEndpoint).create(NewsAPI.class);
}

View file

@ -46,6 +46,9 @@ import android.widget.ImageView;
import android.widget.RelativeLayout;
import android.widget.TextView;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import com.google.android.material.textfield.TextInputLayout;
import com.nextcloud.android.sso.AccountImporter;
import com.nextcloud.android.sso.api.NextcloudAPI;
@ -63,8 +66,6 @@ import java.net.URL;
import javax.inject.Inject;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
@ -377,7 +378,7 @@ public class LoginDialogActivity extends AppCompatActivity {
}
private void finishLogin(final ProgressDialog dialogLogin) {
mApi.getAPI().version()
mApi.getNewsAPI().version()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<NextcloudNewsVersion>() {

View file

@ -22,6 +22,13 @@ import android.widget.EditText;
import android.widget.Spinner;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import com.nbsp.materialfilepicker.MaterialFilePicker;
import com.nbsp.materialfilepicker.ui.FilePickerActivity;
@ -47,13 +54,6 @@ import java.util.Map;
import javax.inject.Inject;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;
@ -66,7 +66,6 @@ import de.luhmer.owncloudnewsreader.helper.OpmlXmlParser;
import de.luhmer.owncloudnewsreader.helper.ThemeChooser;
import de.luhmer.owncloudnewsreader.helper.URLConnectionReader;
import de.luhmer.owncloudnewsreader.ssl.OkHttpSSLClient;
import io.reactivex.functions.Consumer;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
@ -282,7 +281,7 @@ public class NewFeedActivity extends AppCompatActivity {
final HashMap<String, Long> existingFolders = new HashMap<>();
mApi.getAPI().folders().blockingSubscribe(folders -> {
mApi.getNewsAPI().folders().blockingSubscribe(folders -> {
for(Folder folder : folders) {
existingFolders.put(folder.getLabel(), folder.getId());
}
@ -298,13 +297,13 @@ public class NewFeedActivity extends AppCompatActivity {
//mApi.getAPI().createFolder(foldername) // HttpJsonRequest.getInstance().performCreateFolderRequest(api.getFolderUrl(), folderName);
final Map<String, Object> folderMap = new HashMap<>(2);
folderMap.put("name", folderName);
Folder folder = mApi.getAPI().createFolder(folderMap).execute().body().get(0);
Folder folder = mApi.getNewsAPI().createFolder(folderMap).execute().body().get(0);
//TODO test this!!!
existingFolders.put(folder.getLabel(), folder.getId()); //Add folder to list of existing folder in order to prevent that the method tries to create it multiple times
}
}
Feed feed = mApi.getAPI().createFeed(feedUrl, folderId).execute().body().get(0);
Feed feed = mApi.getNewsAPI().createFeed(feedUrl, folderId).execute().body().get(0);
Log.v(TAG, "New Feed-ID: " + feed.getId());
}
} catch (Exception e) {
@ -381,7 +380,7 @@ public class NewFeedActivity extends AppCompatActivity {
// perform the user login attempt.
showProgress(true);
mApi.getAPI().createFeed(urlToFeed, folder.getId()).enqueue(new Callback<List<Feed>>() {
mApi.getNewsAPI().createFeed(urlToFeed, folder.getId()).enqueue(new Callback<List<Feed>>() {
@Override
public void onResponse(Call<List<Feed>> call, final Response<List<Feed>> response) {
runOnUiThread(() -> {

View file

@ -512,7 +512,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
UpdateItemList();
updatePodcastView();
if(mApi.getAPI() != null) {
if(mApi.getNewsAPI() != null) {
getSlidingListFragment().startAsyncTaskGetUserInfo();
}
@ -914,7 +914,7 @@ public class NewsReaderListActivity extends PodcastFragmentActivity implements
}
int type = 0; // the type of the query (Feed: 0, Folder: 1, Starred: 2, All: 3)
List<RssItem> buffer = mApi.getAPI().items(100, offset, type, feedId, true, false).execute().body();
List<RssItem> buffer = mApi.getNewsAPI().items(100, offset, type, feedId, true, false).execute().body();
RssItemObservable.performDatabaseBatchInsert(dbConn, buffer);
}
})

View file

@ -20,6 +20,8 @@ import android.widget.RelativeLayout;
import android.widget.TextView;
import android.widget.Toast;
import androidx.fragment.app.DialogFragment;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
@ -27,7 +29,6 @@ import java.util.Map;
import javax.inject.Inject;
import androidx.fragment.app.DialogFragment;
import butterknife.BindView;
import butterknife.ButterKnife;
import de.luhmer.owncloudnewsreader.database.DatabaseConnectionOrm;
@ -232,7 +233,7 @@ public class NewsReaderListDialogFragment extends DialogFragment {
Map<String, String> paramMap = new LinkedHashMap<>();
paramMap.put("feedTitle", mFeedName.getText().toString());
mApi.getAPI().renameFeed(feedId, paramMap)
mApi.getNewsAPI().renameFeed(feedId, paramMap)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action() {
@ -275,7 +276,7 @@ public class NewsReaderListDialogFragment extends DialogFragment {
getDialog().setCanceledOnTouchOutside(false);
mApi.getAPI().deleteFeed(feedId)
mApi.getNewsAPI().deleteFeed(feedId)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action() {
@ -337,7 +338,7 @@ public class NewsReaderListDialogFragment extends DialogFragment {
Map<String, Long> paramMap = new LinkedHashMap<>();
paramMap.put("folderId", folder.getId());
mApi.getAPI().moveFeed(mFeedId, paramMap)
mApi.getNewsAPI().moveFeed(mFeedId, paramMap)
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Action() {

View file

@ -24,12 +24,10 @@ package de.luhmer.owncloudnewsreader;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.net.Uri;
import android.os.Bundle;
import android.util.Base64;
import android.util.Log;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.View;
import android.view.View.OnCreateContextMenuListener;
@ -44,11 +42,9 @@ import androidx.annotation.VisibleForTesting;
import androidx.fragment.app.Fragment;
import com.google.android.material.navigation.NavigationView;
import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.display.CircleBitmapDisplayer;
import com.nostra13.universalimageloader.core.display.RoundedBitmapDisplayer;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
@ -67,7 +63,7 @@ import de.luhmer.owncloudnewsreader.di.ApiProvider;
import de.luhmer.owncloudnewsreader.interfaces.ExpListTextClicked;
import de.luhmer.owncloudnewsreader.model.AbstractItem;
import de.luhmer.owncloudnewsreader.model.ConcreteFeedItem;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import de.luhmer.owncloudnewsreader.model.OcsUser;
import io.reactivex.Observer;
import io.reactivex.android.schedulers.AndroidSchedulers;
import io.reactivex.annotations.NonNull;
@ -253,7 +249,7 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
footerNavigation.setNavigationItemSelectedListener(item -> {
switch(item.getItemId()) {
case R.id.action_add_new_feed:
if(mApi.getAPI() != null) {
if(mApi.getNewsAPI() != null) {
Intent newFeedIntent = new Intent(getContext(), NewFeedActivity.class);
getActivity().startActivityForResult(newFeedIntent, NewsReaderListActivity.RESULT_ADD_NEW_FEED);
} else {
@ -341,21 +337,21 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
}
public void startAsyncTaskGetUserInfo() {
mApi.getAPI().user()
mApi.getServerAPI().user()
.subscribeOn(Schedulers.newThread())
.observeOn(AndroidSchedulers.mainThread())
.subscribe(new Observer<UserInfo>() {
.subscribe(new Observer<OcsUser>() {
@Override
public void onSubscribe(@NonNull Disposable d) {
}
@Override
public void onNext(@NonNull UserInfo userInfo) {
public void onNext(@NonNull OcsUser userInfo) {
Log.d(TAG, "onNext() called with: userInfo = [" + userInfo + "]");
try {
String userInfoAsString = NewsReaderListFragment.toString(userInfo);
String userInfoAsString = NewsReaderListFragment.toString((Serializable) userInfo);
//Log.v(TAG, userInfoAsString);
mPrefs.edit().putString(USER_INFO_STRING, userInfoAsString).apply();
} catch (IOException e) {
@ -400,13 +396,14 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
urlTextView.setText(mOc_root_path_without_protocol);
String uInfo = mPrefs.getString(USER_INFO_STRING, null);
if(uInfo == null)
if(uInfo == null) {
return;
}
try {
UserInfo userInfo = (UserInfo) fromString(uInfo);
if (userInfo.displayName != null)
userTextView.setText(userInfo.displayName);
OcsUser userInfo = (OcsUser) fromString(uInfo);
if (userInfo.getDisplayName() != null)
userTextView.setText(userInfo.getDisplayName());
final int placeHolder = R.mipmap.ic_launcher;
DisplayImageOptions displayImageOptions = new DisplayImageOptions.Builder()
.displayer(new CircleBitmapDisplayer())
@ -416,14 +413,10 @@ public class NewsReaderListFragment extends Fragment implements OnCreateContextM
.cacheOnDisk(true)
.cacheInMemory(true)
.build();
String avatarUrl = mOc_root_path + "/index.php/avatar/" + Uri.encode(userInfo.userId) + "/64";
ImageLoader.getInstance().displayImage(avatarUrl, this.headerLogo, displayImageOptions);
if (userInfo.avatar != null) {
Resources r = getResources();
float px = TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, 3, r.getDisplayMetrics());
RoundedBitmapDisplayer.RoundedDrawable roundedAvatar =
new RoundedBitmapDisplayer.RoundedDrawable(userInfo.avatar, (int) px, 0);
headerLogo.setImageDrawable(roundedAvatar);
if(userInfo.getId() != null) {
String avatarUrl = mOc_root_path + "/index.php/avatar/" + Uri.encode(userInfo.getId()) + "/64";
ImageLoader.getInstance().displayImage(avatarUrl, this.headerLogo, displayImageOptions);
}
} catch (Exception ex) {
ex.printStackTrace();

View file

@ -10,7 +10,6 @@ import android.content.SyncResult;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.preference.PreferenceManager;
import android.util.Log;
import android.widget.Toast;
@ -112,7 +111,7 @@ public class OwnCloudSyncAdapter extends AbstractThreadedSyncAdapter {
// Start sync
private void sync() {
if(mApi.getAPI() == null) {
if(mApi.getNewsAPI() == null) {
throwException(new IllegalStateException("API is NOT initialized"));
Log.e(TAG, "API is NOT initialized..");
return;
@ -128,7 +127,7 @@ public class OwnCloudSyncAdapter extends AbstractThreadedSyncAdapter {
public void subscribe(Subscriber<? super Boolean> s) {
Log.v(TAG, "(rssStateSync) subscribe() called with: s = [" + s + "] [" + Thread.currentThread().getName() + "]");
try {
boolean success = ItemStateSync.PerformItemStateSync(mApi.getAPI(), dbConn);
boolean success = ItemStateSync.PerformItemStateSync(mApi.getNewsAPI(), dbConn);
s.onNext(success);
s.onComplete();
} catch(Exception ex) {
@ -139,12 +138,12 @@ public class OwnCloudSyncAdapter extends AbstractThreadedSyncAdapter {
// First sync Feeds and Folders and rss item states (in parallel)
Observable<List<Folder>> folderObservable = mApi
.getAPI()
.getNewsAPI()
.folders()
.subscribeOn(Schedulers.newThread());
Observable<List<Feed>> feedsObservable = mApi
.getAPI()
.getNewsAPI()
.feeds()
.subscribeOn(Schedulers.newThread());
@ -180,7 +179,7 @@ public class OwnCloudSyncAdapter extends AbstractThreadedSyncAdapter {
// .observeOn(AndroidSchedulers.mainThread())
Observable.fromPublisher(new RssItemObservable(dbConn, mApi.getAPI(), mPrefs))
Observable.fromPublisher(new RssItemObservable(dbConn, mApi.getNewsAPI(), mPrefs))
.subscribeOn(Schedulers.newThread())
.blockingSubscribe(new Observer<Integer>() {
@Override

View file

@ -4,6 +4,9 @@ import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import com.nextcloud.android.sso.api.NextcloudAPI;
import com.nextcloud.android.sso.exceptions.SSOException;
import com.nextcloud.android.sso.helper.SingleAccountHelper;
@ -13,12 +16,11 @@ import com.nostra13.universalimageloader.core.DisplayImageOptions;
import com.nostra13.universalimageloader.core.ImageLoader;
import com.nostra13.universalimageloader.core.ImageLoaderConfiguration;
import androidx.annotation.NonNull;
import androidx.annotation.VisibleForTesting;
import de.luhmer.owncloudnewsreader.SettingsActivity;
import de.luhmer.owncloudnewsreader.helper.GsonConfig;
import de.luhmer.owncloudnewsreader.reader.OkHttpImageDownloader;
import de.luhmer.owncloudnewsreader.reader.nextcloud.API;
import de.luhmer.owncloudnewsreader.reader.nextcloud.NewsAPI;
import de.luhmer.owncloudnewsreader.reader.nextcloud.OcsAPI;
import de.luhmer.owncloudnewsreader.ssl.MemorizingTrustManager;
import de.luhmer.owncloudnewsreader.ssl.OkHttpSSLClient;
import okhttp3.HttpUrl;
@ -38,9 +40,12 @@ public class ApiProvider {
private final MemorizingTrustManager mMemorizingTrustManager;
protected final SharedPreferences mPrefs;
protected Context context;
protected API mApi;
private NextcloudAPI mNextcloudSsoApi;
protected NewsAPI mNewsApi;
private OcsAPI mServerApi;
public ApiProvider(MemorizingTrustManager mtm, SharedPreferences sp, Context context) {
this.mMemorizingTrustManager = mtm;
@ -94,14 +99,15 @@ public class ApiProvider {
.client(client)
.build();
mApi = retrofit.create(API.class);
mNewsApi = retrofit.create(NewsAPI.class);
}
protected void initSsoApi(final NextcloudAPI.ApiConnectedListener callback) {
try {
SingleSignOnAccount ssoAccount = SingleAccountHelper.getCurrentSingleSignOnAccount(context);
mNextcloudSsoApi = new NextcloudAPI(context, ssoAccount, GsonConfig.GetGson(), callback);
mApi = new NextcloudRetrofitApiBuilder(mNextcloudSsoApi, API.mApiEndpoint).create(API.class);
mNewsApi = new NextcloudRetrofitApiBuilder(mNextcloudSsoApi, NewsAPI.mApiEndpoint).create(NewsAPI.class);
mServerApi = new NextcloudRetrofitApiBuilder(mNextcloudSsoApi, OcsAPI.mApiEndpoint).create(OcsAPI.class);
} catch (SSOException e) {
callback.onError(e);
}
@ -131,12 +137,16 @@ public class ApiProvider {
ImageLoader.getInstance().init(config);
}
public API getAPI() {
return mApi;
public NewsAPI getNewsAPI() {
return mNewsApi;
}
public OcsAPI getServerAPI() {
return mServerApi;
}
@VisibleForTesting
public void setAPI(API api) {
this.mApi = api;
public void setAPI(NewsAPI newsApi) {
this.mNewsApi = newsApi;
}
}

View file

@ -1,13 +1,7 @@
package de.luhmer.owncloudnewsreader.helper;
import android.graphics.BitmapFactory;
import android.util.Base64;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.reflect.TypeToken;
import java.lang.reflect.Type;
@ -16,10 +10,10 @@ import java.util.List;
import de.luhmer.owncloudnewsreader.database.model.Feed;
import de.luhmer.owncloudnewsreader.database.model.Folder;
import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import de.luhmer.owncloudnewsreader.reader.nextcloud.NextcloudDeserializer;
import de.luhmer.owncloudnewsreader.model.OcsUser;
import de.luhmer.owncloudnewsreader.reader.nextcloud.NextcloudNewsDeserializer;
import de.luhmer.owncloudnewsreader.reader.nextcloud.NextcloudServerDeserializer;
import de.luhmer.owncloudnewsreader.reader.nextcloud.Types;
import de.luhmer.owncloudnewsreader.ssl.OkHttpSSLClient;
/**
* Created by david on 27.06.17.
@ -31,31 +25,15 @@ public class GsonConfig {
Type feedList = new TypeToken<List<Feed>>() {}.getType();
Type folderList = new TypeToken<List<Folder>>() {}.getType();
Type rssItemsList = new TypeToken<List<RssItem>>() {}.getType();
Type ocsUser = new TypeToken<OcsUser>() {}.getType();
// Info: RssItems are handled as a stream (to be more memory efficient - see @OwnCloudSyncService and @RssItemObservable)
return new GsonBuilder()
.setLenient()
.registerTypeAdapter(folderList, new NextcloudDeserializer<>(Types.FOLDERS.toString(), Folder.class))
.registerTypeAdapter(feedList, new NextcloudDeserializer<>(Types.FEEDS.toString(), Feed.class))
.registerTypeAdapter(rssItemsList, new NextcloudDeserializer<>(Types.ITEMS.toString(), RssItem.class))
.registerTypeAdapter(UserInfo.class, (JsonDeserializer<UserInfo>) (json, typeOfT, context) -> {
try {
JsonObject jObj = json.getAsJsonObject();
JsonElement avatar = jObj.get("avatar");
byte[] decodedString = {};
if (!avatar.isJsonNull()) {
decodedString = Base64.decode(avatar.getAsJsonObject().get("data").getAsString(), Base64.DEFAULT);
}
return new UserInfo.Builder()
.setDisplayName(jObj.get("displayName").getAsString())
.setUserId(jObj.get("userId").getAsString())
.setAvatar(BitmapFactory.decodeByteArray(decodedString, 0, decodedString.length))
.setLastLoginTimestamp(jObj.get("lastLoginTimestamp").getAsLong())
.build();
} catch(IllegalStateException ex) {
throw OkHttpSSLClient.HandleExceptions(ex);
}
})
.registerTypeAdapter(folderList, new NextcloudNewsDeserializer<>(Types.FOLDERS.toString(), Folder.class))
.registerTypeAdapter(feedList, new NextcloudNewsDeserializer<>(Types.FEEDS.toString(), Feed.class))
.registerTypeAdapter(rssItemsList, new NextcloudNewsDeserializer<>(Types.ITEMS.toString(), RssItem.class))
.registerTypeAdapter(ocsUser, new NextcloudServerDeserializer<>("ocsUser", OcsUser.class))
.create();
}

View file

@ -0,0 +1,55 @@
package de.luhmer.owncloudnewsreader.model;
import java.io.Serializable;
/**
* thanks to stefan and artur
* https://github.com/stefan-niedermann/nextcloud-deck/blob/master/app/src/main/java/it/niedermann/nextcloud/deck/model/ocs/user/OcsUser.java
*/
public class OcsUser implements Serializable {
private static final long serialVersionUID = 1L;
String id;
String displayName;
public OcsUser() { }
public OcsUser(String id, String displayName) {
this.id = id;
this.displayName = displayName;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getDisplayName() {
return displayName;
}
public void setDisplayName(String displayName) {
this.displayName = displayName;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
OcsUser ocsUser = (OcsUser) o;
if (id != null ? !id.equals(ocsUser.id) : ocsUser.id != null) return false;
return displayName != null ? displayName.equals(ocsUser.displayName) : ocsUser.displayName == null;
}
@Override
public int hashCode() {
int result = id != null ? id.hashCode() : 0;
result = 31 * result + (displayName != null ? displayName.hashCode() : 0);
return result;
}
}

View file

@ -1,54 +0,0 @@
package de.luhmer.owncloudnewsreader.model;
import android.graphics.Bitmap;
import java.io.Serializable;
/**
* Created by dluhmer on 19.03.16.
*/
public class UserInfo implements Serializable {
public static class Builder {
private String userId;
private String displayName;
private Bitmap avatar;
private Long lastLoginTimestamp;
public Builder setUserId(String userId) {
this.userId = userId;
return this;
}
public Builder setDisplayName(String displayName) {
this.displayName = displayName;
return this;
}
public Builder setAvatar(Bitmap avatar) {
this.avatar = avatar;
return this;
}
public Builder setLastLoginTimestamp(Long lastLoginTimestamp) {
this.lastLoginTimestamp = lastLoginTimestamp;
return this;
}
public UserInfo build() {
return new UserInfo(userId, displayName, avatar, lastLoginTimestamp);
}
}
private UserInfo(String userId, String displayName, Bitmap avatar, Long lastLoginTimestamp) {
this.userId = userId;
this.displayName = displayName;
this.avatar = avatar;
this.lastLoginTimestamp = lastLoginTimestamp;
}
public final String userId;
public final String displayName;
public final Bitmap avatar;
public final Long lastLoginTimestamp;
}

View file

@ -12,33 +12,33 @@ import de.luhmer.owncloudnewsreader.reader.FeedItemTags;
public class ItemStateSync {
public static boolean PerformItemStateSync(API api, DatabaseConnectionOrm dbConn) throws IOException {
public static boolean PerformItemStateSync(NewsAPI newsApi, DatabaseConnectionOrm dbConn) throws IOException {
boolean successful;
//Mark as READ
List<String> itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewReadRssItems());
boolean result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_READ, dbConn, api);
boolean result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_READ, dbConn, newsApi);
if(result)
dbConn.change_readUnreadStateOfItem(itemIds, true);
successful = result;
//Mark as UNREAD
itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewUnreadRssItems());
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_UNREAD, dbConn, api);
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_UNREAD, dbConn, newsApi);
if(result)
dbConn.change_readUnreadStateOfItem(itemIds, false);
successful &= result;
//Mark as STARRED
itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewStarredRssItems());
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_STARRED, dbConn, api);
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_STARRED, dbConn, newsApi);
if(result)
dbConn.changeStarrUnstarrStateOfItem(itemIds, true);
successful &= result;
//Mark as UNSTARRED
itemIds = dbConn.getRssItemsIdsFromList(dbConn.getAllNewUnstarredRssItems());
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_UNSTARRED, dbConn, api);
result = PerformTagExecution(itemIds, FeedItemTags.MARK_ITEM_AS_UNSTARRED, dbConn, newsApi);
if(result)
dbConn.changeStarrUnstarrStateOfItem(itemIds, false);
successful &= result;
@ -46,20 +46,20 @@ public class ItemStateSync {
return successful;
}
private static boolean PerformTagExecution(List<String> itemIds, FeedItemTags tag, DatabaseConnectionOrm dbConn, API api) throws IOException {
private static boolean PerformTagExecution(List<String> itemIds, FeedItemTags tag, DatabaseConnectionOrm dbConn, NewsAPI newsApi) throws IOException {
if(itemIds.size() <= 0) { // Nothing to sync --> Skip
return true;
}
switch(tag) {
case MARK_ITEM_AS_READ:
return api.markItemsRead(new ItemIds(itemIds)).execute().isSuccessful();
return newsApi.markItemsRead(new ItemIds(itemIds)).execute().isSuccessful();
case MARK_ITEM_AS_UNREAD:
return api.markItemsUnread(new ItemIds(itemIds)).execute().isSuccessful();
return newsApi.markItemsUnread(new ItemIds(itemIds)).execute().isSuccessful();
case MARK_ITEM_AS_STARRED:
return api.markItemsStarred(new ItemMap(itemIds, dbConn)).execute().isSuccessful();
return newsApi.markItemsStarred(new ItemMap(itemIds, dbConn)).execute().isSuccessful();
case MARK_ITEM_AS_UNSTARRED:
return api.markItemsUnstarred(new ItemMap(itemIds, dbConn)).execute().isSuccessful();
return newsApi.markItemsUnstarred(new ItemMap(itemIds, dbConn)).execute().isSuccessful();
}
return false;
}

View file

@ -8,7 +8,6 @@ import de.luhmer.owncloudnewsreader.database.model.Folder;
import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.model.NextcloudNewsVersion;
import de.luhmer.owncloudnewsreader.model.NextcloudStatus;
import de.luhmer.owncloudnewsreader.model.UserInfo;
import io.reactivex.Completable;
import io.reactivex.Observable;
import okhttp3.ResponseBody;
@ -29,22 +28,16 @@ import retrofit2.http.Streaming;
*/
public interface API {
public interface NewsAPI {
String mApiEndpoint = "/index.php/apps/news/api/v1-2/";
/** Since 6.0.5 **/
@GET("user")
Observable<UserInfo> user();
@GET("status")
Observable<NextcloudStatus> status();
@GET("version")
Observable<NextcloudNewsVersion> version();
/** FOLDERS **/
@GET("folders")
Observable<List<Folder>> folders();
@ -105,6 +98,4 @@ public interface API {
@PUT("items/unstar/multiple")
Call<Void> markItemsUnstarred(@Body ItemMap itemMap);
}

View file

@ -14,23 +14,24 @@ import java.util.List;
import de.luhmer.owncloudnewsreader.database.model.Feed;
import de.luhmer.owncloudnewsreader.database.model.Folder;
import de.luhmer.owncloudnewsreader.database.model.RssItem;
import de.luhmer.owncloudnewsreader.model.OcsUser;
/**
* Created by david on 24.05.17.
*/
public class NextcloudDeserializer<T> implements JsonDeserializer<List<T>> {
public class NextcloudNewsDeserializer<T> implements JsonDeserializer<List<T>> {
private final String mKey;
private final Class<T> mType;
public NextcloudDeserializer(String key, Class<T> type) {
public NextcloudNewsDeserializer(String key, Class<T> type) {
this.mKey = key;
this.mType = type;
}
public static final String TAG = NextcloudDeserializer.class.getCanonicalName();
public static final String TAG = NextcloudNewsDeserializer.class.getCanonicalName();
@Override
public List<T> deserialize(final JsonElement json, final Type typeOfT, final JsonDeserializationContext context) throws JsonParseException {
@ -45,6 +46,8 @@ public class NextcloudDeserializer<T> implements JsonDeserializer<List<T>> {
items.add((T) parseFeed(jArr.get(i).getAsJsonObject()));
} else if(mType == RssItem.class) {
items.add((T) InsertRssItemIntoDatabase.parseItem(jArr.get(i).getAsJsonObject()));
} else if(mType == OcsUser.class) {
items.add((T) this.parseOcsUser(jArr.get(i).getAsJsonObject()));
}
//items.add(gson.fromJson(jArr.get(i), mType));
@ -66,6 +69,20 @@ public class NextcloudDeserializer<T> implements JsonDeserializer<List<T>> {
}
*/
private static OcsUser parseOcsUser(JsonObject obj) {
OcsUser ocsUser = new OcsUser();
JsonElement data = obj.get("ocs").getAsJsonObject().get("data");
if (!data.isJsonNull()) {
JsonObject user = data.getAsJsonObject();
if (user.has("id")) {
ocsUser.setId(user.get("id").getAsString());
}
if (user.has("displayname")) {
ocsUser.setDisplayName(user.get("displayname").getAsString());
}
}
return ocsUser;
}
private Folder parseFolder(JsonObject e)
{
@ -81,7 +98,14 @@ public class NextcloudDeserializer<T> implements JsonDeserializer<List<T>> {
Feed feed = new Feed();
feed.setId(e.get("id").getAsLong());
feed.setFolderId(e.get("folderId").getAsLong());
JsonElement folderId = e.get("folderId");
if(folderId.isJsonNull()) {
feed.setFolderId(0L);
} else {
feed.setFolderId(folderId.getAsLong());
}
feed.setFaviconUrl(faviconLink);
//Possible XSS fields

View file

@ -0,0 +1,54 @@
package de.luhmer.owncloudnewsreader.reader.nextcloud;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import java.lang.reflect.Type;
import de.luhmer.owncloudnewsreader.model.OcsUser;
/**
* Created by david on 24.05.17.
*/
public class NextcloudServerDeserializer<T> implements JsonDeserializer<T> {
private final String mKey;
private final Class<T> mType;
public NextcloudServerDeserializer(String key, Class<T> type) {
this.mKey = key;
this.mType = type;
}
public static final String TAG = NextcloudServerDeserializer.class.getCanonicalName();
@Override
public T deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
if(typeOfT == OcsUser.class) {
return (T) this.parseOcsUser(json.getAsJsonObject());
}
return null;
}
private static OcsUser parseOcsUser(JsonObject obj) {
OcsUser ocsUser = new OcsUser();
JsonElement data = obj.get("ocs").getAsJsonObject().get("data");
if (!data.isJsonNull()) {
JsonObject user = data.getAsJsonObject();
if (user.has("id")) {
ocsUser.setId(user.get("id").getAsString());
}
if (user.has("displayname")) {
ocsUser.setDisplayName(user.get("displayname").getAsString());
} else if (user.has("display-name")) {
ocsUser.setDisplayName(user.get("display-name").getAsString());
}
}
return ocsUser;
}
}

View file

@ -0,0 +1,14 @@
package de.luhmer.owncloudnewsreader.reader.nextcloud;
import de.luhmer.owncloudnewsreader.model.OcsUser;
import io.reactivex.Observable;
import retrofit2.http.GET;
public interface OcsAPI {
String mApiEndpoint = "/ocs/v2.php/";
@GET("cloud/user?format=json")
Observable<OcsUser> user();
}

View file

@ -36,14 +36,14 @@ import okio.BufferedSource;
public class RssItemObservable implements Publisher<Integer> {
private DatabaseConnectionOrm mDbConn;
private API mApi;
private NewsAPI mNewsApi;
private SharedPreferences mPrefs;
private static final String TAG = RssItemObservable.class.getCanonicalName();
private static int maxSizePerSync = 300;
public RssItemObservable(DatabaseConnectionOrm dbConn, API api, SharedPreferences prefs) {
public RssItemObservable(DatabaseConnectionOrm dbConn, NewsAPI newsApi, SharedPreferences prefs) {
this.mDbConn = dbConn;
this.mApi = api;
this.mNewsApi = newsApi;
this.mPrefs = prefs;
}
@ -80,7 +80,7 @@ public class RssItemObservable implements Publisher<Integer> {
do {
Log.v(TAG, "offset=" + offset + ", requestCount=" + requestCount + "");
List<RssItem> buffer = (mApi.items(maxSyncSize, offset, Integer.parseInt(FeedItemTags.ALL.toString()), 0, false, true).execute().body());
List<RssItem> buffer = (mNewsApi.items(maxSyncSize, offset, Integer.parseInt(FeedItemTags.ALL.toString()), 0, false, true).execute().body());
requestCount = 0;
if(buffer != null) {
@ -103,7 +103,7 @@ public class RssItemObservable implements Publisher<Integer> {
offset = 0;
do {
List<RssItem> buffer = mApi.items(maxSyncSize, offset, Integer.parseInt(FeedItemTags.ALL_STARRED.toString()), 0, false, true).execute().body();
List<RssItem> buffer = mNewsApi.items(maxSyncSize, offset, Integer.parseInt(FeedItemTags.ALL_STARRED.toString()), 0, false, true).execute().body();
requestCount = 0;
if(buffer != null) {
requestCount = buffer.size();
@ -125,7 +125,7 @@ public class RssItemObservable implements Publisher<Integer> {
//long highestItemIdBeforeSync = mDbConn.getHighestItemId();
//Get all updated items
mApi.updatedItems(lastModified, Integer.parseInt(FeedItemTags.ALL.toString()), 0)
mNewsApi.updatedItems(lastModified, Integer.parseInt(FeedItemTags.ALL.toString()), 0)
.flatMap((Function<ResponseBody, ObservableSource<RssItem>>) responseBody -> events(responseBody.source()))
.subscribe(new Observer<RssItem>() {
int totalUpdatedUnreadItemCount = 0;

View file

@ -63,7 +63,7 @@ public class SyncItemStateService extends JobIntentService {
@Override
protected void onHandleWork(Intent intent) {
if(mApi.getAPI() == null) {
if(mApi.getNewsAPI() == null) {
Log.w(TAG, "API is not initialized");
return;
}
@ -71,7 +71,7 @@ public class SyncItemStateService extends JobIntentService {
final DatabaseConnectionOrm dbConn = new DatabaseConnectionOrm(this);
try {
boolean success = ItemStateSync.PerformItemStateSync(mApi.getAPI(), dbConn);
boolean success = ItemStateSync.PerformItemStateSync(mApi.getNewsAPI(), dbConn);
Log.v(TAG, "SyncItemStateService finished. Success: " + success);
} catch (IOException e) {
e.printStackTrace();