diff --git a/.gitignore b/.gitignore index 74c68661..261dea50 100644 --- a/.gitignore +++ b/.gitignore @@ -33,4 +33,5 @@ target .DS_Store Thumbs.db *.swp -*.bak \ No newline at end of file +*.bak +marvel.properties diff --git a/build.gradle b/build.gradle index 1c96b603..93bde1a6 100644 --- a/build.gradle +++ b/build.gradle @@ -26,6 +26,7 @@ buildscript { allprojects { repositories { + mavenCentral() jcenter() } diff --git a/rosie/src/main/java/com/karumi/rosie/mapper/Mapper.java b/rosie/src/main/java/com/karumi/rosie/mapper/Mapper.java new file mode 100644 index 00000000..deaf2f3e --- /dev/null +++ b/rosie/src/main/java/com/karumi/rosie/mapper/Mapper.java @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.mapper; + +import java.util.ArrayList; +import java.util.Collection; + +public abstract class Mapper { + public abstract T2 map(T1 value); + public abstract T1 reverseMap(T2 value); + + public Collection map(Collection values) { + Collection returnValues = new ArrayList<>(); + for (T1 value : values) { + returnValues.add(map(value)); + } + return returnValues; + } + + public Collection reverseMap(Collection values) { + Collection returnValues = new ArrayList<>(); + for (T2 value : values) { + returnValues.add(reverseMap(value)); + } + return returnValues; + } +} diff --git a/rosie/src/main/java/com/karumi/rosie/repository/PaginatedRosieRepository.java b/rosie/src/main/java/com/karumi/rosie/repository/PaginatedRosieRepository.java index fd4848fc..43e1de1e 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/PaginatedRosieRepository.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/PaginatedRosieRepository.java @@ -30,13 +30,13 @@ */ public class PaginatedRosieRepository> extends RosieRepository { - private final Collection> paginatedReadableDataSources = + private final Collection> paginatedReadableDataSources = new LinkedList<>(); private final Collection> paginatedCacheDataSources = new LinkedList<>(); @SafeVarargs - protected final > void addPaginatedReadableDataSources( + protected final > void addPaginatedReadableDataSources( R... readables) { this.paginatedReadableDataSources.addAll(Arrays.asList(readables)); } @@ -52,7 +52,7 @@ protected final > void addPaginatedCach * * @param page Page to be retrieved */ - public PaginatedCollection getPage(Page page) { + public PaginatedCollection getPage(Page page) throws Exception { return getPage(page, ReadPolicy.READ_ALL); } @@ -62,7 +62,7 @@ public PaginatedCollection getPage(Page page) { * @param page Page to be retrieved * @param policy Specifies how the value is going to be retrieved. */ - public PaginatedCollection getPage(Page page, ReadPolicy policy) { + public PaginatedCollection getPage(Page page, ReadPolicy policy) throws Exception { PaginatedCollection values = null; if (policy.useCache()) { @@ -80,7 +80,7 @@ public PaginatedCollection getPage(Page page, ReadPolicy policy) { return values; } - protected PaginatedCollection getPaginatedValuesFromCaches(Page page) { + protected PaginatedCollection getPaginatedValuesFromCaches(Page page) throws Exception { PaginatedCollection values = null; for (PaginatedCacheDataSource cacheDataSource : paginatedCacheDataSources) { @@ -99,10 +99,10 @@ protected PaginatedCollection getPaginatedValuesFromCaches(Page page) { return values; } - protected PaginatedCollection getPaginatedValuesFromReadables(Page page) { + protected PaginatedCollection getPaginatedValuesFromReadables(Page page) throws Exception { PaginatedCollection values = null; - for (PaginatedReadableDataSource readable : paginatedReadableDataSources) { + for (PaginatedReadableDataSource readable : paginatedReadableDataSources) { values = readable.getPage(page); if (values != null) { @@ -113,7 +113,8 @@ protected PaginatedCollection getPaginatedValuesFromReadables(Page page) { return values; } - protected void populatePaginatedCaches(Page page, PaginatedCollection values) { + protected void populatePaginatedCaches(Page page, PaginatedCollection values) + throws Exception { for (PaginatedCacheDataSource cacheDataSource : paginatedCacheDataSources) { cacheDataSource.addOrUpdatePage(page, values.getItems(), values.hasMore()); } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/RosieRepository.java b/rosie/src/main/java/com/karumi/rosie/repository/RosieRepository.java index f7e19722..6a05822f 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/RosieRepository.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/RosieRepository.java @@ -61,7 +61,7 @@ public class RosieRepository> /** * {@link ReadableDataSource#getByKey(Object)} */ - @Override public V getByKey(K key) { + @Override public V getByKey(K key) throws Exception { return getByKey(key, ReadPolicy.READ_ALL); } @@ -70,7 +70,7 @@ public class RosieRepository> * * @param policy Specifies how the value is going to be retrieved. */ - public V getByKey(K key, ReadPolicy policy) { + public V getByKey(K key, ReadPolicy policy) throws Exception { validateKey(key); V value = null; @@ -93,7 +93,7 @@ public V getByKey(K key, ReadPolicy policy) { /** * {@link ReadableDataSource#getAll()} */ - @Override public Collection getAll() { + @Override public Collection getAll() throws Exception { return getAll(ReadPolicy.READ_ALL); } @@ -102,7 +102,7 @@ public V getByKey(K key, ReadPolicy policy) { * * @param policy Specifies how the value is going to be retrieved. */ - public Collection getAll(ReadPolicy policy) { + public Collection getAll(ReadPolicy policy) throws Exception { Collection values = null; if (policy.useCache()) { @@ -123,7 +123,7 @@ public Collection getAll(ReadPolicy policy) { /** * {@link WriteableDataSource#addOrUpdate(Identifiable)} */ - @Override public V addOrUpdate(V value) { + @Override public V addOrUpdate(V value) throws Exception { return addOrUpdate(value, WritePolicy.WRITE_ALL); } @@ -132,7 +132,7 @@ public Collection getAll(ReadPolicy policy) { * * @param policy Specifies how the value is going to be stored. */ - public V addOrUpdate(V value, WritePolicy policy) { + public V addOrUpdate(V value, WritePolicy policy) throws Exception { validateValue(value); V updatedValue = null; @@ -155,11 +155,11 @@ public V addOrUpdate(V value, WritePolicy policy) { /** * {@link WriteableDataSource#addOrUpdateAll(Collection)} */ - @Override public Collection addOrUpdateAll(Collection values) { + @Override public Collection addOrUpdateAll(Collection values) throws Exception { return addOrUpdateAll(values, WritePolicy.WRITE_ALL); } - public Collection addOrUpdateAll(Collection values, WritePolicy policy) { + public Collection addOrUpdateAll(Collection values, WritePolicy policy) throws Exception { validateValues(values); Collection updatedValues = null; @@ -182,7 +182,7 @@ public Collection addOrUpdateAll(Collection values, WritePolicy policy) { /** * {@link WriteableDataSource#deleteByKey(Object)} */ - @Override public void deleteByKey(K key) { + @Override public void deleteByKey(K key) throws Exception { for (WriteableDataSource writeableDataSource : writeableDataSources) { writeableDataSource.deleteByKey(key); } @@ -195,7 +195,7 @@ public Collection addOrUpdateAll(Collection values, WritePolicy policy) { /** * {@link WriteableDataSource#deleteAll()} */ - @Override public void deleteAll() { + @Override public void deleteAll() throws Exception { for (WriteableDataSource writeableDataSource : writeableDataSources) { writeableDataSource.deleteAll(); } @@ -205,7 +205,7 @@ public Collection addOrUpdateAll(Collection values, WritePolicy policy) { } } - private V getValueFromCaches(K id) { + private V getValueFromCaches(K id) throws Exception { V value = null; for (CacheDataSource cacheDataSource : cacheDataSources) { @@ -224,7 +224,7 @@ private V getValueFromCaches(K id) { return value; } - private Collection getValuesFromCaches() { + private Collection getValuesFromCaches() throws Exception { Collection values = null; for (CacheDataSource cacheDataSource : cacheDataSources) { @@ -243,7 +243,7 @@ private Collection getValuesFromCaches() { return values; } - private V getValueFromReadables(K key) { + private V getValueFromReadables(K key) throws Exception { V value = null; for (ReadableDataSource readableDataSource : readableDataSources) { @@ -257,7 +257,7 @@ private V getValueFromReadables(K key) { return value; } - protected Collection getValuesFromReadables() { + protected Collection getValuesFromReadables() throws Exception { Collection values = null; for (ReadableDataSource readableDataSource : readableDataSources) { @@ -271,13 +271,13 @@ protected Collection getValuesFromReadables() { return values; } - private void populateCaches(V value) { + private void populateCaches(V value) throws Exception { for (CacheDataSource cacheDataSource : cacheDataSources) { cacheDataSource.addOrUpdate(value); } } - protected void populateCaches(Collection values) { + protected void populateCaches(Collection values) throws Exception { for (CacheDataSource cacheDataSource : cacheDataSources) { cacheDataSource.addOrUpdateAll(values); } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyCacheDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyCacheDataSource.java index c9347956..fea29ee8 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyCacheDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyCacheDataSource.java @@ -23,27 +23,27 @@ */ public class EmptyCacheDataSource> implements CacheDataSource { - @Override public V getByKey(K key) { + @Override public V getByKey(K key) throws Exception { return null; } - @Override public Collection getAll() { + @Override public Collection getAll() throws Exception { return null; } - @Override public V addOrUpdate(V value) { + @Override public V addOrUpdate(V value) throws Exception { return null; } - @Override public Collection addOrUpdateAll(Collection values) { + @Override public Collection addOrUpdateAll(Collection values) throws Exception { return null; } - @Override public void deleteByKey(K key) { + @Override public void deleteByKey(K key) throws Exception { } - @Override public void deleteAll() { + @Override public void deleteAll() throws Exception { } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyPaginatedReadableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyPaginatedReadableDataSource.java new file mode 100644 index 00000000..05163a27 --- /dev/null +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyPaginatedReadableDataSource.java @@ -0,0 +1,33 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.repository.datasource; + +import com.karumi.rosie.repository.PaginatedCollection; +import com.karumi.rosie.repository.datasource.paginated.Page; +import com.karumi.rosie.repository.datasource.paginated.PaginatedReadableDataSource; + +/** + * Utility class to only override methods that are needed by your readable data source + * implementation. + */ +public class EmptyPaginatedReadableDataSource extends EmptyReadableDataSource + implements PaginatedReadableDataSource { + + @Override public PaginatedCollection getPage(Page page) throws Exception { + return null; + } +} diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyReadableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyReadableDataSource.java index a2986680..dec2e3f8 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyReadableDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/EmptyReadableDataSource.java @@ -24,11 +24,11 @@ */ public class EmptyReadableDataSource implements ReadableDataSource { - @Override public V getByKey(K key) { + @Override public V getByKey(K key) throws Exception { return null; } - @Override public Collection getAll() { + @Override public Collection getAll() throws Exception { return null; } } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/InMemoryCacheDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/InMemoryCacheDataSource.java index 1e3f9f8d..0fcfd2d7 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/InMemoryCacheDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/InMemoryCacheDataSource.java @@ -28,11 +28,11 @@ public class InMemoryCacheDataSource> implements CacheDataSource { - private final TimeProvider timeProvider; - private final long ttlInMillis; - private final List items; + protected final TimeProvider timeProvider; + protected final long ttlInMillis; + protected final List items; - private long lastItemsUpdate; + protected long lastItemsUpdate; public InMemoryCacheDataSource(TimeProvider timeProvider, long ttlInMillis) { this.timeProvider = timeProvider; diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/ReadableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/ReadableDataSource.java index 95bac3e8..d7d498ee 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/ReadableDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/ReadableDataSource.java @@ -32,7 +32,7 @@ public interface ReadableDataSource { * @param key The key that uniquely identifies the requested value. * @return The value associated to the provided key or null if there is not any. */ - V getByKey(K key); + V getByKey(K key) throws Exception; /** * Returns all the values available in the data source or null if the operation does not make @@ -40,5 +40,5 @@ public interface ReadableDataSource { * * @return A collection of values or null if the operation is not implemented by this data source. */ - Collection getAll(); + Collection getAll() throws Exception; } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/WriteableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/WriteableDataSource.java index 19f57857..b39b495d 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/WriteableDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/WriteableDataSource.java @@ -31,7 +31,7 @@ public interface WriteableDataSource> { * @param value The value to be persisted. * @return The value after its addition or update. */ - V addOrUpdate(V value); + V addOrUpdate(V value) throws Exception; /** * Add or updates all the provided values into this data source. @@ -39,17 +39,17 @@ public interface WriteableDataSource> { * @param values A collection of values to be added or persisted. * @return The values that has been persisted. */ - Collection addOrUpdateAll(Collection values); + Collection addOrUpdateAll(Collection values) throws Exception; /** * Deletes a value given its associated key. * * @param key The key that uniquely identifies the value to be deleted. */ - void deleteByKey(K key); + void deleteByKey(K key) throws Exception; /** * Delete all the values stored in this data source. */ - void deleteAll(); + void deleteAll() throws Exception; } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/EmptyPaginatedCacheDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/EmptyPaginatedCacheDataSource.java index d0ba9d44..465209a4 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/EmptyPaginatedCacheDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/EmptyPaginatedCacheDataSource.java @@ -27,16 +27,36 @@ public class EmptyPaginatedCacheDataSource> return false; } - @Override public PaginatedCollection getPage(Page page) { + @Override public PaginatedCollection getPage(Page page) throws Exception { return null; } @Override - public PaginatedCollection addOrUpdatePage(Page page, Collection values, boolean hasMore) { + public PaginatedCollection addOrUpdatePage(Page page, Collection values, boolean hasMore) throws Exception { return null; } - @Override public void deleteAll() { + @Override public V addOrUpdate(V value) throws Exception { + return null; + } + + @Override public Collection addOrUpdateAll(Collection values) throws Exception { + return null; + } + + @Override public void deleteByKey(K key) throws Exception { + + } + @Override public void deleteAll() throws Exception { + + } + + @Override public V getByKey(K key) throws Exception { + return null; + } + + @Override public Collection getAll() throws Exception { + return null; } } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/InMemoryPaginatedCacheDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/InMemoryPaginatedCacheDataSource.java index 7bb48b6a..c2ea294b 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/InMemoryPaginatedCacheDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/InMemoryPaginatedCacheDataSource.java @@ -18,26 +18,19 @@ import com.karumi.rosie.repository.PaginatedCollection; import com.karumi.rosie.repository.datasource.Identifiable; +import com.karumi.rosie.repository.datasource.InMemoryCacheDataSource; import com.karumi.rosie.time.TimeProvider; -import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; import java.util.List; public class InMemoryPaginatedCacheDataSource> - implements PaginatedCacheDataSource { + extends InMemoryCacheDataSource implements PaginatedCacheDataSource { - private final TimeProvider timeProvider; - private final long ttlInMillis; - private final List items; - - private long lastItemsUpdate; private boolean hasMore; public InMemoryPaginatedCacheDataSource(TimeProvider timeProvider, long ttlInMillis) { - this.timeProvider = timeProvider; - this.ttlInMillis = ttlInMillis; - this.items = new ArrayList<>(); + super(timeProvider, ttlInMillis); } @Override public PaginatedCollection getPage(Page page) { diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedCacheDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedCacheDataSource.java index bee869f1..fa00f0ba 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedCacheDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedCacheDataSource.java @@ -16,6 +16,7 @@ package com.karumi.rosie.repository.datasource.paginated; +import com.karumi.rosie.repository.datasource.CacheDataSource; import com.karumi.rosie.repository.datasource.Identifiable; /** @@ -26,7 +27,8 @@ * @param The class of the values retrieved from this data source. */ public interface PaginatedCacheDataSource> - extends PaginatedReadableDataSource, PaginatedWriteableDataSource { + extends PaginatedReadableDataSource, CacheDataSource, + PaginatedWriteableDataSource { /** * Returns true whether the value stored in this cache is still valid. diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedReadableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedReadableDataSource.java index 60a19211..30b77b01 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedReadableDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedReadableDataSource.java @@ -17,17 +17,18 @@ package com.karumi.rosie.repository.datasource.paginated; import com.karumi.rosie.repository.PaginatedCollection; +import com.karumi.rosie.repository.datasource.ReadableDataSource; /** * Data source interface meant to be used only to retrieve pages of data. * * @param The class of the values retrieved from this data source. */ -public interface PaginatedReadableDataSource { +public interface PaginatedReadableDataSource extends ReadableDataSource { /** * Returns a page of values bounded by the provided page. * * @param page page to be retrieved */ - PaginatedCollection getPage(Page page); + PaginatedCollection getPage(Page page) throws Exception; } diff --git a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedWriteableDataSource.java b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedWriteableDataSource.java index b74020d9..96c2f081 100644 --- a/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedWriteableDataSource.java +++ b/rosie/src/main/java/com/karumi/rosie/repository/datasource/paginated/PaginatedWriteableDataSource.java @@ -34,10 +34,11 @@ public interface PaginatedWriteableDataSource> { * @param values Collection of values to be stored * @param hasMore True whether the persisted page has more elements */ - PaginatedCollection addOrUpdatePage(Page page, Collection values, boolean hasMore); + PaginatedCollection addOrUpdatePage(Page page, Collection values, boolean hasMore) + throws Exception; /** * Deletes all the pages stored in this data source. */ - void deleteAll(); + void deleteAll() throws Exception; } diff --git a/rosie/src/test/java/com/karumi/rosie/repository/PaginatedRosieRepositoryTest.java b/rosie/src/test/java/com/karumi/rosie/repository/PaginatedRosieRepositoryTest.java index 762d4ffe..7fba9eeb 100644 --- a/rosie/src/test/java/com/karumi/rosie/repository/PaginatedRosieRepositoryTest.java +++ b/rosie/src/test/java/com/karumi/rosie/repository/PaginatedRosieRepositoryTest.java @@ -38,7 +38,8 @@ public class PaginatedRosieRepositoryTest extends UnitTest { private static final int ANY_LIMIT = 20; @Mock private PaginatedCacheDataSource cacheDataSource; - @Mock private PaginatedReadableDataSource readableDataSource; + @Mock private PaginatedReadableDataSource + readableDataSource; @Test public void shouldReturnValuesFromCacheDataSourceIfDataIsValid() throws Exception { Page page = Page.withOffsetAndLimit(ANY_OFFSET, ANY_LIMIT); @@ -143,14 +144,15 @@ private PaginatedCollection givenCacheDataSourceReturnsNonVa } private PaginatedCollection givenCacheDataSourceReturnsValues(Page page, - boolean areValidValues) { + boolean areValidValues) throws Exception { PaginatedCollection values = getSomeValues(page); when(cacheDataSource.getPage(page)).thenReturn(values); when(cacheDataSource.isValid(any(AnyRepositoryValue.class))).thenReturn(areValidValues); return values; } - private PaginatedCollection givenReadableDataSourceReturnsValues(Page page) { + private PaginatedCollection givenReadableDataSourceReturnsValues(Page page) + throws Exception { PaginatedCollection values = getSomeValues(page); when(readableDataSource.getPage(page)).thenReturn(values); return values; diff --git a/rosie/src/test/java/com/karumi/rosie/repository/RosieRepositoryTest.java b/rosie/src/test/java/com/karumi/rosie/repository/RosieRepositoryTest.java index f630fcdb..90990a36 100644 --- a/rosie/src/test/java/com/karumi/rosie/repository/RosieRepositoryTest.java +++ b/rosie/src/test/java/com/karumi/rosie/repository/RosieRepositoryTest.java @@ -344,7 +344,7 @@ private AnyRepositoryValue givenCacheDataSourceReturnsNonValidValueWithKey(AnyRe } @NonNull private AnyRepositoryValue givenCacheDataSourceReturnsValueWithKey(AnyRepositoryKey key, - boolean isValidValue) { + boolean isValidValue) throws Exception { AnyRepositoryValue value = new AnyRepositoryValue(key); when(cacheDataSource.getByKey(key)).thenReturn(value); when(cacheDataSource.isValid(value)).thenReturn(isValidValue); @@ -352,7 +352,8 @@ private AnyRepositoryValue givenCacheDataSourceReturnsNonValidValueWithKey(AnyRe } @NonNull - private AnyRepositoryValue givenReadableDataSourceReturnsValidValueWithKey(AnyRepositoryKey key) { + private AnyRepositoryValue givenReadableDataSourceReturnsValidValueWithKey(AnyRepositoryKey key) + throws Exception { AnyRepositoryValue value = new AnyRepositoryValue(key); when(readableDataSource.getByKey(key)).thenReturn(value); return value; @@ -367,7 +368,8 @@ private Collection givenCacheDataSourceReturnsNonValidValues return givenCacheDataSourceReturnsValues(false); } - private Collection givenCacheDataSourceReturnsValues(boolean areValidValues) { + private Collection givenCacheDataSourceReturnsValues(boolean areValidValues) + throws Exception { Collection values = getSomeValues(); when(cacheDataSource.getAll()).thenReturn(values); when(cacheDataSource.isValid(any(AnyRepositoryValue.class))).thenReturn(areValidValues); @@ -381,26 +383,29 @@ private Collection givenReadableDataSourceReturnsValidValues return values; } - private void givenReadableDataSourceThrowsException() { + private void givenReadableDataSourceThrowsException() throws Exception { when(readableDataSource.getAll()).thenThrow(new Exception()); } - private AnyRepositoryValue givenWriteableDataSourceWritesValue(AnyRepositoryValue value) { + private AnyRepositoryValue givenWriteableDataSourceWritesValue(AnyRepositoryValue value) + throws Exception { AnyRepositoryValue writeableValue = new AnyRepositoryValue(value.getKey()); when(writeableDataSource.addOrUpdate(value)).thenReturn(writeableValue); return writeableValue; } - private void givenWriteableDataSourceDoesNotWriteValue(AnyRepositoryValue value) { + private void givenWriteableDataSourceDoesNotWriteValue(AnyRepositoryValue value) + throws Exception { when(writeableDataSource.addOrUpdate(value)).thenReturn(null); } - private void givenWriteableDataSourceDoesNotWriteValues(Collection values) { + private void givenWriteableDataSourceDoesNotWriteValues(Collection values) + throws Exception { when(writeableDataSource.addOrUpdateAll(values)).thenReturn(null); } private Collection givenWriteableDataSourceWritesValues( - Collection values) { + Collection values) throws Exception { Collection updatedValues = new LinkedList<>(values); when(writeableDataSource.addOrUpdateAll(values)).thenReturn(values); return updatedValues; diff --git a/sample/build.gradle b/sample/build.gradle index 206d5eb4..e522bf3a 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -16,6 +16,32 @@ apply plugin: 'com.android.application' +private Properties loadMarvelProperties() { + Properties props = new Properties() + props.load(new FileInputStream("./sample/marvel.properties")) + props +} + +private checkMarvelProperties() { + new File("./sample/marvel.properties").exists() +} + +def getPublicMarvelKey() { + if (checkMarvelProperties()) { + Properties props = loadMarvelProperties() + return props['MARVEL_PUBLIC_KEY'] + } + "null" +} + +def getPrivateMarvelKey() { + if (checkMarvelProperties()) { + Properties props = loadMarvelProperties() + return props['MARVEL_PRIVATE_KEY'] + } + "null" +} + android { compileSdkVersion 23 buildToolsVersion "23.0.1" @@ -26,6 +52,8 @@ android { targetSdkVersion 23 versionCode 1 versionName "1.0" + buildConfigField "String", "MARVEL_PUBLIC_KEY", getPublicMarvelKey() + buildConfigField "String", "MARVEL_PRIVATE_KEY", getPrivateMarvelKey() } } @@ -36,9 +64,9 @@ dependencies { compile 'com.android.support:support-v13:23.1.1' compile 'com.android.support:design:23.1.1' compile 'com.squareup.picasso:picasso:2.5.2' - compile 'fr.avianey.com.viewpagerindicator:library:2.4.1@aar' compile 'com.karumi:dividers:1.0.3' - compile 'com.victor:lib:1.0.1' + compile 'com.victor:lib:1.0.1' // https://github.com/yankai-victor/Loading + compile 'com.karumi:marvelapiclient:0.0.1' provided 'com.squareup.dagger:dagger-compiler:1.2.2' compile project(':rosie') } diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 63968d4a..d9aa7bc9 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -31,7 +31,7 @@ @@ -41,7 +41,7 @@ - + diff --git a/sample/src/main/java/com/karumi/rosie/sample/base/view/activity/MarvelActivity.java b/sample/src/main/java/com/karumi/rosie/sample/base/view/activity/MarvelActivity.java new file mode 100644 index 00000000..26fe2823 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/base/view/activity/MarvelActivity.java @@ -0,0 +1,31 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.base.view.activity; + +import android.support.annotation.Nullable; +import butterknife.OnClick; +import com.karumi.rosie.sample.R; +import com.karumi.rosie.view.RosieActivity; + +public abstract class MarvelActivity extends RosieActivity { + @Override protected abstract int getLayoutId(); + + @Nullable @OnClick(R.id.iv_toolbar_back) public void onBackButtonClicked() { + finish(); + } + +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/domain/usecase/GetCharacterDetails.java b/sample/src/main/java/com/karumi/rosie/sample/characters/domain/usecase/GetCharacterDetails.java index 838920dd..9c3a8d99 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/characters/domain/usecase/GetCharacterDetails.java +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/domain/usecase/GetCharacterDetails.java @@ -30,7 +30,7 @@ public class GetCharacterDetails extends RosieUseCase { this.charactersRepository = charactersRepository; } - @UseCase public void getCharacterDetails(String characterKey) { + @UseCase public void getCharacterDetails(String characterKey) throws Exception { Character character = charactersRepository.getByKey(characterKey); notifySuccess(character); } diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharacterDataSourceFactory.java b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharacterDataSourceFactory.java new file mode 100644 index 00000000..6de8ed5b --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharacterDataSourceFactory.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.characters.repository; + +import com.karumi.marvelapiclient.CharacterApiClient; +import com.karumi.marvelapiclient.MarvelApiConfig; +import com.karumi.rosie.repository.datasource.paginated.PaginatedReadableDataSource; +import com.karumi.rosie.sample.BuildConfig; +import com.karumi.rosie.sample.characters.domain.model.Character; +import com.karumi.rosie.sample.characters.repository.datasource.CharactersApiDataSource; +import com.karumi.rosie.sample.characters.repository.datasource.CharactersFakeDataSource; +import javax.inject.Inject; + +class CharacterDataSourceFactory { + + @Inject public CharacterDataSourceFactory() { + } + + PaginatedReadableDataSource createDataSource() { + if (hasKeys()) { + MarvelApiConfig marvelApiConfig = + MarvelApiConfig.with(BuildConfig.MARVEL_PUBLIC_KEY, BuildConfig.MARVEL_PRIVATE_KEY); + CharacterApiClient characterApiClient = new CharacterApiClient(marvelApiConfig); + return new CharactersApiDataSource(characterApiClient); + } else { + return new CharactersFakeDataSource(); + } + } + + private boolean hasKeys() { + return BuildConfig.MARVEL_PUBLIC_KEY != null && BuildConfig.MARVEL_PRIVATE_KEY != null; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharactersRepository.java b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharactersRepository.java index 133d6012..37e36268 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharactersRepository.java +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/CharactersRepository.java @@ -17,24 +17,21 @@ package com.karumi.rosie.sample.characters.repository; import com.karumi.rosie.repository.PaginatedRosieRepository; -import com.karumi.rosie.repository.datasource.CacheDataSource; import com.karumi.rosie.repository.datasource.paginated.PaginatedCacheDataSource; +import com.karumi.rosie.repository.datasource.paginated.PaginatedReadableDataSource; import com.karumi.rosie.sample.characters.domain.model.Character; -import com.karumi.rosie.sample.characters.repository.datasource.CharactersApiDataSource; -import com.karumi.rosie.sample.main.ApplicationModule; import javax.inject.Inject; -import javax.inject.Named; public class CharactersRepository extends PaginatedRosieRepository { - @Inject public CharactersRepository(CharactersApiDataSource apiDataSource, - @Named(ApplicationModule.CHARACTERS_PAGE_IN_MEMORY_CACHE) - PaginatedCacheDataSource inMemoryPaginatedCache, - @Named(ApplicationModule.CHARACTERS_IN_MEMORY_CACHE) - CacheDataSource inMemoryCache) { - addReadableDataSources(apiDataSource); - addCacheDataSources(inMemoryCache); - addPaginatedReadableDataSources(apiDataSource); + @Inject public CharactersRepository(CharacterDataSourceFactory characterDataSourceFactory, + PaginatedCacheDataSource inMemoryPaginatedCache) { + addCacheDataSources(inMemoryPaginatedCache); addPaginatedCacheDataSources(inMemoryPaginatedCache); + + PaginatedReadableDataSource characterDataSource = + characterDataSourceFactory.createDataSource(); + addReadableDataSources(characterDataSource); + addPaginatedReadableDataSources(characterDataSource); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersApiDataSource.java b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersApiDataSource.java index 316fa0f1..50ac7880 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersApiDataSource.java +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersApiDataSource.java @@ -16,154 +16,50 @@ package com.karumi.rosie.sample.characters.repository.datasource; -import android.support.annotation.NonNull; +import com.karumi.marvelapiclient.CharacterApiClient; +import com.karumi.marvelapiclient.MarvelApiException; +import com.karumi.marvelapiclient.model.CharacterDto; +import com.karumi.marvelapiclient.model.CharactersDto; +import com.karumi.marvelapiclient.model.MarvelResponse; import com.karumi.rosie.repository.PaginatedCollection; import com.karumi.rosie.repository.datasource.EmptyReadableDataSource; import com.karumi.rosie.repository.datasource.paginated.Page; import com.karumi.rosie.repository.datasource.paginated.PaginatedReadableDataSource; import com.karumi.rosie.sample.characters.domain.model.Character; +import com.karumi.rosie.sample.characters.repository.datasource.mapper.CharacterToCharacterDtoMapper; import java.util.Collection; -import java.util.LinkedList; -import java.util.Random; import javax.inject.Inject; public class CharactersApiDataSource extends EmptyReadableDataSource - implements PaginatedReadableDataSource { + implements PaginatedReadableDataSource { - private static final int NUMBER_OF_CHARACTERS = 45; - private static final long SLEEP_TIME_IN_MILLISECONDS = 1000; - private static final Random RANDOM = new Random(System.nanoTime()); - private static final String SPIDERMAN_KEY = "54"; - private static final String CAPTAIN_MARVEL_KEY = "9"; - private static final String HULK_KEY = "25"; - private static final String THOR_KEY = "60"; - private static final String IRON_MAN_KEY = "29"; + private final CharacterApiClient characterApiClient; + private final CharacterToCharacterDtoMapper mapper = new CharacterToCharacterDtoMapper(); - @Inject public CharactersApiDataSource() { + @Inject public CharactersApiDataSource(CharacterApiClient characterApiClient) { + this.characterApiClient = characterApiClient; } - @Override public Character getByKey(String key) { - Character character; + @Override public Character getByKey(String key) throws Exception { + MarvelResponse characterResponse = characterApiClient.getCharacter(key); + CharacterDto characterDto = characterResponse.getResponse(); - fakeDelay(); - - switch (key) { - case SPIDERMAN_KEY: - character = getSpiderman(); - break; - case CAPTAIN_MARVEL_KEY: - character = getCaptainMarvel(); - break; - case HULK_KEY: - character = getHulk(); - break; - case THOR_KEY: - character = getThor(); - break; - case IRON_MAN_KEY: - default: - character = getIronMan(); - break; - } - - return character; + return mapper.reverseMap(characterDto); } - @Override public PaginatedCollection getPage(Page page) { - Collection characters = new LinkedList<>(); - - fakeDelay(); - + @Override public PaginatedCollection getPage(Page page) + throws MarvelApiException { int offset = page.getOffset(); int limit = page.getLimit(); + MarvelResponse charactersApiResponse = characterApiClient.getAll(offset, limit); - for (int i = offset; i - offset < limit && i < NUMBER_OF_CHARACTERS; i++) { - characters.add(getCharacter(i)); - } + CharactersDto charactersDto = charactersApiResponse.getResponse(); + Collection characters = mapper.reverseMap(charactersDto.getCharacters()); PaginatedCollection charactersPage = new PaginatedCollection<>(characters); charactersPage.setPage(page); - charactersPage.setHasMore(offset + characters.size() < NUMBER_OF_CHARACTERS); + charactersPage.setHasMore( + charactersDto.getOffset() + charactersDto.getCount() < charactersDto.getTotal()); return charactersPage; } - - private Character getCharacter(int i) { - Character[] characters = - {getSpiderman(), getCaptainMarvel(), getHulk(), getThor(), getIronMan()}; - - Character character = characters[RANDOM.nextInt(characters.length)]; - character.setName(character.getName() + " " + i); - return character; - } - - @NonNull private Character getSpiderman() { - Character spiderman = new Character(); - spiderman.setKey(SPIDERMAN_KEY); - spiderman.setName("Spiderman"); - spiderman.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/6/60/538cd3628a05e.jpg"); - spiderman.setDescription( - "Bitten by a radioactive spider, high school student Peter Parker gained the speed, " - + "strength and powers of a spider. Adopting the name Spider-Man, Peter hoped to start" - + " a career using his new abilities. Taught that with great power comes great" - + " responsibility, Spidey has vowed to use his powers to help people."); - return spiderman; - } - - @NonNull private Character getCaptainMarvel() { - Character captainMarvel = new Character(); - captainMarvel.setKey(CAPTAIN_MARVEL_KEY); - captainMarvel.setName("Captain Marvel"); - captainMarvel.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/6/30/537ba61b764b4.jpg"); - captainMarvel.setDescription( - "Carol Danvers entered the Air Force upon graduating from high school to pursue her love" - + " of aircrafts and her dreams of flying."); - return captainMarvel; - } - - @NonNull private Character getHulk() { - Character hulk = new Character(); - hulk.setKey(HULK_KEY); - hulk.setName("Hulk"); - hulk.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/e/e0/537bafa34baa9.jpg"); - hulk.setDescription( - "Caught in a gamma bomb explosion while trying to save the life of a teenager, Dr. Bruce" - + " Banner was transformed into the incredibly powerful creature called the Hulk. An" - + " all too often misunderstood hero, the angrier the Hulk gets, the stronger the Hulk" - + " gets."); - return hulk; - } - - @NonNull private Character getThor() { - Character hulk = new Character(); - hulk.setKey(THOR_KEY); - hulk.setName("Thor"); - hulk.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/7/10/537bc71e9286f.jpg"); - hulk.setDescription( - "As the Norse God of thunder and lightning, Thor wields one of the greatest weapons ever" - + " made, the enchanted hammer Mjolnir. While others have described Thor as an" - + " over-muscled, oafish imbecile, he's quite smart and compassionate." - + " He's self-assured, and he would never, ever stop fighting for a worthwhile cause."); - return hulk; - } - - @NonNull private Character getIronMan() { - Character hulk = new Character(); - hulk.setKey(IRON_MAN_KEY); - hulk.setName("Iron Man"); - hulk.setThumbnailUrl("http://i.annihil.us/u/prod/marvel/i/mg/c/60/55b6a28ef24fa.jpg"); - hulk.setDescription( - "Wounded, captured and forced to build a weapon by his enemies, billionaire industrialist" - + " Tony Stark instead created an advanced suit of armor to save his life and escape" - + " captivity. Now with a new outlook on life, Tony uses his money and intelligence" - + " to make the world a safer, better place as Iron Man."); - return hulk; - } - - private void fakeDelay() { - try { - Thread.sleep(SLEEP_TIME_IN_MILLISECONDS); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersFakeDataSource.java b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersFakeDataSource.java new file mode 100644 index 00000000..dd619e4c --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/CharactersFakeDataSource.java @@ -0,0 +1,166 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.characters.repository.datasource; + +import android.support.annotation.NonNull; +import com.karumi.marvelapiclient.MarvelApiException; +import com.karumi.rosie.repository.PaginatedCollection; +import com.karumi.rosie.repository.datasource.EmptyPaginatedReadableDataSource; +import com.karumi.rosie.repository.datasource.paginated.Page; +import com.karumi.rosie.sample.characters.domain.model.Character; +import java.util.Collection; +import java.util.LinkedList; +import java.util.Random; +import javax.inject.Inject; + +public class CharactersFakeDataSource extends EmptyPaginatedReadableDataSource { + + private static final int NUMBER_OF_CHARACTERS = 45; + private static final long SLEEP_TIME_IN_MILLISECONDS = 1000; + private static final Random RANDOM = new Random(System.nanoTime()); + private static final String SPIDERMAN_KEY = "54"; + private static final String CAPTAIN_MARVEL_KEY = "9"; + private static final String HULK_KEY = "25"; + private static final String THOR_KEY = "60"; + private static final String IRON_MAN_KEY = "29"; + + @Inject public CharactersFakeDataSource() { + } + + @Override public Character getByKey(String key) throws Exception { + Character character; + fakeDelay(); + + switch (key) { + case SPIDERMAN_KEY: + character = getSpiderman(); + break; + case CAPTAIN_MARVEL_KEY: + character = getCaptainMarvel(); + break; + case HULK_KEY: + character = getHulk(); + break; + case THOR_KEY: + character = getThor(); + break; + case IRON_MAN_KEY: + default: + character = getIronMan(); + break; + } + + return character; + } + + @Override public PaginatedCollection getPage(Page page) + throws MarvelApiException { + int offset = page.getOffset(); + int limit = page.getLimit(); + + Collection characters = new LinkedList<>(); + fakeDelay(); + + for (int i = offset; i - offset < limit && i < NUMBER_OF_CHARACTERS; i++) { + characters.add(getCharacter(i)); + } + + PaginatedCollection charactersPage = new PaginatedCollection<>(characters); + charactersPage.setPage(page); + charactersPage.setHasMore(offset + characters.size() < NUMBER_OF_CHARACTERS); + return charactersPage; + } + + private Character getCharacter(int i) { + Character[] characters = + {getSpiderman(), getCaptainMarvel(), getHulk(), getThor(), getIronMan()}; + + Character character = characters[RANDOM.nextInt(characters.length)]; + character.setName(character.getName() + " " + i); + return character; + } + + @NonNull private Character getSpiderman() { + Character spiderman = new Character(); + spiderman.setKey(SPIDERMAN_KEY); + spiderman.setName("Spiderman"); + spiderman.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/6/60/538cd3628a05e.jpg"); + spiderman.setDescription( + "Bitten by a radioactive spider, high school student Peter Parker gained the speed, " + + "strength and powers of a spider. Adopting the name Spider-Man, Peter hoped to start" + + " a career using his new abilities. Taught that with great power comes great" + + " responsibility, Spidey has vowed to use his powers to help people."); + return spiderman; + } + + @NonNull private Character getCaptainMarvel() { + Character captainMarvel = new Character(); + captainMarvel.setKey(CAPTAIN_MARVEL_KEY); + captainMarvel.setName("Captain Marvel"); + captainMarvel.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/6/30/537ba61b764b4.jpg"); + captainMarvel.setDescription( + "Carol Danvers entered the Air Force upon graduating from high school to pursue her love" + + " of aircrafts and her dreams of flying."); + return captainMarvel; + } + + @NonNull private Character getHulk() { + Character hulk = new Character(); + hulk.setKey(HULK_KEY); + hulk.setName("Hulk"); + hulk.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/e/e0/537bafa34baa9.jpg"); + hulk.setDescription( + "Caught in a gamma bomb explosion while trying to save the life of a teenager, Dr. Bruce" + + " Banner was transformed into the incredibly powerful creature called the Hulk. An" + + " all too often misunderstood hero, the angrier the Hulk gets, the stronger the Hulk" + + " gets."); + return hulk; + } + + @NonNull private Character getThor() { + Character hulk = new Character(); + hulk.setKey(THOR_KEY); + hulk.setName("Thor"); + hulk.setThumbnailUrl("http://x.annihil.us/u/prod/marvel/i/mg/7/10/537bc71e9286f.jpg"); + hulk.setDescription( + "As the Norse God of thunder and lightning, Thor wields one of the greatest weapons ever" + + " made, the enchanted hammer Mjolnir. While others have described Thor as an" + + " over-muscled, oafish imbecile, he's quite smart and compassionate." + + " He's self-assured, and he would never, ever stop fighting for a worthwhile cause."); + return hulk; + } + + @NonNull private Character getIronMan() { + Character hulk = new Character(); + hulk.setKey(IRON_MAN_KEY); + hulk.setName("Iron Man"); + hulk.setThumbnailUrl("http://i.annihil.us/u/prod/marvel/i/mg/c/60/55b6a28ef24fa.jpg"); + hulk.setDescription( + "Wounded, captured and forced to build a weapon by his enemies, billionaire industrialist" + + " Tony Stark instead created an advanced suit of armor to save his life and escape" + + " captivity. Now with a new outlook on life, Tony uses his money and intelligence" + + " to make the world a safer, better place as Iron Man."); + return hulk; + } + + private void fakeDelay() { + try { + Thread.sleep(SLEEP_TIME_IN_MILLISECONDS); + } catch (InterruptedException e) { + } + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/mapper/CharacterToCharacterDtoMapper.java b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/mapper/CharacterToCharacterDtoMapper.java new file mode 100644 index 00000000..bbcfad5b --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/repository/datasource/mapper/CharacterToCharacterDtoMapper.java @@ -0,0 +1,38 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.characters.repository.datasource.mapper; + +import com.karumi.marvelapiclient.model.CharacterDto; +import com.karumi.marvelapiclient.model.MarvelImage; +import com.karumi.rosie.mapper.Mapper; +import com.karumi.rosie.sample.characters.domain.model.Character; + +public class CharacterToCharacterDtoMapper extends Mapper { + + @Override public CharacterDto map(Character value) { + throw new UnsupportedOperationException(); + } + + @Override public Character reverseMap(CharacterDto value) { + Character character = new Character(); + character.setKey(value.getId()); + character.setName(value.getName()); + character.setDescription(value.getDescription()); + character.setThumbnailUrl(value.getThumbnail().getImageUrl(MarvelImage.Size.PORTRAIT_UNCANNY)); + return character; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/characters/view/activity/CharacterDetailsActivity.java b/sample/src/main/java/com/karumi/rosie/sample/characters/view/activity/CharacterDetailsActivity.java index 117e5a11..1a0f64c4 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/characters/view/activity/CharacterDetailsActivity.java +++ b/sample/src/main/java/com/karumi/rosie/sample/characters/view/activity/CharacterDetailsActivity.java @@ -24,22 +24,23 @@ import android.widget.TextView; import butterknife.Bind; import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.base.view.activity.MarvelActivity; import com.karumi.rosie.sample.characters.CharactersModule; import com.karumi.rosie.sample.characters.view.presenter.CharacterDetailsPresenter; import com.karumi.rosie.sample.characters.view.viewmodel.CharacterDetailViewModel; import com.karumi.rosie.view.Presenter; -import com.karumi.rosie.view.RosieActivity; import com.squareup.picasso.Picasso; import com.victor.loading.rotate.RotateLoading; import java.util.Arrays; import java.util.List; import javax.inject.Inject; -public class CharacterDetailsActivity extends RosieActivity +public class CharacterDetailsActivity extends MarvelActivity implements CharacterDetailsPresenter.View { private static final String CHARACTER_KEY_EXTRA = "CharacterDetailsActivity.CharacterKey"; + @Bind(R.id.tv_toolbar_title) TextView toolbarTitleView; @Bind(R.id.iv_character_image) ImageView characterHeaderView; @Bind(R.id.ll_character_detail) View characterDetailView; @Bind(R.id.tv_character_name) TextView characterNameView; @@ -79,6 +80,7 @@ public class CharacterDetailsActivity extends RosieActivity @Override public void showCharacterDetail(CharacterDetailViewModel character) { characterDetailView.setVisibility(View.VISIBLE); + toolbarTitleView.setText(character.getName()); Picasso.with(this) .load(character.getHeaderImage()) .fit() @@ -88,6 +90,7 @@ public class CharacterDetailsActivity extends RosieActivity characterDescriptionView.setText(character.getDescription()); } + public static void open(Context context, String characterKey) { Intent intent = new Intent(context, CharacterDetailsActivity.class); intent.putExtra(CHARACTER_KEY_EXTRA, characterKey); diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/ComicsModule.java b/sample/src/main/java/com/karumi/rosie/sample/comics/ComicsModule.java index 1701d04c..432421df 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/ComicsModule.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/ComicsModule.java @@ -16,13 +16,13 @@ package com.karumi.rosie.sample.comics; -import com.karumi.rosie.sample.comics.view.activity.ComicDetailsActivity; +import com.karumi.rosie.sample.comics.view.activity.ComicSeriesDetailsActivity; import dagger.Module; @Module( library = true, complete = false, injects = { - ComicDetailsActivity.class + ComicSeriesDetailsActivity.class }) public class ComicsModule { } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/Comic.java b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/Comic.java index 5dd7ef88..e9bd7c46 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/Comic.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/Comic.java @@ -22,11 +22,7 @@ public class Comic implements Identifiable { private int key; private String name; - private int number; - private String description; - private String coverUrl; - private int releaseYear; - private Rating rating; + private String thumbnailUrl; @Override public Integer getKey() { return key; @@ -44,51 +40,11 @@ public void setName(String name) { this.name = name; } - public int getNumber() { - return number; + public String getThumbnailUrl() { + return thumbnailUrl; } - public void setNumber(int number) { - this.number = number; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getCoverUrl() { - return coverUrl; - } - - public void setCoverUrl(String coverUrl) { - this.coverUrl = coverUrl; - } - - public int getReleaseYear() { - return releaseYear; - } - - public void setReleaseYear(int releaseYear) { - this.releaseYear = releaseYear; - } - - public Rating getRating() { - return rating; - } - - public void setRating(Rating rating) { - this.rating = rating; - } - - public enum Rating { - ALL_AGES, - T, - TEENS_AND_UP, - PARENTAL_ADVISORY, - EXPLICIT_CONTENT + public void setThumbnailUrl(String thumbnailUrl) { + this.thumbnailUrl = thumbnailUrl; } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/ComicSeries.java b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/ComicSeries.java new file mode 100644 index 00000000..7526e688 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/model/ComicSeries.java @@ -0,0 +1,105 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.domain.model; + +import com.karumi.rosie.repository.datasource.Identifiable; +import java.util.ArrayList; +import java.util.List; + +public class ComicSeries implements Identifiable { + + private int key; + private String name; + private int number; + private String description; + private String coverUrl; + private int releaseYear; + private Rating rating; + private List comics = new ArrayList<>(); + + @Override public Integer getKey() { + return key; + } + + public void setKey(int key) { + this.key = key; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public int getNumber() { + return number; + } + + public void setNumber(int number) { + this.number = number; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } + + public int getReleaseYear() { + return releaseYear; + } + + public void setReleaseYear(int releaseYear) { + this.releaseYear = releaseYear; + } + + public Rating getRating() { + return rating; + } + + public void setRating(Rating rating) { + this.rating = rating; + } + + public List getComics() { + return comics; + } + + public void setComics(List comics) { + this.comics = comics; + } + + public enum Rating { + ALL_AGES, + T, + TEENS_AND_UP, + PARENTAL_ADVISORY, + EXPLICIT_CONTENT + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicDetails.java b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesDetails.java similarity index 62% rename from sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicDetails.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesDetails.java index 1921571f..c120cdcc 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicDetails.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesDetails.java @@ -18,20 +18,20 @@ import com.karumi.rosie.domain.usecase.RosieUseCase; import com.karumi.rosie.domain.usecase.annotation.UseCase; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.repository.ComicsRepository; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.repository.ComicSeriesRepository; import javax.inject.Inject; -public class GetComicDetails extends RosieUseCase { +public class GetComicSeriesDetails extends RosieUseCase { - private final ComicsRepository repository; + private final ComicSeriesRepository repository; - @Inject public GetComicDetails(ComicsRepository repository) { + @Inject public GetComicSeriesDetails(ComicSeriesRepository repository) { this.repository = repository; } - @UseCase public void getComicDetails(int comicKey) { - Comic comic = repository.getByKey(comicKey); - notifySuccess(comic); + @UseCase public void getComicSeriesDetails(int comicSeriesKey) throws Exception { + ComicSeries comicSeries = repository.getByKey(comicSeriesKey); + notifySuccess(comicSeries); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComics.java b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesPage.java similarity index 73% rename from sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComics.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesPage.java index 522d88eb..901c0851 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComics.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/domain/usecase/GetComicSeriesPage.java @@ -20,20 +20,20 @@ import com.karumi.rosie.domain.usecase.annotation.UseCase; import com.karumi.rosie.repository.PaginatedCollection; import com.karumi.rosie.repository.datasource.paginated.Page; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.repository.ComicsRepository; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.repository.ComicSeriesRepository; import javax.inject.Inject; -public class GetComics extends RosieUseCase { +public class GetComicSeriesPage extends RosieUseCase { - private final ComicsRepository repository; + private final ComicSeriesRepository repository; - @Inject public GetComics(ComicsRepository repository) { + @Inject public GetComicSeriesPage(ComicSeriesRepository repository) { this.repository = repository; } @UseCase public void getComics(Page page) throws Exception { - PaginatedCollection comics = repository.getPage(page); + PaginatedCollection comics = repository.getPage(page); notifySuccess(comics); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicsRepository.java b/sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicSeriesRepository.java similarity index 61% rename from sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicsRepository.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicSeriesRepository.java index 914941f5..1abc7908 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicsRepository.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/repository/ComicSeriesRepository.java @@ -17,24 +17,18 @@ package com.karumi.rosie.sample.comics.repository; import com.karumi.rosie.repository.PaginatedRosieRepository; -import com.karumi.rosie.repository.datasource.CacheDataSource; import com.karumi.rosie.repository.datasource.paginated.PaginatedCacheDataSource; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.repository.datasource.ComicsApiDataSource; -import com.karumi.rosie.sample.main.ApplicationModule; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.repository.datasource.ComicSeriesApiDataSource; import javax.inject.Inject; -import javax.inject.Named; -public class ComicsRepository extends PaginatedRosieRepository { +public class ComicSeriesRepository extends PaginatedRosieRepository { - @Inject public ComicsRepository(ComicsApiDataSource apiDataSource, - @Named(ApplicationModule.COMICS_PAGE_IN_MEMORY_CACHE) - PaginatedCacheDataSource inMemoryPaginatedCache, - @Named(ApplicationModule.COMICS_IN_MEMORY_CACHE) - CacheDataSource inMemoryCache) { + @Inject public ComicSeriesRepository(ComicSeriesApiDataSource apiDataSource, + PaginatedCacheDataSource inMemoryPaginatedCache) { addReadableDataSources(apiDataSource); - addCacheDataSources(inMemoryCache); addPaginatedReadableDataSources(apiDataSource); + addCacheDataSources(inMemoryPaginatedCache); addPaginatedCacheDataSources(inMemoryPaginatedCache); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicsApiDataSource.java b/sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicSeriesApiDataSource.java similarity index 68% rename from sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicsApiDataSource.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicSeriesApiDataSource.java index 8c262e4c..3fae72d1 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicsApiDataSource.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/repository/datasource/ComicSeriesApiDataSource.java @@ -22,14 +22,19 @@ import com.karumi.rosie.repository.datasource.paginated.Page; import com.karumi.rosie.repository.datasource.paginated.PaginatedReadableDataSource; import com.karumi.rosie.sample.comics.domain.model.Comic; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import java.util.ArrayList; import java.util.Collection; import java.util.LinkedList; +import java.util.List; import java.util.Random; import javax.inject.Inject; -public class ComicsApiDataSource extends EmptyReadableDataSource - implements PaginatedReadableDataSource { +public class ComicSeriesApiDataSource extends EmptyReadableDataSource + implements PaginatedReadableDataSource { + private static final int MIN_NUMBER_OF_COMICS_PER_COMIC_SERIES = 9; + private static final int MAX_NUMBER_OF_COMICS_PER_COMIC_SERIES = 24; private static final int NUMBER_OF_COMICS = 80; private static final int GUARDIANS_OF_INFINITY_KEY = 58086; private static final int VISION_KEY = 57309; @@ -39,38 +44,38 @@ public class ComicsApiDataSource extends EmptyReadableDataSource private static final long SLEEP_TIME_IN_MILLISECONDS = 750; private static final Random RANDOM = new Random(System.nanoTime()); - @Inject public ComicsApiDataSource() { + @Inject public ComicSeriesApiDataSource() { } - @Override public Comic getByKey(Integer key) { - Comic comic; + @Override public ComicSeries getByKey(Integer key) { + ComicSeries comicSeries; fakeDelay(); switch (key) { case GUARDIANS_OF_INFINITY_KEY: - comic = getGuardiansOfInfinity(); + comicSeries = getGuardiansOfInfinity(); break; case VISION_KEY: - comic = getVision(); + comicSeries = getVision(); break; case SPIDEY_KEY: - comic = getSpidey(); + comicSeries = getSpidey(); break; case RED_WOLF_KEY: - comic = getRedWolf(); + comicSeries = getRedWolf(); break; case NOVA_KEY: default: - comic = getNova(); + comicSeries = getNova(); break; } - return comic; + return comicSeries; } - @Override public PaginatedCollection getPage(Page page) { - Collection comics = new LinkedList<>(); + @Override public PaginatedCollection getPage(Page page) { + Collection comics = new LinkedList<>(); fakeDelay(); @@ -78,25 +83,26 @@ public class ComicsApiDataSource extends EmptyReadableDataSource int limit = page.getLimit(); for (int i = offset; i - offset < limit && i < NUMBER_OF_COMICS; i++) { - comics.add(getComic(i)); + comics.add(getComicSeries(i)); } - PaginatedCollection comicsPage = new PaginatedCollection<>(comics); + PaginatedCollection comicsPage = new PaginatedCollection<>(comics); comicsPage.setPage(page); comicsPage.setHasMore(offset + comics.size() < NUMBER_OF_COMICS); return comicsPage; } - private Comic getComic(int i) { - Comic[] comics = {getGuardiansOfInfinity(), getVision(), getSpidey(), getRedWolf(), getNova()}; + private ComicSeries getComicSeries(int i) { + ComicSeries[] allComicSeries = + {getGuardiansOfInfinity(), getVision(), getSpidey(), getRedWolf(), getNova()}; - Comic comic = comics[RANDOM.nextInt(comics.length)]; - comic.setName(comic.getName() + " " + i); - return comic; + ComicSeries comicSeries = allComicSeries[RANDOM.nextInt(allComicSeries.length)]; + comicSeries.setName(comicSeries.getName() + " " + i); + return comicSeries; } - @NonNull private Comic getGuardiansOfInfinity() { - Comic guardiansOfInfinity = new Comic(); + @NonNull private ComicSeries getGuardiansOfInfinity() { + ComicSeries guardiansOfInfinity = new ComicSeries(); guardiansOfInfinity.setKey(GUARDIANS_OF_INFINITY_KEY); guardiansOfInfinity.setName("Guardians of Infinity"); guardiansOfInfinity.setNumber(2); @@ -113,12 +119,13 @@ private Comic getComic(int i) { + " where culture is based on Earth-style professional wrestling…but the stakes are" + " life and death! THIS AIN’T KAYFABE, BROTHER! "); guardiansOfInfinity.setReleaseYear(2015); - guardiansOfInfinity.setRating(Comic.Rating.ALL_AGES); + guardiansOfInfinity.setRating(ComicSeries.Rating.ALL_AGES); + guardiansOfInfinity.setComics(getComics(guardiansOfInfinity.getName())); return guardiansOfInfinity; } - @NonNull private Comic getVision() { - Comic vision = new Comic(); + @NonNull private ComicSeries getVision() { + ComicSeries vision = new ComicSeries(); vision.setKey(VISION_KEY); vision.setName("Vision"); vision.setNumber(1); @@ -134,12 +141,13 @@ private Comic getComic(int i) { + " where culture is based on Earth-style professional wrestling…but the stakes are" + " life and death! THIS AIN’T KAYFABE, BROTHER! "); vision.setReleaseYear(2015); - vision.setRating(Comic.Rating.T); + vision.setRating(ComicSeries.Rating.T); + vision.setComics(getComics(vision.getName())); return vision; } - @NonNull private Comic getSpidey() { - Comic spidey = new Comic(); + @NonNull private ComicSeries getSpidey() { + ComicSeries spidey = new ComicSeries(); spidey.setKey(SPIDEY_KEY); spidey.setName("Spidey"); spidey.setNumber(1); @@ -155,12 +163,13 @@ private Comic getComic(int i) { + " where culture is based on Earth-style professional wrestling…but the stakes are" + " life and death! THIS AIN’T KAYFABE, BROTHER! "); spidey.setReleaseYear(2015); - spidey.setRating(Comic.Rating.TEENS_AND_UP); + spidey.setRating(ComicSeries.Rating.TEENS_AND_UP); + spidey.setComics(getComics(spidey.getName())); return spidey; } - @NonNull private Comic getRedWolf() { - Comic redWolf = new Comic(); + @NonNull private ComicSeries getRedWolf() { + ComicSeries redWolf = new ComicSeries(); redWolf.setKey(RED_WOLF_KEY); redWolf.setName("Red Wolf"); redWolf.setNumber(2); @@ -176,12 +185,13 @@ private Comic getComic(int i) { + " where culture is based on Earth-style professional wrestling…but the stakes are" + " life and death! THIS AIN’T KAYFABE, BROTHER! "); redWolf.setReleaseYear(2015); - redWolf.setRating(Comic.Rating.EXPLICIT_CONTENT); + redWolf.setRating(ComicSeries.Rating.EXPLICIT_CONTENT); + redWolf.setComics(getComics(redWolf.getName())); return redWolf; } - @NonNull private Comic getNova() { - Comic nova = new Comic(); + @NonNull private ComicSeries getNova() { + ComicSeries nova = new ComicSeries(); nova.setKey(NOVA_KEY); nova.setName("Nova"); nova.setNumber(1); @@ -197,10 +207,38 @@ private Comic getComic(int i) { + " where culture is based on Earth-style professional wrestling…but the stakes are" + " life and death! THIS AIN’T KAYFABE, BROTHER! "); nova.setReleaseYear(2015); - nova.setRating(Comic.Rating.PARENTAL_ADVISORY); + nova.setRating(ComicSeries.Rating.PARENTAL_ADVISORY); + nova.setComics(getComics(nova.getName())); return nova; } + @NonNull private List getComics(String comicSeriesName) { + List comics = new ArrayList<>(); + + String[] allComicThumbnailUrls = { + "http://x.annihil.us/u/prod/marvel/i/mg/6/c0/5554eab0886b8/detail.jpg", + "http://i.annihil.us/u/prod/marvel/i/mg/c/a0/553514e108202/detail.jpg", + "http://i.annihil.us/u/prod/marvel/i/mg/6/30/5503446dc71bf/detail.jpg", + "http://i.annihil.us/u/prod/marvel/i/mg/f/10/54cfb2f5f0b2e/detail.jpg", + "http://x.annihil.us/u/prod/marvel/i/mg/4/20/54b55c72b7896/detail.jpg", + "http://i.annihil.us/u/prod/marvel/i/mg/4/00/5491a1de66768/detail.jpg", + "http://x.annihil.us/u/prod/marvel/i/mg/6/c0/5464eabe99180/detail.jpg", + "http://x.annihil.us/u/prod/marvel/i/mg/3/00/55b242ad84037/detail.jpg" + }; + + int numberOfComics = MIN_NUMBER_OF_COMICS_PER_COMIC_SERIES + RANDOM.nextInt( + MAX_NUMBER_OF_COMICS_PER_COMIC_SERIES - MIN_NUMBER_OF_COMICS_PER_COMIC_SERIES + 1); + for (int i = 0; i < numberOfComics; i++) { + Comic comic = new Comic(); + comic.setKey(i); + comic.setName(comicSeriesName + " #" + (i + 1)); + comic.setThumbnailUrl(allComicThumbnailUrls[RANDOM.nextInt(allComicThumbnailUrls.length)]); + comics.add(comic); + } + + return comics; + } + private void fakeDelay() { try { Thread.sleep(SLEEP_TIME_IN_MILLISECONDS); diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicDetailsActivity.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicDetailsActivity.java deleted file mode 100644 index 9507690d..00000000 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicDetailsActivity.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (C) 2015 Karumi. - * - * 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 com.karumi.rosie.sample.comics.view.activity; - -import android.content.Context; -import android.content.Intent; -import android.os.Bundle; -import android.view.View; -import android.widget.ImageView; -import android.widget.TextView; -import butterknife.Bind; -import com.karumi.rosie.sample.R; -import com.karumi.rosie.sample.comics.ComicsModule; -import com.karumi.rosie.sample.comics.view.presenter.ComicDetailsPresenter; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicDetailsViewModel; -import com.karumi.rosie.view.Presenter; -import com.karumi.rosie.view.RosieActivity; -import com.squareup.picasso.Picasso; -import com.victor.loading.rotate.RotateLoading; -import java.util.Arrays; -import java.util.List; -import javax.inject.Inject; - -public class ComicDetailsActivity extends RosieActivity implements ComicDetailsPresenter.View { - - private static final String COMIC_KEY_EXTRA = "ComicDetailsActivity.ComicKey"; - private static final int INVALID_COMIC_KEY_EXTRA = -1; - - @Bind(R.id.ll_comic_detail) View comicView; - @Bind(R.id.iv_cover) ImageView coverView; - @Bind(R.id.tv_rating) TextView ratingView; - @Bind(R.id.tv_description) TextView descriptionView; - @Bind(R.id.loading) RotateLoading loadingView; - - @Inject @Presenter ComicDetailsPresenter presenter; - - @Override protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - int comicKey = getIntent().getIntExtra(COMIC_KEY_EXTRA, INVALID_COMIC_KEY_EXTRA); - presenter.setComicKey(comicKey); - } - - @Override protected int getLayoutId() { - return R.layout.activity_comic_details; - } - - @Override protected List getActivityScopeModules() { - return Arrays.asList((Object) new ComicsModule()); - } - - @Override public void hideLoading() { - loadingView.stop(); - loadingView.setVisibility(View.GONE); - } - - @Override public void showLoading() { - loadingView.setVisibility(View.VISIBLE); - loadingView.start(); - } - - @Override public void hideComicDetails() { - comicView.setVisibility(View.GONE); - } - - @Override public void showComicDetails(ComicDetailsViewModel comic) { - Picasso.with(this).load(comic.getCoverUrl()).fit().centerCrop().into(coverView); - String rating = getString(comic.getRatingNameResourceId()); - ratingView.setText(getString(R.string.marvel_rating_text, rating)); - descriptionView.setText(comic.getDescription()); - comicView.setVisibility(View.VISIBLE); - } - - public static void open(Context context, int comicKey) { - Intent intent = new Intent(context, ComicDetailsActivity.class); - intent.putExtra(COMIC_KEY_EXTRA, comicKey); - context.startActivity(intent); - } -} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicSeriesDetailsActivity.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicSeriesDetailsActivity.java new file mode 100644 index 00000000..5db601f4 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/activity/ComicSeriesDetailsActivity.java @@ -0,0 +1,122 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.activity; + +import android.content.Context; +import android.content.Intent; +import android.os.Bundle; +import android.support.v7.widget.GridLayoutManager; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; +import butterknife.Bind; +import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.base.view.activity.MarvelActivity; +import com.karumi.rosie.sample.comics.ComicsModule; +import com.karumi.rosie.sample.comics.view.presenter.ComicSeriesDetailsPresenter; +import com.karumi.rosie.sample.comics.view.renderer.ComicSeriesDetailRendererBuilder; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailsViewModel; +import com.karumi.rosie.view.Presenter; +import com.pedrogomez.renderers.ListAdapteeCollection; +import com.pedrogomez.renderers.RVRendererAdapter; +import com.pedrogomez.renderers.RendererBuilder; +import com.victor.loading.rotate.RotateLoading; +import java.util.Arrays; +import java.util.List; +import javax.inject.Inject; + +public class ComicSeriesDetailsActivity extends MarvelActivity + implements ComicSeriesDetailsPresenter.View { + + private static final String COMIC_SERIES_KEY_EXTRA = "ComicSeriesDetailsActivity.ComicSeriesKey"; + private static final int INVALID_COMIC_SERIES_KEY_EXTRA = -1; + private static final int NUMBER_OF_COLUMNS = 3; + + @Bind(R.id.tv_toolbar_title) TextView toolbarTitleView; + @Bind(R.id.loading) RotateLoading loadingView; + @Bind(R.id.rv_comics) RecyclerView comicsView; + + @Inject @Presenter ComicSeriesDetailsPresenter presenter; + + private RVRendererAdapter comicDetailsAdapter; + + @Override protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + initializeComicsView(); + int comicKey = getIntent().getIntExtra(COMIC_SERIES_KEY_EXTRA, INVALID_COMIC_SERIES_KEY_EXTRA); + presenter.setComicSeriesKey(comicKey); + } + + @Override protected int getLayoutId() { + return R.layout.activity_comic_series_details; + } + + @Override protected List getActivityScopeModules() { + return Arrays.asList((Object) new ComicsModule()); + } + + @Override public void hideLoading() { + loadingView.stop(); + loadingView.setVisibility(View.GONE); + } + + @Override public void showLoading() { + loadingView.setVisibility(View.VISIBLE); + loadingView.start(); + } + + @Override public void hideComicSeriesDetails() { + comicsView.setVisibility(View.GONE); + } + + @Override public void showComicSeriesDetails(ComicSeriesDetailsViewModel comicSeries) { + toolbarTitleView.setText(comicSeries.getTitle()); + comicsView.setVisibility(View.VISIBLE); + comicDetailsAdapter.clear(); + comicDetailsAdapter.addAll(comicSeries.getComicSeriesDetailViewModels()); + comicDetailsAdapter.notifyDataSetChanged(); + } + + public static void open(Context context, int comicSeriesKey) { + Intent intent = new Intent(context, ComicSeriesDetailsActivity.class); + intent.putExtra(COMIC_SERIES_KEY_EXTRA, comicSeriesKey); + context.startActivity(intent); + } + + private void initializeComicsView() { + GridLayoutManager layoutManager = new GridLayoutManager(this, NUMBER_OF_COLUMNS); + layoutManager.setSpanSizeLookup(new GridLayoutManager.SpanSizeLookup() { + @Override public int getSpanSize(int position) { + return position == 0 ? NUMBER_OF_COLUMNS : 1; + } + }); + comicsView.setHasFixedSize(true); + comicsView.setLayoutManager(layoutManager); + initializeAdapter(); + comicsView.setAdapter(comicDetailsAdapter); + } + + private void initializeAdapter() { + LayoutInflater layoutInflater = LayoutInflater.from(this); + RendererBuilder rendererBuilder = + new ComicSeriesDetailRendererBuilder(); + comicDetailsAdapter = new RVRendererAdapter<>(layoutInflater, rendererBuilder, + new ListAdapteeCollection()); + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicsFragment.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicSeriesFragment.java similarity index 64% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicsFragment.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicSeriesFragment.java index eb7b907c..519e77a4 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicsFragment.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/fragment/ComicSeriesFragment.java @@ -32,11 +32,11 @@ import com.karumi.dividers.LayersBuilder; import com.karumi.dividers.selector.HeaderSelector; import com.karumi.rosie.sample.R; -import com.karumi.rosie.sample.comics.view.activity.ComicDetailsActivity; -import com.karumi.rosie.sample.comics.view.presenter.ComicsPresenter; -import com.karumi.rosie.sample.comics.view.renderer.ComicRendererBuilder; -import com.karumi.rosie.sample.comics.view.renderer.ComicsAdapteeCollection; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.karumi.rosie.sample.comics.view.activity.ComicSeriesDetailsActivity; +import com.karumi.rosie.sample.comics.view.presenter.ComicsSeriesPresenter; +import com.karumi.rosie.sample.comics.view.renderer.ComicSeriesRendererBuilder; +import com.karumi.rosie.sample.comics.view.renderer.ComicsSeriesAdapteeCollection; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; import com.karumi.rosie.view.Presenter; import com.karumi.rosie.view.RosieFragment; import com.karumi.rosie.view.paginated.ScrollToBottomListener; @@ -47,24 +47,24 @@ import java.util.List; import javax.inject.Inject; -public class ComicsFragment extends RosieFragment implements ComicsPresenter.View { +public class ComicSeriesFragment extends RosieFragment implements ComicsSeriesPresenter.View { - @Bind(R.id.rv_comics) RecyclerView comicsView; + @Bind(R.id.rv_comics) RecyclerView comicSeriesView; @Bind(R.id.loading) RotateLoading loadingView; - @Inject @Presenter ComicsPresenter presenter; + @Inject @Presenter ComicsSeriesPresenter presenter; - private RVRendererAdapter comicsAdapter; - private ComicsAdapteeCollection comicsCollection; + private RVRendererAdapter comicSeriesAdapter; + private ComicsSeriesAdapteeCollection comicsCollection; private ScrollToBottomListener loadMoreListener; @Override protected int getLayoutId() { - return R.layout.fragment_comics; + return R.layout.fragment_comic_series; } @Override public void onViewCreated(View view, Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); - initializeComicsView(); + initializeComicSeriesView(); } @Override public void hideLoading() { @@ -77,14 +77,15 @@ public class ComicsFragment extends RosieFragment implements ComicsPresenter.Vie loadingView.start(); } - @Override public void hideComics() { - comicsView.setVisibility(View.GONE); + @Override public void hideComicSeries() { + comicSeriesView.setVisibility(View.GONE); } - @Override public void showComics(List comics) { - comicsAdapter.addAll(comics); - comicsAdapter.notifyDataSetChanged(); - comicsView.setVisibility(View.VISIBLE); + @Override public void showComicSeries(List comicSeries) { + comicSeriesAdapter.clear(); + comicSeriesAdapter.addAll(comicSeries); + comicSeriesAdapter.notifyDataSetChanged(); + comicSeriesView.setVisibility(View.VISIBLE); } @Override public void showHasMore(boolean hasMore) { @@ -93,24 +94,24 @@ public class ComicsFragment extends RosieFragment implements ComicsPresenter.Vie loadMoreListener.setIsEnabled(hasMore); } - @Override public void openComicDetails(int comicKey) { - ComicDetailsActivity.open(getActivity(), comicKey); + @Override public void openComicSeriesDetails(int comicSeriesKey) { + ComicSeriesDetailsActivity.open(getActivity(), comicSeriesKey); } - private void initializeComicsView() { + private void initializeComicSeriesView() { LinearLayoutManager layoutManager = new LinearLayoutManager(getActivity()); - comicsView.setHasFixedSize(true); - comicsView.setLayoutManager(layoutManager); + comicSeriesView.setHasFixedSize(true); + comicSeriesView.setLayoutManager(layoutManager); initializeAdapter(); - comicsView.addItemDecoration(getDivider()); - comicsView.setAdapter(comicsAdapter); + comicSeriesView.addItemDecoration(getDivider()); + comicSeriesView.setAdapter(comicSeriesAdapter); loadMoreListener = new ScrollToBottomListener(layoutManager, new ScrollToBottomListener.Listener() { @Override public void onScrolledToBottom() { presenter.onLoadMore(); } }); - comicsView.addOnScrollListener(loadMoreListener); + comicSeriesView.addOnScrollListener(loadMoreListener); } @NonNull private DividerItemDecoration getDivider() { @@ -125,8 +126,8 @@ private void initializeComicsView() { private void initializeAdapter() { LayoutInflater layoutInflater = LayoutInflater.from(getActivity()); - RendererBuilder rendererBuilder = new ComicRendererBuilder(presenter); - comicsCollection = new ComicsAdapteeCollection(); - comicsAdapter = new RVRendererAdapter<>(layoutInflater, rendererBuilder, comicsCollection); + RendererBuilder rendererBuilder = new ComicSeriesRendererBuilder(presenter); + comicsCollection = new ComicsSeriesAdapteeCollection(); + comicSeriesAdapter = new RVRendererAdapter<>(layoutInflater, rendererBuilder, comicsCollection); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicDetailsPresenter.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicDetailsPresenter.java deleted file mode 100644 index 89a9b646..00000000 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicDetailsPresenter.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (C) 2015 Karumi. - * - * 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 com.karumi.rosie.sample.comics.view.presenter; - -import com.karumi.rosie.domain.usecase.UseCaseHandler; -import com.karumi.rosie.domain.usecase.annotation.Success; -import com.karumi.rosie.domain.usecase.callback.OnSuccessCallback; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.domain.usecase.GetComicDetails; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicDetailsViewModel; -import com.karumi.rosie.sample.comics.view.viewmodel.mapper.ComicToComicDetailsViewModelMapper; -import com.karumi.rosie.view.loading.RosiePresenterWithLoading; -import javax.inject.Inject; - -public class ComicDetailsPresenter extends RosiePresenterWithLoading { - - private final GetComicDetails getComicDetails; - private final ComicToComicDetailsViewModelMapper mapper; - private int comicKey; - - @Inject - public ComicDetailsPresenter(UseCaseHandler useCaseHandler, GetComicDetails getComicDetails, - ComicToComicDetailsViewModelMapper mapper) { - super(useCaseHandler); - this.getComicDetails = getComicDetails; - this.mapper = mapper; - } - - public void setComicKey(int comicKey) { - this.comicKey = comicKey; - } - - @Override protected void update() { - super.update(); - showLoading(); - getView().hideComicDetails(); - loadComicDetails(); - } - - private void loadComicDetails() { - createUseCaseCall(getComicDetails).args(comicKey).onSuccess(new OnSuccessCallback() { - @Success public void onComicDetailsLoaded(Comic comic) { - ComicDetailsViewModel comicDetailsViewModel = - mapper.mapComicToComicDetailsViewModel(comic); - hideLoading(); - getView().showComicDetails(comicDetailsViewModel); - } - }).execute(); - } - - public interface View extends RosiePresenterWithLoading.View { - void hideComicDetails(); - - void showComicDetails(ComicDetailsViewModel comic); - } -} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicSeriesDetailsPresenter.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicSeriesDetailsPresenter.java new file mode 100644 index 00000000..e0490e70 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicSeriesDetailsPresenter.java @@ -0,0 +1,73 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.presenter; + +import com.karumi.rosie.domain.usecase.UseCaseHandler; +import com.karumi.rosie.domain.usecase.annotation.Success; +import com.karumi.rosie.domain.usecase.callback.OnSuccessCallback; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.domain.usecase.GetComicSeriesDetails; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailsViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.mapper.ComicSeriesToComicSeriesDetailsViewModelMapper; +import com.karumi.rosie.view.loading.RosiePresenterWithLoading; +import javax.inject.Inject; + +public class ComicSeriesDetailsPresenter + extends RosiePresenterWithLoading { + + private final GetComicSeriesDetails getComicSeriesDetails; + private final ComicSeriesToComicSeriesDetailsViewModelMapper mapper; + private int comicSeriesKey; + + @Inject public ComicSeriesDetailsPresenter(UseCaseHandler useCaseHandler, + GetComicSeriesDetails getComicSeriesDetails, + ComicSeriesToComicSeriesDetailsViewModelMapper mapper) { + super(useCaseHandler); + this.getComicSeriesDetails = getComicSeriesDetails; + this.mapper = mapper; + } + + public void setComicSeriesKey(int comicKey) { + this.comicSeriesKey = comicKey; + } + + @Override protected void update() { + super.update(); + showLoading(); + getView().hideComicSeriesDetails(); + loadComicDetails(); + } + + private void loadComicDetails() { + createUseCaseCall(getComicSeriesDetails).args(comicSeriesKey) + .onSuccess(new OnSuccessCallback() { + @Success public void onComicSeriesDetailsLoaded(ComicSeries comicSeries) { + ComicSeriesDetailsViewModel comicSeriesDetailsViewModel = + mapper.map(comicSeries); + hideLoading(); + getView().showComicSeriesDetails(comicSeriesDetailsViewModel); + } + }) + .execute(); + } + + public interface View extends RosiePresenterWithLoading.View { + void hideComicSeriesDetails(); + + void showComicSeriesDetails(ComicSeriesDetailsViewModel comicSeries); + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsPresenter.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsSeriesPresenter.java similarity index 50% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsPresenter.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsSeriesPresenter.java index 19897036..112bfc1a 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsPresenter.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/presenter/ComicsSeriesPresenter.java @@ -21,31 +21,31 @@ import com.karumi.rosie.domain.usecase.callback.OnSuccessCallback; import com.karumi.rosie.repository.PaginatedCollection; import com.karumi.rosie.repository.datasource.paginated.Page; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.domain.usecase.GetComics; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; -import com.karumi.rosie.sample.comics.view.viewmodel.mapper.ComicToComicViewModelMapper; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.domain.usecase.GetComicSeriesPage; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.mapper.ComicSeriesToComicSeriesViewModelMapper; import com.karumi.rosie.view.loading.RosiePresenterWithLoading; import java.util.List; import javax.inject.Inject; -public class ComicsPresenter extends RosiePresenterWithLoading { +public class ComicsSeriesPresenter extends RosiePresenterWithLoading { - private static final int NUMBER_OF_COMICS_PER_PAGE = 14; - private final ComicToComicViewModelMapper mapper; - private final GetComics getComics; + private static final int NUMBER_OF_COMIC_SERIES_PER_PAGE = 14; + private final ComicSeriesToComicSeriesViewModelMapper mapper; + private final GetComicSeriesPage getComicSeriesPage; private int offset = 0; - @Inject public ComicsPresenter(UseCaseHandler useCaseHandler, ComicToComicViewModelMapper mapper, - GetComics getComics) { + @Inject public ComicsSeriesPresenter(UseCaseHandler useCaseHandler, + ComicSeriesToComicSeriesViewModelMapper mapper, GetComicSeriesPage getComicSeriesPage) { super(useCaseHandler); this.mapper = mapper; - this.getComics = getComics; + this.getComicSeriesPage = getComicSeriesPage; } @Override protected void update() { super.update(); - getView().hideComics(); + getView().hideComicSeries(); showLoading(); loadComics(); } @@ -54,31 +54,34 @@ public void onLoadMore() { loadComics(); } - public void onComicClicked(ComicViewModel comic) { - getView().openComicDetails(comic.getKey()); + public void onComicSeriesClicked(ComicSeriesViewModel comicSeries) { + getView().openComicSeriesDetails(comicSeries.getKey()); } private void loadComics() { - createUseCaseCall(getComics).args(Page.withOffsetAndLimit(offset, NUMBER_OF_COMICS_PER_PAGE)) + + createUseCaseCall(getComicSeriesPage).args( + Page.withOffsetAndLimit(offset, NUMBER_OF_COMIC_SERIES_PER_PAGE)) .onSuccess(new OnSuccessCallback() { - @Success public void onComicsLoaded(PaginatedCollection comics) { - List comicViewModels = mapper.mapComicsToComicViewModels(comics); + @Success public void onComicSeriesLoaded(PaginatedCollection comicSeries) { + List comicSeriesViewModels = + mapper.mapComicSeriesToComicSeriesViewModels(comicSeries); hideLoading(); - getView().showHasMore(comics.hasMore()); - getView().showComics(comicViewModels); - offset = comics.getPage().getOffset() + NUMBER_OF_COMICS_PER_PAGE; + getView().showHasMore(comicSeries.hasMore()); + getView().showComicSeries(comicSeriesViewModels); + offset = comicSeries.getPage().getOffset() + NUMBER_OF_COMIC_SERIES_PER_PAGE; } }) .execute(); } public interface View extends RosiePresenterWithLoading.View { - void hideComics(); + void hideComicSeries(); - void showComics(List comics); + void showComicSeries(List comicSeries); void showHasMore(boolean hasMore); - void openComicDetails(int comicKey); + void openComicSeriesDetails(int comicSeriesKey); } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRenderer.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRenderer.java index 1fdfe2e5..462753cb 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRenderer.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRenderer.java @@ -19,37 +19,33 @@ import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import butterknife.Bind; -import butterknife.OnClick; import com.karumi.rosie.renderer.RosieRenderer; import com.karumi.rosie.sample.R; -import com.karumi.rosie.sample.comics.view.presenter.ComicsPresenter; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailViewModel; import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.squareup.picasso.Picasso; -public class ComicRenderer extends RosieRenderer { +public class ComicRenderer extends RosieRenderer { - private final ComicsPresenter presenter; - - @Bind(R.id.tv_comic_name) TextView nameView; - - public ComicRenderer(ComicsPresenter presenter) { - this.presenter = presenter; - } + @Bind(R.id.iv_thumbnail) ImageView thumbnailView; + @Bind(R.id.tv_title) TextView titleView; @Override public void render() { super.render(); - ComicViewModel comic = getContent(); - nameView.setText(comic.getTitle()); + ComicViewModel comic = (ComicViewModel) getContent(); + titleView.setText(comic.getTitle()); + Picasso.with(getRootView().getContext()) + .load(comic.getThumbnailUrl()) + .fit() + .centerCrop() + .into(thumbnailView); } @Override protected View inflate(LayoutInflater inflater, ViewGroup parent) { return inflater.inflate(R.layout.item_comic, parent, false); } - - @OnClick(R.id.ll_root) public void onItemClicked() { - ComicViewModel comic = getContent(); - presenter.onComicClicked(comic); - } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesDetailRendererBuilder.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesDetailRendererBuilder.java new file mode 100644 index 00000000..4bf3036f --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesDetailRendererBuilder.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.renderer; + +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesHeaderDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.pedrogomez.renderers.Renderer; +import com.pedrogomez.renderers.RendererBuilder; +import java.util.HashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +public class ComicSeriesDetailRendererBuilder extends RendererBuilder { + + private Map rendererMapping = new HashMap<>(); + + public ComicSeriesDetailRendererBuilder() { + List> prototypes = new LinkedList<>(); + prototypes.add(new ComicRenderer()); + rendererMapping.put(ComicViewModel.class, ComicRenderer.class); + prototypes.add(new ComicSeriesHeaderDetailRenderer()); + rendererMapping.put(ComicSeriesHeaderDetailViewModel.class, + ComicSeriesHeaderDetailRenderer.class); + setPrototypes(prototypes); + } + + @Override protected Class getPrototypeClass(ComicSeriesDetailViewModel content) { + return rendererMapping.get(content.getClass()); + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesHeaderDetailRenderer.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesHeaderDetailRenderer.java new file mode 100644 index 00000000..64c3eca9 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesHeaderDetailRenderer.java @@ -0,0 +1,53 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.renderer; + +import android.content.Context; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; +import butterknife.Bind; +import com.karumi.rosie.renderer.RosieRenderer; +import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesHeaderDetailViewModel; +import com.squareup.picasso.Picasso; + +public class ComicSeriesHeaderDetailRenderer extends RosieRenderer { + + @Bind(R.id.iv_cover) ImageView coverView; + @Bind(R.id.tv_rating) TextView ratingView; + @Bind(R.id.tv_description) TextView descriptionView; + + @Override public void render() { + super.render(); + + Context context = getRootView().getContext(); + ComicSeriesHeaderDetailViewModel comicSeries = (ComicSeriesHeaderDetailViewModel) getContent(); + + Picasso.with(context).load(comicSeries.getCoverUrl()).fit().centerCrop().into(coverView); + String rating = context.getString(comicSeries.getRatingNameResourceId()); + ratingView.setText(context.getString(R.string.marvel_rating_text, rating)); + descriptionView.setText(comicSeries.getDescription()); + } + + @Override protected View inflate(LayoutInflater inflater, ViewGroup parent) { + return inflater.inflate(R.layout.item_comic_series_header, parent, false); + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRenderer.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRenderer.java new file mode 100644 index 00000000..43483cd4 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRenderer.java @@ -0,0 +1,54 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.renderer; + +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.TextView; +import butterknife.Bind; +import butterknife.OnClick; +import com.karumi.rosie.renderer.RosieRenderer; +import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.comics.view.presenter.ComicsSeriesPresenter; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; + +public class ComicSeriesRenderer extends RosieRenderer { + + private final ComicsSeriesPresenter presenter; + + @Bind(R.id.tv_comic_series_name) TextView nameView; + + public ComicSeriesRenderer(ComicsSeriesPresenter presenter) { + this.presenter = presenter; + } + + @Override public void render() { + super.render(); + ComicSeriesViewModel comicSeries = getContent(); + nameView.setText(comicSeries.getTitle()); + } + + @Override protected View inflate(LayoutInflater inflater, ViewGroup parent) { + return inflater.inflate(R.layout.item_comic_series, parent, false); + } + + @OnClick(R.id.ll_root) public void onItemClicked() { + ComicSeriesViewModel comicSeries = getContent(); + presenter.onComicSeriesClicked(comicSeries); + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRendererBuilder.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRendererBuilder.java similarity index 59% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRendererBuilder.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRendererBuilder.java index fb2be2a6..f5e838aa 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicRendererBuilder.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicSeriesRendererBuilder.java @@ -16,8 +16,8 @@ package com.karumi.rosie.sample.comics.view.renderer; -import com.karumi.rosie.sample.comics.view.presenter.ComicsPresenter; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.karumi.rosie.sample.comics.view.presenter.ComicsSeriesPresenter; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; import com.pedrogomez.renderers.Renderer; import com.pedrogomez.renderers.RendererBuilder; import java.util.HashMap; @@ -25,23 +25,23 @@ import java.util.List; import java.util.Map; -public class ComicRendererBuilder extends RendererBuilder { +public class ComicSeriesRendererBuilder extends RendererBuilder { private Map rendererMapping = new HashMap<>(); - public ComicRendererBuilder(ComicsPresenter presenter) { - List> prototypes = new LinkedList<>(); - prototypes.add(new ComicRenderer(presenter)); - rendererMapping.put(ComicViewModel.class, ComicRenderer.class); - prototypes.add(new LoadMoreComicsRenderer()); + public ComicSeriesRendererBuilder(ComicsSeriesPresenter presenter) { + List> prototypes = new LinkedList<>(); + prototypes.add(new ComicSeriesRenderer(presenter)); + rendererMapping.put(ComicSeriesViewModel.class, ComicSeriesRenderer.class); + prototypes.add(new LoadMoreComicSeriesRenderer()); setPrototypes(prototypes); } - @Override protected Class getPrototypeClass(ComicViewModel content) { + @Override protected Class getPrototypeClass(ComicSeriesViewModel content) { if (content != null) { return rendererMapping.get(content.getClass()); } else { - return LoadMoreComicsRenderer.class; + return LoadMoreComicSeriesRenderer.class; } } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsAdapteeCollection.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsSeriesAdapteeCollection.java similarity index 79% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsAdapteeCollection.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsSeriesAdapteeCollection.java index e6f2ac90..9baaf55c 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsAdapteeCollection.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/ComicsSeriesAdapteeCollection.java @@ -16,10 +16,10 @@ package com.karumi.rosie.sample.comics.view.renderer; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; import com.pedrogomez.renderers.ListAdapteeCollection; -public class ComicsAdapteeCollection extends ListAdapteeCollection { +public class ComicsSeriesAdapteeCollection extends ListAdapteeCollection { private boolean showLoadMore = true; @@ -32,8 +32,8 @@ public void setShowLoadMore(boolean showLoadMore) { return showLoadMore ? size + 1 : size; } - @Override public ComicViewModel get(int i) { - ComicViewModel item = null; + @Override public ComicSeriesViewModel get(int i) { + ComicSeriesViewModel item = null; if (i < super.size()) { item = super.get(i); } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicsRenderer.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicSeriesRenderer.java similarity index 85% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicsRenderer.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicSeriesRenderer.java index 9e0429f9..f7b9fa43 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicsRenderer.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/renderer/LoadMoreComicSeriesRenderer.java @@ -21,9 +21,9 @@ import android.view.ViewGroup; import com.karumi.rosie.renderer.RosieRenderer; import com.karumi.rosie.sample.R; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; -public class LoadMoreComicsRenderer extends RosieRenderer { +public class LoadMoreComicSeriesRenderer extends RosieRenderer { @Override protected View inflate(LayoutInflater inflater, ViewGroup parent) { return inflater.inflate(R.layout.item_load_more, parent, false); diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailViewModel.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailViewModel.java new file mode 100644 index 00000000..e0bbb2ac --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailViewModel.java @@ -0,0 +1,20 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.viewmodel; + +public interface ComicSeriesDetailViewModel { +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailsViewModel.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailsViewModel.java new file mode 100644 index 00000000..e2709c67 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesDetailsViewModel.java @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.viewmodel; + +import java.util.List; + +public class ComicSeriesDetailsViewModel { + + private String title; + private List comicSeriesDetailViewModels; + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public List getComicSeriesDetailViewModels() { + return comicSeriesDetailViewModels; + } + + public void setComicSeriesDetailViewModels( + List comicSeriesDetailViewModels) { + this.comicSeriesDetailViewModels = comicSeriesDetailViewModels; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicDetailsViewModel.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesHeaderDetailViewModel.java similarity index 94% rename from sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicDetailsViewModel.java rename to sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesHeaderDetailViewModel.java index ca0eb144..2d32dbe5 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicDetailsViewModel.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesHeaderDetailViewModel.java @@ -16,7 +16,7 @@ package com.karumi.rosie.sample.comics.view.viewmodel; -public class ComicDetailsViewModel { +public class ComicSeriesHeaderDetailViewModel implements ComicSeriesDetailViewModel { private String title; private String coverUrl; diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesViewModel.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesViewModel.java new file mode 100644 index 00000000..194b2997 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicSeriesViewModel.java @@ -0,0 +1,48 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.viewmodel; + +public class ComicSeriesViewModel { + + private int key; + private String title; + private String coverUrl; + + public int getKey() { + return key; + } + + public void setKey(int key) { + this.key = key; + } + + public String getTitle() { + return title; + } + + public void setTitle(String title) { + this.title = title; + } + + public String getCoverUrl() { + return coverUrl; + } + + public void setCoverUrl(String coverUrl) { + this.coverUrl = coverUrl; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicViewModel.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicViewModel.java index f2ce2763..e3ff3df4 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicViewModel.java +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/ComicViewModel.java @@ -16,11 +16,11 @@ package com.karumi.rosie.sample.comics.view.viewmodel; -public class ComicViewModel { +public class ComicViewModel implements ComicSeriesDetailViewModel { private int key; private String title; - private String coverUrl; + private String thumbnailUrl; public int getKey() { return key; @@ -38,11 +38,11 @@ public void setTitle(String title) { this.title = title; } - public String getCoverUrl() { - return coverUrl; + public String getThumbnailUrl() { + return thumbnailUrl; } - public void setCoverUrl(String coverUrl) { - this.coverUrl = coverUrl; + public void setThumbnailUrl(String thumbnailUrl) { + this.thumbnailUrl = thumbnailUrl; } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesDetailsViewModelMapper.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesDetailsViewModelMapper.java new file mode 100644 index 00000000..ea97e49b --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesDetailsViewModelMapper.java @@ -0,0 +1,107 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.viewmodel.mapper; + +import com.karumi.rosie.mapper.Mapper; +import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.comics.domain.model.Comic; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesDetailsViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesHeaderDetailViewModel; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; +import javax.inject.Inject; + +public class ComicSeriesToComicSeriesDetailsViewModelMapper + extends Mapper { + + @Inject public ComicSeriesToComicSeriesDetailsViewModelMapper() { + } + + @Override public ComicSeriesDetailsViewModel map(ComicSeries comicSeries) { + ComicSeriesDetailsViewModel comicSeriesDetailsViewModel = new ComicSeriesDetailsViewModel(); + + comicSeriesDetailsViewModel.setTitle(comicSeries.getName()); + List comicSeriesDetailViewModels = new LinkedList<>(); + comicSeriesDetailViewModels.add(mapComicSeriesToComicSeriesHeaderDetailViewModel(comicSeries)); + comicSeriesDetailViewModels.addAll(mapComicsToComicViewModels(comicSeries.getComics())); + comicSeriesDetailsViewModel.setComicSeriesDetailViewModels(comicSeriesDetailViewModels); + + return comicSeriesDetailsViewModel; + } + + @Override public ComicSeries reverseMap(ComicSeriesDetailsViewModel value) { + throw new UnsupportedOperationException(); + } + + private ComicSeriesHeaderDetailViewModel mapComicSeriesToComicSeriesHeaderDetailViewModel( + ComicSeries comicSeries) { + ComicSeriesHeaderDetailViewModel comicSeriesHeaderDetailViewModel = + new ComicSeriesHeaderDetailViewModel(); + + comicSeriesHeaderDetailViewModel.setTitle( + comicSeries.getName() + " (" + comicSeries.getReleaseYear() + ") #" + + comicSeries.getNumber()); + comicSeriesHeaderDetailViewModel.setCoverUrl(comicSeries.getCoverUrl()); + comicSeriesHeaderDetailViewModel.setDescription(comicSeries.getDescription()); + comicSeriesHeaderDetailViewModel.setRatingNameResourceId( + mapRatingToRatingNameResourceId(comicSeries.getRating())); + + return comicSeriesHeaderDetailViewModel; + } + + private int mapRatingToRatingNameResourceId(ComicSeries.Rating rating) { + int ratingNameResourceId; + switch (rating) { + case ALL_AGES: + ratingNameResourceId = R.string.marvel_rating_all_ages; + break; + case T: + ratingNameResourceId = R.string.marvel_rating_t; + break; + case TEENS_AND_UP: + ratingNameResourceId = R.string.marvel_rating_teens_and_up; + break; + case PARENTAL_ADVISORY: + ratingNameResourceId = R.string.marvel_rating_parental_advisory; + break; + case EXPLICIT_CONTENT: + default: + ratingNameResourceId = R.string.marvel_rating_explicit_content; + break; + } + + return ratingNameResourceId; + } + + private List mapComicsToComicViewModels(List comics) { + List comicViewModels = new ArrayList<>(); + + for (Comic comic : comics) { + ComicViewModel comicViewModel = new ComicViewModel(); + comicViewModel.setKey(comic.getKey()); + comicViewModel.setTitle(comic.getName()); + comicViewModel.setThumbnailUrl(comic.getThumbnailUrl()); + comicViewModels.add(comicViewModel); + } + + return comicViewModels; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesViewModelMapper.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesViewModelMapper.java new file mode 100644 index 00000000..6811dca5 --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicSeriesToComicSeriesViewModelMapper.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.comics.view.viewmodel.mapper; + +import com.karumi.rosie.repository.PaginatedCollection; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; +import com.karumi.rosie.sample.comics.view.viewmodel.ComicSeriesViewModel; +import java.util.LinkedList; +import java.util.List; +import javax.inject.Inject; + +public class ComicSeriesToComicSeriesViewModelMapper { + + @Inject public ComicSeriesToComicSeriesViewModelMapper() { + } + + public List mapComicSeriesToComicSeriesViewModels( + PaginatedCollection comics) { + List comicSeriesViewModels = new LinkedList<>(); + + for (ComicSeries comicSeries : comics.getItems()) { + ComicSeriesViewModel comicSeriesViewModel = new ComicSeriesViewModel(); + comicSeriesViewModel.setKey(comicSeries.getKey()); + String titleFormatted = + String.format("%1$s (%2$s)", comicSeries.getName(), comicSeries.getReleaseYear()); + comicSeriesViewModel.setTitle(titleFormatted); + comicSeriesViewModel.setCoverUrl(comicSeries.getCoverUrl()); + comicSeriesViewModels.add(comicSeriesViewModel); + } + + return comicSeriesViewModels; + } +} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicDetailsViewModelMapper.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicDetailsViewModelMapper.java deleted file mode 100644 index 36846854..00000000 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicDetailsViewModelMapper.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2015 Karumi. - * - * 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 com.karumi.rosie.sample.comics.view.viewmodel.mapper; - -import com.karumi.rosie.sample.R; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicDetailsViewModel; -import javax.inject.Inject; - -public class ComicToComicDetailsViewModelMapper { - - @Inject public ComicToComicDetailsViewModelMapper() { - } - - public ComicDetailsViewModel mapComicToComicDetailsViewModel(Comic comic) { - ComicDetailsViewModel comicDetailsViewModel = new ComicDetailsViewModel(); - - comicDetailsViewModel.setTitle( - comic.getName() + " (" + comic.getReleaseYear() + ") #" + comic.getNumber()); - comicDetailsViewModel.setCoverUrl(comic.getCoverUrl()); - comicDetailsViewModel.setDescription(comic.getDescription()); - comicDetailsViewModel.setRatingNameResourceId(getRatingNameResourceId(comic.getRating())); - - return comicDetailsViewModel; - } - - private int getRatingNameResourceId(Comic.Rating rating) { - int ratingNameResourceId; - switch (rating) { - case ALL_AGES: - ratingNameResourceId = R.string.marvel_rating_all_ages; - break; - case T: - ratingNameResourceId = R.string.marvel_rating_t; - break; - case TEENS_AND_UP: - ratingNameResourceId = R.string.marvel_rating_teens_and_up; - break; - case PARENTAL_ADVISORY: - ratingNameResourceId = R.string.marvel_rating_parental_advisory; - break; - case EXPLICIT_CONTENT: - default: - ratingNameResourceId = R.string.marvel_rating_explicit_content; - break; - } - - return ratingNameResourceId; - } -} diff --git a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicViewModelMapper.java b/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicViewModelMapper.java deleted file mode 100644 index 05426430..00000000 --- a/sample/src/main/java/com/karumi/rosie/sample/comics/view/viewmodel/mapper/ComicToComicViewModelMapper.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (C) 2015 Karumi. - * - * 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 com.karumi.rosie.sample.comics.view.viewmodel.mapper; - -import com.karumi.rosie.repository.PaginatedCollection; -import com.karumi.rosie.sample.comics.domain.model.Comic; -import com.karumi.rosie.sample.comics.view.viewmodel.ComicViewModel; -import java.util.LinkedList; -import java.util.List; -import javax.inject.Inject; - -public class ComicToComicViewModelMapper { - - @Inject public ComicToComicViewModelMapper() { - } - - public List mapComicsToComicViewModels(PaginatedCollection comics) { - List comicViewModels = new LinkedList<>(); - - for (Comic comic : comics.getItems()) { - ComicViewModel comicViewModel = new ComicViewModel(); - comicViewModel.setKey(comic.getKey()); - comicViewModel.setTitle(comic.getName() + " (" + comic.getReleaseYear() + ")"); - comicViewModel.setCoverUrl(comic.getCoverUrl()); - comicViewModels.add(comicViewModel); - } - - return comicViewModels; - } -} diff --git a/sample/src/main/java/com/karumi/rosie/sample/main/ApplicationModule.java b/sample/src/main/java/com/karumi/rosie/sample/main/ApplicationModule.java index c224ba6c..50df4909 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/main/ApplicationModule.java +++ b/sample/src/main/java/com/karumi/rosie/sample/main/ApplicationModule.java @@ -16,16 +16,13 @@ package com.karumi.rosie.sample.main; -import com.karumi.rosie.repository.datasource.CacheDataSource; -import com.karumi.rosie.repository.datasource.InMemoryCacheDataSource; import com.karumi.rosie.repository.datasource.paginated.InMemoryPaginatedCacheDataSource; import com.karumi.rosie.repository.datasource.paginated.PaginatedCacheDataSource; import com.karumi.rosie.sample.characters.domain.model.Character; -import com.karumi.rosie.sample.comics.domain.model.Comic; +import com.karumi.rosie.sample.comics.domain.model.ComicSeries; import com.karumi.rosie.time.TimeProvider; import dagger.Module; import dagger.Provides; -import javax.inject.Named; import javax.inject.Singleton; import static java.util.concurrent.TimeUnit.MINUTES; @@ -36,33 +33,18 @@ MainApplication.class }) public class ApplicationModule { - public static final String CHARACTERS_PAGE_IN_MEMORY_CACHE = "CharactersInMemoryCache"; - public static final String CHARACTERS_IN_MEMORY_CACHE = "CharactersInMemoryCache"; - - public static final String COMICS_PAGE_IN_MEMORY_CACHE = "ComicsInMemoryCache"; - public static final String COMICS_IN_MEMORY_CACHE = "ComicsInMemoryCache"; - private static final long CHARACTERS_IN_MEMORY_CACHE_TTL = MINUTES.toMillis(5); private static final long COMICS_IN_MEMORY_CACHE_TTL = MINUTES.toMillis(5); - @Provides @Singleton @Named(CHARACTERS_PAGE_IN_MEMORY_CACHE) + @Provides @Singleton public PaginatedCacheDataSource provideCharactersPageInMemoryCache() { return new InMemoryPaginatedCacheDataSource<>(new TimeProvider(), CHARACTERS_IN_MEMORY_CACHE_TTL); } - @Provides @Singleton @Named(CHARACTERS_IN_MEMORY_CACHE) - public CacheDataSource provideCharactersInMemoryCache() { - return new InMemoryCacheDataSource<>(new TimeProvider(), CHARACTERS_IN_MEMORY_CACHE_TTL); - } - - @Provides @Singleton @Named(COMICS_PAGE_IN_MEMORY_CACHE) - public PaginatedCacheDataSource provideComicsPageInMemoryCache() { + @Provides @Singleton + public PaginatedCacheDataSource provideComicsPageInMemoryCache() { return new InMemoryPaginatedCacheDataSource<>(new TimeProvider(), COMICS_IN_MEMORY_CACHE_TTL); } - @Provides @Singleton @Named(COMICS_IN_MEMORY_CACHE) - public CacheDataSource provideComicsInMemoryCache() { - return new InMemoryCacheDataSource<>(new TimeProvider(), COMICS_IN_MEMORY_CACHE_TTL); - } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/main/MainModule.java b/sample/src/main/java/com/karumi/rosie/sample/main/MainModule.java index d856c471..82f9eece 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/main/MainModule.java +++ b/sample/src/main/java/com/karumi/rosie/sample/main/MainModule.java @@ -17,13 +17,13 @@ package com.karumi.rosie.sample.main; import com.karumi.rosie.sample.characters.view.fragment.CharactersFragment; -import com.karumi.rosie.sample.comics.view.fragment.ComicsFragment; +import com.karumi.rosie.sample.comics.view.fragment.ComicSeriesFragment; import com.karumi.rosie.sample.main.view.activity.MainActivity; import dagger.Module; @Module(library = true, complete = false, injects = { - MainActivity.class, CharactersFragment.class, ComicsFragment.class + MainActivity.class, CharactersFragment.class, ComicSeriesFragment.class }) public class MainModule { } diff --git a/sample/src/main/java/com/karumi/rosie/sample/main/view/activity/MainActivity.java b/sample/src/main/java/com/karumi/rosie/sample/main/view/activity/MainActivity.java index b29ea8a9..3b3066e1 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/main/view/activity/MainActivity.java +++ b/sample/src/main/java/com/karumi/rosie/sample/main/view/activity/MainActivity.java @@ -18,23 +18,31 @@ import android.app.Fragment; import android.os.Bundle; +import android.support.design.widget.TabLayout; import android.support.v4.view.ViewPager; +import android.view.View; +import android.widget.TextView; import butterknife.Bind; import com.karumi.rosie.sample.R; +import com.karumi.rosie.sample.base.view.activity.MarvelActivity; import com.karumi.rosie.sample.characters.view.fragment.CharactersFragment; -import com.karumi.rosie.sample.comics.view.fragment.ComicsFragment; +import com.karumi.rosie.sample.comics.view.fragment.ComicSeriesFragment; import com.karumi.rosie.sample.main.MainModule; import com.karumi.rosie.sample.main.view.adapter.FragmentAdapter; -import com.karumi.rosie.view.RosieActivity; -import com.viewpagerindicator.TabPageIndicator; +import com.karumi.rosie.sample.main.view.presenter.FakeDataPresenter; +import com.karumi.rosie.view.Presenter; import java.util.Arrays; import java.util.List; +import javax.inject.Inject; -public class MainActivity extends RosieActivity { +public class MainActivity extends MarvelActivity implements FakeDataPresenter.View { @Bind(R.id.vp_main) ViewPager viewPager; - @Bind(R.id.tab_page_indicator) TabPageIndicator pagerTabView; + @Bind(R.id.tab_page_indicator) TabLayout pagerTabView; + @Bind(R.id.tv_disclaimer) TextView disclaimerView; + private FragmentAdapter adapter; + @Inject @Presenter FakeDataPresenter fakeDataPresenter; @Override protected int getLayoutId() { return R.layout.activity_main; @@ -54,11 +62,25 @@ private void initializeViewPager() { viewPager.setAdapter(adapter); Fragment charactersFragment = new CharactersFragment(); - Fragment comicsFragment = new ComicsFragment(); + Fragment comicsFragment = new ComicSeriesFragment(); adapter.addFragment(charactersFragment, getString(R.string.characters_page_title)); - adapter.addFragment(comicsFragment, getString(R.string.comics_page_title)); + adapter.addFragment(comicsFragment, getString(R.string.comic_series_page_title)); adapter.notifyDataSetChanged(); - pagerTabView.setViewPager(viewPager); + pagerTabView.setupWithViewPager(viewPager); + } + + @Override public void showFakeDisclaimer() { + disclaimerView.setVisibility(View.VISIBLE); + } + + @Override public void hideFakeDisclaimer() { + disclaimerView.setVisibility(View.GONE); + } + + @Override public void hideLoading() { + } + + @Override public void showLoading() { } } diff --git a/sample/src/main/java/com/karumi/rosie/sample/main/view/adapter/FragmentAdapter.java b/sample/src/main/java/com/karumi/rosie/sample/main/view/adapter/FragmentAdapter.java index 4d136c5a..81da066d 100644 --- a/sample/src/main/java/com/karumi/rosie/sample/main/view/adapter/FragmentAdapter.java +++ b/sample/src/main/java/com/karumi/rosie/sample/main/view/adapter/FragmentAdapter.java @@ -18,11 +18,11 @@ import android.app.Fragment; import android.app.FragmentManager; -import android.support.v13.app.FragmentStatePagerAdapter; +import android.support.v13.app.FragmentPagerAdapter; import java.util.ArrayList; import java.util.List; -public class FragmentAdapter extends FragmentStatePagerAdapter { +public class FragmentAdapter extends FragmentPagerAdapter { private final List fragments = new ArrayList<>(); diff --git a/sample/src/main/java/com/karumi/rosie/sample/main/view/presenter/FakeDataPresenter.java b/sample/src/main/java/com/karumi/rosie/sample/main/view/presenter/FakeDataPresenter.java new file mode 100644 index 00000000..2280901a --- /dev/null +++ b/sample/src/main/java/com/karumi/rosie/sample/main/view/presenter/FakeDataPresenter.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2015 Karumi. + * + * 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 com.karumi.rosie.sample.main.view.presenter; + +import com.karumi.rosie.domain.usecase.UseCaseHandler; +import com.karumi.rosie.sample.BuildConfig; +import com.karumi.rosie.view.RosiePresenter; +import com.karumi.rosie.view.loading.RosiePresenterWithLoading; +import javax.inject.Inject; + +public class FakeDataPresenter extends RosiePresenter { + @Inject public FakeDataPresenter(UseCaseHandler useCaseHandler) { + super(useCaseHandler); + } + + @Override protected void initialize() { + super.initialize(); + if (BuildConfig.MARVEL_PUBLIC_KEY == null || BuildConfig.MARVEL_PRIVATE_KEY == null) { + getView().showFakeDisclaimer(); + } else { + getView().hideFakeDisclaimer(); + } + } + + public interface View extends RosiePresenterWithLoading.View { + void showFakeDisclaimer(); + + void hideFakeDisclaimer(); + } +} diff --git a/sample/src/main/res/drawable-hdpi/ic_chevron_left_white_48dp.png b/sample/src/main/res/drawable-hdpi/ic_chevron_left_white_48dp.png new file mode 100644 index 00000000..7141cc61 Binary files /dev/null and b/sample/src/main/res/drawable-hdpi/ic_chevron_left_white_48dp.png differ diff --git a/sample/src/main/res/drawable-hdpi/ic_chevron_right_white_24dp.png b/sample/src/main/res/drawable-hdpi/ic_chevron_right_white_24dp.png new file mode 100644 index 00000000..1f10ee46 Binary files /dev/null and b/sample/src/main/res/drawable-hdpi/ic_chevron_right_white_24dp.png differ diff --git a/sample/src/main/res/drawable-hdpi/ic_keyboard_arrow_right_white_24dp.png b/sample/src/main/res/drawable-hdpi/ic_keyboard_arrow_right_white_24dp.png deleted file mode 100644 index b14e8bb5..00000000 Binary files a/sample/src/main/res/drawable-hdpi/ic_keyboard_arrow_right_white_24dp.png and /dev/null differ diff --git a/sample/src/main/res/drawable-mdpi/ic_chevron_left_white_48dp.png b/sample/src/main/res/drawable-mdpi/ic_chevron_left_white_48dp.png new file mode 100644 index 00000000..62f3590e Binary files /dev/null and b/sample/src/main/res/drawable-mdpi/ic_chevron_left_white_48dp.png differ diff --git a/sample/src/main/res/drawable-mdpi/ic_chevron_right_white_24dp.png b/sample/src/main/res/drawable-mdpi/ic_chevron_right_white_24dp.png new file mode 100644 index 00000000..b4f3c6d4 Binary files /dev/null and b/sample/src/main/res/drawable-mdpi/ic_chevron_right_white_24dp.png differ diff --git a/sample/src/main/res/drawable-mdpi/ic_keyboard_arrow_right_white_24dp.png b/sample/src/main/res/drawable-mdpi/ic_keyboard_arrow_right_white_24dp.png deleted file mode 100644 index a00a2509..00000000 Binary files a/sample/src/main/res/drawable-mdpi/ic_keyboard_arrow_right_white_24dp.png and /dev/null differ diff --git a/sample/src/main/res/drawable-xhdpi/ic_chevron_left_white_48dp.png b/sample/src/main/res/drawable-xhdpi/ic_chevron_left_white_48dp.png new file mode 100644 index 00000000..a68bc5fb Binary files /dev/null and b/sample/src/main/res/drawable-xhdpi/ic_chevron_left_white_48dp.png differ diff --git a/sample/src/main/res/drawable-xhdpi/ic_chevron_right_white_24dp.png b/sample/src/main/res/drawable-xhdpi/ic_chevron_right_white_24dp.png new file mode 100644 index 00000000..93dec392 Binary files /dev/null and b/sample/src/main/res/drawable-xhdpi/ic_chevron_right_white_24dp.png differ diff --git a/sample/src/main/res/drawable-xhdpi/ic_keyboard_arrow_right_white_24dp.png b/sample/src/main/res/drawable-xhdpi/ic_keyboard_arrow_right_white_24dp.png deleted file mode 100644 index aa55964e..00000000 Binary files a/sample/src/main/res/drawable-xhdpi/ic_keyboard_arrow_right_white_24dp.png and /dev/null differ diff --git a/sample/src/main/res/drawable-xxhdpi/ic_chevron_left_white_48dp.png b/sample/src/main/res/drawable-xxhdpi/ic_chevron_left_white_48dp.png new file mode 100644 index 00000000..42a4e219 Binary files /dev/null and b/sample/src/main/res/drawable-xxhdpi/ic_chevron_left_white_48dp.png differ diff --git a/sample/src/main/res/drawable-xxhdpi/ic_chevron_right_white_24dp.png b/sample/src/main/res/drawable-xxhdpi/ic_chevron_right_white_24dp.png new file mode 100644 index 00000000..7920aa3d Binary files /dev/null and b/sample/src/main/res/drawable-xxhdpi/ic_chevron_right_white_24dp.png differ diff --git a/sample/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_right_white_24dp.png b/sample/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_right_white_24dp.png deleted file mode 100644 index e9bc3889..00000000 Binary files a/sample/src/main/res/drawable-xxhdpi/ic_keyboard_arrow_right_white_24dp.png and /dev/null differ diff --git a/sample/src/main/res/drawable/comic_border.xml b/sample/src/main/res/drawable/comic_border.xml new file mode 100644 index 00000000..afc4e4d7 --- /dev/null +++ b/sample/src/main/res/drawable/comic_border.xml @@ -0,0 +1,28 @@ + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/drawable/dark_blue_divider.xml b/sample/src/main/res/drawable/dark_blue_divider.xml index 56ade1f2..2b212682 100644 --- a/sample/src/main/res/drawable/dark_blue_divider.xml +++ b/sample/src/main/res/drawable/dark_blue_divider.xml @@ -19,10 +19,10 @@ > - + \ No newline at end of file diff --git a/sample/src/main/res/drawable/toolbar_gradient.xml b/sample/src/main/res/drawable/toolbar_gradient.xml new file mode 100644 index 00000000..80c65ad2 --- /dev/null +++ b/sample/src/main/res/drawable/toolbar_gradient.xml @@ -0,0 +1,24 @@ + + + + + \ No newline at end of file diff --git a/sample/src/main/res/drawable/view_pager_tab_background.xml b/sample/src/main/res/drawable/view_pager_tab_background.xml deleted file mode 100644 index 693c2b42..00000000 --- a/sample/src/main/res/drawable/view_pager_tab_background.xml +++ /dev/null @@ -1,39 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_character_details.xml b/sample/src/main/res/layout/activity_character_details.xml index 7d5d1227..7c1e035b 100644 --- a/sample/src/main/res/layout/activity_character_details.xml +++ b/sample/src/main/res/layout/activity_character_details.xml @@ -14,7 +14,8 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - - - + android:orientation="vertical" + android:padding="@dimen/character_description_padding" + > - + + + - + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_comic_details.xml b/sample/src/main/res/layout/activity_comic_details.xml deleted file mode 100644 index aa141de4..00000000 --- a/sample/src/main/res/layout/activity_comic_details.xml +++ /dev/null @@ -1,64 +0,0 @@ - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_comic_series_details.xml b/sample/src/main/res/layout/activity_comic_series_details.xml new file mode 100644 index 00000000..e3a6be83 --- /dev/null +++ b/sample/src/main/res/layout/activity_comic_series_details.xml @@ -0,0 +1,33 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/activity_main.xml b/sample/src/main/res/layout/activity_main.xml index 63859944..f03d2a11 100644 --- a/sample/src/main/res/layout/activity_main.xml +++ b/sample/src/main/res/layout/activity_main.xml @@ -16,16 +16,26 @@ --> - + diff --git a/sample/src/main/res/layout/item_comic.xml b/sample/src/main/res/layout/item_comic.xml index 6de31dba..83e92202 100644 --- a/sample/src/main/res/layout/item_comic.xml +++ b/sample/src/main/res/layout/item_comic.xml @@ -14,36 +14,29 @@ ~ See the License for the specific language governing permissions and ~ limitations under the License. --> - + + - - - \ No newline at end of file + \ No newline at end of file diff --git a/sample/src/main/res/layout/item_comic_series.xml b/sample/src/main/res/layout/item_comic_series.xml new file mode 100644 index 00000000..01992643 --- /dev/null +++ b/sample/src/main/res/layout/item_comic_series.xml @@ -0,0 +1,49 @@ + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/item_comic_series_header.xml b/sample/src/main/res/layout/item_comic_series_header.xml new file mode 100644 index 00000000..dd1165ea --- /dev/null +++ b/sample/src/main/res/layout/item_comic_series_header.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/layout/item_load_more.xml b/sample/src/main/res/layout/item_load_more.xml index bf6f70e1..7471162e 100644 --- a/sample/src/main/res/layout/item_load_more.xml +++ b/sample/src/main/res/layout/item_load_more.xml @@ -18,7 +18,7 @@ android:orientation="vertical" android:layout_width="match_parent" android:layout_height="match_parent" - android:background="@android:color/holo_blue_dark" + android:background="@color/load_more_background" > \ No newline at end of file diff --git a/sample/src/main/res/layout/toolbar.xml b/sample/src/main/res/layout/toolbar.xml new file mode 100644 index 00000000..27f0cc82 --- /dev/null +++ b/sample/src/main/res/layout/toolbar.xml @@ -0,0 +1,48 @@ + + + + + + + + + \ No newline at end of file diff --git a/sample/src/main/res/values/colors.xml b/sample/src/main/res/values/colors.xml index fb68fce8..48dc0886 100644 --- a/sample/src/main/res/values/colors.xml +++ b/sample/src/main/res/values/colors.xml @@ -15,17 +15,25 @@ ~ limitations under the License. --> + #1D252D #2D353D + #FF1D252D + #001D252D + #FFFFFF #404B58 #00C8FF #FFFFFF #2D353D #EEEEEE #EEEEEE - #2D353D - @color/view_pager_tab_background #EEEEEE - @color/comic_item_background - #EEEEEE + #404B58 + #2D353D + @color/view_pager_tab_background + #EEEEEE + @color/comic_series_item_background + #EEEEEE + @color/character_item_background + @android:color/white #FFFFFF diff --git a/sample/src/main/res/values/dimens.xml b/sample/src/main/res/values/dimens.xml index 13832cba..9eb12fcb 100644 --- a/sample/src/main/res/values/dimens.xml +++ b/sample/src/main/res/values/dimens.xml @@ -18,25 +18,38 @@ 40dp 38dp 50dp - 50dp - 10dp - 14sp - 10dp - 24dp - 1dp - 300dp - 14sp - 16dp - 8dp + 24sp + 56dp + 48dp + 8dp + 50dp + 10dp + 14sp + 10dp + 24dp + 1dp + 350dp + 16sp + 20dp + 8dp + 8dp + 10dp + 1dp + 180dp + 6dp + 12sp + 1dp 50dp 10dp 14sp - 300dp + @dimen/comic_series_cover_height 24dp 10dp - 14sp - 16dp - 8dp + @dimen/comic_series_description_text_size + @dimen/comic_series_description_padding + @dimen/comic_series_description_margin_top 80dp 5dp + 14sp + 14dp diff --git a/sample/src/main/res/values/strings.xml b/sample/src/main/res/values/strings.xml index 5cb23637..7d9511f3 100644 --- a/sample/src/main/res/values/strings.xml +++ b/sample/src/main/res/values/strings.xml @@ -16,17 +16,22 @@ --> Rosie + Go back Loading… Characters - Comics + Comics Rating: %1$s All Ages T T+ Parental Advisory Max: Explicit Content - See comic details - Comic cover + See comic series details + Comic series cover + Comic thumbnail See character details Character thumbnail + Mavel keys doesn\'t exist, you need it to access to real data. + This is the DEMO mode with fake information. + diff --git a/sample/src/main/res/values/styles.xml b/sample/src/main/res/values/styles.xml index 4fc31491..29638a09 100644 --- a/sample/src/main/res/values/styles.xml +++ b/sample/src/main/res/values/styles.xml @@ -17,27 +17,44 @@ - - + + + + + + + + - -