diff --git a/mobile/com.sap.sailing.racecommittee.app/res/layout/footer_progress.xml b/mobile/com.sap.sailing.racecommittee.app/res/layout/footer_progress.xml new file mode 100644 index 00000000000..b475256b408 --- /dev/null +++ b/mobile/com.sap.sailing.racecommittee.app/res/layout/footer_progress.xml @@ -0,0 +1,12 @@ + + + + + diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java index 45ba8125a9e..c7ea5d6cf18 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OfflineDataManager.java @@ -1,16 +1,7 @@ package com.sap.sailing.racecommittee.app.data; -import java.io.Serializable; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Calendar; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.List; -import java.util.Map; -import java.util.UUID; -import java.util.concurrent.Callable; +import android.content.Context; +import android.support.v4.app.LoaderManager.LoaderCallbacks; import com.sap.sailing.domain.abstractlog.AbstractLogEventAuthor; import com.sap.sailing.domain.abstractlog.race.RaceLog; @@ -57,8 +48,17 @@ import com.sap.sse.common.Color; import com.sap.sse.common.TimePoint; import com.sap.sse.common.impl.MillisecondsTimePoint; -import android.content.Context; -import android.support.v4.app.LoaderManager.LoaderCallbacks; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Calendar; +import java.util.Collection; +import java.util.Collections; +import java.util.Date; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Callable; public class OfflineDataManager extends DataManager { @@ -82,13 +82,13 @@ public class OfflineDataManager extends DataManager { final TimePoint endDate = new MillisecondsTimePoint(cal.getTimeInMillis()); dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Cardiff)", startDate, endDate, "Cardiff", - true, UUID.randomUUID(), Collections. emptySet(), Collections.emptySet())); + true, UUID.randomUUID(), Collections.emptySet(), Collections.emptySet())); dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Nice)", startDate, endDate, "Nice", true, - UUID.randomUUID(), Collections. emptySet(), Collections.emptySet())); + UUID.randomUUID(), Collections.emptySet(), Collections.emptySet())); dataStore.addEvent(new StrippedEventImpl("Extreme Sailing Series 2012 (Rio)", startDate, endDate, "Rio", true, - UUID.randomUUID(), Collections. emptySet(), Collections.emptySet())); + UUID.randomUUID(), Collections.emptySet(), Collections.emptySet())); EventBase newEvent = new StrippedEventImpl("Extreme Sailing Series 2013 (Muscat)", startDate, endDate, "Muscat", - true, UUID.randomUUID(), Collections. emptySet(), Collections.emptySet()); + true, UUID.randomUUID(), Collections.emptySet(), Collections.emptySet()); final CourseAreaImpl offshore = new CourseAreaImpl("Offshore", UUID.randomUUID()); newEvent.getVenue().addCourseArea(offshore); final CourseAreaImpl stadium = new CourseAreaImpl("Stadium", UUID.randomUUID()); @@ -165,14 +165,19 @@ public class OfflineDataManager extends DataManager { @Override public LoaderCallbacks>> createEventsLoader( - LoadClient> callback) { - return new ImmediateDataLoaderCallbacks>(context, callback, - new Callable>() { - @Override - public Collection call() throws Exception { - return dataStore.getEvents(); - } - }); + LoadClient> callback, + UUID... eventIds + ) { + return new ImmediateDataLoaderCallbacks<>(context, callback, () -> { + if (eventIds.length == 0) { + return dataStore.getEvents(); + } + final List events = new ArrayList<>(); + for (UUID eventId : eventIds) { + events.add(dataStore.getEvent(eventId)); + } + return events; + }); } @Override @@ -201,8 +206,10 @@ public class OfflineDataManager extends DataManager { } @Override - public LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, - LoadClient> callback) { + public LoaderCallbacks>> createRacesLoader( + Serializable courseAreaId, + LoadClient> callback + ) { return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { @Override @@ -213,8 +220,10 @@ public class OfflineDataManager extends DataManager { } @Override - public LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, - LoadClient> callback) { + public LoaderCallbacks>> createMarksLoader( + ManagedRace managedRace, + LoadClient> callback + ) { return new ImmediateDataLoaderCallbacks>(context, callback, new Callable>() { @Override public Collection call() throws Exception { @@ -224,8 +233,10 @@ public class OfflineDataManager extends DataManager { } @Override - public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, - LoadClient callback) { + public LoaderCallbacks> createCourseLoader( + final ManagedRace managedRace, + LoadClient callback + ) { return new ImmediateDataLoaderCallbacks(context, callback, new Callable() { @Override public CourseBase call() throws Exception { @@ -259,8 +270,10 @@ public class OfflineDataManager extends DataManager { } @Override - public LoaderCallbacks> createLeaderboardLoader(ManagedRace managedRace, - LoadClient callback) { + public LoaderCallbacks> createLeaderboardLoader( + ManagedRace managedRace, + LoadClient callback + ) { return new ImmediateDataLoaderCallbacks<>(context, callback, new Callable() { @Override public LeaderboardResult call() throws Exception { @@ -283,7 +296,7 @@ public class OfflineDataManager extends DataManager { @Override public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, - boolean showStreamlets, boolean showSimulation, boolean showMapControls) { + boolean showStreamlets, boolean showSimulation, boolean showMapControls) { throw new IllegalStateException("No wind map in offline mode."); } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java index 001fdd1e668..b37f2f4cb15 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/OnlineDataManager.java @@ -71,8 +71,8 @@ import com.sap.sailing.server.gateway.deserialization.impl.EventBaseJsonDeserial import com.sap.sailing.server.gateway.deserialization.impl.LeaderboardGroupBaseJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.RaceColumnFactorJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.RegattaConfigurationJsonDeserializer; -import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.impl.TrackingConnectorInfoJsonDeserializer; +import com.sap.sailing.server.gateway.deserialization.impl.VenueJsonDeserializer; import com.sap.sailing.server.gateway.deserialization.racegroup.impl.RaceGroupDeserializer; import com.sap.sse.common.Util; @@ -120,24 +120,28 @@ public class OnlineDataManager extends DataManager { @Override public LoaderCallbacks>> createEventsLoader( - LoadClient> callback) { - return new DataLoaderCallbacks<>(callback, new LoaderCreator>() { - @Override - public Loader>> create(int id, Bundle args) throws Exception { - ExLog.i(context, TAG, "Creating Events-OnlineDataLoader " + id); - EventBaseJsonDeserializer serializer = new EventBaseJsonDeserializer( - new VenueJsonDeserializer(new CourseAreaJsonDeserializer(domainFactory)), - new LeaderboardGroupBaseJsonDeserializer(), - new TrackingConnectorInfoJsonDeserializer()); - DataParser> parser = new EventsDataParser(serializer); - DataHandler> handler = new EventsDataHandler(OnlineDataManager.this); - - // ExLog.i(context, TAG, "getEventsLoader created new loader..."); - List> params = new ArrayList<>(); - params.add(new Util.Pair("showNonPublic", AppPreferences.on(context).showNonPublic())); - URL url = UrlHelper.generateUrl(preferences.getServerBaseURL(), "/sailingserver/api/v1/events", params); - return new OnlineDataLoader<>(context, url, parser, handler); + LoadClient> callback, + UUID... eventIds + ) { + return new DataLoaderCallbacks<>(callback, (id, args) -> { + ExLog.i(context, TAG, "Creating Events-OnlineDataLoader " + id); + final EventBaseJsonDeserializer serializer = new EventBaseJsonDeserializer( + new VenueJsonDeserializer(new CourseAreaJsonDeserializer(domainFactory)), + new LeaderboardGroupBaseJsonDeserializer(), + new TrackingConnectorInfoJsonDeserializer() + ); + final DataParser> parser = new EventsDataParser(serializer); + final DataHandler> handler = new EventsDataHandler(OnlineDataManager.this); + final List> params = new ArrayList<>(); + params.add(new Util.Pair<>("showNonPublic", AppPreferences.on(context).showNonPublic())); + if (eventIds.length > 0) { + params.add(new Util.Pair<>("include", true)); + for (UUID eventId : eventIds) { + params.add(new Util.Pair<>("id", eventId)); + } } + URL url = UrlHelper.generateUrl(preferences.getServerBaseURL(), "/sailingserver/api/v1/events", params); + return new OnlineDataLoader<>(context, url, parser, handler); }, getContext()); } @@ -173,8 +177,10 @@ public class OnlineDataManager extends DataManager { } @Override - public LoaderCallbacks>> createRacesLoader(final Serializable courseAreaId, - LoadClient> callback) { + public LoaderCallbacks>> createRacesLoader( + final Serializable courseAreaId, + LoadClient> callback + ) { return new DataLoaderCallbacks<>(callback, new LoaderCreator>() { @Override public Loader>> create(int id, Bundle args) throws Exception { @@ -199,8 +205,10 @@ public class OnlineDataManager extends DataManager { } @Override - public LoaderCallbacks>> createMarksLoader(final ManagedRace managedRace, - LoadClient> callback) { + public LoaderCallbacks>> createMarksLoader( + final ManagedRace managedRace, + LoadClient> callback + ) { return new DataLoaderCallbacks<>(callback, new LoaderCreator>() { @Override public Loader>> create(int id, Bundle args) throws Exception { @@ -229,8 +237,10 @@ public class OnlineDataManager extends DataManager { } @Override - public LoaderCallbacks> createCourseLoader(final ManagedRace managedRace, - LoadClient callback) { + public LoaderCallbacks> createCourseLoader( + final ManagedRace managedRace, + LoadClient callback + ) { return new DataLoaderCallbacks<>(callback, new LoaderCreator() { @Override public Loader> create(int id, Bundle args) throws Exception { @@ -319,8 +329,10 @@ public class OnlineDataManager extends DataManager { } @Override - public LoaderCallbacks> createLeaderboardLoader(final ManagedRace managedRace, - LoadClient callback) { + public LoaderCallbacks> createLeaderboardLoader( + final ManagedRace managedRace, + LoadClient callback + ) { return new DataLoaderCallbacks<>(callback, new LoaderCreator() { @Override public Loader> create(int id, Bundle args) throws Exception { @@ -371,7 +383,7 @@ public class OnlineDataManager extends DataManager { @Override public String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, - boolean showStreamlets, boolean showSimulation, boolean showMapControls) { + boolean showStreamlets, boolean showSimulation, boolean showMapControls) { String url = ""; // get simple race log identifier Util.Triple triple = FleetIdentifierImpl.unescape(race.getId()); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/ReadonlyDataManager.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/ReadonlyDataManager.java index bdcf2653377..6f4426a62bb 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/ReadonlyDataManager.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/ReadonlyDataManager.java @@ -1,9 +1,7 @@ package com.sap.sailing.racecommittee.app.data; -import java.io.Serializable; -import java.util.Collection; -import java.util.Map; -import java.util.UUID; +import android.support.v4.app.LoaderManager; +import android.support.v4.app.LoaderManager.LoaderCallbacks; import com.sap.sailing.domain.base.Boat; import com.sap.sailing.domain.base.Competitor; @@ -20,20 +18,22 @@ import com.sap.sailing.racecommittee.app.domain.ManagedRace; import com.sap.sailing.racecommittee.app.domain.impl.LeaderboardResult; import com.sap.sailing.racecommittee.app.ui.fragments.lists.PositionListFragment; -import android.support.v4.app.LoaderManager; -import android.support.v4.app.LoaderManager.LoaderCallbacks; +import java.io.Serializable; +import java.util.Collection; +import java.util.Map; +import java.util.UUID; /** *

* Interface for everything read related when working with data. *

- * + * *

* The result values of this interface's methods are meant to be used in conjunction with the Android's * {@link LoaderManager} facility. Everything that is loaded by this interface is stored and cached in the underlying * {@link DataStore}. *

- * + * *

* If there are cached results your {@link LoadClient}'s callback methods might be called twice (first cached results; * afterwards remote results). See {@link LoadClient} for restrictions that apply to your data handling code. @@ -43,144 +43,149 @@ public interface ReadonlyDataManager { /** * Gets the underlying data store. - * + * * @return the {@link DataStore}. */ DataStore getDataStore(); /** * Creates a new {@link LoaderCallbacks} object for loading {@link EventBase}s. - * - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param callback {@link LoadClient} implementing your data handling code. + * @param eventIds Event IDs to filter the results. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ LoaderCallbacks>> createEventsLoader( - LoadClient> callback); + LoadClient> callback, + UUID... eventIds + ); /** * Creates a new {@link LoaderCallbacks} object for loading {@link CourseArea}s. - * - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks>> createCourseAreasLoader(Serializable parentEventId, - LoadClient> callback); + LoaderCallbacks>> createCourseAreasLoader( + Serializable parentEventId, + LoadClient> callback + ); - LoaderCallbacks>> createCourseAreasLoader(EventBase parentEvent, - LoadClient> callback); + LoaderCallbacks>> createCourseAreasLoader( + EventBase parentEvent, + LoadClient> callback + ); /** * Creates a new {@link LoaderCallbacks} object for loading racing referee positions. - * + * * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ LoaderCallbacks>> createPositionLoader( PositionListFragment positionListFragment); /** * Creates a new {@link LoaderCallbacks} object for loading {@link ManagedRace}s of a specific {@link CourseArea}. - * - * @param courseAreaId - * the {@link CourseArea}'s Identifier. - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param courseAreaId the {@link CourseArea}'s Identifier. + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks>> createRacesLoader(Serializable courseAreaId, - LoadClient> callback); + LoaderCallbacks>> createRacesLoader( + Serializable courseAreaId, + LoadClient> callback + ); /** * Creates a new {@link LoaderCallbacks} object for loading a race's {@link Mark}s. - * - * @param managedRace - * the {@link ManagedRace}. - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param managedRace the {@link ManagedRace}. + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks>> createMarksLoader(ManagedRace managedRace, - LoadClient> callback); + LoaderCallbacks>> createMarksLoader( + ManagedRace managedRace, + LoadClient> callback + ); /** * Creates a new {@link LoaderCallbacks} object for loading a race's {@link CourseBase}. - * - * @param managedRace - * the {@link ManagedRace}. - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param managedRace the {@link ManagedRace}. + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks> createCourseLoader(ManagedRace managedRace, - LoadClient callback); + LoaderCallbacks> createCourseLoader( + ManagedRace managedRace, + LoadClient callback + ); /** * Creates a new {@link LoaderCallbacks} object for loading {@link Competitor}s. - * - * @param callback - * {@link LoadClient} implementing your data handling code. + * + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks>> createCompetitorsLoader(ManagedRace managedRace, - LoadClient> callback); + LoaderCallbacks>> createCompetitorsLoader( + ManagedRace managedRace, + LoadClient> callback + ); /** * Create a new {@link LoaderCallbacks} object for loading {@link Competitor} * - * @param callback - * {@link LoadClient} implementing your data handling code. + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks>> createStartOrderLoader(ManagedRace managedRace, - LoadClient> callback); + LoaderCallbacks>> createStartOrderLoader( + ManagedRace managedRace, + LoadClient> callback + ); /** * Create a new {@link LoaderCallbacks} object for loading {@link LeaderboardResult} * - * @param managedRace - * the {@link ManagedRace} - * @param callback - * {@link LoadClient} implementing your data handling code + * @param managedRace the {@link ManagedRace} + * @param callback {@link LoadClient} implementing your data handling code * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ - LoaderCallbacks> createLeaderboardLoader(ManagedRace managedRace, - LoadClient callback); + LoaderCallbacks> createLeaderboardLoader( + ManagedRace managedRace, + LoadClient callback + ); /** * Creates a new {@link LoaderCallbacks} object for loading a client's configuration. - * * * @param deviceConfigurationUuid - * @param callback - * {@link LoadClient} implementing your data handling code. + * @param callback {@link LoadClient} implementing your data handling code. * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ LoaderCallbacks> createConfigurationLoader( String deviceConfigurationName, UUID deviceConfigurationUuid, LoadClient callback); String getMapUrl(String baseUrl, ManagedRace race, String eventId, boolean showWindCharts, boolean showStreamlets, - boolean showSimulation, boolean showMapControls); + boolean showSimulation, boolean showMapControls); /** * Create a new {@link LoaderCallbacks} object for loading the race columns (e.g. factors) @@ -188,10 +193,9 @@ public interface ReadonlyDataManager { * @param leaderboard * @param race_column * @param callback - * * @return {@link LoaderCallbacks} to be used in - * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or - * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. + * {@link LoaderManager#initLoader(int, android.os.Bundle, LoaderCallbacks)} or + * {@link LoaderManager#restartLoader(int, android.os.Bundle, LoaderCallbacks)}. */ LoaderCallbacks> createRaceColumnFactorLoader( LoadClient callback); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/clients/LoadClient.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/clients/LoadClient.java index 9e188e26542..827cff5b29e 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/clients/LoadClient.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/clients/LoadClient.java @@ -6,28 +6,23 @@ import android.support.v4.content.Loader; /** * Interface to hide complexity of {@link LoaderCallbacks#onLoadFinished(Loader, Object)}. Keep in mind that all * restrictions that apply on the LoaderCallback's method also apply to all methods of this interface. - * - * @param - * loaded data type. + * + * @param loaded data type. */ public interface LoadClient { /** * Called when a {@link Loader} returned a failure to its {@link LoaderCallbacks#onLoadFinished(Loader, Object)}. - * - * @param reason - * the loading has failed. + * + * @param reason the loading has failed. */ - public void onLoadFailed(Exception reason); + void onLoadFailed(int loaderId, Exception reason); /** * Called when a {@link Loader} returned successfully to its {@link LoaderCallbacks#onLoadFinished(Loader, Object)}. - * - * @param data - * that was loaded. - * @param isCached - * true if returned data is cached data. + * + * @param data that was loaded. + * @param isCached true if returned data is cached data. */ - public void onLoadSucceeded(T data, boolean isCached); - + void onLoadSucceeded(int loaderId, T data, boolean isCached); } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/loaders/DataLoaderCallbacks.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/loaders/DataLoaderCallbacks.java index 85c07c7803a..de512a4af83 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/loaders/DataLoaderCallbacks.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/data/loaders/DataLoaderCallbacks.java @@ -1,30 +1,29 @@ package com.sap.sailing.racecommittee.app.data.loaders; -import com.sap.sailing.android.shared.logging.ExLog; -import com.sap.sailing.racecommittee.app.data.clients.LoadClient; - import android.content.Context; import android.os.Bundle; import android.support.v4.app.LoaderManager.LoaderCallbacks; import android.support.v4.content.Loader; +import com.sap.sailing.android.shared.logging.ExLog; +import com.sap.sailing.racecommittee.app.data.clients.LoadClient; + /** *

* {@link LoaderCallbacks} wrapper to be used with {@link LoadClient}s. *

- * + * *

* On result {@link DataLoaderResult#isSuccessful()} is checked. If true - * {@link LoadClient#onLoadSucceeded(Object, boolean)} is called; other {@link LoadClient#onLoadFailed(Exception)} is + * {@link LoadClient#onLoadSucceeded(int, Object, boolean)} is called; other {@link LoadClient#onLoadFailed(int, Exception)} is * called. *

- * + * *

* There is currently no handling of a {@link Loader}'s reset. *

- * - * @param - * result type. + * + * @param result type. */ public class DataLoaderCallbacks implements LoaderCallbacks> { private static String TAG = DataLoaderCallbacks.class.getName(); @@ -57,9 +56,9 @@ public class DataLoaderCallbacks implements LoaderCallbacks> loader, DataLoaderResult result) { if (result.isSuccessful()) { - clientCallback.onLoadSucceeded(result.getResult(), result.isResultCached()); + clientCallback.onLoadSucceeded(loader.getId(), result.getResult(), result.isResultCached()); } else { - clientCallback.onLoadFailed(result.getException()); + clientCallback.onLoadFailed(loader.getId(), result.getException()); } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java index a078fae074a..552f28a99fe 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/LoginActivity.java @@ -461,7 +461,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener LoaderCallbacks configurationLoader = dataManager.createConfigurationLoader(deviceConfigurationName, deviceConfigurationUuid, new LoadClient() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { dismissProgressSpinner(); if (reason instanceof FileNotFoundException) { @@ -479,7 +479,7 @@ public class LoginActivity extends BaseActivity implements EventSelectedListener } @Override - public void onLoadSucceeded(DeviceConfiguration configuration, boolean isCached) { + public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration, boolean isCached) { getSupportLoaderManager().destroyLoader(0); dismissProgressSpinner(); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java index c86f0c332a4..3d7e7e65728 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/activities/RacingActivity.java @@ -677,7 +677,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks } @Override - public void onLoadFailed(Exception ex) { + public void onLoadFailed(int loaderId, Exception ex) { setProgressSpinnerVisibility(false); AlertDialog.Builder builder = new AlertDialog.Builder(RacingActivity.this); builder.setMessage(String.format(getString(R.string.generic_load_failure), ex.getMessage())) @@ -694,7 +694,7 @@ public class RacingActivity extends SessionActivity implements RaceListCallbacks } @Override - public void onLoadSucceeded(Collection data, boolean isCached) { + public void onLoadSucceeded(int loaderId, Collection data, boolean isCached) { // need to be a new instance, because of Activity restart after background kill // more information see bug 3741 lastSeenRaces = new ArrayList<>(data); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java index c419f2bafba..40f554c82bc 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/LoginListViews.java @@ -5,6 +5,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.os.Bundle; +import android.support.v4.app.Fragment; import android.support.v4.content.LocalBroadcastManager; import android.view.LayoutInflater; import android.view.View; @@ -20,6 +21,7 @@ import com.sap.sailing.android.shared.util.ViewHelper; import com.sap.sailing.racecommittee.app.AppConstants; import com.sap.sailing.racecommittee.app.R; import com.sap.sailing.racecommittee.app.ui.fragments.dialogs.LoggableDialogFragment; +import com.sap.sailing.racecommittee.app.ui.fragments.lists.EventListFragment; import java.util.ArrayList; import java.util.List; @@ -118,7 +120,15 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli case R.id.event_header: mCourseAreaContainer.close(); mPositionContainer.close(); - mEventContainer.toggle(); + final boolean expanded = mEventContainer.toggle(); + final Fragment fragment = requireFragmentManager().findFragmentById(R.id.event_fragment); + if (fragment instanceof EventListFragment) { + if (expanded) { + ((EventListFragment) fragment).onExpanded(); + } else { + ((EventListFragment) fragment).onCollapsed(); + } + } break; case R.id.area_header: @@ -174,7 +184,7 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli mAppUtils = AppUtils.with(getActivity()); } - public void toggle() { + public boolean toggle() { final int[] pos = new int[2]; if (mFrame != null && mFrame.getLayoutParams() != null) { @@ -194,10 +204,12 @@ public class LoginListViews extends LoggableDialogFragment implements View.OnCli mFrame.getLayoutParams().height = ScreenHelper.on(getActivity()).getScreenHeight() - pos[1]; mFrame.requestLayout(); setVisibility(mText, View.GONE); + return true; } else { close(); } } + return false; } public void close() { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/MainPreferenceFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/MainPreferenceFragment.java index 06b9d1b5fb4..acd059ea470 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/MainPreferenceFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/MainPreferenceFragment.java @@ -79,7 +79,7 @@ public class MainPreferenceFragment extends LoggableFragment { .createConfigurationLoader(deviceConfigurationName, deviceConfigurationUuid, new LoadClient() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { if (reason instanceof FileNotFoundException) { Toast.makeText(getActivity(), getString(R.string.loading_configuration_not_found), @@ -96,8 +96,8 @@ public class MainPreferenceFragment extends LoggableFragment { } @Override - public void onLoadSucceeded(DeviceConfiguration configuration, - boolean isCached) { + public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration, + boolean isCached) { getLoaderManager().destroyLoader(0); // this is our 'global' configuration, let's store it in app preferences diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/CourseAreaListFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/CourseAreaListFragment.java index a271c201855..a0cda87463d 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/CourseAreaListFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/CourseAreaListFragment.java @@ -61,8 +61,8 @@ public class CourseAreaListFragment extends NamedListFragment { } @Override - public void onLoadSucceeded(Collection data, boolean isCached) { - super.onLoadSucceeded(data, isCached); + public void onLoadSucceeded(int loaderId, Collection data, boolean isCached) { + super.onLoadSucceeded(loaderId, data, isCached); for (CheckedItem item : checkedItems) { item.setDisabled(true); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/EventListFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/EventListFragment.java index 1f924fa226a..d5914e1cffa 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/EventListFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/EventListFragment.java @@ -4,6 +4,7 @@ import android.app.Activity; import android.os.Bundle; import android.support.annotation.Nullable; import android.support.v4.app.LoaderManager.LoaderCallbacks; +import android.support.v4.content.Loader; import android.text.TextUtils; import com.sap.sailing.domain.base.EventBase; @@ -14,6 +15,7 @@ import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.EventSelec import com.sap.sailing.racecommittee.app.ui.fragments.lists.selection.ItemSelectedListener; import java.util.Collection; +import java.util.UUID; public class EventListFragment extends NamedListFragment { @@ -41,7 +43,12 @@ public class EventListFragment extends NamedListFragment { @Override protected LoaderCallbacks>> createLoaderCallbacks( - ReadonlyDataManager manager) { + ReadonlyDataManager manager + ) { + if (getArguments() != null && getArguments().containsKey(AppConstants.EXTRA_EVENT_ID)) { + final UUID eventId = UUID.fromString(getArguments().getString(AppConstants.EXTRA_EVENT_ID)); + return manager.createEventsLoader(this, eventId); + } return manager.createEventsLoader(this); } @@ -51,8 +58,11 @@ public class EventListFragment extends NamedListFragment { } @Override - public void onLoadSucceeded(Collection data, boolean isCached) { - super.onLoadSucceeded(data, isCached); + public void onLoadSucceeded(int loaderId, Collection data, boolean isCached) { + if (loaderId == 1 && isCached) { + return; + } + super.onLoadSucceeded(loaderId, data, isCached); final Bundle arguments = getArguments(); if (arguments != null && mSelectedIndex == -1) { final String id = arguments.getString(AppConstants.EXTRA_EVENT_ID); @@ -64,4 +74,32 @@ public class EventListFragment extends NamedListFragment { } } } + + @Override + public void onLoadFailed(int loaderId, Exception reason) { + super.onLoadFailed(loaderId, reason); + if (loaderId == 0) { + showProgressBar(false); + } + } + + public void onExpanded() { + if (getArguments() != null && getArguments().containsKey(AppConstants.EXTRA_EVENT_ID)) { + showProgressBar(true); + Loader>> loader = getLoaderManager().getLoader(1); + if (loader == null) { + getLoadMoreLoader().forceLoad(); + } else { + getLoadMoreLoader(); + } + } + } + + private Loader>> getLoadMoreLoader() { + return getLoaderManager().initLoader(1, null, getDataManager().createEventsLoader(this)); + } + + public void onCollapsed() { + showProgressBar(false); + } } diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/NamedListFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/NamedListFragment.java index fd4e051c162..e5ba0c04fc6 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/NamedListFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/lists/NamedListFragment.java @@ -46,6 +46,7 @@ public abstract class NamedListFragment extends LoggableListFra protected ItemSelectedListener listener; protected CheckedItemAdapter listAdapter; protected int mSelectedIndex = -1; + private View footerView; protected abstract ItemSelectedListener attachListener(Activity activity); @@ -84,6 +85,9 @@ public abstract class NamedListFragment extends LoggableListFra @Override public void onViewCreated(@NonNull View view, @Nullable Bundle savedInstanceState) { super.onViewCreated(view, savedInstanceState); + footerView = View.inflate(requireContext(), R.layout.footer_progress, null); + getListView().addFooterView(footerView); + showProgressBar(true); loadItems(); } @@ -100,7 +104,7 @@ public abstract class NamedListFragment extends LoggableListFra } @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { namedList.clear(); listAdapter.notifyDataSetChanged(); @@ -122,7 +126,7 @@ public abstract class NamedListFragment extends LoggableListFra } @Override - public void onLoadSucceeded(Collection data, boolean isCached) { + public void onLoadSucceeded(int loaderId, Collection data, boolean isCached) { namedList.clear(); checkedItems.clear(); if (isForceLoad() && !isCached) { @@ -183,8 +187,12 @@ public abstract class NamedListFragment extends LoggableListFra super.onSaveInstanceState(outState); } - public Loader>> getLoader() { - return getLoaderManager().initLoader(0, null, createLoaderCallbacks(OnlineDataManager.create(getActivity()))); + ReadonlyDataManager getDataManager() { + return OnlineDataManager.create(getActivity()); + } + + Loader>> getLoader() { + return getLoaderManager().initLoader(0, null, createLoaderCallbacks(getDataManager())); } private void loadItems() { @@ -209,11 +217,8 @@ public abstract class NamedListFragment extends LoggableListFra manager.beginTransaction().add(dialog, "failedDialog").commitAllowingStateLoss(); } - private void showProgressBar(boolean visible) { - Activity activity = getActivity(); - if (activity != null) { - activity.setProgressBarIndeterminateVisibility(visible); - } + void showProgressBar(boolean visible) { + footerView.setVisibility(visible ? View.VISIBLE : View.GONE); } protected void selectItem(T eventBase) { diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java index 3215da89f97..a080854025c 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/preference/GeneralPreferenceFragment.java @@ -236,7 +236,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment { .createConfigurationLoader(deviceConfigurationName, deviceConfigurationUuid, new LoadClient() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { if (reason instanceof FileNotFoundException) { Toast.makeText(getActivity(), getString(R.string.loading_configuration_not_found), @@ -256,7 +256,7 @@ public class GeneralPreferenceFragment extends BasePreferenceFragment { } @Override - public void onLoadSucceeded(DeviceConfiguration configuration, + public void onLoadSucceeded(int loaderId, DeviceConfiguration configuration, boolean isCached) { getLoaderManager().destroyLoader(0); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/CourseFragmentMarks.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/CourseFragmentMarks.java index 41e5b606b61..a458d2f0586 100644 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/CourseFragmentMarks.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/CourseFragmentMarks.java @@ -246,14 +246,14 @@ public class CourseFragmentMarks extends CourseFragment Loader marksLoader = getLoaderManager().restartLoader(0, null, mDataManager.createMarksLoader(getRace(), new LoadClient>() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { String toastText = getString(R.string.marks_w_placeholder); Toast.makeText(getActivity(), String.format(toastText, reason.toString()), Toast.LENGTH_LONG) .show(); } @Override - public void onLoadSucceeded(Collection data, boolean isCached) { + public void onLoadSucceeded(int loaderId, Collection data, boolean isCached) { onLoadMarksSucceeded(data); } })); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/PenaltyFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/PenaltyFragment.java index 84ecace8039..5f0e0dc1d9e 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/PenaltyFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/PenaltyFragment.java @@ -375,13 +375,13 @@ public class PenaltyFragment extends BaseFragment final Loader competitorLoader = getLoaderManager().initLoader(COMPETITOR_LOADER, null, dataManager.createCompetitorsLoader(getRace(), new LoadClient>() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { Toast.makeText(getActivity(), getString(R.string.competitor_load_error, reason.toString()), Toast.LENGTH_LONG).show(); } @Override - public void onLoadSucceeded(Map data, boolean isCached) { + public void onLoadSucceeded(int loaderId, Map data, boolean isCached) { if (isAdded() && !isCached) { onLoadCompetitorsSucceeded(data); } @@ -396,11 +396,11 @@ public class PenaltyFragment extends BaseFragment final Loader leaderboardResultLoader = getLoaderManager().initLoader(LEADERBOARD_ORDER_LOADER, null, dataManager.createLeaderboardLoader(getRace(), new LoadClient() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { } @Override - public void onLoadSucceeded(LeaderboardResult data, boolean isCached) { + public void onLoadSucceeded(int loaderId, LeaderboardResult data, boolean isCached) { onLoadLeaderboardResultSucceeded(data); } })); diff --git a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java index 674311dac6a..e1c410d8f64 100755 --- a/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java +++ b/mobile/com.sap.sailing.racecommittee.app/src/com/sap/sailing/racecommittee/app/ui/fragments/raceinfo/TrackingListFragment.java @@ -457,13 +457,13 @@ public class TrackingListFragment extends BaseFragment dataManager.createCompetitorsLoader(getRace(), new LoadClient>() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { Toast.makeText(getActivity(), getString(R.string.competitor_load_error, reason.toString()), Toast.LENGTH_LONG).show(); } @Override - public void onLoadSucceeded(Map data, boolean isCached) { + public void onLoadSucceeded(int loaderId, Map data, boolean isCached) { if (isAdded() && !isCached) { onLoadCompetitorsSucceeded(data); } @@ -480,11 +480,11 @@ public class TrackingListFragment extends BaseFragment final Loader leaderboardResultLoader = getLoaderManager().initLoader(LEADERBOARD_ORDER_LOADER, null, dataManager.createLeaderboardLoader(getRace(), new LoadClient() { @Override - public void onLoadFailed(Exception reason) { + public void onLoadFailed(int loaderId, Exception reason) { } @Override - public void onLoadSucceeded(LeaderboardResult data, boolean isCached) { + public void onLoadSucceeded(int loaderId, LeaderboardResult data, boolean isCached) { List> sortByRank = data.getResult(getRace().getName()); if (isAdded() && sortByRank != null) { CompetitorGoalPassingComparator comparator = (CompetitorGoalPassingComparator) mComparators