Skip to content

Commit

Permalink
Merge pull request nickbutcher#253 from nickbutcher/repo_dn
Browse files Browse the repository at this point in the history
Encapsulating work with Designer News in a repo.
  • Loading branch information
nickbutcher authored Jun 11, 2018
2 parents d9e8723 + a33a763 commit 6eeca86
Show file tree
Hide file tree
Showing 9 changed files with 230 additions and 126 deletions.
9 changes: 5 additions & 4 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ repositories {
}

dependencies {
implementation 'androidx.core:core-ktx:0.1'
implementation "androidx.core:core-ktx:${versions.ktx}"
implementation 'com.android.support.constraint:constraint-layout:1.1.0-beta5'
implementation "com.android.support:customtabs:${versions.supportLibrary}"
implementation "com.android.support:design:${versions.supportLibrary}"
Expand All @@ -80,13 +80,14 @@ dependencies {
annotationProcessor "com.github.bumptech.glide:compiler:${versions.glide}"
implementation "com.github.bumptech.glide:okhttp3-integration:${versions.glide}"
implementation "com.github.bumptech.glide:recyclerview-integration:${versions.glide}"
implementation 'com.google.code.gson:gson:2.8.2'
implementation "com.google.code.gson:gson:${versions.gson}"
implementation "com.jakewharton:butterknife:${versions.butterknife}"
annotationProcessor "com.jakewharton:butterknife-compiler:${versions.butterknife}"
implementation "com.squareup.retrofit2:retrofit:${versions.retrofit}"
implementation "com.squareup.retrofit2:converter-gson:${versions.retrofit}"
implementation 'com.squareup.okhttp3:okhttp:3.9.1'
implementation "com.squareup.okhttp3:okhttp:${versions.okhttp}"
implementation "com.squareup.okhttp3:logging-interceptor:${versions.okhttp}"
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:${versions.kotlin}"
implementation 'org.jsoup:jsoup:1.10.3'
implementation "org.jsoup:jsoup:${versions.jsoup}"
implementation project(':bypass')
}
30 changes: 17 additions & 13 deletions app/src/main/java/io/plaidapp/data/BaseDataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,14 +28,14 @@
import io.plaidapp.BuildConfig;
import io.plaidapp.data.api.AuthInterceptor;
import io.plaidapp.data.api.DenvelopingConverter;
import io.plaidapp.data.api.designernews.DesignerNewsService;
import io.plaidapp.data.api.dribbble.DribbbleSearchConverter;
import io.plaidapp.data.api.dribbble.DribbbleSearchService;
import io.plaidapp.data.api.dribbble.DribbbleService;
import io.plaidapp.data.api.producthunt.ProductHuntService;
import io.plaidapp.data.prefs.DesignerNewsPrefs;
import io.plaidapp.data.prefs.DribbblePrefs;
import okhttp3.OkHttpClient;
import okhttp3.logging.HttpLoggingInterceptor;
import okhttp3.logging.HttpLoggingInterceptor.Level;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;

Expand All @@ -47,15 +47,13 @@
public abstract class BaseDataManager<T> implements DataLoadingSubject {

private final AtomicInteger loadingCount;
private final DesignerNewsPrefs designerNewsPrefs;
private final DribbblePrefs dribbblePrefs;
private DribbbleSearchService dribbbleSearchApi;
private ProductHuntService productHuntApi;
private List<DataLoadingSubject.DataLoadingCallbacks> loadingCallbacks;

public BaseDataManager(@NonNull Context context) {
loadingCount = new AtomicInteger(0);
designerNewsPrefs = DesignerNewsPrefs.get(context);
dribbblePrefs = DribbblePrefs.get(context);
}

Expand All @@ -68,14 +66,6 @@ public boolean isDataLoading() {
return loadingCount.get() > 0;
}

public DesignerNewsPrefs getDesignerNewsPrefs() {
return designerNewsPrefs;
}

public DesignerNewsService getDesignerNewsApi() {
return designerNewsPrefs.getApi();
}

public DribbblePrefs getDribbblePrefs() {
return dribbblePrefs;
}
Expand Down Expand Up @@ -152,16 +142,22 @@ protected void dispatchLoadingFinishedCallbacks() {
}

private void createDribbbleSearchApi() {
final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(getHttpLoggingInterceptor())
.build();

dribbbleSearchApi = new Retrofit.Builder()
.baseUrl(DribbbleSearchService.ENDPOINT)
.addConverterFactory(new DribbbleSearchConverter.Factory())
.client(client)
.build()
.create((DribbbleSearchService.class));
}

private void createProductHuntApi() {
final OkHttpClient client = new OkHttpClient.Builder()
.addInterceptor(new AuthInterceptor(BuildConfig.PRODUCT_HUNT_DEVELOPER_TOKEN))
.addInterceptor(new AuthInterceptor(BuildConfig.PROCUCT_HUNT_DEVELOPER_TOKEN))
.addInterceptor(getHttpLoggingInterceptor())
.build();
final Gson gson = new Gson();
productHuntApi = new Retrofit.Builder()
Expand All @@ -173,4 +169,12 @@ private void createProductHuntApi() {
.create(ProductHuntService.class);
}

@NonNull
private HttpLoggingInterceptor getHttpLoggingInterceptor() {
Level debugLevel = BuildConfig.DEBUG ? Level.BASIC : Level.NONE;
HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor();
loggingInterceptor.setLevel(debugLevel);
return loggingInterceptor;
}

}
115 changes: 40 additions & 75 deletions app/src/main/java/io/plaidapp/data/DataManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,22 @@
package io.plaidapp.data;

import android.content.Context;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import io.plaidapp.data.api.designernews.model.Story;
import io.plaidapp.data.api.designernews.DesignerNewsRepository;
import io.plaidapp.data.api.dribbble.DribbbleSearchService;
import io.plaidapp.data.api.dribbble.DribbbleService;
import io.plaidapp.data.api.dribbble.model.Like;
import io.plaidapp.data.api.dribbble.model.Shot;
import io.plaidapp.data.api.dribbble.model.User;
import io.plaidapp.data.api.producthunt.model.Post;
import io.plaidapp.data.prefs.DesignerNewsPrefs;
import io.plaidapp.data.prefs.SourceManager;
import io.plaidapp.ui.FilterAdapter;
import retrofit2.Call;
Expand All @@ -40,15 +43,20 @@
* Responsible for loading data from the various sources. Instantiating classes are responsible for
* providing the {code onDataLoaded} method to do something with the data.
*/
public abstract class DataManager extends BaseDataManager<List<? extends PlaidItem>> {
public abstract class DataManager extends BaseDataManager<List<? extends PlaidItem>>
implements LoadSourceCallback {

private final DesignerNewsRepository designerNewsRepository;
private final FilterAdapter filterAdapter;
private Map<String, Integer> pageIndexes;
private Map<String, Call> inflight;

public DataManager(Context context,
FilterAdapter filterAdapter) {
super(context);
DesignerNewsPrefs designerNewsPrefs = DesignerNewsPrefs.get(context);
designerNewsRepository = new DesignerNewsRepository(designerNewsPrefs.getApi(),
designerNewsPrefs);
this.filterAdapter = filterAdapter;
filterAdapter.registerFilterChangedCallback(filterListener);
setupPageIndexes();
Expand All @@ -69,26 +77,28 @@ public void cancelLoading() {
}
inflight.clear();
}
designerNewsRepository.cancelAllRequests();
}

private final FilterAdapter.FiltersChangedCallbacks filterListener =
new FilterAdapter.FiltersChangedCallbacks() {
@Override
public void onFiltersChanged(Source changedFilter) {
if (changedFilter.active) {
loadSource(changedFilter);
} else { // filter deactivated
final String key = changedFilter.key;
if (inflight.containsKey(key)) {
final Call call = inflight.get(key);
if (call != null) call.cancel();
inflight.remove(key);
@Override
public void onFiltersChanged(Source changedFilter) {
if (changedFilter.active) {
loadSource(changedFilter);
} else { // filter deactivated
final String key = changedFilter.key;
if (inflight.containsKey(key)) {
final Call call = inflight.get(key);
if (call != null) call.cancel();
inflight.remove(key);
}
designerNewsRepository.cancelRequestOfSource(key);
// clear the page index for the source
pageIndexes.put(key, 0);
}
}
// clear the page index for the source
pageIndexes.put(key, 0);
}
}
};
};

private void loadSource(Source source) {
if (source.active) {
Expand Down Expand Up @@ -157,80 +167,35 @@ private boolean sourceIsEnabled(String key) {
return pageIndexes.get(key) != 0;
}

private void sourceLoaded(List<? extends PlaidItem> data, int page, String key) {
@Override
public void sourceLoaded(@Nullable List<? extends PlaidItem> data, int page,
@NonNull String source) {
loadFinished();
if (data != null && !data.isEmpty() && sourceIsEnabled(key)) {
if (data != null && !data.isEmpty() && sourceIsEnabled(source)) {
setPage(data, page);
setDataSource(data, key);
setDataSource(data, source);
onDataLoaded(data);
}
inflight.remove(key);
inflight.remove(source);
}

private void loadFailed(String key) {
@Override
public void loadFailed(@NonNull String source) {
loadFinished();
inflight.remove(key);
inflight.remove(source);
}

private void loadDesignerNewsTopStories(final int page) {
final Call<List<Story>> topStories = getDesignerNewsApi().getTopStories(page);
topStories.enqueue(new Callback<List<Story>>() {
@Override
public void onResponse(Call<List<Story>> call, Response<List<Story>> response) {
if (response.isSuccessful()) {
sourceLoaded(response.body(), page, SourceManager.SOURCE_DESIGNER_NEWS_POPULAR);
} else {
loadFailed(SourceManager.SOURCE_DESIGNER_NEWS_POPULAR);
}
}

@Override
public void onFailure(Call<List<Story>> call, Throwable t) {
loadFailed(SourceManager.SOURCE_DESIGNER_NEWS_POPULAR);
}
});
inflight.put(SourceManager.SOURCE_DESIGNER_NEWS_POPULAR, topStories);
designerNewsRepository.loadTopStories(page, this);
}

private void loadDesignerNewsRecent(final int page) {
final Call<List<Story>> recentStoriesCall = getDesignerNewsApi().getRecentStories(page);
recentStoriesCall.enqueue(new Callback<List<Story>>() {
@Override
public void onResponse(Call<List<Story>> call, Response<List<Story>> response) {
if (response.isSuccessful()) {
sourceLoaded(response.body(), page, SourceManager.SOURCE_DESIGNER_NEWS_RECENT);
} else {
loadFailed(SourceManager.SOURCE_DESIGNER_NEWS_RECENT);
}
}

@Override
public void onFailure(Call<List<Story>> call, Throwable t) {
loadFailed(SourceManager.SOURCE_DESIGNER_NEWS_RECENT);
}
});
inflight.put(SourceManager.SOURCE_DESIGNER_NEWS_RECENT, recentStoriesCall);
designerNewsRepository.loadRecent(page, this);
}

private void loadDesignerNewsSearch(final Source.DesignerNewsSearchSource source,
final int page) {
final Call<List<Story>> searchCall = getDesignerNewsApi().search(source.query, page);
searchCall.enqueue(new Callback<List<Story>>() {
@Override
public void onResponse(Call<List<Story>> call, Response<List<Story>> response) {
if (response.isSuccessful()) {
sourceLoaded(response.body(), page, source.key);
} else {
loadFailed(source.key);
}
}

@Override
public void onFailure(Call<List<Story>> call, Throwable t) {
loadFailed(source.key);
}
});
inflight.put(source.key, searchCall);
final int page) {
designerNewsRepository.search(source.key, page, this);
}

private void loadDribbblePopular(final int page) {
Expand Down
25 changes: 25 additions & 0 deletions app/src/main/java/io/plaidapp/data/LoadSourceCallback.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* Copyright 2018 Google Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/

package io.plaidapp.data

interface LoadSourceCallback {

fun sourceLoaded(result: List<PlaidItem>?, page: Int, source: String)

fun loadFailed(source: String)
}
Loading

0 comments on commit 6eeca86

Please sign in to comment.