mirror of https://github.com/readrops/Readrops.git
Merge branch 'feature/di' into develop
This commit is contained in:
commit
02a0702aac
|
@ -49,6 +49,7 @@ dependencies {
|
||||||
androidTestImplementation 'androidx.test:rules:1.3.0'
|
androidTestImplementation 'androidx.test:rules:1.3.0'
|
||||||
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
|
||||||
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.9.0'
|
androidTestImplementation 'com.squareup.okhttp3:mockwebserver:4.9.0'
|
||||||
|
testImplementation "org.koin:koin-test:2.1.6"
|
||||||
|
|
||||||
implementation 'com.gitlab.mvysny.konsume-xml:konsume-xml:0.12'
|
implementation 'com.gitlab.mvysny.konsume-xml:konsume-xml:0.12'
|
||||||
|
|
||||||
|
|
|
@ -4,13 +4,13 @@ import android.accounts.NetworkErrorException
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import androidx.test.ext.junit.runners.AndroidJUnit4
|
import androidx.test.ext.junit.runners.AndroidJUnit4
|
||||||
import androidx.test.platform.app.InstrumentationRegistry
|
import androidx.test.platform.app.InstrumentationRegistry
|
||||||
import com.readrops.api.utils.HttpManager
|
|
||||||
import com.readrops.api.utils.LibUtils
|
import com.readrops.api.utils.LibUtils
|
||||||
import com.readrops.api.utils.ParseException
|
import com.readrops.api.utils.ParseException
|
||||||
import com.readrops.api.utils.UnknownFormatException
|
import com.readrops.api.utils.UnknownFormatException
|
||||||
import junit.framework.TestCase.*
|
import junit.framework.TestCase.*
|
||||||
import okhttp3.Headers
|
import okhttp3.Headers
|
||||||
import okhttp3.HttpUrl
|
import okhttp3.HttpUrl
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
import okhttp3.mockwebserver.MockResponse
|
import okhttp3.mockwebserver.MockResponse
|
||||||
import okhttp3.mockwebserver.MockWebServer
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
import okio.Buffer
|
import okio.Buffer
|
||||||
|
@ -28,7 +28,7 @@ class LocalRSSDataSourceTest {
|
||||||
private lateinit var url: HttpUrl
|
private lateinit var url: HttpUrl
|
||||||
|
|
||||||
private val mockServer: MockWebServer = MockWebServer()
|
private val mockServer: MockWebServer = MockWebServer()
|
||||||
private val localRSSDataSource = LocalRSSDataSource(HttpManager.getInstance().okHttpClient)
|
private val localRSSDataSource = LocalRSSDataSource(OkHttpClient())
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
fun before() {
|
fun before() {
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.readrops.api.utils
|
||||||
|
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSCredentials
|
||||||
|
import junit.framework.TestCase.assertEquals
|
||||||
|
import junit.framework.TestCase.assertNull
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import okhttp3.Request
|
||||||
|
import okhttp3.mockwebserver.MockResponse
|
||||||
|
import okhttp3.mockwebserver.MockWebServer
|
||||||
|
import org.junit.After
|
||||||
|
import org.junit.Before
|
||||||
|
import org.junit.Test
|
||||||
|
|
||||||
|
class AuthInterceptorTest {
|
||||||
|
|
||||||
|
private val interceptor = AuthInterceptor()
|
||||||
|
private val mockServer = MockWebServer()
|
||||||
|
private lateinit var okHttpClient: OkHttpClient
|
||||||
|
|
||||||
|
@Before
|
||||||
|
fun before() {
|
||||||
|
okHttpClient = OkHttpClient.Builder().addInterceptor(interceptor).build()
|
||||||
|
mockServer.start(8080)
|
||||||
|
}
|
||||||
|
|
||||||
|
@After
|
||||||
|
fun tearDown() {
|
||||||
|
mockServer.close()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun credentialsUrlTest() {
|
||||||
|
mockServer.enqueue(MockResponse())
|
||||||
|
interceptor.credentials = FreshRSSCredentials("token", "http://localhost:8080/rss")
|
||||||
|
|
||||||
|
okHttpClient.newCall(Request.Builder().url(mockServer.url("/url")).build()).execute()
|
||||||
|
val request = mockServer.takeRequest()
|
||||||
|
|
||||||
|
assertEquals(request.requestUrl.toString(), "http://localhost:8080/rss/url")
|
||||||
|
assertEquals(request.headers["Authorization"], "GoogleLogin auth=token")
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun nullCredentialsTest() {
|
||||||
|
mockServer.enqueue(MockResponse())
|
||||||
|
interceptor.credentials = null
|
||||||
|
|
||||||
|
okHttpClient.newCall(Request.Builder().url(mockServer.url("/url")).build()).execute()
|
||||||
|
val request = mockServer.takeRequest()
|
||||||
|
|
||||||
|
assertEquals(request.requestUrl.toString(), "http://localhost:8080/url")
|
||||||
|
assertNull(request.headers["Authorization"])
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,102 @@
|
||||||
|
package com.readrops.api
|
||||||
|
|
||||||
|
import com.readrops.api.localfeed.LocalRSSDataSource
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSDataSource
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSService
|
||||||
|
import com.readrops.api.services.freshrss.adapters.FreshRSSFeedsAdapter
|
||||||
|
import com.readrops.api.services.freshrss.adapters.FreshRSSFoldersAdapter
|
||||||
|
import com.readrops.api.services.freshrss.adapters.FreshRSSItemsAdapter
|
||||||
|
import com.readrops.api.services.nextcloudnews.NextNewsDataSource
|
||||||
|
import com.readrops.api.services.nextcloudnews.NextNewsService
|
||||||
|
import com.readrops.api.services.nextcloudnews.adapters.NextNewsFeedsAdapter
|
||||||
|
import com.readrops.api.services.nextcloudnews.adapters.NextNewsFoldersAdapter
|
||||||
|
import com.readrops.api.services.nextcloudnews.adapters.NextNewsItemsAdapter
|
||||||
|
import com.readrops.api.utils.AuthInterceptor
|
||||||
|
import com.readrops.db.entities.Item
|
||||||
|
import com.squareup.moshi.Moshi
|
||||||
|
import com.squareup.moshi.Types
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.koin.core.qualifier.named
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import retrofit2.Retrofit
|
||||||
|
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory
|
||||||
|
import retrofit2.converter.moshi.MoshiConverterFactory
|
||||||
|
import java.util.concurrent.TimeUnit
|
||||||
|
|
||||||
|
val apiModule = module {
|
||||||
|
|
||||||
|
single(createdAtStart = true) {
|
||||||
|
OkHttpClient.Builder()
|
||||||
|
.callTimeout(1, TimeUnit.MINUTES)
|
||||||
|
.readTimeout(1, TimeUnit.HOURS)
|
||||||
|
.addInterceptor(get<AuthInterceptor>())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
single { LocalRSSDataSource(get()) }
|
||||||
|
|
||||||
|
//region freshrss
|
||||||
|
|
||||||
|
single {
|
||||||
|
FreshRSSDataSource(get<FreshRSSService>())
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
get<Retrofit>(named("freshrssRetrofit"))
|
||||||
|
.create(FreshRSSService::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
single(named("freshrssRetrofit")) {
|
||||||
|
get<Retrofit.Builder>()
|
||||||
|
.addConverterFactory(MoshiConverterFactory.create(get<Moshi>(named("freshrssMoshi"))))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
single(named("freshrssMoshi")) {
|
||||||
|
Moshi.Builder()
|
||||||
|
.add(Types.newParameterizedType(List::class.java, Item::class.java), FreshRSSItemsAdapter())
|
||||||
|
.add(FreshRSSFeedsAdapter())
|
||||||
|
.add(FreshRSSFoldersAdapter())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion freshrss
|
||||||
|
|
||||||
|
//region nextcloud news
|
||||||
|
|
||||||
|
single {
|
||||||
|
NextNewsDataSource(get<NextNewsService>())
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
get<Retrofit>(named("nextcloudNewsRetrofit"))
|
||||||
|
.create(NextNewsService::class.java)
|
||||||
|
}
|
||||||
|
|
||||||
|
single(named("nextcloudNewsRetrofit")) {
|
||||||
|
get<Retrofit.Builder>()
|
||||||
|
.addConverterFactory(MoshiConverterFactory.create(get<Moshi>(named("nextcloudNewsMoshi"))))
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
single(named("nextcloudNewsMoshi")) {
|
||||||
|
Moshi.Builder()
|
||||||
|
.add(NextNewsFeedsAdapter())
|
||||||
|
.add(NextNewsFoldersAdapter())
|
||||||
|
.add(Types.newParameterizedType(List::class.java, Item::class.java), NextNewsItemsAdapter())
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
|
||||||
|
//endregion nextcloud news
|
||||||
|
|
||||||
|
single {
|
||||||
|
Retrofit.Builder() // url will be set dynamically in an interceptor
|
||||||
|
.baseUrl("https://baseurl.com")
|
||||||
|
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
||||||
|
.client(get<OkHttpClient>())
|
||||||
|
}
|
||||||
|
|
||||||
|
single {
|
||||||
|
AuthInterceptor()
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
package com.readrops.api.services;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
|
||||||
|
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
import com.squareup.moshi.Moshi;
|
|
||||||
|
|
||||||
import retrofit2.Retrofit;
|
|
||||||
import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory;
|
|
||||||
import retrofit2.converter.moshi.MoshiConverterFactory;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Abstraction level for services APIs
|
|
||||||
*
|
|
||||||
* @param <T> an API service interface
|
|
||||||
*/
|
|
||||||
public abstract class API<T> {
|
|
||||||
|
|
||||||
protected static final int MAX_ITEMS = 5000;
|
|
||||||
|
|
||||||
protected T api;
|
|
||||||
private Retrofit retrofit;
|
|
||||||
|
|
||||||
private Class<T> clazz;
|
|
||||||
private String endPoint;
|
|
||||||
|
|
||||||
public API(Credentials credentials, @NonNull Class<T> clazz, @NonNull String endPoint) {
|
|
||||||
this.clazz = clazz;
|
|
||||||
this.endPoint = endPoint;
|
|
||||||
|
|
||||||
api = createAPI(credentials);
|
|
||||||
}
|
|
||||||
|
|
||||||
protected abstract Moshi buildMoshi();
|
|
||||||
|
|
||||||
protected Retrofit getConfiguredRetrofitInstance() {
|
|
||||||
return new Retrofit.Builder()
|
|
||||||
.baseUrl(HttpManager.getInstance().getCredentials().getUrl() + endPoint)
|
|
||||||
.addConverterFactory(MoshiConverterFactory.create(buildMoshi()))
|
|
||||||
.addCallAdapterFactory(RxJava2CallAdapterFactory.create())
|
|
||||||
.client(HttpManager.getInstance().getOkHttpClient())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
private T createAPI(@NonNull Credentials credentials) {
|
|
||||||
HttpManager.getInstance().setCredentials(credentials);
|
|
||||||
retrofit = getConfiguredRetrofitInstance();
|
|
||||||
|
|
||||||
return retrofit.create(clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCredentials(@NonNull Credentials credentials) {
|
|
||||||
HttpManager.getInstance().setCredentials(credentials);
|
|
||||||
|
|
||||||
retrofit = retrofit.newBuilder()
|
|
||||||
.baseUrl(credentials.getUrl() + endPoint)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
api = retrofit.create(clazz);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,16 +1,17 @@
|
||||||
package com.readrops.api.services;
|
package com.readrops.api.services;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.readrops.db.entities.account.Account;
|
|
||||||
import com.readrops.api.services.freshrss.FreshRSSCredentials;
|
import com.readrops.api.services.freshrss.FreshRSSCredentials;
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSService;
|
||||||
import com.readrops.api.services.nextcloudnews.NextNewsCredentials;
|
import com.readrops.api.services.nextcloudnews.NextNewsCredentials;
|
||||||
|
import com.readrops.api.services.nextcloudnews.NextNewsService;
|
||||||
|
import com.readrops.db.entities.account.Account;
|
||||||
|
import com.readrops.db.entities.account.AccountType;
|
||||||
|
|
||||||
public abstract class Credentials {
|
public abstract class Credentials {
|
||||||
|
|
||||||
private String authorization;
|
private final String authorization;
|
||||||
|
|
||||||
private String url;
|
private final String url;
|
||||||
|
|
||||||
public Credentials(String authorization, String url) {
|
public Credentials(String authorization, String url) {
|
||||||
this.authorization = authorization;
|
this.authorization = authorization;
|
||||||
|
@ -25,15 +26,27 @@ public abstract class Credentials {
|
||||||
return url;
|
return url;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
|
||||||
public static Credentials toCredentials(Account account) {
|
public static Credentials toCredentials(Account account) {
|
||||||
|
String endPoint = getEndPoint(account.getAccountType());
|
||||||
|
|
||||||
switch (account.getAccountType()) {
|
switch (account.getAccountType()) {
|
||||||
case NEXTCLOUD_NEWS:
|
case NEXTCLOUD_NEWS:
|
||||||
return new NextNewsCredentials(account.getLogin(), account.getPassword(), account.getUrl());
|
return new NextNewsCredentials(account.getLogin(), account.getPassword(), account.getUrl() + endPoint);
|
||||||
case FRESHRSS:
|
case FRESHRSS:
|
||||||
return new FreshRSSCredentials(account.getToken(), account.getUrl());
|
return new FreshRSSCredentials(account.getToken(), account.getUrl() + endPoint);
|
||||||
default:
|
default:
|
||||||
return null;
|
throw new IllegalArgumentException("Unknown account type");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static String getEndPoint(AccountType accountType) {
|
||||||
|
switch (accountType) {
|
||||||
|
case FRESHRSS:
|
||||||
|
return FreshRSSService.END_POINT;
|
||||||
|
case NEXTCLOUD_NEWS:
|
||||||
|
return NextNewsService.END_POINT;
|
||||||
|
default:
|
||||||
|
throw new IllegalArgumentException("Unknown account type");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,19 +3,12 @@ package com.readrops.api.services.freshrss;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.readrops.api.services.SyncResult;
|
||||||
|
import com.readrops.api.services.SyncType;
|
||||||
|
import com.readrops.api.services.freshrss.json.FreshRSSUserInfo;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
import com.readrops.api.services.API;
|
|
||||||
import com.readrops.api.services.Credentials;
|
|
||||||
import com.readrops.api.services.SyncResult;
|
|
||||||
import com.readrops.api.services.SyncType;
|
|
||||||
import com.readrops.api.services.freshrss.adapters.FreshRSSFeedsAdapter;
|
|
||||||
import com.readrops.api.services.freshrss.adapters.FreshRSSFoldersAdapter;
|
|
||||||
import com.readrops.api.services.freshrss.adapters.FreshRSSItemsAdapter;
|
|
||||||
import com.readrops.api.services.freshrss.json.FreshRSSUserInfo;
|
|
||||||
import com.squareup.moshi.Moshi;
|
|
||||||
import com.squareup.moshi.Types;
|
|
||||||
|
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -26,23 +19,18 @@ import io.reactivex.Single;
|
||||||
import okhttp3.MultipartBody;
|
import okhttp3.MultipartBody;
|
||||||
import okhttp3.RequestBody;
|
import okhttp3.RequestBody;
|
||||||
|
|
||||||
public class FreshRSSAPI extends API<FreshRSSService> {
|
public class FreshRSSDataSource {
|
||||||
|
|
||||||
|
private static final int MAX_ITEMS = 5000;
|
||||||
|
|
||||||
public static final String GOOGLE_READ = "user/-/state/com.google/read";
|
public static final String GOOGLE_READ = "user/-/state/com.google/read";
|
||||||
|
|
||||||
private static final String FEED_PREFIX = "feed/";
|
private static final String FEED_PREFIX = "feed/";
|
||||||
|
|
||||||
public FreshRSSAPI(Credentials credentials) {
|
private FreshRSSService api;
|
||||||
super(credentials, FreshRSSService.class, FreshRSSService.END_POINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public FreshRSSDataSource(FreshRSSService api) {
|
||||||
protected Moshi buildMoshi() {
|
this.api = api;
|
||||||
return new Moshi.Builder()
|
|
||||||
.add(Types.newParameterizedType(List.class, Item.class), new FreshRSSItemsAdapter())
|
|
||||||
.add(new FreshRSSFeedsAdapter())
|
|
||||||
.add(new FreshRSSFoldersAdapter())
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
|
@ -2,7 +2,7 @@ package com.readrops.api.services.freshrss.adapters
|
||||||
|
|
||||||
import android.util.TimingLogger
|
import android.util.TimingLogger
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import com.readrops.api.services.freshrss.FreshRSSAPI.GOOGLE_READ
|
import com.readrops.api.services.freshrss.FreshRSSDataSource.GOOGLE_READ
|
||||||
import com.squareup.moshi.JsonAdapter
|
import com.squareup.moshi.JsonAdapter
|
||||||
import com.squareup.moshi.JsonReader
|
import com.squareup.moshi.JsonReader
|
||||||
import com.squareup.moshi.JsonWriter
|
import com.squareup.moshi.JsonWriter
|
||||||
|
|
|
@ -5,6 +5,6 @@ import com.readrops.api.services.Credentials;
|
||||||
public class NextNewsCredentials extends Credentials {
|
public class NextNewsCredentials extends Credentials {
|
||||||
|
|
||||||
public NextNewsCredentials(String login, String password, String url) {
|
public NextNewsCredentials(String login, String password, String url) {
|
||||||
super(okhttp3.Credentials.basic(login, password), url);
|
super(login != null && password != null ? okhttp3.Credentials.basic(login, password) : null, url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,22 +5,15 @@ import android.content.res.Resources;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.readrops.db.entities.Feed;
|
|
||||||
import com.readrops.db.entities.Folder;
|
|
||||||
import com.readrops.db.entities.Item;
|
|
||||||
import com.readrops.api.services.API;
|
|
||||||
import com.readrops.api.services.Credentials;
|
|
||||||
import com.readrops.api.services.SyncResult;
|
import com.readrops.api.services.SyncResult;
|
||||||
import com.readrops.api.services.SyncType;
|
import com.readrops.api.services.SyncType;
|
||||||
import com.readrops.api.services.nextcloudnews.adapters.NextNewsFeedsAdapter;
|
|
||||||
import com.readrops.api.services.nextcloudnews.adapters.NextNewsFoldersAdapter;
|
|
||||||
import com.readrops.api.services.nextcloudnews.adapters.NextNewsItemsAdapter;
|
|
||||||
import com.readrops.api.services.nextcloudnews.json.NextNewsUser;
|
import com.readrops.api.services.nextcloudnews.json.NextNewsUser;
|
||||||
import com.readrops.api.utils.ConflictException;
|
import com.readrops.api.utils.ConflictException;
|
||||||
import com.readrops.api.utils.LibUtils;
|
import com.readrops.api.utils.LibUtils;
|
||||||
import com.readrops.api.utils.UnknownFormatException;
|
import com.readrops.api.utils.UnknownFormatException;
|
||||||
import com.squareup.moshi.Moshi;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.squareup.moshi.Types;
|
import com.readrops.db.entities.Folder;
|
||||||
|
import com.readrops.db.entities.Item;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
|
@ -30,21 +23,16 @@ import java.util.Map;
|
||||||
|
|
||||||
import retrofit2.Response;
|
import retrofit2.Response;
|
||||||
|
|
||||||
public class NextNewsAPI extends API<NextNewsService> {
|
public class NextNewsDataSource {
|
||||||
|
|
||||||
private static final String TAG = NextNewsAPI.class.getSimpleName();
|
private static final String TAG = NextNewsDataSource.class.getSimpleName();
|
||||||
|
|
||||||
public NextNewsAPI(Credentials credentials) {
|
protected static final int MAX_ITEMS = 5000;
|
||||||
super(credentials, NextNewsService.class, NextNewsService.END_POINT);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
private NextNewsService api;
|
||||||
protected Moshi buildMoshi() {
|
|
||||||
return new Moshi.Builder()
|
public NextNewsDataSource(NextNewsService api) {
|
||||||
.add(new NextNewsFeedsAdapter())
|
this.api = api;
|
||||||
.add(new NextNewsFoldersAdapter())
|
|
||||||
.add(Types.newParameterizedType(List.class, Item.class), new NextNewsItemsAdapter())
|
|
||||||
.build();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
|
@ -0,0 +1,35 @@
|
||||||
|
package com.readrops.api.utils
|
||||||
|
|
||||||
|
import android.net.Uri
|
||||||
|
import com.readrops.api.services.Credentials
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSService
|
||||||
|
import com.readrops.api.services.nextcloudnews.NextNewsService
|
||||||
|
import com.readrops.db.entities.account.Account
|
||||||
|
import com.readrops.db.entities.account.AccountType
|
||||||
|
import okhttp3.Interceptor
|
||||||
|
import okhttp3.Response
|
||||||
|
import java.lang.IllegalArgumentException
|
||||||
|
|
||||||
|
class AuthInterceptor(var credentials: Credentials? = null) : Interceptor {
|
||||||
|
|
||||||
|
override fun intercept(chain: Interceptor.Chain): Response {
|
||||||
|
val requestBuilder = chain.request().newBuilder()
|
||||||
|
val urlBuilder = chain.request().url.newBuilder()
|
||||||
|
|
||||||
|
if (credentials != null) {
|
||||||
|
if (credentials!!.url != null) {
|
||||||
|
val uri = Uri.parse(credentials!!.url)
|
||||||
|
urlBuilder
|
||||||
|
.scheme(uri.scheme!!)
|
||||||
|
.host(uri.host!!)
|
||||||
|
.encodedPath(uri.encodedPath + chain.request().url.encodedPath)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (credentials!!.authorization != null) {
|
||||||
|
requestBuilder.addHeader("Authorization", credentials!!.authorization)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return chain.proceed(requestBuilder.url(urlBuilder.build()).build())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,77 +0,0 @@
|
||||||
package com.readrops.api.utils;
|
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
|
||||||
|
|
||||||
import com.readrops.api.services.Credentials;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import okhttp3.Interceptor;
|
|
||||||
import okhttp3.OkHttpClient;
|
|
||||||
import okhttp3.Request;
|
|
||||||
import okhttp3.Response;
|
|
||||||
|
|
||||||
public class HttpManager {
|
|
||||||
|
|
||||||
private OkHttpClient okHttpClient;
|
|
||||||
private Credentials credentials;
|
|
||||||
|
|
||||||
public HttpManager() {
|
|
||||||
buildOkHttp();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void buildOkHttp() {
|
|
||||||
okHttpClient = new OkHttpClient.Builder()
|
|
||||||
.callTimeout(1, TimeUnit.MINUTES)
|
|
||||||
.readTimeout(1, TimeUnit.HOURS)
|
|
||||||
.addInterceptor(new AuthInterceptor())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
public OkHttpClient getOkHttpClient() {
|
|
||||||
return okHttpClient;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setCredentials(@Nullable Credentials credentials) {
|
|
||||||
this.credentials = credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Credentials getCredentials() {
|
|
||||||
return credentials;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static HttpManager instance;
|
|
||||||
|
|
||||||
public static HttpManager getInstance() {
|
|
||||||
if (instance == null) {
|
|
||||||
instance = new HttpManager();
|
|
||||||
}
|
|
||||||
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void setInstance(OkHttpClient client) {
|
|
||||||
instance.okHttpClient = client;
|
|
||||||
}
|
|
||||||
|
|
||||||
public class AuthInterceptor implements Interceptor {
|
|
||||||
|
|
||||||
public AuthInterceptor() {
|
|
||||||
// empty constructor
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Response intercept(Chain chain) throws IOException {
|
|
||||||
Request request = chain.request();
|
|
||||||
|
|
||||||
if (credentials != null && credentials.getAuthorization() != null) {
|
|
||||||
request = request.newBuilder()
|
|
||||||
.addHeader("Authorization", credentials.getAuthorization())
|
|
||||||
.build();
|
|
||||||
}
|
|
||||||
|
|
||||||
return chain.proceed(request);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -76,6 +76,7 @@ dependencies {
|
||||||
implementation "androidx.work:work-runtime-ktx:2.4.0"
|
implementation "androidx.work:work-runtime-ktx:2.4.0"
|
||||||
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
implementation "androidx.fragment:fragment-ktx:1.2.5"
|
||||||
implementation "androidx.browser:browser:1.2.0"
|
implementation "androidx.browser:browser:1.2.0"
|
||||||
|
testImplementation "org.koin:koin-test:2.1.6"
|
||||||
|
|
||||||
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
implementation 'com.github.bumptech.glide:glide:4.11.0'
|
||||||
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
kapt 'com.github.bumptech.glide:compiler:4.11.0'
|
||||||
|
|
|
@ -13,13 +13,10 @@ import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
|
||||||
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
|
import com.facebook.flipper.plugins.inspector.DescriptorMapping;
|
||||||
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
|
import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
|
||||||
import com.facebook.flipper.plugins.navigation.NavigationFlipperPlugin;
|
import com.facebook.flipper.plugins.navigation.NavigationFlipperPlugin;
|
||||||
import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
|
|
||||||
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
|
import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
|
||||||
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
|
import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
|
||||||
import com.facebook.soloader.SoLoader;
|
import com.facebook.soloader.SoLoader;
|
||||||
import com.icapps.niddler.core.AndroidNiddler;
|
import com.icapps.niddler.core.AndroidNiddler;
|
||||||
import com.icapps.niddler.interceptor.okhttp.NiddlerOkHttpInterceptor;
|
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
|
|
||||||
public class ReadropsDebugApp extends ReadropsApp implements Configuration.Provider {
|
public class ReadropsDebugApp extends ReadropsApp implements Configuration.Provider {
|
||||||
|
|
||||||
|
@ -40,13 +37,6 @@ public class ReadropsDebugApp extends ReadropsApp implements Configuration.Provi
|
||||||
NetworkFlipperPlugin networkPlugin = new NetworkFlipperPlugin();
|
NetworkFlipperPlugin networkPlugin = new NetworkFlipperPlugin();
|
||||||
client.addPlugin(networkPlugin);
|
client.addPlugin(networkPlugin);
|
||||||
|
|
||||||
HttpManager.setInstance(
|
|
||||||
HttpManager.getInstance()
|
|
||||||
.getOkHttpClient()
|
|
||||||
.newBuilder()
|
|
||||||
.addInterceptor(new FlipperOkhttpInterceptor(networkPlugin))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
client.addPlugin(new DatabasesFlipperPlugin(this));
|
client.addPlugin(new DatabasesFlipperPlugin(this));
|
||||||
client.addPlugin(CrashReporterPlugin.getInstance());
|
client.addPlugin(CrashReporterPlugin.getInstance());
|
||||||
client.addPlugin(NavigationFlipperPlugin.getInstance());
|
client.addPlugin(NavigationFlipperPlugin.getInstance());
|
||||||
|
@ -65,12 +55,6 @@ public class ReadropsDebugApp extends ReadropsApp implements Configuration.Provi
|
||||||
|
|
||||||
niddler.attachToApplication(this);
|
niddler.attachToApplication(this);
|
||||||
|
|
||||||
HttpManager.setInstance(HttpManager.getInstance().
|
|
||||||
getOkHttpClient().
|
|
||||||
newBuilder().
|
|
||||||
addInterceptor(new NiddlerOkHttpInterceptor(niddler, "default"))
|
|
||||||
.build());
|
|
||||||
|
|
||||||
niddler.start();
|
niddler.start();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package com.readrops.app
|
||||||
|
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.readrops.app.repositories.FreshRSSRepository
|
||||||
|
import com.readrops.app.repositories.LocalFeedRepository
|
||||||
|
import com.readrops.app.repositories.NextNewsRepository
|
||||||
|
import com.readrops.app.utils.GlideApp
|
||||||
|
import com.readrops.app.viewmodels.*
|
||||||
|
import com.readrops.db.entities.account.Account
|
||||||
|
import com.readrops.db.entities.account.AccountType
|
||||||
|
import org.koin.android.ext.koin.androidApplication
|
||||||
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
import org.koin.androidx.viewmodel.dsl.viewModel
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
val appModule = module {
|
||||||
|
|
||||||
|
factory { (account: Account) ->
|
||||||
|
when (account.accountType) {
|
||||||
|
AccountType.LOCAL -> LocalFeedRepository(get(), get(), androidContext(), account)
|
||||||
|
AccountType.NEXTCLOUD_NEWS -> NextNewsRepository(get(), get(), androidContext(), account)
|
||||||
|
AccountType.FRESHRSS -> FreshRSSRepository(get(), get(), androidContext(), account)
|
||||||
|
else -> throw IllegalArgumentException("Account type not supported")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
MainViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
AddFeedsViewModel(get(), get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
ItemViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
ManageFeedsFoldersViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
NotificationPermissionViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
viewModel {
|
||||||
|
AccountViewModel(get())
|
||||||
|
}
|
||||||
|
|
||||||
|
single { GlideApp.with(androidApplication()) }
|
||||||
|
|
||||||
|
single { PreferenceManager.getDefaultSharedPreferences(androidContext()) }
|
||||||
|
}
|
|
@ -1,61 +0,0 @@
|
||||||
package com.readrops.app;
|
|
||||||
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.app.Application;
|
|
||||||
import android.app.NotificationChannel;
|
|
||||||
import android.app.NotificationManager;
|
|
||||||
import android.os.Build;
|
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatDelegate;
|
|
||||||
import androidx.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import com.readrops.app.utils.SharedPreferencesManager;
|
|
||||||
|
|
||||||
import io.reactivex.plugins.RxJavaPlugins;
|
|
||||||
|
|
||||||
@SuppressLint("Registered")
|
|
||||||
public class ReadropsApp extends Application {
|
|
||||||
|
|
||||||
public static final String FEEDS_COLORS_CHANNEL_ID = "feedsColorsChannel";
|
|
||||||
public static final String OPML_EXPORT_CHANNEL_ID = "opmlExportChannel";
|
|
||||||
public static final String SYNC_CHANNEL_ID = "syncChannel";
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onCreate() {
|
|
||||||
super.onCreate();
|
|
||||||
|
|
||||||
RxJavaPlugins.setErrorHandler(e -> {
|
|
||||||
});
|
|
||||||
|
|
||||||
createNotificationChannels();
|
|
||||||
|
|
||||||
PreferenceManager.setDefaultValues(this, R.xml.preferences, false);
|
|
||||||
|
|
||||||
if (Boolean.valueOf(SharedPreferencesManager.readString(this, SharedPreferencesManager.SharedPrefKey.DARK_THEME)))
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES);
|
|
||||||
else
|
|
||||||
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createNotificationChannels() {
|
|
||||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
||||||
NotificationChannel feedsColorsChannel = new NotificationChannel(FEEDS_COLORS_CHANNEL_ID,
|
|
||||||
getString(R.string.feeds_colors), NotificationManager.IMPORTANCE_DEFAULT);
|
|
||||||
feedsColorsChannel.setDescription(getString(R.string.get_feeds_colors));
|
|
||||||
|
|
||||||
NotificationChannel opmlExportChannel = new NotificationChannel(OPML_EXPORT_CHANNEL_ID,
|
|
||||||
getString(R.string.opml_export), NotificationManager.IMPORTANCE_DEFAULT);
|
|
||||||
opmlExportChannel.setDescription(getString(R.string.opml_export_description));
|
|
||||||
|
|
||||||
NotificationChannel syncChannel = new NotificationChannel(SYNC_CHANNEL_ID,
|
|
||||||
getString(R.string.auto_synchro), NotificationManager.IMPORTANCE_LOW);
|
|
||||||
syncChannel.setDescription(getString(R.string.account_synchro));
|
|
||||||
|
|
||||||
NotificationManager manager = getSystemService(NotificationManager.class);
|
|
||||||
|
|
||||||
manager.createNotificationChannel(feedsColorsChannel);
|
|
||||||
manager.createNotificationChannel(opmlExportChannel);
|
|
||||||
manager.createNotificationChannel(syncChannel);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,68 @@
|
||||||
|
package com.readrops.app
|
||||||
|
|
||||||
|
import android.app.Application
|
||||||
|
import android.app.NotificationChannel
|
||||||
|
import android.app.NotificationManager
|
||||||
|
import android.os.Build
|
||||||
|
import androidx.appcompat.app.AppCompatDelegate
|
||||||
|
import androidx.preference.PreferenceManager
|
||||||
|
import com.readrops.api.apiModule
|
||||||
|
import com.readrops.app.utils.SharedPreferencesManager
|
||||||
|
import com.readrops.db.dbModule
|
||||||
|
import io.reactivex.plugins.RxJavaPlugins
|
||||||
|
import org.koin.android.ext.koin.androidContext
|
||||||
|
import org.koin.android.ext.koin.androidLogger
|
||||||
|
import org.koin.core.context.startKoin
|
||||||
|
import org.koin.core.logger.Level
|
||||||
|
|
||||||
|
open class ReadropsApp : Application() {
|
||||||
|
|
||||||
|
override fun onCreate() {
|
||||||
|
super.onCreate()
|
||||||
|
RxJavaPlugins.setErrorHandler { e: Throwable? -> }
|
||||||
|
|
||||||
|
createNotificationChannels()
|
||||||
|
PreferenceManager.setDefaultValues(this, R.xml.preferences, false)
|
||||||
|
|
||||||
|
startKoin {
|
||||||
|
androidLogger(Level.ERROR)
|
||||||
|
androidContext(this@ReadropsApp)
|
||||||
|
|
||||||
|
modules(apiModule, dbModule, appModule)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (SharedPreferencesManager.readString(SharedPreferencesManager.SharedPrefKey.DARK_THEME).toBoolean())
|
||||||
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_YES)
|
||||||
|
else
|
||||||
|
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_NO)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun createNotificationChannels() {
|
||||||
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
||||||
|
val feedsColorsChannel = NotificationChannel(FEEDS_COLORS_CHANNEL_ID,
|
||||||
|
getString(R.string.feeds_colors), NotificationManager.IMPORTANCE_DEFAULT)
|
||||||
|
feedsColorsChannel.description = getString(R.string.get_feeds_colors)
|
||||||
|
|
||||||
|
val opmlExportChannel = NotificationChannel(OPML_EXPORT_CHANNEL_ID,
|
||||||
|
getString(R.string.opml_export), NotificationManager.IMPORTANCE_DEFAULT)
|
||||||
|
opmlExportChannel.description = getString(R.string.opml_export_description)
|
||||||
|
|
||||||
|
val syncChannel = NotificationChannel(SYNC_CHANNEL_ID,
|
||||||
|
getString(R.string.auto_synchro), NotificationManager.IMPORTANCE_LOW)
|
||||||
|
syncChannel.description = getString(R.string.account_synchro)
|
||||||
|
|
||||||
|
val manager = getSystemService(NotificationManager::class.java)!!
|
||||||
|
|
||||||
|
manager.createNotificationChannel(feedsColorsChannel)
|
||||||
|
manager.createNotificationChannel(opmlExportChannel)
|
||||||
|
manager.createNotificationChannel(syncChannel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
const val FEEDS_COLORS_CHANNEL_ID = "feedsColorsChannel"
|
||||||
|
const val OPML_EXPORT_CHANNEL_ID = "opmlExportChannel"
|
||||||
|
const val SYNC_CHANNEL_ID = "syncChannel"
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -11,7 +11,6 @@ import android.widget.LinearLayout;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
|
@ -25,6 +24,8 @@ import com.readrops.app.viewmodels.AccountViewModel;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.entities.account.AccountType;
|
import com.readrops.db.entities.account.AccountType;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -55,7 +56,7 @@ public class AccountTypeListActivity extends AppCompatActivity {
|
||||||
binding = ActivityAccountTypeListBinding.inflate(getLayoutInflater());
|
binding = ActivityAccountTypeListBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(AccountViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, AccountViewModel.class);
|
||||||
|
|
||||||
setTitle(R.string.new_account);
|
setTitle(R.string.new_account);
|
||||||
|
|
||||||
|
@ -158,7 +159,7 @@ public class AccountTypeListActivity extends AppCompatActivity {
|
||||||
account.setId(id.intValue());
|
account.setId(id.intValue());
|
||||||
viewModel.setAccount(account);
|
viewModel.setAccount(account);
|
||||||
|
|
||||||
return viewModel.parseOPMLFile(uri);
|
return viewModel.parseOPMLFile(uri, this);
|
||||||
})
|
})
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
|
|
|
@ -8,7 +8,6 @@ import android.view.MenuItem;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.databinding.ActivityAddAccountBinding;
|
import com.readrops.app.databinding.ActivityAddAccountBinding;
|
||||||
|
@ -18,6 +17,8 @@ import com.readrops.app.viewmodels.AccountViewModel;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.entities.account.AccountType;
|
import com.readrops.db.entities.account.AccountType;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.CompletableObserver;
|
import io.reactivex.CompletableObserver;
|
||||||
import io.reactivex.SingleObserver;
|
import io.reactivex.SingleObserver;
|
||||||
|
@ -46,7 +47,7 @@ public class AddAccountActivity extends AppCompatActivity {
|
||||||
binding = ActivityAddAccountBinding.inflate(getLayoutInflater());
|
binding = ActivityAddAccountBinding.inflate(getLayoutInflater());
|
||||||
setContentView(binding.getRoot());
|
setContentView(binding.getRoot());
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(AccountViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, AccountViewModel.class);
|
||||||
|
|
||||||
accountType = getIntent().getParcelableExtra(ACCOUNT_TYPE);
|
accountType = getIntent().getParcelableExtra(ACCOUNT_TYPE);
|
||||||
|
|
||||||
|
@ -58,26 +59,20 @@ public class AddAccountActivity extends AppCompatActivity {
|
||||||
if (forwardResult || accountToEdit != null)
|
if (forwardResult || accountToEdit != null)
|
||||||
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
|
||||||
|
|
||||||
try {
|
if (accountToEdit != null) {
|
||||||
if (accountToEdit != null) {
|
viewModel.setAccountType(accountToEdit.getAccountType());
|
||||||
viewModel.setAccountType(accountToEdit.getAccountType());
|
editAccount = true;
|
||||||
editAccount = true;
|
fillFields();
|
||||||
fillFields();
|
} else {
|
||||||
} else {
|
viewModel.setAccountType(accountType);
|
||||||
viewModel.setAccountType(accountType);
|
|
||||||
|
|
||||||
binding.providerImage.setImageResource(accountType.getIconRes());
|
binding.providerImage.setImageResource(accountType.getIconRes());
|
||||||
binding.providerName.setText(accountType.getName());
|
binding.providerName.setText(accountType.getName());
|
||||||
binding.addAccountName.setText(accountType.getName());
|
binding.addAccountName.setText(accountType.getName());
|
||||||
if (accountType == AccountType.FRESHRSS) {
|
if (accountType == AccountType.FRESHRSS) {
|
||||||
binding.addAccountPasswordLayout.setHelperText(getString(R.string.password_helper));
|
binding.addAccountPasswordLayout.setHelperText(getString(R.string.password_helper));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
|
||||||
// TODO : see how to handle this exception
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void createAccount(View view) {
|
public void createAccount(View view) {
|
||||||
|
@ -183,8 +178,8 @@ public class AddAccountActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void saveLoginPassword(Account account) {
|
private void saveLoginPassword(Account account) {
|
||||||
SharedPreferencesManager.writeValue(this, account.getLoginKey(), account.getLogin());
|
SharedPreferencesManager.writeValue(account.getLoginKey(), account.getLogin());
|
||||||
SharedPreferencesManager.writeValue(this, account.getPasswordKey(), account.getPassword());
|
SharedPreferencesManager.writeValue(account.getPasswordKey(), account.getPassword());
|
||||||
|
|
||||||
account.setLogin(null);
|
account.setLogin(null);
|
||||||
account.setPassword(null);
|
account.setPassword(null);
|
||||||
|
@ -196,8 +191,8 @@ public class AddAccountActivity extends AppCompatActivity {
|
||||||
|
|
||||||
binding.addAccountUrl.setText(accountToEdit.getUrl());
|
binding.addAccountUrl.setText(accountToEdit.getUrl());
|
||||||
binding.addAccountName.setText(accountToEdit.getAccountName());
|
binding.addAccountName.setText(accountToEdit.getAccountName());
|
||||||
binding.addAccountLogin.setText(SharedPreferencesManager.readString(this, accountToEdit.getLoginKey()));
|
binding.addAccountLogin.setText(SharedPreferencesManager.readString(accountToEdit.getLoginKey()));
|
||||||
binding.addAccountPassword.setText(SharedPreferencesManager.readString(this, accountToEdit.getPasswordKey()));
|
binding.addAccountPassword.setText(SharedPreferencesManager.readString(accountToEdit.getPasswordKey()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateAccount() {
|
private void updateAccount() {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.view.View;
|
||||||
|
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.recyclerview.widget.DiffUtil;
|
import androidx.recyclerview.widget.DiffUtil;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
@ -33,6 +32,8 @@ import com.readrops.app.viewmodels.AddFeedsViewModel;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
@ -69,7 +70,7 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||||
binding.addFeedOk.setOnClickListener(this);
|
binding.addFeedOk.setOnClickListener(this);
|
||||||
binding.addFeedOk.setEnabled(false);
|
binding.addFeedOk.setEnabled(false);
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(AddFeedsViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, AddFeedsViewModel.class);
|
||||||
|
|
||||||
parseItemsAdapter = new ItemAdapter<>();
|
parseItemsAdapter = new ItemAdapter<>();
|
||||||
fastAdapter = FastAdapter.with(parseItemsAdapter);
|
fastAdapter = FastAdapter.with(parseItemsAdapter);
|
||||||
|
@ -259,8 +260,8 @@ public class AddFeedActivity extends AppCompatActivity implements View.OnClickLi
|
||||||
|
|
||||||
Account account = (Account) binding.addFeedAccountSpinner.getSelectedItem();
|
Account account = (Account) binding.addFeedAccountSpinner.getSelectedItem();
|
||||||
|
|
||||||
account.setLogin(SharedPreferencesManager.readString(this, account.getLoginKey()));
|
account.setLogin(SharedPreferencesManager.readString(account.getLoginKey()));
|
||||||
account.setPassword(SharedPreferencesManager.readString(this, account.getPasswordKey()));
|
account.setPassword(SharedPreferencesManager.readString(account.getPasswordKey()));
|
||||||
|
|
||||||
viewModel.addFeeds(feedsToInsert, account)
|
viewModel.addFeeds(feedsToInsert, account)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
|
@ -25,16 +25,15 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.browser.customtabs.CustomTabsIntent;
|
import androidx.browser.customtabs.CustomTabsIntent;
|
||||||
import androidx.core.app.ActivityCompat;
|
import androidx.core.app.ActivityCompat;
|
||||||
import androidx.core.app.ShareCompat;
|
import androidx.core.app.ShareCompat;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.bumptech.glide.request.target.CustomTarget;
|
import com.bumptech.glide.request.target.CustomTarget;
|
||||||
import com.bumptech.glide.request.transition.Transition;
|
import com.bumptech.glide.request.transition.Transition;
|
||||||
|
import com.readrops.api.utils.DateUtils;
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.databinding.ActivityItemBinding;
|
import com.readrops.app.databinding.ActivityItemBinding;
|
||||||
import com.readrops.api.utils.DateUtils;
|
import com.readrops.app.utils.GlideRequests;
|
||||||
import com.readrops.app.utils.GlideApp;
|
|
||||||
import com.readrops.app.utils.PermissionManager;
|
import com.readrops.app.utils.PermissionManager;
|
||||||
import com.readrops.app.utils.SharedPreferencesManager;
|
import com.readrops.app.utils.SharedPreferencesManager;
|
||||||
import com.readrops.app.utils.Utils;
|
import com.readrops.app.utils.Utils;
|
||||||
|
@ -42,6 +41,9 @@ import com.readrops.app.viewmodels.ItemViewModel;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
import com.readrops.db.pojo.ItemWithFeed;
|
import com.readrops.db.pojo.ItemWithFeed;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -92,7 +94,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
binding.appBarLayout.setExpanded(true);
|
binding.appBarLayout.setExpanded(true);
|
||||||
binding.collapsingLayout.setTitleEnabled(true);
|
binding.collapsingLayout.setTitleEnabled(true);
|
||||||
|
|
||||||
GlideApp.with(this)
|
KoinJavaComponent.get(GlideRequests.class)
|
||||||
.load(imageUrl)
|
.load(imageUrl)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.into(binding.collapsingLayoutImage);
|
.into(binding.collapsingLayoutImage);
|
||||||
|
@ -110,7 +112,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
invalidateOptionsMenu();
|
invalidateOptionsMenu();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(ItemViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, ItemViewModel.class);
|
||||||
viewModel.getItemById(itemId).observe(this, this::bindUI);
|
viewModel.getItemById(itemId).observe(this, this::bindUI);
|
||||||
binding.activityItemFab.setOnClickListener(v -> openInNavigator());
|
binding.activityItemFab.setOnClickListener(v -> openInNavigator());
|
||||||
}
|
}
|
||||||
|
@ -214,7 +216,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openUrl() {
|
private void openUrl() {
|
||||||
int value = Integer.parseInt(SharedPreferencesManager.readString(this,
|
int value = Integer.parseInt(SharedPreferencesManager.readString(
|
||||||
SharedPreferencesManager.SharedPrefKey.OPEN_ITEMS_IN));
|
SharedPreferencesManager.SharedPrefKey.OPEN_ITEMS_IN));
|
||||||
switch (value) {
|
switch (value) {
|
||||||
case 0:
|
case 0:
|
||||||
|
@ -243,7 +245,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void openInCustomTab() {
|
private void openInCustomTab() {
|
||||||
boolean darkTheme = Boolean.parseBoolean(SharedPreferencesManager.readString(this, SharedPreferencesManager.SharedPrefKey.DARK_THEME));
|
boolean darkTheme = Boolean.parseBoolean(SharedPreferencesManager.readString(SharedPreferencesManager.SharedPrefKey.DARK_THEME));
|
||||||
int color = itemWithFeed.getBgColor() != 0 ? itemWithFeed.getBgColor() : itemWithFeed.getColor();
|
int color = itemWithFeed.getBgColor() != 0 ? itemWithFeed.getBgColor() : itemWithFeed.getColor();
|
||||||
|
|
||||||
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
|
CustomTabsIntent customTabsIntent = new CustomTabsIntent.Builder()
|
||||||
|
@ -357,7 +359,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void shareImage(String url) {
|
private void shareImage(String url) {
|
||||||
GlideApp.with(this)
|
KoinJavaComponent.get(GlideRequests.class)
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.load(url)
|
.load(url)
|
||||||
|
@ -365,7 +367,7 @@ public class ItemActivity extends AppCompatActivity {
|
||||||
@Override
|
@Override
|
||||||
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
public void onResourceReady(@NonNull Bitmap resource, @Nullable Transition<? super Bitmap> transition) {
|
||||||
try {
|
try {
|
||||||
Uri uri = viewModel.saveImageInCache(resource);
|
Uri uri = viewModel.saveImageInCache(resource, ItemActivity.this);
|
||||||
Intent intent = ShareCompat.IntentBuilder.from(ItemActivity.this)
|
Intent intent = ShareCompat.IntentBuilder.from(ItemActivity.this)
|
||||||
.setType("image/png")
|
.setType("image/png")
|
||||||
.setStream(uri)
|
.setStream(uri)
|
||||||
|
|
|
@ -16,7 +16,6 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.core.content.ContextCompat;
|
import androidx.core.content.ContextCompat;
|
||||||
import androidx.core.graphics.drawable.DrawableCompat;
|
import androidx.core.graphics.drawable.DrawableCompat;
|
||||||
import androidx.drawerlayout.widget.DrawerLayout;
|
import androidx.drawerlayout.widget.DrawerLayout;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.paging.PagedList;
|
import androidx.paging.PagedList;
|
||||||
import androidx.recyclerview.widget.DividerItemDecoration;
|
import androidx.recyclerview.widget.DividerItemDecoration;
|
||||||
import androidx.recyclerview.widget.ItemTouchHelper;
|
import androidx.recyclerview.widget.ItemTouchHelper;
|
||||||
|
@ -38,7 +37,7 @@ import com.readrops.app.R;
|
||||||
import com.readrops.app.adapters.MainItemListAdapter;
|
import com.readrops.app.adapters.MainItemListAdapter;
|
||||||
import com.readrops.app.databinding.ActivityMainBinding;
|
import com.readrops.app.databinding.ActivityMainBinding;
|
||||||
import com.readrops.app.utils.DrawerManager;
|
import com.readrops.app.utils.DrawerManager;
|
||||||
import com.readrops.app.utils.GlideApp;
|
import com.readrops.app.utils.GlideRequests;
|
||||||
import com.readrops.app.utils.ReadropsItemTouchCallback;
|
import com.readrops.app.utils.ReadropsItemTouchCallback;
|
||||||
import com.readrops.app.utils.SharedPreferencesManager;
|
import com.readrops.app.utils.SharedPreferencesManager;
|
||||||
import com.readrops.app.utils.Utils;
|
import com.readrops.app.utils.Utils;
|
||||||
|
@ -51,6 +50,8 @@ import com.readrops.db.filters.ListSortType;
|
||||||
import com.readrops.db.pojo.ItemWithFeed;
|
import com.readrops.db.pojo.ItemWithFeed;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -116,9 +117,9 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
||||||
feedCount = 0;
|
feedCount = 0;
|
||||||
initRecyclerView();
|
initRecyclerView();
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(MainViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, MainViewModel.class);
|
||||||
|
|
||||||
viewModel.setShowReadItems(SharedPreferencesManager.readBoolean(this,
|
viewModel.setShowReadItems(SharedPreferencesManager.readBoolean(
|
||||||
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES));
|
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES));
|
||||||
|
|
||||||
viewModel.getItemsWithFeed().observe(this, itemWithFeeds -> {
|
viewModel.getItemsWithFeed().observe(this, itemWithFeeds -> {
|
||||||
|
@ -300,7 +301,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
||||||
|
|
||||||
private void initRecyclerView() {
|
private void initRecyclerView() {
|
||||||
ViewPreloadSizeProvider preloadSizeProvider = new ViewPreloadSizeProvider();
|
ViewPreloadSizeProvider preloadSizeProvider = new ViewPreloadSizeProvider();
|
||||||
adapter = new MainItemListAdapter(GlideApp.with(this), preloadSizeProvider);
|
adapter = new MainItemListAdapter(KoinJavaComponent.get(GlideRequests.class), preloadSizeProvider);
|
||||||
adapter.setOnItemClickListener(new MainItemListAdapter.OnItemClickListener() {
|
adapter.setOnItemClickListener(new MainItemListAdapter.OnItemClickListener() {
|
||||||
@Override
|
@Override
|
||||||
public void onItemClick(ItemWithFeed itemWithFeed, int position) {
|
public void onItemClick(ItemWithFeed itemWithFeed, int position) {
|
||||||
|
@ -349,7 +350,7 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
||||||
|
|
||||||
binding.itemsRecyclerView.setRecyclerListener(viewHolder -> {
|
binding.itemsRecyclerView.setRecyclerListener(viewHolder -> {
|
||||||
MainItemListAdapter.ItemViewHolder vh = (MainItemListAdapter.ItemViewHolder) viewHolder;
|
MainItemListAdapter.ItemViewHolder vh = (MainItemListAdapter.ItemViewHolder) viewHolder;
|
||||||
GlideApp.with(this).clear(vh.getItemImage());
|
KoinJavaComponent.get(GlideRequests.class).clear(vh.getItemImage());
|
||||||
});
|
});
|
||||||
|
|
||||||
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
|
||||||
|
@ -659,12 +660,12 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
||||||
if (item.isChecked()) {
|
if (item.isChecked()) {
|
||||||
item.setChecked(false);
|
item.setChecked(false);
|
||||||
viewModel.setShowReadItems(false);
|
viewModel.setShowReadItems(false);
|
||||||
SharedPreferencesManager.writeValue(this,
|
SharedPreferencesManager.writeValue(
|
||||||
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES, false);
|
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES, false);
|
||||||
} else {
|
} else {
|
||||||
item.setChecked(true);
|
item.setChecked(true);
|
||||||
viewModel.setShowReadItems(true);
|
viewModel.setShowReadItems(true);
|
||||||
SharedPreferencesManager.writeValue(this,
|
SharedPreferencesManager.writeValue(
|
||||||
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES, true);
|
SharedPreferencesManager.SharedPrefKey.SHOW_READ_ARTICLES, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -708,16 +709,16 @@ public class MainActivity extends AppCompatActivity implements SwipeRefreshLayou
|
||||||
private void getAccountCredentials(List<Account> accounts) {
|
private void getAccountCredentials(List<Account> accounts) {
|
||||||
for (Account account : accounts) {
|
for (Account account : accounts) {
|
||||||
if (account.getLogin() == null)
|
if (account.getLogin() == null)
|
||||||
account.setLogin(SharedPreferencesManager.readString(this, account.getLoginKey()));
|
account.setLogin(SharedPreferencesManager.readString(account.getLoginKey()));
|
||||||
|
|
||||||
if (account.getPassword() == null)
|
if (account.getPassword() == null)
|
||||||
account.setPassword(SharedPreferencesManager.readString(this, account.getPasswordKey()));
|
account.setPassword(SharedPreferencesManager.readString(account.getPasswordKey()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void startAboutActivity() {
|
private void startAboutActivity() {
|
||||||
Libs.ActivityStyle activityStyle;
|
Libs.ActivityStyle activityStyle;
|
||||||
if (Boolean.valueOf(SharedPreferencesManager.readString(this, SharedPreferencesManager.SharedPrefKey.DARK_THEME)))
|
if (Boolean.valueOf(SharedPreferencesManager.readString(SharedPreferencesManager.SharedPrefKey.DARK_THEME)))
|
||||||
activityStyle = Libs.ActivityStyle.DARK;
|
activityStyle = Libs.ActivityStyle.DARK;
|
||||||
else
|
else
|
||||||
activityStyle = Libs.ActivityStyle.LIGHT_DARK_TOOLBAR;
|
activityStyle = Libs.ActivityStyle.LIGHT_DARK_TOOLBAR;
|
||||||
|
|
|
@ -9,9 +9,10 @@ import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.fragment.app.FragmentManager;
|
import androidx.fragment.app.FragmentManager;
|
||||||
import androidx.fragment.app.FragmentPagerAdapter;
|
import androidx.fragment.app.FragmentPagerAdapter;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.readrops.api.utils.ConflictException;
|
||||||
|
import com.readrops.api.utils.UnknownFormatException;
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.databinding.ActivityManageFeedsFoldersBinding;
|
import com.readrops.app.databinding.ActivityManageFeedsFoldersBinding;
|
||||||
import com.readrops.app.fragments.FeedsFragment;
|
import com.readrops.app.fragments.FeedsFragment;
|
||||||
|
@ -20,8 +21,8 @@ import com.readrops.app.utils.Utils;
|
||||||
import com.readrops.app.viewmodels.ManageFeedsFoldersViewModel;
|
import com.readrops.app.viewmodels.ManageFeedsFoldersViewModel;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.api.utils.ConflictException;
|
|
||||||
import com.readrops.api.utils.UnknownFormatException;
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -52,7 +53,7 @@ public class ManageFeedsFoldersActivity extends AppCompatActivity {
|
||||||
binding.manageFeedsFoldersViewpager.setAdapter(pageAdapter);
|
binding.manageFeedsFoldersViewpager.setAdapter(pageAdapter);
|
||||||
binding.manageFeedsFoldersTablayout.setupWithViewPager(binding.manageFeedsFoldersViewpager);
|
binding.manageFeedsFoldersTablayout.setupWithViewPager(binding.manageFeedsFoldersViewpager);
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(ManageFeedsFoldersViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, ManageFeedsFoldersViewModel.class);
|
||||||
viewModel.setAccount(account);
|
viewModel.setAccount(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.readrops.app.activities
|
||||||
import android.content.Intent
|
import android.content.Intent
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.view.MenuItem
|
import android.view.MenuItem
|
||||||
import androidx.activity.viewModels
|
|
||||||
import androidx.appcompat.app.AppCompatActivity
|
import androidx.appcompat.app.AppCompatActivity
|
||||||
import androidx.lifecycle.Observer
|
import androidx.lifecycle.Observer
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager
|
import androidx.recyclerview.widget.LinearLayoutManager
|
||||||
|
@ -20,11 +19,12 @@ import com.readrops.db.entities.Feed
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers
|
import io.reactivex.android.schedulers.AndroidSchedulers
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.koin.androidx.viewmodel.ext.android.getViewModel
|
||||||
|
|
||||||
class NotificationPermissionActivity : AppCompatActivity() {
|
class NotificationPermissionActivity : AppCompatActivity() {
|
||||||
|
|
||||||
private lateinit var binding: ActivityNotificationPermissionBinding
|
private lateinit var binding: ActivityNotificationPermissionBinding
|
||||||
private val viewModel by viewModels<NotificationPermissionViewModel>()
|
private val viewModel = getViewModel<NotificationPermissionViewModel>()
|
||||||
private var adapter: NotificationPermissionListAdapter? = null
|
private var adapter: NotificationPermissionListAdapter? = null
|
||||||
|
|
||||||
private var isFirstCheck = true
|
private var isFirstCheck = true
|
||||||
|
@ -120,7 +120,7 @@ class NotificationPermissionActivity : AppCompatActivity() {
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun displayAutoSynchroPopup() {
|
private fun displayAutoSynchroPopup() {
|
||||||
val autoSynchroValue = SharedPreferencesManager.readString(this, SharedPreferencesManager.SharedPrefKey.AUTO_SYNCHRO)
|
val autoSynchroValue = SharedPreferencesManager.readString(SharedPreferencesManager.SharedPrefKey.AUTO_SYNCHRO)
|
||||||
|
|
||||||
if (autoSynchroValue.toFloat() <= 0) {
|
if (autoSynchroValue.toFloat() <= 0) {
|
||||||
MaterialDialog.Builder(this)
|
MaterialDialog.Builder(this)
|
||||||
|
|
|
@ -4,11 +4,12 @@ import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
|
|
||||||
import androidx.appcompat.app.AppCompatActivity;
|
import androidx.appcompat.app.AppCompatActivity;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.viewmodels.AccountViewModel;
|
import com.readrops.app.viewmodels.AccountViewModel;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.observers.DisposableSingleObserver;
|
import io.reactivex.observers.DisposableSingleObserver;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -22,7 +23,7 @@ public class SplashActivity extends AppCompatActivity {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
setContentView(R.layout.activity_splash);
|
setContentView(R.layout.activity_splash);
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(AccountViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, AccountViewModel.class);
|
||||||
|
|
||||||
viewModel.getAccountCount()
|
viewModel.getAccountCount()
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
|
|
@ -13,9 +13,11 @@ import androidx.recyclerview.widget.RecyclerView;
|
||||||
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
import com.bumptech.glide.load.engine.DiskCacheStrategy;
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.databinding.FeedLayoutBinding;
|
import com.readrops.app.databinding.FeedLayoutBinding;
|
||||||
import com.readrops.app.utils.GlideApp;
|
import com.readrops.app.utils.GlideRequests;
|
||||||
import com.readrops.db.pojo.FeedWithFolder;
|
import com.readrops.db.pojo.FeedWithFolder;
|
||||||
|
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class FeedsAdapter extends ListAdapter<FeedWithFolder, FeedsAdapter.FeedViewHolder> {
|
public class FeedsAdapter extends ListAdapter<FeedWithFolder, FeedsAdapter.FeedViewHolder> {
|
||||||
|
@ -64,7 +66,7 @@ public class FeedsAdapter extends ListAdapter<FeedWithFolder, FeedsAdapter.FeedV
|
||||||
FeedWithFolder feedWithFolder = getItem(i);
|
FeedWithFolder feedWithFolder = getItem(i);
|
||||||
|
|
||||||
if (feedWithFolder.getFeed().getIconUrl() != null) {
|
if (feedWithFolder.getFeed().getIconUrl() != null) {
|
||||||
GlideApp.with(viewHolder.itemView.getContext())
|
KoinJavaComponent.get(GlideRequests.class)
|
||||||
.load(feedWithFolder.getFeed().getIconUrl())
|
.load(feedWithFolder.getFeed().getIconUrl())
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.placeholder(R.drawable.ic_rss_feed_grey)
|
.placeholder(R.drawable.ic_rss_feed_grey)
|
||||||
|
|
|
@ -9,10 +9,13 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy
|
||||||
import com.readrops.app.R
|
import com.readrops.app.R
|
||||||
import com.readrops.app.databinding.NotificationPermissionLayoutBinding
|
import com.readrops.app.databinding.NotificationPermissionLayoutBinding
|
||||||
import com.readrops.app.utils.GlideApp
|
import com.readrops.app.utils.GlideApp
|
||||||
|
import com.readrops.app.utils.GlideRequests
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
|
|
||||||
class NotificationPermissionListAdapter(var enableAll: Boolean, val listener: (feed: Feed) -> Unit) :
|
class NotificationPermissionListAdapter(var enableAll: Boolean, val listener: (feed: Feed) -> Unit) :
|
||||||
ListAdapter<Feed, NotificationPermissionListAdapter.NotificationPermissionViewHolder>(DIFF_CALLBACK) {
|
ListAdapter<Feed, NotificationPermissionListAdapter.NotificationPermissionViewHolder>(DIFF_CALLBACK), KoinComponent {
|
||||||
|
|
||||||
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationPermissionViewHolder {
|
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): NotificationPermissionViewHolder {
|
||||||
val binding = NotificationPermissionLayoutBinding.inflate(LayoutInflater.from(parent.context))
|
val binding = NotificationPermissionLayoutBinding.inflate(LayoutInflater.from(parent.context))
|
||||||
|
@ -30,7 +33,7 @@ class NotificationPermissionListAdapter(var enableAll: Boolean, val listener: (f
|
||||||
|
|
||||||
holder.itemView.setOnClickListener { if (enableAll) listener(getItem(position)) }
|
holder.itemView.setOnClickListener { if (enableAll) listener(getItem(position)) }
|
||||||
|
|
||||||
GlideApp.with(holder.itemView.context)
|
get<GlideRequests>()
|
||||||
.load(feed.iconUrl)
|
.load(feed.iconUrl)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
.placeholder(R.drawable.ic_rss_feed_grey)
|
.placeholder(R.drawable.ic_rss_feed_grey)
|
||||||
|
|
|
@ -11,7 +11,6 @@ import android.widget.Spinner;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.DialogFragment;
|
import androidx.fragment.app.DialogFragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
|
|
||||||
import com.google.android.material.textfield.TextInputEditText;
|
import com.google.android.material.textfield.TextInputEditText;
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
|
@ -21,6 +20,8 @@ import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.pojo.FeedWithFolder;
|
import com.readrops.db.pojo.FeedWithFolder;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.SharedViewModelCompat;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.TreeMap;
|
import java.util.TreeMap;
|
||||||
|
@ -59,7 +60,7 @@ public class EditFeedDialogFragment extends DialogFragment implements AdapterVie
|
||||||
@NonNull
|
@NonNull
|
||||||
@Override
|
@Override
|
||||||
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
public Dialog onCreateDialog(@Nullable Bundle savedInstanceState) {
|
||||||
viewModel = new ViewModelProvider(getActivity()).get(ManageFeedsFoldersViewModel.class);
|
viewModel = SharedViewModelCompat.getSharedViewModel(this, ManageFeedsFoldersViewModel.class);
|
||||||
|
|
||||||
feedWithFolder = getArguments().getParcelable("feedWithFolder");
|
feedWithFolder = getArguments().getParcelable("feedWithFolder");
|
||||||
account = getArguments().getParcelable(ACCOUNT);
|
account = getArguments().getParcelable(ACCOUNT);
|
||||||
|
|
|
@ -10,7 +10,6 @@ import android.view.ViewGroup;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
@ -24,6 +23,8 @@ import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.pojo.FeedWithFolder;
|
import com.readrops.db.pojo.FeedWithFolder;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.SharedViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.observers.DisposableCompletableObserver;
|
import io.reactivex.observers.DisposableCompletableObserver;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -60,11 +61,11 @@ public class FeedsFragment extends Fragment {
|
||||||
account = getArguments().getParcelable(ACCOUNT);
|
account = getArguments().getParcelable(ACCOUNT);
|
||||||
|
|
||||||
if (account.getLogin() == null)
|
if (account.getLogin() == null)
|
||||||
account.setLogin(SharedPreferencesManager.readString(getContext(), account.getLoginKey()));
|
account.setLogin(SharedPreferencesManager.readString(account.getLoginKey()));
|
||||||
if (account.getPassword() == null)
|
if (account.getPassword() == null)
|
||||||
account.setPassword(SharedPreferencesManager.readString(getContext(), account.getPasswordKey()));
|
account.setPassword(SharedPreferencesManager.readString(account.getPasswordKey()));
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(ManageFeedsFoldersViewModel.class);
|
viewModel = SharedViewModelCompat.getSharedViewModel(this, ManageFeedsFoldersViewModel.class);
|
||||||
viewModel.setAccount(account);
|
viewModel.setAccount(account);
|
||||||
|
|
||||||
viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> {
|
viewModel.getFeedsWithFolder().observe(this, feedWithFolders -> {
|
||||||
|
|
|
@ -10,10 +10,11 @@ import android.view.ViewGroup;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||||
|
|
||||||
import com.afollestad.materialdialogs.MaterialDialog;
|
import com.afollestad.materialdialogs.MaterialDialog;
|
||||||
|
import com.readrops.api.utils.ConflictException;
|
||||||
|
import com.readrops.api.utils.UnknownFormatException;
|
||||||
import com.readrops.app.R;
|
import com.readrops.app.R;
|
||||||
import com.readrops.app.adapters.FoldersAdapter;
|
import com.readrops.app.adapters.FoldersAdapter;
|
||||||
import com.readrops.app.databinding.FragmentFoldersBinding;
|
import com.readrops.app.databinding.FragmentFoldersBinding;
|
||||||
|
@ -22,8 +23,8 @@ import com.readrops.app.utils.Utils;
|
||||||
import com.readrops.app.viewmodels.ManageFeedsFoldersViewModel;
|
import com.readrops.app.viewmodels.ManageFeedsFoldersViewModel;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.api.utils.ConflictException;
|
|
||||||
import com.readrops.api.utils.UnknownFormatException;
|
import org.koin.androidx.viewmodel.compat.SharedViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.observers.DisposableSingleObserver;
|
import io.reactivex.observers.DisposableSingleObserver;
|
||||||
|
@ -60,12 +61,12 @@ public class FoldersFragment extends Fragment {
|
||||||
account = getArguments().getParcelable(ACCOUNT);
|
account = getArguments().getParcelable(ACCOUNT);
|
||||||
|
|
||||||
if (account.getLogin() == null)
|
if (account.getLogin() == null)
|
||||||
account.setLogin(SharedPreferencesManager.readString(getContext(), account.getLoginKey()));
|
account.setLogin(SharedPreferencesManager.readString(account.getLoginKey()));
|
||||||
if (account.getPassword() == null)
|
if (account.getPassword() == null)
|
||||||
account.setPassword(SharedPreferencesManager.readString(getContext(), account.getPasswordKey()));
|
account.setPassword(SharedPreferencesManager.readString(account.getPasswordKey()));
|
||||||
|
|
||||||
adapter = new FoldersAdapter(this::openFolderOptionsDialog);
|
adapter = new FoldersAdapter(this::openFolderOptionsDialog);
|
||||||
viewModel = new ViewModelProvider(this).get(ManageFeedsFoldersViewModel.class);
|
viewModel = SharedViewModelCompat.getSharedViewModel(this, ManageFeedsFoldersViewModel.class);
|
||||||
|
|
||||||
viewModel.setAccount(account);
|
viewModel.setAccount(account);
|
||||||
viewModel.getFeedCountByAccount()
|
viewModel.getFeedCountByAccount()
|
||||||
|
|
|
@ -16,7 +16,6 @@ import androidx.annotation.Nullable;
|
||||||
import androidx.core.app.NotificationCompat;
|
import androidx.core.app.NotificationCompat;
|
||||||
import androidx.core.app.NotificationManagerCompat;
|
import androidx.core.app.NotificationManagerCompat;
|
||||||
import androidx.fragment.app.Fragment;
|
import androidx.fragment.app.Fragment;
|
||||||
import androidx.lifecycle.ViewModelProvider;
|
|
||||||
import androidx.preference.Preference;
|
import androidx.preference.Preference;
|
||||||
import androidx.preference.PreferenceFragmentCompat;
|
import androidx.preference.PreferenceFragmentCompat;
|
||||||
|
|
||||||
|
@ -36,6 +35,8 @@ import com.readrops.app.viewmodels.AccountViewModel;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.entities.account.AccountType;
|
import com.readrops.db.entities.account.AccountType;
|
||||||
|
|
||||||
|
import org.koin.androidx.viewmodel.compat.ViewModelCompat;
|
||||||
|
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.observers.DisposableCompletableObserver;
|
import io.reactivex.observers.DisposableCompletableObserver;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
@ -136,7 +137,7 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
|
||||||
public void onCreate(@Nullable Bundle savedInstanceState) {
|
public void onCreate(@Nullable Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
|
||||||
viewModel = new ViewModelProvider(this).get(AccountViewModel.class);
|
viewModel = ViewModelCompat.getViewModel(this, AccountViewModel.class);
|
||||||
viewModel.setAccount(account);
|
viewModel.setAccount(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -146,8 +147,8 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
|
||||||
.positiveText(R.string.validate)
|
.positiveText(R.string.validate)
|
||||||
.negativeText(R.string.cancel)
|
.negativeText(R.string.cancel)
|
||||||
.onPositive(((dialog, which) -> {
|
.onPositive(((dialog, which) -> {
|
||||||
SharedPreferencesManager.remove(getContext(), account.getLoginKey());
|
SharedPreferencesManager.remove(account.getLoginKey());
|
||||||
SharedPreferencesManager.remove(getContext(), account.getPasswordKey());
|
SharedPreferencesManager.remove(account.getPasswordKey());
|
||||||
|
|
||||||
viewModel.delete(account)
|
viewModel.delete(account)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
|
@ -204,7 +205,7 @@ public class AccountSettingsFragment extends PreferenceFragmentCompat {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void parseOPMLFile(Uri uri, MaterialDialog dialog) {
|
private void parseOPMLFile(Uri uri, MaterialDialog dialog) {
|
||||||
viewModel.parseOPMLFile(uri)
|
viewModel.parseOPMLFile(uri, getContext())
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.observeOn(AndroidSchedulers.mainThread())
|
.observeOn(AndroidSchedulers.mainThread())
|
||||||
.subscribe(new DisposableCompletableObserver() {
|
.subscribe(new DisposableCompletableObserver() {
|
||||||
|
|
|
@ -19,6 +19,8 @@ import com.readrops.app.utils.SyncWorker;
|
||||||
import com.readrops.app.utils.feedscolors.FeedsColorsIntentService;
|
import com.readrops.app.utils.feedscolors.FeedsColorsIntentService;
|
||||||
import com.readrops.db.Database;
|
import com.readrops.db.Database;
|
||||||
|
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
@ -38,7 +40,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
|
||||||
|
|
||||||
AtomicBoolean serviceStarted = new AtomicBoolean(false);
|
AtomicBoolean serviceStarted = new AtomicBoolean(false);
|
||||||
feedsColorsPreference.setOnPreferenceClickListener(preference -> {
|
feedsColorsPreference.setOnPreferenceClickListener(preference -> {
|
||||||
Database database = Database.getInstance(getContext());
|
Database database = KoinJavaComponent.get(Database.class);
|
||||||
|
|
||||||
database.feedDao().getAllFeeds().observe(getActivity(), feeds -> {
|
database.feedDao().getAllFeeds().observe(getActivity(), feeds -> {
|
||||||
if (!serviceStarted.get()) {
|
if (!serviceStarted.get()) {
|
||||||
|
|
|
@ -6,6 +6,9 @@ import android.content.Intent;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.readrops.api.services.Credentials;
|
||||||
|
import com.readrops.api.services.SyncResult;
|
||||||
|
import com.readrops.api.utils.AuthInterceptor;
|
||||||
import com.readrops.app.utils.FeedInsertionResult;
|
import com.readrops.app.utils.FeedInsertionResult;
|
||||||
import com.readrops.app.utils.ParsingResult;
|
import com.readrops.app.utils.ParsingResult;
|
||||||
import com.readrops.app.utils.feedscolors.FeedColorsKt;
|
import com.readrops.app.utils.feedscolors.FeedColorsKt;
|
||||||
|
@ -15,8 +18,8 @@ import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.entities.account.AccountType;
|
|
||||||
import com.readrops.api.services.SyncResult;
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Comparator;
|
import java.util.Comparator;
|
||||||
|
@ -30,25 +33,26 @@ import io.reactivex.Single;
|
||||||
|
|
||||||
import static com.readrops.app.utils.ReadropsKeys.FEEDS;
|
import static com.readrops.app.utils.ReadropsKeys.FEEDS;
|
||||||
|
|
||||||
public abstract class ARepository<T> {
|
public abstract class ARepository {
|
||||||
|
|
||||||
protected Context context;
|
protected Context context;
|
||||||
protected Database database;
|
protected Database database;
|
||||||
protected Account account;
|
protected Account account;
|
||||||
|
|
||||||
protected T api;
|
|
||||||
|
|
||||||
protected SyncResult syncResult;
|
protected SyncResult syncResult;
|
||||||
|
|
||||||
protected ARepository(@NonNull Context context, @Nullable Account account) {
|
protected ARepository(Database database, @NonNull Context context, @Nullable Account account) {
|
||||||
this.context = context;
|
this.context = context;
|
||||||
this.database = Database.getInstance(context);
|
this.database = database;
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
|
||||||
api = createAPI();
|
setCredentials(account);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract T createAPI();
|
protected void setCredentials(@Nullable Account account) {
|
||||||
|
KoinJavaComponent.get(AuthInterceptor.class)
|
||||||
|
.setCredentials(account != null && !account.isLocal() ? Credentials.toCredentials(account) : null);
|
||||||
|
}
|
||||||
|
|
||||||
// TODO : replace Single by Completable
|
// TODO : replace Single by Completable
|
||||||
public abstract Single<Boolean> login(Account account, boolean insert);
|
public abstract Single<Boolean> login(Account account, boolean insert);
|
||||||
|
@ -171,23 +175,6 @@ public abstract class ARepository<T> {
|
||||||
context.startService(intent);
|
context.startService(intent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static ARepository repositoryFactory(Account account, AccountType accountType, Context context) throws Exception {
|
|
||||||
switch (accountType) {
|
|
||||||
case LOCAL:
|
|
||||||
return new LocalFeedRepository(context, account);
|
|
||||||
case NEXTCLOUD_NEWS:
|
|
||||||
return new NextNewsRepository(context, account);
|
|
||||||
case FRESHRSS:
|
|
||||||
return new FreshRSSRepository(context, account);
|
|
||||||
default:
|
|
||||||
throw new Exception("account type not supported");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public static ARepository repositoryFactory(Account account, Context context) throws Exception {
|
|
||||||
return ARepository.repositoryFactory(account, account.getAccountType(), context);
|
|
||||||
}
|
|
||||||
|
|
||||||
public SyncResult getSyncResult() {
|
public SyncResult getSyncResult() {
|
||||||
return syncResult;
|
return syncResult;
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,18 +7,17 @@ import android.util.TimingLogger;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
|
import com.readrops.api.services.SyncType;
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSDataSource;
|
||||||
|
import com.readrops.api.services.freshrss.FreshRSSSyncData;
|
||||||
import com.readrops.app.utils.FeedInsertionResult;
|
import com.readrops.app.utils.FeedInsertionResult;
|
||||||
import com.readrops.app.utils.ParsingResult;
|
import com.readrops.app.utils.ParsingResult;
|
||||||
import com.readrops.app.utils.Utils;
|
import com.readrops.app.utils.Utils;
|
||||||
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.api.services.Credentials;
|
|
||||||
import com.readrops.api.services.SyncType;
|
|
||||||
import com.readrops.api.services.freshrss.FreshRSSAPI;
|
|
||||||
import com.readrops.api.services.freshrss.FreshRSSCredentials;
|
|
||||||
import com.readrops.api.services.freshrss.FreshRSSSyncData;
|
|
||||||
|
|
||||||
import org.joda.time.DateTime;
|
import org.joda.time.DateTime;
|
||||||
|
|
||||||
|
@ -30,40 +29,33 @@ import io.reactivex.Completable;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
|
public class FreshRSSRepository extends ARepository {
|
||||||
|
|
||||||
private static final String TAG = FreshRSSRepository.class.getSimpleName();
|
private static final String TAG = FreshRSSRepository.class.getSimpleName();
|
||||||
|
|
||||||
public FreshRSSRepository(@NonNull Context context, @Nullable Account account) {
|
private final FreshRSSDataSource dataSource;
|
||||||
super(context, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public FreshRSSRepository(FreshRSSDataSource dataSource, Database database, @NonNull Context context, @Nullable Account account) {
|
||||||
protected FreshRSSAPI createAPI() {
|
super(database, context, account);
|
||||||
if (account != null)
|
|
||||||
return new FreshRSSAPI(Credentials.toCredentials(account));
|
|
||||||
|
|
||||||
return null;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<Boolean> login(Account account, boolean insert) {
|
public Single<Boolean> login(Account account, boolean insert) {
|
||||||
if (api == null)
|
setCredentials(account);
|
||||||
api = new FreshRSSAPI(Credentials.toCredentials(account));
|
|
||||||
else
|
|
||||||
api.setCredentials(Credentials.toCredentials(account));
|
|
||||||
|
|
||||||
return api.login(account.getLogin(), account.getPassword())
|
return dataSource.login(account.getLogin(), account.getPassword())
|
||||||
.flatMap(token -> {
|
.flatMap(token -> {
|
||||||
account.setToken(token);
|
account.setToken(token);
|
||||||
api.setCredentials(new FreshRSSCredentials(token, account.getUrl()));
|
setCredentials(account);
|
||||||
|
|
||||||
return api.getWriteToken();
|
return dataSource.getWriteToken();
|
||||||
})
|
})
|
||||||
.flatMap(writeToken -> {
|
.flatMap(writeToken -> {
|
||||||
account.setWriteToken(writeToken);
|
account.setWriteToken(writeToken);
|
||||||
|
|
||||||
return api.getUserInfo();
|
return dataSource.getUserInfo();
|
||||||
})
|
})
|
||||||
.flatMap(userInfo -> {
|
.flatMap(userInfo -> {
|
||||||
account.setDisplayedName(userInfo.getUserName());
|
account.setDisplayedName(userInfo.getUserName());
|
||||||
|
@ -100,7 +92,7 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
|
||||||
syncData.setUnreadItemsIds(database.itemDao().getUnreadChanges(account.getId()));
|
syncData.setUnreadItemsIds(database.itemDao().getUnreadChanges(account.getId()));
|
||||||
|
|
||||||
emitter.onSuccess(syncData);
|
emitter.onSuccess(syncData);
|
||||||
}).flatMap(syncData1 -> api.sync(syncType, syncData1, account.getWriteToken()))
|
}).flatMap(syncData1 -> dataSource.sync(syncType, syncData1, account.getWriteToken()))
|
||||||
.flatMapObservable(syncResult -> {
|
.flatMapObservable(syncResult -> {
|
||||||
logger.addSplit("server queries");
|
logger.addSplit("server queries");
|
||||||
|
|
||||||
|
@ -131,7 +123,7 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
|
||||||
List<FeedInsertionResult> insertionResults = new ArrayList<>();
|
List<FeedInsertionResult> insertionResults = new ArrayList<>();
|
||||||
|
|
||||||
for (ParsingResult result : results) {
|
for (ParsingResult result : results) {
|
||||||
completableList.add(api.createFeed(account.getWriteToken(), result.getUrl())
|
completableList.add(dataSource.createFeed(account.getWriteToken(), result.getUrl())
|
||||||
.doOnComplete(() -> {
|
.doOnComplete(() -> {
|
||||||
FeedInsertionResult feedInsertionResult = new FeedInsertionResult();
|
FeedInsertionResult feedInsertionResult = new FeedInsertionResult();
|
||||||
feedInsertionResult.setParsingResult(result);
|
feedInsertionResult.setParsingResult(result);
|
||||||
|
@ -159,26 +151,26 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
|
||||||
Folder folder = feed.getFolderId() == null ? null : database.folderDao().select(feed.getFolderId());
|
Folder folder = feed.getFolderId() == null ? null : database.folderDao().select(feed.getFolderId());
|
||||||
emitter.onSuccess(folder);
|
emitter.onSuccess(folder);
|
||||||
|
|
||||||
}).flatMapCompletable(folder -> api.updateFeed(account.getWriteToken(),
|
}).flatMapCompletable(folder -> dataSource.updateFeed(account.getWriteToken(),
|
||||||
feed.getUrl(), feed.getName(), folder == null ? null : folder.getRemoteId())
|
feed.getUrl(), feed.getName(), folder == null ? null : folder.getRemoteId())
|
||||||
.andThen(super.updateFeed(feed)));
|
.andThen(super.updateFeed(feed)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Completable deleteFeed(Feed feed) {
|
public Completable deleteFeed(Feed feed) {
|
||||||
return api.deleteFeed(account.getWriteToken(), feed.getUrl())
|
return dataSource.deleteFeed(account.getWriteToken(), feed.getUrl())
|
||||||
.andThen(super.deleteFeed(feed));
|
.andThen(super.deleteFeed(feed));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<Long> addFolder(Folder folder) {
|
public Single<Long> addFolder(Folder folder) {
|
||||||
return api.createFolder(account.getWriteToken(), folder.getName())
|
return dataSource.createFolder(account.getWriteToken(), folder.getName())
|
||||||
.andThen(super.addFolder(folder));
|
.andThen(super.addFolder(folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Completable updateFolder(Folder folder) {
|
public Completable updateFolder(Folder folder) {
|
||||||
return api.updateFolder(account.getWriteToken(), folder.getRemoteId(), folder.getName())
|
return dataSource.updateFolder(account.getWriteToken(), folder.getRemoteId(), folder.getName())
|
||||||
.andThen(Completable.create(emitter -> {
|
.andThen(Completable.create(emitter -> {
|
||||||
folder.setRemoteId("user/-/label/" + folder.getName());
|
folder.setRemoteId("user/-/label/" + folder.getName());
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
|
@ -188,7 +180,7 @@ public class FreshRSSRepository extends ARepository<FreshRSSAPI> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Completable deleteFolder(Folder folder) {
|
public Completable deleteFolder(Folder folder) {
|
||||||
return api.deleteFolder(account.getWriteToken(), folder.getRemoteId())
|
return dataSource.deleteFolder(account.getWriteToken(), folder.getRemoteId())
|
||||||
.andThen(super.deleteFolder(folder));
|
.andThen(super.deleteFolder(folder));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.readrops.api.localfeed.LocalRSSDataSource;
|
import com.readrops.api.localfeed.LocalRSSDataSource;
|
||||||
import com.readrops.api.services.SyncResult;
|
import com.readrops.api.services.SyncResult;
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
import com.readrops.api.utils.LibUtils;
|
import com.readrops.api.utils.LibUtils;
|
||||||
import com.readrops.api.utils.ParseException;
|
import com.readrops.api.utils.ParseException;
|
||||||
import com.readrops.api.utils.UnknownFormatException;
|
import com.readrops.api.utils.UnknownFormatException;
|
||||||
|
@ -17,6 +16,7 @@ import com.readrops.app.utils.FeedInsertionResult;
|
||||||
import com.readrops.app.utils.ParsingResult;
|
import com.readrops.app.utils.ParsingResult;
|
||||||
import com.readrops.app.utils.SharedPreferencesManager;
|
import com.readrops.app.utils.SharedPreferencesManager;
|
||||||
import com.readrops.app.utils.Utils;
|
import com.readrops.app.utils.Utils;
|
||||||
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
|
@ -34,22 +34,17 @@ import io.reactivex.Single;
|
||||||
import kotlin.Pair;
|
import kotlin.Pair;
|
||||||
import okhttp3.Headers;
|
import okhttp3.Headers;
|
||||||
|
|
||||||
public class LocalFeedRepository extends ARepository<Void> {
|
public class LocalFeedRepository extends ARepository {
|
||||||
|
|
||||||
private static final String TAG = LocalFeedRepository.class.getSimpleName();
|
private static final String TAG = LocalFeedRepository.class.getSimpleName();
|
||||||
|
|
||||||
private LocalRSSDataSource dataSource;
|
private LocalRSSDataSource dataSource;
|
||||||
|
|
||||||
public LocalFeedRepository(@NonNull Context context, @Nullable Account account) {
|
public LocalFeedRepository(LocalRSSDataSource dataSource, Database database, @NonNull Context context, @Nullable Account account) {
|
||||||
super(context, account);
|
super(database, context, account);
|
||||||
|
|
||||||
syncResult = new SyncResult();
|
syncResult = new SyncResult();
|
||||||
dataSource = new LocalRSSDataSource(HttpManager.getInstance().getOkHttpClient());
|
this.dataSource = dataSource;
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
protected Void createAPI() {
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -138,7 +133,7 @@ public class LocalFeedRepository extends ARepository<Void> {
|
||||||
|
|
||||||
Collections.sort(items, Item::compareTo);
|
Collections.sort(items, Item::compareTo);
|
||||||
|
|
||||||
int maxItems = Integer.parseInt(SharedPreferencesManager.readString(context,
|
int maxItems = Integer.parseInt(SharedPreferencesManager.readString(
|
||||||
SharedPreferencesManager.SharedPrefKey.ITEMS_TO_PARSE_MAX_NB));
|
SharedPreferencesManager.SharedPrefKey.ITEMS_TO_PARSE_MAX_NB));
|
||||||
if (maxItems > 0 && items.size() > maxItems) {
|
if (maxItems > 0 && items.size() > maxItems) {
|
||||||
items = items.subList(items.size() - maxItems, items.size());
|
items = items.subList(items.size() - maxItems, items.size());
|
||||||
|
|
|
@ -7,16 +7,16 @@ import android.util.TimingLogger;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.readrops.api.services.Credentials;
|
|
||||||
import com.readrops.api.services.SyncResult;
|
import com.readrops.api.services.SyncResult;
|
||||||
import com.readrops.api.services.SyncType;
|
import com.readrops.api.services.SyncType;
|
||||||
import com.readrops.api.services.nextcloudnews.NextNewsAPI;
|
import com.readrops.api.services.nextcloudnews.NextNewsDataSource;
|
||||||
import com.readrops.api.services.nextcloudnews.NextNewsSyncData;
|
import com.readrops.api.services.nextcloudnews.NextNewsSyncData;
|
||||||
import com.readrops.api.services.nextcloudnews.json.NextNewsUser;
|
import com.readrops.api.services.nextcloudnews.json.NextNewsUser;
|
||||||
import com.readrops.api.utils.UnknownFormatException;
|
import com.readrops.api.utils.UnknownFormatException;
|
||||||
import com.readrops.app.utils.FeedInsertionResult;
|
import com.readrops.app.utils.FeedInsertionResult;
|
||||||
import com.readrops.app.utils.ParsingResult;
|
import com.readrops.app.utils.ParsingResult;
|
||||||
import com.readrops.app.utils.Utils;
|
import com.readrops.app.utils.Utils;
|
||||||
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.Item;
|
import com.readrops.db.entities.Item;
|
||||||
|
@ -33,31 +33,23 @@ import io.reactivex.Completable;
|
||||||
import io.reactivex.Observable;
|
import io.reactivex.Observable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
public class NextNewsRepository extends ARepository {
|
||||||
|
|
||||||
private static final String TAG = NextNewsRepository.class.getSimpleName();
|
private static final String TAG = NextNewsRepository.class.getSimpleName();
|
||||||
|
|
||||||
public NextNewsRepository(@NonNull Context context, @Nullable Account account) {
|
private final NextNewsDataSource dataSource;
|
||||||
super(context, account);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
public NextNewsRepository(NextNewsDataSource dataSource, Database database, @NonNull Context context, @Nullable Account account) {
|
||||||
protected NextNewsAPI createAPI() {
|
super(database, context, account);
|
||||||
if (account != null)
|
|
||||||
return new NextNewsAPI(Credentials.toCredentials(account));
|
|
||||||
|
|
||||||
return null;
|
this.dataSource = dataSource;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Single<Boolean> login(Account account, boolean insert) {
|
public Single<Boolean> login(Account account, boolean insert) {
|
||||||
|
setCredentials(account);
|
||||||
return Single.<NextNewsUser>create(emitter -> {
|
return Single.<NextNewsUser>create(emitter -> {
|
||||||
if (api == null)
|
NextNewsUser user = dataSource.login();
|
||||||
api = new NextNewsAPI(Credentials.toCredentials(account));
|
|
||||||
else
|
|
||||||
api.setCredentials(Credentials.toCredentials(account));
|
|
||||||
|
|
||||||
NextNewsUser user = api.login();
|
|
||||||
|
|
||||||
if (user != null) {
|
if (user != null) {
|
||||||
emitter.onSuccess(user);
|
emitter.onSuccess(user);
|
||||||
|
@ -101,7 +93,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
}
|
}
|
||||||
|
|
||||||
TimingLogger timings = new TimingLogger(TAG, "nextcloud news " + syncType.name().toLowerCase());
|
TimingLogger timings = new TimingLogger(TAG, "nextcloud news " + syncType.name().toLowerCase());
|
||||||
SyncResult result = api.sync(syncType, syncData);
|
SyncResult result = dataSource.sync(syncType, syncData);
|
||||||
timings.addSplit("server queries");
|
timings.addSplit("server queries");
|
||||||
|
|
||||||
if (!result.isError()) {
|
if (!result.isError()) {
|
||||||
|
@ -141,11 +133,11 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
FeedInsertionResult insertionResult = new FeedInsertionResult();
|
FeedInsertionResult insertionResult = new FeedInsertionResult();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
List<Feed> nextNewsFeeds = api.createFeed(result.getUrl(), 0);
|
List<Feed> nextNewsFeeds = dataSource.createFeed(result.getUrl(), 0);
|
||||||
|
|
||||||
if (nextNewsFeeds != null) {
|
if (nextNewsFeeds != null) {
|
||||||
List<Feed> newFeeds = insertFeeds(nextNewsFeeds, true);
|
List<Feed> newFeeds = insertFeeds(nextNewsFeeds, true);
|
||||||
// there is always only one object in the list, see nextcloud news api doc
|
// there is always only one object in the list, see nextcloud news dataSource doc
|
||||||
insertionResult.setFeed(newFeeds.get(0));
|
insertionResult.setFeed(newFeeds.get(0));
|
||||||
} else
|
} else
|
||||||
insertionResult.setInsertionError(FeedInsertionResult.FeedInsertionError.UNKNOWN_ERROR);
|
insertionResult.setInsertionError(FeedInsertionResult.FeedInsertionError.UNKNOWN_ERROR);
|
||||||
|
@ -180,7 +172,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
feed.setRemoteFolderId(String.valueOf(0)); // 0 for no folder
|
feed.setRemoteFolderId(String.valueOf(0)); // 0 for no folder
|
||||||
|
|
||||||
try {
|
try {
|
||||||
if (api.renameFeed(feed) && api.changeFeedFolder(feed)) {
|
if (dataSource.renameFeed(feed) && dataSource.changeFeedFolder(feed)) {
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
} else
|
} else
|
||||||
emitter.onError(new Exception("Unknown error when updating feed"));
|
emitter.onError(new Exception("Unknown error when updating feed"));
|
||||||
|
@ -194,7 +186,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
public Completable deleteFeed(Feed feed) {
|
public Completable deleteFeed(Feed feed) {
|
||||||
return Completable.create(emitter -> {
|
return Completable.create(emitter -> {
|
||||||
try {
|
try {
|
||||||
if (api.deleteFeed(Integer.parseInt(feed.getRemoteId()))) {
|
if (dataSource.deleteFeed(Integer.parseInt(feed.getRemoteId()))) {
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
} else
|
} else
|
||||||
emitter.onError(new Exception("Unknown error"));
|
emitter.onError(new Exception("Unknown error"));
|
||||||
|
@ -210,7 +202,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
public Single<Long> addFolder(Folder folder) {
|
public Single<Long> addFolder(Folder folder) {
|
||||||
return Single.<Folder>create(emitter -> {
|
return Single.<Folder>create(emitter -> {
|
||||||
try {
|
try {
|
||||||
List<Folder> folders = api.createFolder(folder);
|
List<Folder> folders = dataSource.createFolder(folder);
|
||||||
|
|
||||||
if (folders != null) {
|
if (folders != null) {
|
||||||
Folder nextNewsFolder = folders.get(0); // always only one item returned by the server, see doc
|
Folder nextNewsFolder = folders.get(0); // always only one item returned by the server, see doc
|
||||||
|
@ -229,7 +221,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
public Completable updateFolder(Folder folder) {
|
public Completable updateFolder(Folder folder) {
|
||||||
return Completable.create(emitter -> {
|
return Completable.create(emitter -> {
|
||||||
try {
|
try {
|
||||||
if (api.renameFolder(folder)) {
|
if (dataSource.renameFolder(folder)) {
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
} else
|
} else
|
||||||
emitter.onError(new Exception("Unknown error"));
|
emitter.onError(new Exception("Unknown error"));
|
||||||
|
@ -246,7 +238,7 @@ public class NextNewsRepository extends ARepository<NextNewsAPI> {
|
||||||
public Completable deleteFolder(Folder folder) {
|
public Completable deleteFolder(Folder folder) {
|
||||||
return Completable.create(emitter -> {
|
return Completable.create(emitter -> {
|
||||||
try {
|
try {
|
||||||
if (api.deleteFolder(folder)) {
|
if (dataSource.deleteFolder(folder)) {
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
} else
|
} else
|
||||||
emitter.onError(new Exception("Unknown error"));
|
emitter.onError(new Exception("Unknown error"));
|
||||||
|
|
|
@ -6,18 +6,19 @@ import androidx.annotation.NonNull;
|
||||||
import androidx.annotation.Nullable;
|
import androidx.annotation.Nullable;
|
||||||
|
|
||||||
import com.readrops.api.localfeed.LocalRSSHelper;
|
import com.readrops.api.localfeed.LocalRSSHelper;
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
import com.readrops.api.utils.LibUtils;
|
import com.readrops.api.utils.LibUtils;
|
||||||
|
|
||||||
import org.jsoup.Jsoup;
|
import org.jsoup.Jsoup;
|
||||||
import org.jsoup.nodes.Document;
|
import org.jsoup.nodes.Document;
|
||||||
import org.jsoup.nodes.Element;
|
import org.jsoup.nodes.Element;
|
||||||
import org.jsoup.select.Elements;
|
import org.jsoup.select.Elements;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import okhttp3.OkHttpClient;
|
||||||
import okhttp3.Request;
|
import okhttp3.Request;
|
||||||
import okhttp3.Response;
|
import okhttp3.Response;
|
||||||
|
|
||||||
|
@ -83,7 +84,7 @@ public final class HtmlParser {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Response response = HttpManager.getInstance().getOkHttpClient()
|
Response response = KoinJavaComponent.get(OkHttpClient.class)
|
||||||
.newCall(new Request.Builder().url(url).build()).execute();
|
.newCall(new Request.Builder().url(url).build()).execute();
|
||||||
|
|
||||||
if (response.header("Content-Type").contains(LibUtils.HTML_CONTENT_TYPE)) {
|
if (response.header("Content-Type").contains(LibUtils.HTML_CONTENT_TYPE)) {
|
||||||
|
@ -98,6 +99,7 @@ public final class HtmlParser {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
|
Log.d(TAG, e.getMessage());
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,15 +7,17 @@ import com.bumptech.glide.annotation.GlideModule
|
||||||
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
|
import com.bumptech.glide.integration.okhttp3.OkHttpUrlLoader
|
||||||
import com.bumptech.glide.load.model.GlideUrl
|
import com.bumptech.glide.load.model.GlideUrl
|
||||||
import com.bumptech.glide.module.AppGlideModule
|
import com.bumptech.glide.module.AppGlideModule
|
||||||
import com.readrops.api.utils.HttpManager
|
import okhttp3.OkHttpClient
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
import java.io.InputStream
|
import java.io.InputStream
|
||||||
|
|
||||||
@GlideModule
|
@GlideModule
|
||||||
class ReadropsGlideModule : AppGlideModule() {
|
class ReadropsGlideModule : AppGlideModule(), KoinComponent {
|
||||||
|
|
||||||
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
override fun registerComponents(context: Context, glide: Glide, registry: Registry) {
|
||||||
val factory = OkHttpUrlLoader.Factory(HttpManager.getInstance().okHttpClient)
|
val factory = OkHttpUrlLoader.Factory(get<OkHttpClient>())
|
||||||
|
|
||||||
glide.registry.replace(GlideUrl::class.java, InputStream::class.java, factory)
|
glide.registry.replace(GlideUrl::class.java, InputStream::class.java, factory)
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,19 +1,15 @@
|
||||||
package com.readrops.app.utils;
|
package com.readrops.app.utils;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
public final class SharedPreferencesManager {
|
public final class SharedPreferencesManager {
|
||||||
|
|
||||||
private static SharedPreferences getSharedPreferences(Context context) {
|
public static void writeValue(String key, Object value) {
|
||||||
return PreferenceManager.getDefaultSharedPreferences(context);
|
SharedPreferences sharedPref = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
}
|
|
||||||
|
|
||||||
public static void writeValue(Context context, String key, Object value) {
|
|
||||||
SharedPreferences sharedPref = getSharedPreferences(context);
|
|
||||||
SharedPreferences.Editor editor = sharedPref.edit();
|
SharedPreferences.Editor editor = sharedPref.edit();
|
||||||
|
|
||||||
if (value instanceof Boolean)
|
if (value instanceof Boolean)
|
||||||
|
@ -24,32 +20,32 @@ public final class SharedPreferencesManager {
|
||||||
editor.apply();
|
editor.apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void writeValue(Context context, SharedPrefKey sharedPrefKey, Object value) {
|
public static void writeValue(SharedPrefKey sharedPrefKey, Object value) {
|
||||||
writeValue(context, sharedPrefKey.key, value);
|
writeValue(sharedPrefKey.key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static int readInt(Context context, SharedPrefKey sharedPrefKey) {
|
public static int readInt(SharedPrefKey sharedPrefKey) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
return sharedPreferences.getInt(sharedPrefKey.key, sharedPrefKey.getIntDefaultValue());
|
return sharedPreferences.getInt(sharedPrefKey.key, sharedPrefKey.getIntDefaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean readBoolean(Context context, SharedPrefKey sharedPrefKey) {
|
public static boolean readBoolean(SharedPrefKey sharedPrefKey) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
return sharedPreferences.getBoolean(sharedPrefKey.key, sharedPrefKey.getBooleanDefaultValue());
|
return sharedPreferences.getBoolean(sharedPrefKey.key, sharedPrefKey.getBooleanDefaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readString(Context context, String key) {
|
public static String readString(String key) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
return sharedPreferences.getString(key, null);
|
return sharedPreferences.getString(key, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static String readString(Context context, SharedPrefKey sharedPrefKey) {
|
public static String readString(SharedPrefKey sharedPrefKey) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
return sharedPreferences.getString(sharedPrefKey.key, sharedPrefKey.getStringDefaultValue());
|
return sharedPreferences.getString(sharedPrefKey.key, sharedPrefKey.getStringDefaultValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
public static void remove(Context context, String key) {
|
public static void remove(String key) {
|
||||||
SharedPreferences sharedPreferences = getSharedPreferences(context);
|
SharedPreferences sharedPreferences = KoinJavaComponent.get(SharedPreferences.class);
|
||||||
SharedPreferences.Editor editor = sharedPreferences.edit();
|
SharedPreferences.Editor editor = sharedPreferences.edit();
|
||||||
|
|
||||||
editor.remove(key);
|
editor.remove(key);
|
||||||
|
|
|
@ -9,11 +9,13 @@ import com.readrops.db.entities.Feed
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.api.services.SyncResult
|
import com.readrops.api.services.SyncResult
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Simple class to get synchro notification content (title, content and largeIcon) according to some rules
|
* Simple class to get synchro notification content (title, content and largeIcon) according to some rules
|
||||||
*/
|
*/
|
||||||
class SyncResultAnalyser(val context: Context, private val syncResults: Map<Account, SyncResult>, val database: Database) {
|
class SyncResultAnalyser(val context: Context, private val syncResults: Map<Account, SyncResult>, val database: Database) : KoinComponent {
|
||||||
|
|
||||||
private val notifContent = SyncResultNotifContent()
|
private val notifContent = SyncResultNotifContent()
|
||||||
|
|
||||||
|
@ -66,7 +68,7 @@ class SyncResultAnalyser(val context: Context, private val syncResults: Map<Acco
|
||||||
notifContent.title = feed?.name
|
notifContent.title = feed?.name
|
||||||
|
|
||||||
feed?.iconUrl?.let {
|
feed?.iconUrl?.let {
|
||||||
val target = GlideApp.with(context)
|
val target = get<GlideRequests>()
|
||||||
.asBitmap()
|
.asBitmap()
|
||||||
.load(it)
|
.load(it)
|
||||||
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
.diskCacheStrategy(DiskCacheStrategy.ALL)
|
||||||
|
|
|
@ -1,20 +1,22 @@
|
||||||
package com.readrops.app.utils
|
package com.readrops.app.utils
|
||||||
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
|
import com.readrops.api.services.SyncResult
|
||||||
import com.readrops.db.Database
|
import com.readrops.db.Database
|
||||||
import com.readrops.db.entities.Item
|
import com.readrops.db.entities.Item
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import com.readrops.db.entities.account.AccountType
|
import com.readrops.db.entities.account.AccountType
|
||||||
import com.readrops.api.services.SyncResult
|
|
||||||
import org.jetbrains.annotations.TestOnly
|
import org.jetbrains.annotations.TestOnly
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
|
|
||||||
class SyncResultDebugData {
|
class SyncResultDebugData {
|
||||||
|
|
||||||
companion object {
|
companion object : KoinComponent {
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun oneAccountOneFeedOneItem(context: Context): Map<Account, SyncResult> {
|
fun oneAccountOneFeedOneItem(): Map<Account, SyncResult> {
|
||||||
val database = Database.getInstance(context)
|
val database = get<Database>()
|
||||||
val account1 = database.accountDao().select(2)
|
val account1 = database.accountDao().select(2)
|
||||||
|
|
||||||
|
|
||||||
|
@ -27,14 +29,14 @@ class SyncResultDebugData {
|
||||||
}
|
}
|
||||||
|
|
||||||
@TestOnly
|
@TestOnly
|
||||||
fun oneAccountOneFeedMultipleItems(context: Context): Map<Account, SyncResult> {
|
fun oneAccountOneFeedMultipleItems(): Map<Account, SyncResult> {
|
||||||
val account1 = Account().apply {
|
val account1 = Account().apply {
|
||||||
id = 1
|
id = 1
|
||||||
accountType = AccountType.FRESHRSS
|
accountType = AccountType.FRESHRSS
|
||||||
isNotificationsEnabled = true
|
isNotificationsEnabled = true
|
||||||
}
|
}
|
||||||
|
|
||||||
val database = Database.getInstance(context)
|
val database = get<Database>()
|
||||||
val item = database.itemDao().select(5055)
|
val item = database.itemDao().select(5055)
|
||||||
database.feedDao().updateFeedNotificationState(item.feedId, false).subscribe()
|
database.feedDao().updateFeedNotificationState(item.feedId, false).subscribe()
|
||||||
|
|
||||||
|
|
|
@ -19,13 +19,16 @@ import com.readrops.db.entities.Item
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import io.reactivex.disposables.Disposable
|
import io.reactivex.disposables.Disposable
|
||||||
import io.reactivex.schedulers.Schedulers
|
import io.reactivex.schedulers.Schedulers
|
||||||
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
|
import org.koin.core.parameter.parametersOf
|
||||||
|
|
||||||
class SyncWorker(context: Context, parameters: WorkerParameters) : Worker(context, parameters) {
|
class SyncWorker(context: Context, parameters: WorkerParameters) : Worker(context, parameters), KoinComponent {
|
||||||
|
|
||||||
private var disposable: Disposable? = null
|
private var disposable: Disposable? = null
|
||||||
|
|
||||||
private val notificationManager = NotificationManagerCompat.from(applicationContext)
|
private val notificationManager = NotificationManagerCompat.from(applicationContext)
|
||||||
private val database = Database.getInstance(applicationContext)
|
private val database = get<Database>()
|
||||||
|
|
||||||
override fun doWork(): Result {
|
override fun doWork(): Result {
|
||||||
var result = Result.success()
|
var result = Result.success()
|
||||||
|
@ -39,15 +42,15 @@ class SyncWorker(context: Context, parameters: WorkerParameters) : Worker(contex
|
||||||
.setProgress(0, 0, true)
|
.setProgress(0, 0, true)
|
||||||
.setSmallIcon(R.drawable.ic_notif)
|
.setSmallIcon(R.drawable.ic_notif)
|
||||||
.setOnlyAlertOnce(true)
|
.setOnlyAlertOnce(true)
|
||||||
|
|
||||||
accounts.forEach {
|
accounts.forEach {
|
||||||
notificationBuilder.setContentText(it.accountName)
|
notificationBuilder.setContentText(it.accountName)
|
||||||
notificationManager.notify(SYNC_NOTIFICATION_ID, notificationBuilder.build())
|
notificationManager.notify(SYNC_NOTIFICATION_ID, notificationBuilder.build())
|
||||||
|
|
||||||
it.login = SharedPreferencesManager.readString(applicationContext, it.loginKey)
|
it.login = SharedPreferencesManager.readString(it.loginKey)
|
||||||
it.password = SharedPreferencesManager.readString(applicationContext, it.passwordKey)
|
it.password = SharedPreferencesManager.readString(it.passwordKey)
|
||||||
|
|
||||||
val repository = ARepository.repositoryFactory(it, applicationContext)
|
val repository = get<ARepository>(parameters = { parametersOf(it) })
|
||||||
|
|
||||||
disposable = repository.sync(null)
|
disposable = repository.sync(null)
|
||||||
.doOnError { throwable ->
|
.doOnError { throwable ->
|
||||||
|
@ -138,12 +141,12 @@ class SyncWorker(context: Context, parameters: WorkerParameters) : Worker(contex
|
||||||
.build()
|
.build()
|
||||||
}
|
}
|
||||||
|
|
||||||
class MarkReadReceiver : BroadcastReceiver() {
|
class MarkReadReceiver : BroadcastReceiver(), KoinComponent {
|
||||||
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
val itemId = intent?.getIntExtra(ReadropsKeys.ITEM_ID, 0)!!
|
val itemId = intent?.getIntExtra(ReadropsKeys.ITEM_ID, 0)!!
|
||||||
|
|
||||||
with(Database.getInstance(context)) {
|
with(get<Database>()) {
|
||||||
itemDao().setReadState(itemId, true, true)
|
itemDao().setReadState(itemId, true, true)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
@ -155,12 +158,12 @@ class SyncWorker(context: Context, parameters: WorkerParameters) : Worker(contex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ReadLaterReceiver : BroadcastReceiver() {
|
class ReadLaterReceiver : BroadcastReceiver(), KoinComponent {
|
||||||
|
|
||||||
override fun onReceive(context: Context?, intent: Intent?) {
|
override fun onReceive(context: Context?, intent: Intent?) {
|
||||||
val itemId = intent?.getIntExtra(ReadropsKeys.ITEM_ID, 0)!!
|
val itemId = intent?.getIntExtra(ReadropsKeys.ITEM_ID, 0)!!
|
||||||
|
|
||||||
with(Database.getInstance(context)) {
|
with(get<Database>()) {
|
||||||
itemDao().setReadItLater(itemId)
|
itemDao().setReadItLater(itemId)
|
||||||
.subscribeOn(Schedulers.io())
|
.subscribeOn(Schedulers.io())
|
||||||
.subscribe()
|
.subscribe()
|
||||||
|
|
|
@ -15,7 +15,8 @@ import androidx.annotation.ColorInt;
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
|
|
||||||
import com.google.android.material.snackbar.Snackbar;
|
import com.google.android.material.snackbar.Snackbar;
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
|
@ -34,10 +35,9 @@ public final class Utils {
|
||||||
|
|
||||||
public static Bitmap getImageFromUrl(String url) {
|
public static Bitmap getImageFromUrl(String url) {
|
||||||
try {
|
try {
|
||||||
OkHttpClient okHttpClient = HttpManager.getInstance().getOkHttpClient();
|
|
||||||
Request request = new Request.Builder().url(url).build();
|
Request request = new Request.Builder().url(url).build();
|
||||||
|
|
||||||
Response response = okHttpClient.newCall(request).execute();
|
Response response = KoinJavaComponent.get(OkHttpClient.class).newCall(request).execute();
|
||||||
|
|
||||||
if (response.isSuccessful()) {
|
if (response.isSuccessful()) {
|
||||||
InputStream inputStream = response.body().byteStream();
|
InputStream inputStream = response.body().byteStream();
|
||||||
|
|
|
@ -6,15 +6,17 @@ import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import com.readrops.app.R
|
import com.readrops.app.R
|
||||||
import com.readrops.app.ReadropsApp
|
import com.readrops.app.ReadropsApp
|
||||||
|
import com.readrops.app.utils.ReadropsKeys.FEEDS
|
||||||
import com.readrops.db.Database
|
import com.readrops.db.Database
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
import com.readrops.app.utils.ReadropsKeys.FEEDS
|
import org.koin.core.KoinComponent
|
||||||
|
import org.koin.core.get
|
||||||
|
|
||||||
class FeedsColorsIntentService : IntentService("FeedsColorsIntentService") {
|
class FeedsColorsIntentService : IntentService("FeedsColorsIntentService"), KoinComponent {
|
||||||
|
|
||||||
override fun onHandleIntent(intent: Intent?) {
|
override fun onHandleIntent(intent: Intent?) {
|
||||||
val feeds: List<Feed> = intent!!.getParcelableArrayListExtra(FEEDS)!!
|
val feeds: List<Feed> = intent!!.getParcelableArrayListExtra(FEEDS)!!
|
||||||
val database = Database.getInstance(this)
|
val database = get<Database>()
|
||||||
|
|
||||||
val notificationBuilder = NotificationCompat.Builder(this, ReadropsApp.FEEDS_COLORS_CHANNEL_ID)
|
val notificationBuilder = NotificationCompat.Builder(this, ReadropsApp.FEEDS_COLORS_CHANNEL_ID)
|
||||||
.setContentTitle(getString(R.string.get_feeds_colors))
|
.setContentTitle(getString(R.string.get_feeds_colors))
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
package com.readrops.app.viewmodels;
|
package com.readrops.app.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.content.Context;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.readrops.api.opml.OPMLParser;
|
import com.readrops.api.opml.OPMLParser;
|
||||||
import com.readrops.app.repositories.ARepository;
|
import com.readrops.app.repositories.ARepository;
|
||||||
|
@ -15,35 +14,32 @@ import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.entities.account.AccountType;
|
import com.readrops.db.entities.account.AccountType;
|
||||||
|
|
||||||
|
import org.koin.core.parameter.DefinitionParametersKt;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public class AccountViewModel extends AndroidViewModel {
|
public class AccountViewModel extends ViewModel {
|
||||||
|
|
||||||
private static final String TAG = AccountViewModel.class.getSimpleName();
|
|
||||||
|
|
||||||
private ARepository repository;
|
private ARepository repository;
|
||||||
private Database database;
|
private final Database database;
|
||||||
|
|
||||||
public AccountViewModel(@NonNull Application application) {
|
public AccountViewModel(@NonNull Database database) {
|
||||||
super(application);
|
this.database = database;
|
||||||
|
|
||||||
database = Database.getInstance(application);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAccountType(AccountType accountType) throws Exception {
|
public void setAccountType(AccountType accountType) {
|
||||||
repository = ARepository.repositoryFactory(null, accountType, getApplication());
|
repository = KoinJavaComponent.get(ARepository.class, null,
|
||||||
|
() -> DefinitionParametersKt.parametersOf(new Account(null, null, accountType)));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setAccount(Account account) {
|
public void setAccount(Account account) {
|
||||||
try {
|
repository = KoinJavaComponent.get(ARepository.class, null,
|
||||||
repository = ARepository.repositoryFactory(account, getApplication());
|
() -> DefinitionParametersKt.parametersOf(account));
|
||||||
} catch (Exception e) {
|
|
||||||
Log.e(TAG, e.getMessage());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Boolean> login(Account account, boolean insert) {
|
public Single<Boolean> login(Account account, boolean insert) {
|
||||||
|
@ -71,8 +67,8 @@ public class AccountViewModel extends AndroidViewModel {
|
||||||
return repository.getFoldersWithFeeds();
|
return repository.getFoldersWithFeeds();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable parseOPMLFile(Uri uri) {
|
public Completable parseOPMLFile(Uri uri, Context context) {
|
||||||
return OPMLParser.read(uri, getApplication())
|
return OPMLParser.read(uri, context)
|
||||||
.flatMapCompletable(foldersAndFeeds -> repository.insertOPMLFoldersAndFeeds(foldersAndFeeds));
|
.flatMapCompletable(foldersAndFeeds -> repository.insertOPMLFoldersAndFeeds(foldersAndFeeds));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,10 @@
|
||||||
package com.readrops.app.viewmodels;
|
package com.readrops.app.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.readrops.api.localfeed.LocalRSSDataSource;
|
import com.readrops.api.localfeed.LocalRSSDataSource;
|
||||||
import com.readrops.api.utils.HttpManager;
|
|
||||||
import com.readrops.app.repositories.ARepository;
|
import com.readrops.app.repositories.ARepository;
|
||||||
import com.readrops.app.utils.FeedInsertionResult;
|
import com.readrops.app.utils.FeedInsertionResult;
|
||||||
import com.readrops.app.utils.HtmlParser;
|
import com.readrops.app.utils.HtmlParser;
|
||||||
|
@ -16,42 +12,36 @@ import com.readrops.app.utils.ParsingResult;
|
||||||
import com.readrops.db.Database;
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
|
|
||||||
|
import org.koin.core.parameter.DefinitionParametersKt;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public class AddFeedsViewModel extends AndroidViewModel {
|
public class AddFeedsViewModel extends ViewModel {
|
||||||
|
|
||||||
private static final String TAG = AddFeedsViewModel.class.getSimpleName();
|
private final Database database;
|
||||||
|
private final LocalRSSDataSource localRSSDataSource;
|
||||||
|
|
||||||
private ARepository repository;
|
public AddFeedsViewModel(@NonNull Database database, @NonNull LocalRSSDataSource localRSSDataSource) {
|
||||||
private Database database;
|
this.database = database;
|
||||||
|
this.localRSSDataSource = localRSSDataSource;
|
||||||
public AddFeedsViewModel(@NonNull Application application) {
|
|
||||||
super(application);
|
|
||||||
|
|
||||||
database = Database.getInstance(application);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results, Account account) {
|
public Single<List<FeedInsertionResult>> addFeeds(List<ParsingResult> results, Account account) {
|
||||||
try {
|
ARepository repository = KoinJavaComponent.get(ARepository.class, null,
|
||||||
repository = ARepository.repositoryFactory(account, getApplication());
|
() -> DefinitionParametersKt.parametersOf(account));
|
||||||
|
|
||||||
return repository.addFeeds(results);
|
return repository.addFeeds(results);
|
||||||
} catch (Exception e) {
|
|
||||||
Log.d(TAG, e.getMessage());
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<List<ParsingResult>> parseUrl(String url) {
|
public Single<List<ParsingResult>> parseUrl(String url) {
|
||||||
return Single.create(emitter -> {
|
return Single.create(emitter -> {
|
||||||
LocalRSSDataSource dataSource = new LocalRSSDataSource(HttpManager.getInstance().getOkHttpClient());
|
|
||||||
List<ParsingResult> results = new ArrayList<>();
|
List<ParsingResult> results = new ArrayList<>();
|
||||||
|
|
||||||
if (dataSource.isUrlRSSResource(url)) {
|
if (localRSSDataSource.isUrlRSSResource(url)) {
|
||||||
ParsingResult parsingResult = new ParsingResult(url, null);
|
ParsingResult parsingResult = new ParsingResult(url, null);
|
||||||
results.add(parsingResult);
|
results.add(parsingResult);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -1,16 +1,15 @@
|
||||||
package com.readrops.app.viewmodels;
|
package com.readrops.app.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
import android.content.Context;
|
||||||
import android.graphics.Bitmap;
|
import android.graphics.Bitmap;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.core.content.FileProvider;
|
import androidx.core.content.FileProvider;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
import com.readrops.db.Database;
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.dao.ItemDao;
|
|
||||||
import com.readrops.db.pojo.ItemWithFeed;
|
import com.readrops.db.pojo.ItemWithFeed;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -18,22 +17,21 @@ import java.io.FileOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class ItemViewModel extends AndroidViewModel {
|
public class ItemViewModel extends ViewModel {
|
||||||
|
|
||||||
private ItemDao itemDao;
|
private final Database database;
|
||||||
|
|
||||||
public ItemViewModel(@NonNull Application application) {
|
public ItemViewModel(@NonNull Database database) {
|
||||||
super(application);
|
this.database = database;
|
||||||
itemDao = Database.getInstance(application).itemDao();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<ItemWithFeed> getItemById(int id) {
|
public LiveData<ItemWithFeed> getItemById(int id) {
|
||||||
return itemDao.getItemById(id);
|
return database.itemDao().getItemById(id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public Uri saveImageInCache(Bitmap bitmap) throws IOException {
|
public Uri saveImageInCache(Bitmap bitmap, Context context) throws IOException {
|
||||||
File imagesFolder = new File(getApplication().getCacheDir().getAbsolutePath(), "images");
|
File imagesFolder = new File(context.getCacheDir().getAbsolutePath(), "images");
|
||||||
|
|
||||||
if (!imagesFolder.exists())
|
if (!imagesFolder.exists())
|
||||||
imagesFolder.mkdirs();
|
imagesFolder.mkdirs();
|
||||||
|
@ -45,6 +43,6 @@ public class ItemViewModel extends AndroidViewModel {
|
||||||
stream.flush();
|
stream.flush();
|
||||||
stream.close();
|
stream.close();
|
||||||
|
|
||||||
return FileProvider.getUriForFile(getApplication(), getApplication().getPackageName(), image);
|
return FileProvider.getUriForFile(context, context.getPackageName(), image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,14 +1,13 @@
|
||||||
package com.readrops.app.viewmodels;
|
package com.readrops.app.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
import androidx.lifecycle.MediatorLiveData;
|
import androidx.lifecycle.MediatorLiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
import androidx.paging.LivePagedListBuilder;
|
import androidx.paging.LivePagedListBuilder;
|
||||||
import androidx.paging.PagedList;
|
import androidx.paging.PagedList;
|
||||||
|
|
||||||
|
import com.readrops.app.repositories.ARepository;
|
||||||
import com.readrops.db.Database;
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.ItemsListQueryBuilder;
|
import com.readrops.db.ItemsListQueryBuilder;
|
||||||
import com.readrops.db.RoomFactoryWrapper;
|
import com.readrops.db.RoomFactoryWrapper;
|
||||||
|
@ -18,7 +17,9 @@ import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.filters.FilterType;
|
import com.readrops.db.filters.FilterType;
|
||||||
import com.readrops.db.filters.ListSortType;
|
import com.readrops.db.filters.ListSortType;
|
||||||
import com.readrops.db.pojo.ItemWithFeed;
|
import com.readrops.db.pojo.ItemWithFeed;
|
||||||
import com.readrops.app.repositories.ARepository;
|
|
||||||
|
import org.koin.core.parameter.DefinitionParametersKt;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
|
@ -31,45 +32,40 @@ import io.reactivex.Single;
|
||||||
import io.reactivex.android.schedulers.AndroidSchedulers;
|
import io.reactivex.android.schedulers.AndroidSchedulers;
|
||||||
import io.reactivex.schedulers.Schedulers;
|
import io.reactivex.schedulers.Schedulers;
|
||||||
|
|
||||||
public class MainViewModel extends AndroidViewModel {
|
public class MainViewModel extends ViewModel {
|
||||||
|
|
||||||
private MediatorLiveData<PagedList<ItemWithFeed>> itemsWithFeed;
|
private final MediatorLiveData<PagedList<ItemWithFeed>> itemsWithFeed;
|
||||||
private LiveData<PagedList<ItemWithFeed>> lastFetch;
|
private LiveData<PagedList<ItemWithFeed>> lastFetch;
|
||||||
private ARepository repository;
|
private ARepository repository;
|
||||||
private Database db;
|
private final Database database;
|
||||||
|
|
||||||
private ItemsListQueryBuilder queryBuilder;
|
private final ItemsListQueryBuilder queryBuilder;
|
||||||
|
|
||||||
private Account currentAccount;
|
private Account currentAccount;
|
||||||
private List<Account> accounts;
|
private List<Account> accounts;
|
||||||
|
|
||||||
public MainViewModel(@NonNull Application application) {
|
public MainViewModel(@NonNull Database database) {
|
||||||
super(application);
|
|
||||||
|
|
||||||
queryBuilder = new ItemsListQueryBuilder();
|
queryBuilder = new ItemsListQueryBuilder();
|
||||||
|
|
||||||
queryBuilder.setFilterType(FilterType.NO_FILTER);
|
queryBuilder.setFilterType(FilterType.NO_FILTER);
|
||||||
queryBuilder.setSortType(ListSortType.NEWEST_TO_OLDEST);
|
queryBuilder.setSortType(ListSortType.NEWEST_TO_OLDEST);
|
||||||
|
|
||||||
db = Database.getInstance(application);
|
this.database = database;
|
||||||
itemsWithFeed = new MediatorLiveData<>();
|
itemsWithFeed = new MediatorLiveData<>();
|
||||||
}
|
}
|
||||||
|
|
||||||
//region main query
|
//region main query
|
||||||
|
|
||||||
private void setRepository() {
|
private void setRepository() {
|
||||||
try {
|
repository = KoinJavaComponent.get(ARepository.class, null,
|
||||||
repository = ARepository.repositoryFactory(currentAccount, getApplication());
|
() -> DefinitionParametersKt.parametersOf(currentAccount));
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void buildPagedList() {
|
private void buildPagedList() {
|
||||||
if (lastFetch != null)
|
if (lastFetch != null)
|
||||||
itemsWithFeed.removeSource(lastFetch);
|
itemsWithFeed.removeSource(lastFetch);
|
||||||
|
|
||||||
lastFetch = new LivePagedListBuilder<>(new RoomFactoryWrapper<>(db.itemDao().selectAll(queryBuilder.getQuery())),
|
lastFetch = new LivePagedListBuilder<>(new RoomFactoryWrapper<>(database.itemDao().selectAll(queryBuilder.getQuery())),
|
||||||
new PagedList.Config.Builder()
|
new PagedList.Config.Builder()
|
||||||
.setPageSize(100)
|
.setPageSize(100)
|
||||||
.setPrefetchDistance(150)
|
.setPrefetchDistance(150)
|
||||||
|
@ -77,7 +73,7 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
.build())
|
.build())
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
itemsWithFeed.addSource(lastFetch, itemWithFeeds -> itemsWithFeed.setValue(itemWithFeeds));
|
itemsWithFeed.addSource(lastFetch, itemsWithFeed::setValue);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void invalidate() {
|
public void invalidate() {
|
||||||
|
@ -124,7 +120,6 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
return repository.getFeedCount(currentAccount.getId());
|
return repository.getFeedCount(currentAccount.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
public Single<Map<Folder, List<Feed>>> getFoldersWithFeeds() {
|
public Single<Map<Folder, List<Feed>>> getFoldersWithFeeds() {
|
||||||
return repository.getFoldersWithFeeds();
|
return repository.getFoldersWithFeeds();
|
||||||
}
|
}
|
||||||
|
@ -134,12 +129,12 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
//region Account
|
//region Account
|
||||||
|
|
||||||
public LiveData<List<Account>> getAllAccounts() {
|
public LiveData<List<Account>> getAllAccounts() {
|
||||||
return db.accountDao().selectAllAsync();
|
return database.accountDao().selectAllAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Completable deselectOldCurrentAccount(int accountId) {
|
private Completable deselectOldCurrentAccount(int accountId) {
|
||||||
return Completable.create(emitter -> {
|
return Completable.create(emitter -> {
|
||||||
db.accountDao().deselectOldCurrentAccount(accountId);
|
database.accountDao().deselectOldCurrentAccount(accountId);
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -170,7 +165,7 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
|
|
||||||
// set the new account as the current one
|
// set the new account as the current one
|
||||||
Completable setCurrentAccount = Completable.create(emitter -> {
|
Completable setCurrentAccount = Completable.create(emitter -> {
|
||||||
db.accountDao().setCurrentAccount(currentAccount.getId());
|
database.accountDao().setCurrentAccount(currentAccount.getId());
|
||||||
emitter.onComplete();
|
emitter.onComplete();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -202,7 +197,7 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!currentAccountExists && accounts.size() > 0) {
|
if (!currentAccountExists && !accounts.isEmpty()) {
|
||||||
setCurrentAccount(accounts.get(0));
|
setCurrentAccount(accounts.get(0));
|
||||||
accounts.get(0).setCurrentAccount(true);
|
accounts.get(0).setCurrentAccount(true);
|
||||||
}
|
}
|
||||||
|
@ -242,7 +237,7 @@ public class MainViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Completable setItemReadItLater(int itemId) {
|
public Completable setItemReadItLater(int itemId) {
|
||||||
return db.itemDao().setReadItLater(itemId);
|
return database.itemDao().setReadItLater(itemId);
|
||||||
}
|
}
|
||||||
|
|
||||||
//endregion
|
//endregion
|
||||||
|
|
|
@ -1,48 +1,44 @@
|
||||||
package com.readrops.app.viewmodels;
|
package com.readrops.app.viewmodels;
|
||||||
|
|
||||||
import android.app.Application;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.lifecycle.AndroidViewModel;
|
|
||||||
import androidx.lifecycle.LiveData;
|
import androidx.lifecycle.LiveData;
|
||||||
|
import androidx.lifecycle.ViewModel;
|
||||||
|
|
||||||
|
import com.readrops.app.repositories.ARepository;
|
||||||
import com.readrops.db.Database;
|
import com.readrops.db.Database;
|
||||||
import com.readrops.db.entities.Feed;
|
import com.readrops.db.entities.Feed;
|
||||||
import com.readrops.db.entities.Folder;
|
import com.readrops.db.entities.Folder;
|
||||||
import com.readrops.db.entities.account.Account;
|
import com.readrops.db.entities.account.Account;
|
||||||
import com.readrops.db.pojo.FeedWithFolder;
|
import com.readrops.db.pojo.FeedWithFolder;
|
||||||
import com.readrops.db.pojo.FolderWithFeedCount;
|
import com.readrops.db.pojo.FolderWithFeedCount;
|
||||||
import com.readrops.app.repositories.ARepository;
|
|
||||||
|
import org.koin.core.parameter.DefinitionParametersKt;
|
||||||
|
import org.koin.java.KoinJavaComponent;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import io.reactivex.Completable;
|
import io.reactivex.Completable;
|
||||||
import io.reactivex.Single;
|
import io.reactivex.Single;
|
||||||
|
|
||||||
public class ManageFeedsFoldersViewModel extends AndroidViewModel {
|
public class ManageFeedsFoldersViewModel extends ViewModel {
|
||||||
|
|
||||||
private Database db;
|
private final Database database;
|
||||||
private LiveData<List<FeedWithFolder>> feedsWithFolder;
|
private LiveData<List<FeedWithFolder>> feedsWithFolder;
|
||||||
private LiveData<List<Folder>> folders;
|
private LiveData<List<Folder>> folders;
|
||||||
private ARepository repository;
|
private ARepository repository;
|
||||||
|
|
||||||
private Account account;
|
private Account account;
|
||||||
|
|
||||||
public ManageFeedsFoldersViewModel(@NonNull Application application) {
|
public ManageFeedsFoldersViewModel(@NonNull Database database) {
|
||||||
super(application);
|
this.database = database;
|
||||||
|
|
||||||
db = Database.getInstance(application);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setup() {
|
private void setup() {
|
||||||
try {
|
repository = KoinJavaComponent.get(ARepository.class, null,
|
||||||
repository = ARepository.repositoryFactory(account, getApplication());
|
() -> DefinitionParametersKt.parametersOf(account));
|
||||||
|
|
||||||
feedsWithFolder = db.feedDao().getAllFeedsWithFolder(account.getId());
|
feedsWithFolder = database.feedDao().getAllFeedsWithFolder(account.getId());
|
||||||
folders = db.folderDao().getAllFolders(account.getId());
|
folders = database.folderDao().getAllFolders(account.getId());
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<FeedWithFolder>> getFeedsWithFolder() {
|
public LiveData<List<FeedWithFolder>> getFeedsWithFolder() {
|
||||||
|
@ -67,7 +63,7 @@ public class ManageFeedsFoldersViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiveData<List<FolderWithFeedCount>> getFoldersWithFeedCount() {
|
public LiveData<List<FolderWithFeedCount>> getFoldersWithFeedCount() {
|
||||||
return db.folderDao().getFoldersWithFeedCount(account.getId());
|
return database.folderDao().getFoldersWithFeedCount(account.getId());
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Long> addFolder(Folder folder) {
|
public Single<Long> addFolder(Folder folder) {
|
||||||
|
@ -87,6 +83,6 @@ public class ManageFeedsFoldersViewModel extends AndroidViewModel {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Single<Integer> getFeedCountByAccount() {
|
public Single<Integer> getFeedCountByAccount() {
|
||||||
return db.feedDao().getFeedCount(account.getId());
|
return database.feedDao().getFeedCount(account.getId());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,14 @@
|
||||||
package com.readrops.app.viewmodels
|
package com.readrops.app.viewmodels
|
||||||
|
|
||||||
import android.app.Application
|
|
||||||
import androidx.lifecycle.AndroidViewModel
|
|
||||||
import androidx.lifecycle.LiveData
|
import androidx.lifecycle.LiveData
|
||||||
|
import androidx.lifecycle.ViewModel
|
||||||
import com.readrops.db.Database
|
import com.readrops.db.Database
|
||||||
import com.readrops.db.entities.Feed
|
import com.readrops.db.entities.Feed
|
||||||
import com.readrops.db.entities.account.Account
|
import com.readrops.db.entities.account.Account
|
||||||
import io.reactivex.Completable
|
import io.reactivex.Completable
|
||||||
|
|
||||||
class NotificationPermissionViewModel(application: Application) : AndroidViewModel(application) {
|
class NotificationPermissionViewModel(val database: Database) : ViewModel() {
|
||||||
|
|
||||||
val database: Database = Database.getInstance(application)
|
|
||||||
var account: Account? = null
|
var account: Account? = null
|
||||||
|
|
||||||
fun getAccount(accountId: Int): LiveData<Account> = database.accountDao().selectAsync(accountId)
|
fun getAccount(accountId: Int): LiveData<Account> = database.accountDao().selectAsync(accountId)
|
||||||
|
|
|
@ -1,35 +0,0 @@
|
||||||
package com.readrops.app;
|
|
||||||
|
|
||||||
import com.readrops.app.utils.HtmlParser;
|
|
||||||
import com.readrops.app.utils.ParsingResult;
|
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
|
||||||
|
|
||||||
public class HtmlParserTest {
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getFeedLinkTest() throws Exception {
|
|
||||||
String url = "https://github.com/readrops/Readrops";
|
|
||||||
|
|
||||||
ParsingResult parsingResult = new ParsingResult("https://github.com/readrops/Readrops/commits/develop.atom", "Recent Commits to Readrops:develop");
|
|
||||||
List<ParsingResult> parsingResultList = new ArrayList<>();
|
|
||||||
parsingResultList.add(parsingResult);
|
|
||||||
|
|
||||||
List<ParsingResult> parsingResultList1 = HtmlParser.getFeedLink(url);
|
|
||||||
|
|
||||||
Assert.assertEquals(parsingResultList, parsingResultList1);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public void getFaviconLinkTest() {
|
|
||||||
String url = "https://github.com/readrops/Readrops";
|
|
||||||
|
|
||||||
assertEquals("https://github.com/fluidicon.png", HtmlParser.getFaviconLink(url));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,40 @@
|
||||||
|
package com.readrops.app
|
||||||
|
|
||||||
|
import com.readrops.app.utils.HtmlParser
|
||||||
|
import com.readrops.app.utils.ParsingResult
|
||||||
|
import junit.framework.TestCase
|
||||||
|
import okhttp3.OkHttpClient
|
||||||
|
import org.junit.Assert
|
||||||
|
import org.junit.Rule
|
||||||
|
import org.junit.Test
|
||||||
|
import org.koin.dsl.module
|
||||||
|
import org.koin.test.KoinTestRule
|
||||||
|
|
||||||
|
class HtmlParserTest {
|
||||||
|
|
||||||
|
@get:Rule
|
||||||
|
val koinTestRule = KoinTestRule.create {
|
||||||
|
modules(module {
|
||||||
|
single { OkHttpClient() }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getFeedLinkTest() {
|
||||||
|
val url = "https://github.com/readrops/Readrops"
|
||||||
|
val parsingResult = ParsingResult("https://github.com/readrops/Readrops/commits/develop.atom",
|
||||||
|
"Recent Commits to Readrops:develop")
|
||||||
|
|
||||||
|
val parsingResultList = mutableListOf(parsingResult)
|
||||||
|
|
||||||
|
val parsingResultList1 = HtmlParser.getFeedLink(url)
|
||||||
|
Assert.assertEquals(parsingResultList, parsingResultList1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun getFaviconLinkTest() {
|
||||||
|
val url = "https://github.com/readrops/Readrops"
|
||||||
|
|
||||||
|
TestCase.assertEquals("https://github.com/fluidicon.png", HtmlParser.getFaviconLink(url))
|
||||||
|
}
|
||||||
|
}
|
|
@ -72,4 +72,9 @@ dependencies {
|
||||||
api 'androidx.paging:paging-common:2.1.2'
|
api 'androidx.paging:paging-common:2.1.2'
|
||||||
|
|
||||||
api 'joda-time:joda-time:2.10.5'
|
api 'joda-time:joda-time:2.10.5'
|
||||||
|
|
||||||
|
def koin_version = "2.1.6"
|
||||||
|
api "org.koin:koin-android:$koin_version"
|
||||||
|
api "org.koin:koin-androidx-scope:$koin_version"
|
||||||
|
api "org.koin:koin-androidx-viewmodel:$koin_version"
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,6 @@
|
||||||
package com.readrops.db;
|
package com.readrops.db;
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
|
|
||||||
import androidx.annotation.NonNull;
|
import androidx.annotation.NonNull;
|
||||||
import androidx.room.Room;
|
|
||||||
import androidx.room.RoomDatabase;
|
import androidx.room.RoomDatabase;
|
||||||
import androidx.room.TypeConverters;
|
import androidx.room.TypeConverters;
|
||||||
import androidx.room.migration.Migration;
|
import androidx.room.migration.Migration;
|
||||||
|
@ -30,18 +27,7 @@ public abstract class Database extends RoomDatabase {
|
||||||
public abstract FolderDao folderDao();
|
public abstract FolderDao folderDao();
|
||||||
|
|
||||||
public abstract AccountDao accountDao();
|
public abstract AccountDao accountDao();
|
||||||
|
|
||||||
private static Database database;
|
|
||||||
|
|
||||||
public static Database getInstance(Context context) {
|
|
||||||
if (database == null)
|
|
||||||
database = Room.databaseBuilder(context, Database.class, "readrops-db")
|
|
||||||
.addMigrations(MIGRATION_1_2)
|
|
||||||
.build();
|
|
||||||
|
|
||||||
return database;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
|
public static final Migration MIGRATION_1_2 = new Migration(1, 2) {
|
||||||
@Override
|
@Override
|
||||||
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
public void migrate(@NonNull SupportSQLiteDatabase database) {
|
||||||
|
|
|
@ -0,0 +1,13 @@
|
||||||
|
package com.readrops.db
|
||||||
|
|
||||||
|
import androidx.room.Room
|
||||||
|
import org.koin.dsl.module
|
||||||
|
|
||||||
|
val dbModule = module {
|
||||||
|
|
||||||
|
single(createdAtStart = true) {
|
||||||
|
Room.databaseBuilder(get(), Database::class.java, "readrops-db")
|
||||||
|
.addMigrations(Database.MIGRATION_1_2)
|
||||||
|
.build()
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue