diff --git a/build.gradle b/build.gradle index 4db545949..6e745f49b 100644 --- a/build.gradle +++ b/build.gradle @@ -41,7 +41,7 @@ ext { app = [ versionMajor : 2, versionMinor : 6, - versionPatch : 1 + versionPatch : 2 ] // Sdk and tools diff --git a/data/build.gradle b/data/build.gradle index d1a163f58..bd376397f 100644 --- a/data/build.gradle +++ b/data/build.gradle @@ -43,10 +43,10 @@ dependencies { implementation "io.reactivex.rxjava2:rxjava:2.1.15" implementation 'io.reactivex.rxjava2:rxandroid:2.0.2' implementation 'com.squareup.retrofit2:adapter-rxjava2:2.4.0' - implementation 'com.squareup.okhttp3:okhttp:3.9.1' - implementation 'com.squareup.retrofit2:retrofit:2.3.0' + implementation 'com.squareup.okhttp3:okhttp:3.10.0' + implementation 'com.squareup.retrofit2:retrofit:2.4.0' implementation 'com.squareup.retrofit2:converter-simplexml:2.4.0' implementation 'com.squareup.retrofit2:converter-gson:2.3.0' - implementation 'com.google.code.gson:gson:2.8.2' + implementation 'com.google.code.gson:gson:2.8.4' implementation 'com.jakewharton.timber:timber:4.6.0' } diff --git a/data/proguard-rules.pro b/data/proguard-rules.pro index 386afc80a..8bd74d647 100644 --- a/data/proguard-rules.pro +++ b/data/proguard-rules.pro @@ -17,7 +17,7 @@ #} -keep class me.calebjones.spacelaunchnow.data.** { *; } - +-dontwarn java.lang.invoke.** -keepattributes Signature -keepattributes *Annotation* -keep class okhttp3.** { *; } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/helpers/Utils.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/helpers/Utils.java index 76f840c04..e44b665ed 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/helpers/Utils.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/helpers/Utils.java @@ -27,8 +27,14 @@ import android.view.ViewPropertyAnimator; import android.view.animation.PathInterpolator; +import com.google.gson.TypeAdapter; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Calendar; +import java.util.Date; public class Utils { @@ -104,4 +110,22 @@ public static boolean isNetworkAvailable(Context context) { return activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting(); } + public static class EpochDateConverter extends TypeAdapter { + @Override + public void write(JsonWriter out, Date value) throws IOException { + if (value == null) + out.nullValue(); + else + out.value(value.getTime() / 1000); + } + + @Override + public Date read(JsonReader in) throws IOException { + if (in != null) + return new Date(in.nextLong() * 1000); + else + return null; + } + } + } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/Constants.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/Constants.java index 4aac82c56..55434f2a1 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/Constants.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/Constants.java @@ -42,8 +42,10 @@ public final class Constants { public static String FORECAST_IO_BASE_URL = "https://api.forecast.io/"; public static String API_BASE_URL = "https://spacelaunchnow.me/"; + public static String API_DEBUG_BASE_URL = "http://10.0.2.2:8000/"; public static String LIBRARY_BASE_URL = "https://launchlibrary.net/"; public static String DEBUG_BASE_URL = "https://launchlibrary.net/"; + public static String NEWS_BASE_URL = "https://api.spaceflightnewsapi.net"; //These values are +1'd at runtime. public static final int DEFAULT_BLUR = 0; diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Agency.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Agency.java index 0d00bbd9c..938c79848 100755 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Agency.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Agency.java @@ -4,8 +4,6 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; -import java.util.List; - import io.realm.RealmList; import io.realm.RealmObject; import io.realm.annotations.PrimaryKey; @@ -25,12 +23,9 @@ public class Agency extends RealmObject { @SerializedName("featured") @Expose public Boolean featured; - @SerializedName("launchers") + @SerializedName("launcherConfigs") @Expose public String launchers_string; - @SerializedName("orbiters") - @Expose - public String orbiters; @SerializedName("description") @Expose public String description; @@ -69,15 +64,18 @@ public class Agency extends RealmObject { public String type; @SerializedName("launcher_list") @Expose - public RealmList launchers; + public RealmList launcherConfigs; + @SerializedName("orbiter_list") + @Expose + public RealmList orbiters; - public RealmList getLaunchers() { - return launchers; + public RealmList getLauncherConfigs() { + return launcherConfigs; } - public void setLaunchers(RealmList launchers) { - this.launchers = launchers; + public void setLauncherConfigs(RealmList launcherConfigs) { + this.launcherConfigs = launcherConfigs; } public Integer getId() { @@ -120,11 +118,11 @@ public void setLaunchers_string(String launchers_string) { this.launchers_string = launchers_string; } - public String getOrbiters() { + public RealmList getOrbiters() { return orbiters; } - public void setOrbiters(String orbiters) { + public void setOrbiters(RealmList orbiters) { this.orbiters = orbiters; } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Landing.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Landing.java new file mode 100644 index 000000000..4ae2aa9c9 --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Landing.java @@ -0,0 +1,66 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; + +public class Landing extends RealmObject{ + + @SerializedName("success") + @Expose + public Boolean success; + @SerializedName("attempt") + @Expose + public Boolean attempt; + @SerializedName("description") + @Expose + public String description; + @SerializedName("type") + @Expose + public LandingType landingType; + @SerializedName("location") + @Expose + public LandingLocation landingLocation; + + + public Boolean getSuccess() { + return success; + } + + public void setSuccess(Boolean success) { + this.success = success; + } + + public Boolean getAttempt() { + return attempt; + } + + public void setAttempt(Boolean attempt) { + this.attempt = attempt; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public LandingType getLandingType() { + return landingType; + } + + public void setLandingType(LandingType landingType) { + this.landingType = landingType; + } + + public LandingLocation getLandingLocation() { + return landingLocation; + } + + public void setLandingLocation(LandingLocation landingLocation) { + this.landingLocation = landingLocation; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingLocation.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingLocation.java new file mode 100644 index 000000000..18b0b12d5 --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingLocation.java @@ -0,0 +1,44 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; + +public class LandingLocation extends RealmObject{ + + @SerializedName("name") + @Expose + public String name; + @SerializedName("abbrev") + @Expose + public String abbrev; + @SerializedName("description") + @Expose + public String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAbbrev() { + return abbrev; + } + + public void setAbbrev(String abbrev) { + this.abbrev = abbrev; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingType.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingType.java new file mode 100644 index 000000000..6638fe10d --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LandingType.java @@ -0,0 +1,44 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; + +public class LandingType extends RealmObject{ + + @SerializedName("name") + @Expose + public String name; + @SerializedName("abbrev") + @Expose + public String abbrev; + @SerializedName("description") + @Expose + public String description; + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getAbbrev() { + return abbrev; + } + + public void setAbbrev(String abbrev) { + this.abbrev = abbrev; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launch.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launch.java index a36aadbe8..a802eb8b7 100755 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launch.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launch.java @@ -27,16 +27,7 @@ public class Launch extends RealmObject { public String imgUrl; @SerializedName("status") @Expose - public Integer status; - @SerializedName("netstamp") - @Expose - public Integer netstamp; - @SerializedName("wsstamp") - @Expose - public Integer wsstamp; - @SerializedName("westamp") - @Expose - public Integer westamp; + public Status status; @SerializedName("net") @Expose public Date net; @@ -46,15 +37,6 @@ public class Launch extends RealmObject { @SerializedName("window_start") @Expose public Date windowStart; - @SerializedName("isonet") - @Expose - public String isonet; - @SerializedName("isostart") - @Expose - public String isostart; - @SerializedName("isoend") - @Expose - public String isoend; @SerializedName("inhold") @Expose public Boolean inhold; @@ -76,18 +58,9 @@ public class Launch extends RealmObject { @SerializedName("hashtag") @Expose public String hashtag; - @SerializedName("launcher") - @Expose - public Launcher launcher; @SerializedName("mission") @Expose public Mission mission; - @SerializedName("lsp") - @Expose - public Agency lsp; - @SerializedName("location") - @Expose - public Location location; @SerializedName("pad") @Expose public Pad pad; @@ -97,10 +70,21 @@ public class Launch extends RealmObject { @SerializedName("vidURLs") @Expose public RealmList vidURLs = null; + @SerializedName("rocket") + @Expose + public Rocket rocket; public Integer eventID; public Date lastUpdate; + public Rocket getRocket() { + return rocket; + } + + public void setRocket(Rocket rocket) { + this.rocket = rocket; + } + public Date getLastUpdate() { return lastUpdate; } @@ -149,38 +133,14 @@ public void setImgUrl(String imgUrl) { this.imgUrl = imgUrl; } - public Integer getStatus() { + public Status getStatus() { return status; } - public void setStatus(Integer status) { + public void setStatus(Status status) { this.status = status; } - public Integer getNetstamp() { - return netstamp; - } - - public void setNetstamp(Integer netstamp) { - this.netstamp = netstamp; - } - - public Integer getWsstamp() { - return wsstamp; - } - - public void setWsstamp(Integer wsstamp) { - this.wsstamp = wsstamp; - } - - public Integer getWestamp() { - return westamp; - } - - public void setWestamp(Integer westamp) { - this.westamp = westamp; - } - public Date getNet() { return net; } @@ -205,30 +165,6 @@ public void setWindowStart(Date windowStart) { this.windowStart = windowStart; } - public String getIsonet() { - return isonet; - } - - public void setIsonet(String isonet) { - this.isonet = isonet; - } - - public String getIsostart() { - return isostart; - } - - public void setIsostart(String isostart) { - this.isostart = isostart; - } - - public String getIsoend() { - return isoend; - } - - public void setIsoend(String isoend) { - this.isoend = isoend; - } - public Boolean getInhold() { return inhold; } @@ -285,14 +221,6 @@ public void setHashtag(String hashtag) { this.hashtag = hashtag; } - public Launcher getLauncher() { - return launcher; - } - - public void setLauncher(Launcher launcher) { - this.launcher = launcher; - } - public Mission getMission() { return mission; } @@ -301,22 +229,6 @@ public void setMission(Mission mission) { this.mission = mission; } - public Agency getLsp() { - return lsp; - } - - public void setLsp(Agency lsp) { - this.lsp = lsp; - } - - public Location getLocation() { - return location; - } - - public void setLocation(Location location) { - this.location = location; - } - public Pad getPad() { return pad; } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LaunchList.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LaunchList.java new file mode 100644 index 000000000..1bac9a72d --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LaunchList.java @@ -0,0 +1,181 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import java.util.Date; + +import io.realm.RealmList; +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; +import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; + +public class LaunchList extends RealmObject { + + @PrimaryKey + @SerializedName("id") + @Expose + public Integer id; + @SerializedName("url") + @Expose + public String url; + @SerializedName("name") + @Expose + public String name; + @SerializedName("status") + @Expose + public Status status; + @SerializedName("net") + @Expose + public Date net; + @SerializedName("window_end") + @Expose + public Date windowEnd; + @SerializedName("window_start") + @Expose + public Date windowStart; + @SerializedName("mission") + @Expose + public String mission; + @SerializedName("mission_type") + @Expose + public String missionType; + @SerializedName("pad") + @Expose + public String pad; + @SerializedName("location") + @Expose + public String location; + @SerializedName("landing") + @Expose + public String landing; + @SerializedName("launcher") + @Expose + public String launcher; + @SerializedName("orbit") + @Expose + public String orbit; + @SerializedName("landing_success") + @Expose + public Integer landingSuccess; + + public String getOrbit() { + return orbit; + } + + public void setOrbit(String orbit) { + this.orbit = orbit; + } + + public Integer getLandingSuccess() { + return landingSuccess; + } + + public void setLandingSuccess(Integer landingSuccess) { + this.landingSuccess = landingSuccess; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Date getNet() { + return net; + } + + public void setNet(Date net) { + this.net = net; + } + + public Date getWindowEnd() { + return windowEnd; + } + + public void setWindowEnd(Date windowEnd) { + this.windowEnd = windowEnd; + } + + public Date getWindowStart() { + return windowStart; + } + + public void setWindowStart(Date windowStart) { + this.windowStart = windowStart; + } + + public String getMission() { + return mission; + } + + public void setMission(String mission) { + this.mission = mission; + } + + public String getMissionType() { + return missionType; + } + + public void setMissionType(String missionType) { + this.missionType = missionType; + } + + public String getPad() { + return pad; + } + + public void setPad(String pad) { + this.pad = pad; + } + + public String getLocation() { + return location; + } + + public void setLocation(String location) { + this.location = location; + } + + public String getLanding() { + return landing; + } + + public void setLanding(String landing) { + this.landing = landing; + } + + public String getLauncher() { + return launcher; + } + + public void setLauncher(String launcher) { + this.launcher = launcher; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launcher.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launcher.java index 93df55b33..673625d43 100755 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launcher.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Launcher.java @@ -12,232 +12,63 @@ public class Launcher extends RealmObject { @SerializedName("id") @Expose public Integer id; - @SerializedName("url") + @SerializedName("previous_flights") @Expose - public String url; - @SerializedName("name") + public Integer previousFlights; + @SerializedName("flight_proven") @Expose - public String name; - @SerializedName("description") + public Boolean flightProven; + @SerializedName("serial_number") @Expose - public String description; - @SerializedName("family") + public String serialNumber; + @SerializedName("status") @Expose - public String family; - @SerializedName("full_name") + public String status; + @SerializedName("details") @Expose - public String fullName; - @SerializedName("variant") - @Expose - public String variant; - @SerializedName("alias") - @Expose - public String alias; - @SerializedName("min_stage") - @Expose - public Integer minStage; - @SerializedName("max_stage") - @Expose - public Integer maxStage; - @SerializedName("length") - @Expose - public Float length; - @SerializedName("diameter") - @Expose - public Float diameter; - @SerializedName("launch_mass") - @Expose - public Integer launchMass; - @SerializedName("leo_capacity") - @Expose - public Integer leoCapacity; - @SerializedName("gto_capacity") - @Expose - public Integer gtoCapacity; - @SerializedName("to_thrust") - @Expose - public Integer toThrust; - @SerializedName("apogee") - @Expose - public Integer apogee; - @SerializedName("vehicle_range") - @Expose - public Integer vehicleRange; - @SerializedName("image_url") - @Expose - public String imageUrl; - @SerializedName("info_url") - @Expose - public String infoUrl; - @SerializedName("wiki_url") - @Expose - public String wikiUrl; - - public Integer getId() { - return id; - } - - public void setId(Integer id) { - this.id = id; - } - - public String getUrl() { - return url; - } - - public void setUrl(String url) { - this.url = url; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; - } - - public String getFamily() { - return family; - } - - public void setFamily(String family) { - this.family = family; - } - - public String getFullName() { - return fullName; - } - - public void setFullName(String fullName) { - this.fullName = fullName; - } + public String details; - public String getVariant() { - return variant; + public Integer getPreviousFlights() { + return previousFlights; } - public void setVariant(String variant) { - this.variant = variant; + public void setPreviousFlights(Integer previousFlights) { + this.previousFlights = previousFlights; } - public String getAlias() { - return alias; + public Boolean getFlightProven() { + return flightProven; } - public void setAlias(String alias) { - this.alias = alias; + public String getDetails() { + return details; } - public Integer getMinStage() { - return minStage; + public void setDetails(String details) { + this.details = details; } - public void setMinStage(Integer minStage) { - this.minStage = minStage; + public String getStatus() { + return status; } - public Integer getMaxStage() { - return maxStage; + public void setStatus(String status) { + this.status = status; } - public void setMaxStage(Integer maxStage) { - this.maxStage = maxStage; - } - - public Float getLength() { - return length; - } - - public void setLength(Float length) { - this.length = length; - } - - public Float getDiameter() { - return diameter; - } - - public void setDiameter(Float diameter) { - this.diameter = diameter; - } - - public Integer getLaunchMass() { - return launchMass; - } - - public void setLaunchMass(Integer launchMass) { - this.launchMass = launchMass; - } - - public Integer getLeoCapacity() { - return leoCapacity; - } - - public void setLeoCapacity(Integer leoCapacity) { - this.leoCapacity = leoCapacity; - } - - public Integer getGtoCapacity() { - return gtoCapacity; - } - - public void setGtoCapacity(Integer gtoCapacity) { - this.gtoCapacity = gtoCapacity; - } - - public Integer getToThrust() { - return toThrust; - } - - public void setToThrust(Integer toThrust) { - this.toThrust = toThrust; - } - - public Integer getApogee() { - return apogee; - } - - public void setApogee(Integer apogee) { - this.apogee = apogee; - } - - public Integer getVehicleRange() { - return vehicleRange; - } - - public void setVehicleRange(Integer vehicleRange) { - this.vehicleRange = vehicleRange; - } - - public String getImageUrl() { - return imageUrl; - } - - public void setImageUrl(String imageUrl) { - this.imageUrl = imageUrl; - } - - public String getInfoUrl() { - return infoUrl; + public Integer getId() { + return id; } - public void setInfoUrl(String infoUrl) { - this.infoUrl = infoUrl; + public void setId(Integer id) { + this.id = id; } - public String getWikiUrl() { - return wikiUrl; + public String getSerialNumber() { + return serialNumber; } - public void setWikiUrl(String wikiUrl) { - this.wikiUrl = wikiUrl; + public void setSerialNumber(String serialNumber) { + this.serialNumber = serialNumber; } } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LauncherConfig.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LauncherConfig.java new file mode 100644 index 000000000..810f12eac --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/LauncherConfig.java @@ -0,0 +1,254 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +public class LauncherConfig extends RealmObject { + + @PrimaryKey + @SerializedName("id") + @Expose + public Integer id; + @SerializedName("url") + @Expose + public String url; + @SerializedName("name") + @Expose + public String name; + @SerializedName("launch_service_provider") + @Expose + public Agency launchServiceProvider; + @SerializedName("description") + @Expose + public String description; + @SerializedName("family") + @Expose + public String family; + @SerializedName("full_name") + @Expose + public String fullName; + @SerializedName("variant") + @Expose + public String variant; + @SerializedName("alias") + @Expose + public String alias; + @SerializedName("min_stage") + @Expose + public Integer minStage; + @SerializedName("max_stage") + @Expose + public Integer maxStage; + @SerializedName("length") + @Expose + public Float length; + @SerializedName("diameter") + @Expose + public Float diameter; + @SerializedName("launch_mass") + @Expose + public Integer launchMass; + @SerializedName("leo_capacity") + @Expose + public Integer leoCapacity; + @SerializedName("gto_capacity") + @Expose + public Integer gtoCapacity; + @SerializedName("to_thrust") + @Expose + public Integer toThrust; + @SerializedName("apogee") + @Expose + public Integer apogee; + @SerializedName("vehicle_range") + @Expose + public Integer vehicleRange; + @SerializedName("image_url") + @Expose + public String imageUrl; + @SerializedName("info_url") + @Expose + public String infoUrl; + @SerializedName("wiki_url") + @Expose + public String wikiUrl; + + public Agency getLaunchServiceProvider() { + return launchServiceProvider; + } + + public void setLaunchServiceProvider(Agency launchServiceProvider) { + this.launchServiceProvider = launchServiceProvider; + } + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public String getFamily() { + return family; + } + + public void setFamily(String family) { + this.family = family; + } + + public String getFullName() { + return fullName; + } + + public void setFullName(String fullName) { + this.fullName = fullName; + } + + public String getVariant() { + return variant; + } + + public void setVariant(String variant) { + this.variant = variant; + } + + public String getAlias() { + return alias; + } + + public void setAlias(String alias) { + this.alias = alias; + } + + public Integer getMinStage() { + return minStage; + } + + public void setMinStage(Integer minStage) { + this.minStage = minStage; + } + + public Integer getMaxStage() { + return maxStage; + } + + public void setMaxStage(Integer maxStage) { + this.maxStage = maxStage; + } + + public Float getLength() { + return length; + } + + public void setLength(Float length) { + this.length = length; + } + + public Float getDiameter() { + return diameter; + } + + public void setDiameter(Float diameter) { + this.diameter = diameter; + } + + public Integer getLaunchMass() { + return launchMass; + } + + public void setLaunchMass(Integer launchMass) { + this.launchMass = launchMass; + } + + public Integer getLeoCapacity() { + return leoCapacity; + } + + public void setLeoCapacity(Integer leoCapacity) { + this.leoCapacity = leoCapacity; + } + + public Integer getGtoCapacity() { + return gtoCapacity; + } + + public void setGtoCapacity(Integer gtoCapacity) { + this.gtoCapacity = gtoCapacity; + } + + public Integer getToThrust() { + return toThrust; + } + + public void setToThrust(Integer toThrust) { + this.toThrust = toThrust; + } + + public Integer getApogee() { + return apogee; + } + + public void setApogee(Integer apogee) { + this.apogee = apogee; + } + + public Integer getVehicleRange() { + return vehicleRange; + } + + public void setVehicleRange(Integer vehicleRange) { + this.vehicleRange = vehicleRange; + } + + public String getImageUrl() { + return imageUrl; + } + + public void setImageUrl(String imageUrl) { + this.imageUrl = imageUrl; + } + + public String getInfoUrl() { + return infoUrl; + } + + public void setInfoUrl(String infoUrl) { + this.infoUrl = infoUrl; + } + + public String getWikiUrl() { + return wikiUrl; + } + + public void setWikiUrl(String wikiUrl) { + this.wikiUrl = wikiUrl; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Mission.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Mission.java index 8aece06c8..31f651ced 100755 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Mission.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Mission.java @@ -18,12 +18,35 @@ public class Mission extends RealmObject { @SerializedName("description") @Expose public String description; - @SerializedName("type") + @SerializedName("type_name") @Expose public Integer type; - @SerializedName("type_name") + @SerializedName("type") @Expose public String typeName; + @SerializedName("orbit") + @Expose + public String orbit; + @SerializedName("orbit_abbrev") + @Expose + public String orbitAbbrev; + + + public String getOrbit() { + return orbit; + } + + public void setOrbit(String orbit) { + this.orbit = orbit; + } + + public String getOrbitAbbrev() { + return orbitAbbrev; + } + + public void setOrbitAbbrev(String orbitAbbrev) { + this.orbitAbbrev = orbitAbbrev; + } public Integer getId() { return id; diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Orbiter.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Orbiter.java index cd7664f0c..44103b45f 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Orbiter.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Orbiter.java @@ -3,6 +3,8 @@ import com.google.gson.annotations.Expose; import com.google.gson.annotations.SerializedName; +import java.util.Date; + import io.realm.RealmObject; public class Orbiter extends RealmObject { @@ -34,9 +36,52 @@ public class Orbiter extends RealmObject { @SerializedName("wiki_link") @Expose public String wikiLink; + @SerializedName("info_link") + @Expose + public String infoLink; @SerializedName("capability") @Expose public String capability; + @SerializedName("maiden_flight") + @Expose + public Date maidenFlight; + @SerializedName("height") + @Expose + public Float height; + @SerializedName("diameter") + @Expose + public Float diameter; + @SerializedName("human_rated") + @Expose + public Boolean humanRated; + @SerializedName("in_use") + @Expose + public Boolean inUse; + @SerializedName("crew_capacity") + @Expose + public Integer crewCapacity; + @SerializedName("payload_capacity") + @Expose + public Integer payloadCapacity; + @SerializedName("flight_life") + @Expose + public String flightLife; + + public String getInfoLink() { + return infoLink; + } + + public void setInfoLink(String infoLink) { + this.infoLink = infoLink; + } + + public Boolean getInUse() { + return inUse; + } + + public void setInUse(Boolean inUse) { + this.inUse = inUse; + } public String getName() { return name; @@ -109,4 +154,60 @@ public String getCapability() { public void setCapability(String capability) { this.capability = capability; } + + public Date getMaidenFlight() { + return maidenFlight; + } + + public void setMaidenFlight(Date maidenFlight) { + this.maidenFlight = maidenFlight; + } + + public Float getHeight() { + return height; + } + + public void setHeight(Float height) { + this.height = height; + } + + public Float getDiameter() { + return diameter; + } + + public void setDiameter(Float diameter) { + this.diameter = diameter; + } + + public Boolean getHumanRated() { + return humanRated; + } + + public void setHumanRated(Boolean humanRated) { + this.humanRated = humanRated; + } + + public Integer getCrewCapacity() { + return crewCapacity; + } + + public void setCrewCapacity(Integer crewCapacity) { + this.crewCapacity = crewCapacity; + } + + public Integer getPayloadCapacity() { + return payloadCapacity; + } + + public void setPayloadCapacity(Integer payloadCapacity) { + this.payloadCapacity = payloadCapacity; + } + + public String getFlightLife() { + return flightLife; + } + + public void setFlightLife(String flightLife) { + this.flightLife = flightLife; + } } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Pad.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Pad.java index 42319d793..330d04016 100755 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Pad.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Pad.java @@ -33,6 +33,17 @@ public class Pad extends RealmObject { @SerializedName("longitude") @Expose public String longitude; + @SerializedName("location") + @Expose + public Location location; + + public Location getLocation() { + return location; + } + + public void setLocation(Location location) { + this.location = location; + } public Integer getId() { return id; diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Rocket.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Rocket.java new file mode 100644 index 000000000..0234614bf --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Rocket.java @@ -0,0 +1,54 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmList; +import io.realm.RealmObject; + +public class Rocket extends RealmObject { + @SerializedName("configuration") + @Expose + public LauncherConfig configuration; + @SerializedName("first_stage") + @Expose + public RealmList firstStage; + @SerializedName("second_stage") + @Expose + public Stage secondStage; + @SerializedName("reused") + @Expose + public Boolean reused; + + public Boolean getReused() { + return reused; + } + + public void setReused(Boolean reused) { + this.reused = reused; + } + + public LauncherConfig getConfiguration() { + return configuration; + } + + public void setConfiguration(LauncherConfig configuration) { + this.configuration = configuration; + } + + public RealmList getFirstStage() { + return firstStage; + } + + public void setFirstStage(RealmList firstStage) { + this.firstStage = firstStage; + } + + public Stage getSecondStage() { + return secondStage; + } + + public void setSecondStage(Stage secondStage) { + this.secondStage = secondStage; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Stage.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Stage.java new file mode 100644 index 000000000..8965a636c --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Stage.java @@ -0,0 +1,56 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; + +public class Stage extends RealmObject { + @SerializedName("launcher") + @Expose + public Launcher launcher; + + @SerializedName("landing") + @Expose + public Landing landing; + + @SerializedName("type") + @Expose + public String type; + + @SerializedName("reused") + @Expose + public Boolean reused; + + public String getType() { + return type; + } + + public void setType(String type) { + this.type = type; + } + + public Boolean getReused() { + return reused; + } + + public void setReused(Boolean reused) { + this.reused = reused; + } + + public Launcher getLauncher() { + return launcher; + } + + public void setLauncher(Launcher launcher) { + this.launcher = launcher; + } + + public Landing getLanding() { + return landing; + } + + public void setLanding(Landing landing) { + this.landing = landing; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Status.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Status.java new file mode 100644 index 000000000..c646c1ca8 --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/main/Status.java @@ -0,0 +1,35 @@ +package me.calebjones.spacelaunchnow.data.models.main; + +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; + +import io.realm.RealmObject; +import io.realm.annotations.PrimaryKey; + +public class Status extends RealmObject { + + @PrimaryKey + @SerializedName("id") + @Expose + public Integer id; + + @SerializedName("name") + @Expose + public String name; + + public Integer getId() { + return id; + } + + public void setId(Integer id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Article.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Article.java index 360139149..39dd5ce85 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Article.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Article.java @@ -1,51 +1,64 @@ package me.calebjones.spacelaunchnow.data.models.news; -import org.simpleframework.xml.Attribute; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.Namespace; -import org.simpleframework.xml.Path; -import org.simpleframework.xml.Root; -import org.simpleframework.xml.Text; +import com.google.gson.annotations.Expose; +import com.google.gson.annotations.SerializedName; import java.util.Date; +import java.util.List; + +public class Article { + + @SerializedName("tags") + @Expose + public List tags = null; + @SerializedName("categories") + @Expose + public List categories = null; + @SerializedName("news_site_long") + @Expose + public String newsSite; + @SerializedName("title") + @Expose + public String title; + @SerializedName("url") + @Expose + public String url; + @SerializedName("id") + @Expose + public String id; + @SerializedName("date_published") + @Expose + public Date datePublished; + @SerializedName("date_Added") + @Expose + public Date dateAdded; + @SerializedName("featured_image") + @Expose + public String featuredImage; + + public List getTags() { + return tags; + } -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.annotations.Index; -import io.realm.annotations.LinkingObjects; -import io.realm.annotations.PrimaryKey; - -@Root(strict = false, name="item") -public class Article extends RealmObject { - - @PrimaryKey - @Element(name = "title") - private String title; - - @Element(name = "link") - private String link; - - @Element(name = "description") - private String description; - - @Element(name = "guid", required = false) - private String guid; - - @Element(name = "pubDate", required = false) - private String pubDate; + public void setTags(List tags) { + this.tags = tags; + } - @Element(name = "content", required = false) - private String content; + public List getCategories() { + return categories; + } - @Index - private Date date; + public void setCategories(List categories) { + this.categories = categories; + } - @Path("enclosure") - @Attribute(name = "url", required = false) - private String mediaUrl; + public String getNewsSite() { + return newsSite; + } - @LinkingObjects("articles") - private final RealmResults channel = null; + public void setNewsSite(String newsSite) { + this.newsSite = newsSite; + } public String getTitle() { return title; @@ -55,55 +68,43 @@ public void setTitle(String title) { this.title = title; } - public String getLink() { - return link; - } - - public void setLink(String link) { - this.link = link; - } - - public String getDescription() { - return description; - } - - public void setDescription(String description) { - this.description = description; + public String getUrl() { + return url; } - public String getGuid() { - return guid; + public void setUrl(String url) { + this.url = url; } - public void setGuid(String guid) { - this.guid = guid; + public String getId() { + return id; } - public String getPubDate() { - return pubDate; + public void setId(String id) { + this.id = id; } - public void setPubDate(String pubDate) { - this.pubDate = pubDate; + public Date getDatePublished() { + return datePublished; } - public RealmResults getChannel() { - return channel; + public void setDatePublished(Date datePublished) { + this.datePublished = datePublished; } - public String getMediaUrl() { - return mediaUrl; + public Date getDateAdded() { + return dateAdded; } - public void setMediaUrl(String mediaUrl) { - this.mediaUrl = mediaUrl; + public void setDateAdded(Date dateAdded) { + this.dateAdded = dateAdded; } - public Date getDate() { - return date; + public String getFeaturedImage() { + return featuredImage; } - public void setDate(Date date) { - this.date = date; + public void setFeaturedImage(String featuredImage) { + this.featuredImage = featuredImage; } } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Channel.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Channel.java deleted file mode 100644 index 0232df48a..000000000 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/Channel.java +++ /dev/null @@ -1,40 +0,0 @@ -package me.calebjones.spacelaunchnow.data.models.news; - -import org.simpleframework.xml.Attribute; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.ElementList; -import org.simpleframework.xml.Root; - -import io.realm.RealmList; -import io.realm.RealmObject; -import io.realm.RealmResults; -import io.realm.annotations.LinkingObjects; - -@Root(strict = false) -public class Channel extends RealmObject { - - @Element(name = "title") - public String title; - - @ElementList(inline = true, name="item") - public RealmList
articles; - - @LinkingObjects("channel") - final RealmResults newsFeedResponse = null; - - public String getTitle() { - return title; - } - - public void setTitle(String title) { - this.title = title; - } - - public RealmList
getArticles() { - return articles; - } - - public void setArticles(RealmList
articles) { - this.articles = articles; - } -} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/NewsFeedResponse.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/NewsFeedResponse.java deleted file mode 100644 index 13efc915c..000000000 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/models/news/NewsFeedResponse.java +++ /dev/null @@ -1,46 +0,0 @@ -package me.calebjones.spacelaunchnow.data.models.news; - -import org.simpleframework.xml.Attribute; -import org.simpleframework.xml.Element; -import org.simpleframework.xml.ElementList; -import org.simpleframework.xml.Root; - -import io.realm.RealmObject; -import io.realm.annotations.PrimaryKey; - -@Root(name = "rss", strict = false) -public class NewsFeedResponse extends RealmObject { - - @Attribute(name = "version") - private String version; - - @Element(name = "channel") - public Channel channel; - - @PrimaryKey - private long lastUpdate; - - public long getLastUpdate() { - return lastUpdate; - } - - public void setLastUpdate(long lastUpdate) { - this.lastUpdate = lastUpdate; - } - - public String getVersion() { - return version; - } - - public void setVersion(String version) { - this.version = version; - } - - public Channel getChannel() { - return channel; - } - - public void setChannel(Channel channel) { - this.channel = channel; - } -} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/DataClient.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/DataClient.java index 11a60fb65..102957402 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/DataClient.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/DataClient.java @@ -3,6 +3,7 @@ import me.calebjones.spacelaunchnow.data.models.main.Launch; import me.calebjones.spacelaunchnow.data.networking.interfaces.SpaceLaunchNowService; import me.calebjones.spacelaunchnow.data.networking.responses.base.AgencyResponse; +import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchListResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.VehicleResponse; import retrofit2.Call; @@ -19,11 +20,11 @@ public class DataClient { private Retrofit spaceLaunchNowRetrofit; - private DataClient(String version, String token) { + private DataClient(String version, String token, boolean debug) { libraryRetrofit = RetrofitBuilder.getLibraryRetrofit(version); libraryRetrofitThreaded = RetrofitBuilder.getLibraryRetrofitThreaded(version); - spaceLaunchNowRetrofit = RetrofitBuilder.getSpaceLaunchNowRetrofit(token); + spaceLaunchNowRetrofit = RetrofitBuilder.getSpaceLaunchNowRetrofit(token, debug); spaceLaunchNowService = spaceLaunchNowRetrofit.create(SpaceLaunchNowService.class); } @@ -39,14 +40,14 @@ public Retrofit getSpaceLaunchNowRetrofit() { /** * Applications must call create to configure the DataClient singleton */ - public static void create(String version, String token) { - mInstance = new DataClient(version, token); + public static void create(String version, String token, boolean debug) { + mInstance = new DataClient(version, token, debug); } /** * Singleton accessor *

- * Will throw an exception if {@link #create(String version, String token)} was never called + * Will throw an exception if {@link #create(String version, String token, boolean debug)} was never called * * @return the DataClient singleton */ @@ -91,6 +92,14 @@ public Call getUpcomingLaunches(int limit, int offset, String se return call; } + public Call getUpcomingLaunchesMini(int limit, int offset, String search, String lspName, String serialNumber, Integer launchId, Callback callback) { + Call call = spaceLaunchNowService.getUpcomingLaunchesMini(limit, offset, "list", search, lspName, serialNumber, launchId); + + call.enqueue(callback); + + return call; + } + public Call getPreviousLaunches(int limit, int offset, String search, String lspName, Integer launchId, Callback callback) { Call call = spaceLaunchNowService.getPreviousLaunches(limit, offset, "detailed", search, lspName, launchId); @@ -99,6 +108,14 @@ public Call getPreviousLaunches(int limit, int offset, String se return call; } + public Call getPreviousLaunchesMini(int limit, int offset, String search, String lspName, String serialNumber, Integer launchId, Callback callback) { + Call call = spaceLaunchNowService.getPreviousLaunchesMini(limit, offset, "list", search, lspName, serialNumber, launchId); + + call.enqueue(callback); + + return call; + } + public Call getLaunchesByDate(int limit, int offset,String startDate, String endDate, Integer launchId, Callback callback) { Call call = spaceLaunchNowService.getLaunchesByDate(limit, offset, startDate, endDate, launchId); diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/RetrofitBuilder.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/RetrofitBuilder.java index da4d19fe3..b190bb71a 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/RetrofitBuilder.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/RetrofitBuilder.java @@ -18,11 +18,13 @@ import java.util.concurrent.Executors; import java.util.concurrent.ThreadFactory; import java.util.concurrent.TimeUnit; + import io.realm.RealmList; import io.realm.RealmObject; import me.calebjones.spacelaunchnow.data.models.Constants; import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; import okhttp3.Cache; +import okhttp3.CacheControl; import okhttp3.Interceptor; import okhttp3.OkHttpClient; import okhttp3.Request; @@ -30,6 +32,7 @@ import retrofit2.Retrofit; import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory; import retrofit2.converter.gson.GsonConverterFactory; +import timber.log.Timber; import static android.os.Process.THREAD_PRIORITY_BACKGROUND; import static android.os.Process.THREAD_PRIORITY_LESS_FAVORABLE; @@ -40,12 +43,13 @@ public class RetrofitBuilder { private static Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() { - @Override public okhttp3.Response intercept(Chain chain) throws IOException { + @Override + public okhttp3.Response intercept(Chain chain) throws IOException { okhttp3.Response originalResponse = chain.proceed(chain.request()); - int maxAge = 60 * 60 * 24 * 3; // Three day cache - return originalResponse.newBuilder() - .header("Cache-Control", "public, max-age=" + maxAge) - .build(); + int maxAge = 60 * 60 * 24 * 3; // Three day cache + return originalResponse.newBuilder() + .header("Cache-Control", "public, max-age=" + maxAge) + .build(); } }; @@ -64,12 +68,9 @@ public static Retrofit getLibraryRetrofitThreaded(String version) { Executor httpExecutor = Executors.newCachedThreadPool(new ThreadFactory() { @Override public Thread newThread(final Runnable r) { - return new Thread(new Runnable() { - @Override - public void run() { - android.os.Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); - r.run(); - } + return new Thread(() -> { + android.os.Process.setThreadPriority(THREAD_PRIORITY_BACKGROUND); + r.run(); }, "Retrofit-Idle-Background"); } }); @@ -84,18 +85,10 @@ public void run() { } public static Retrofit getLibraryRetrofitLowestThreaded(String version) { - Executor httpExecutor = Executors.newCachedThreadPool(new ThreadFactory() { - @Override - public Thread newThread(final Runnable r) { - return new Thread(new Runnable() { - @Override - public void run() { - android.os.Process.setThreadPriority(THREAD_PRIORITY_MORE_FAVORABLE); - r.run(); - } - }, "Retrofit-Idle-Background"); - } - }); + Executor httpExecutor = Executors.newCachedThreadPool(r -> new Thread(() -> { + android.os.Process.setThreadPriority(THREAD_PRIORITY_MORE_FAVORABLE); + r.run(); + }, "Retrofit-Idle-Background")); Retrofit retrofit = new Retrofit.Builder() .baseUrl(Constants.LIBRARY_BASE_URL + version + "/") @@ -107,10 +100,18 @@ public void run() { } - public static Retrofit getSpaceLaunchNowRetrofit(String token) { + public static Retrofit getSpaceLaunchNowRetrofit(String token, boolean debug) { + + String BASE_URL; + + if (debug) { + BASE_URL = Constants.API_DEBUG_BASE_URL; + } else { + BASE_URL = Constants.API_BASE_URL; + } Retrofit retrofit = new Retrofit.Builder() - .baseUrl(Constants.API_BASE_URL) + .baseUrl(BASE_URL) .client(spaceLaunchNowClient(token)) .addConverterFactory(GsonConverterFactory.create(getGson())) .build(); @@ -130,16 +131,14 @@ private static OkHttpClient spaceLaunchNowClient(final String token) { client.connectTimeout(15, TimeUnit.SECONDS); client.readTimeout(15, TimeUnit.SECONDS); client.writeTimeout(15, TimeUnit.SECONDS); - client.addInterceptor(new Interceptor() { - @Override public Response intercept(Chain chain) throws IOException { - Request request = chain.request().newBuilder().addHeader("Authorization", "Token " + token).build(); - return chain.proceed(request); - } + client.addInterceptor(chain -> { + Request request = chain.request().newBuilder().addHeader("Authorization", "Token " + token).build(); + return chain.proceed(request); }); return client.build(); } - public static Gson getGson(){ + public static Gson getGson() { return new GsonBuilder() .setDateFormat("MMMM dd, yyyy HH:mm:ss zzz") .setExclusionStrategies(new ExclusionStrategy() { @@ -174,7 +173,7 @@ public RealmList read(JsonReader in) throws io.realm.internal.IOExcept .create(); } - private static Type getToken(){ + private static Type getToken() { return new TypeToken>() { }.getType(); } diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/interfaces/SpaceLaunchNowService.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/interfaces/SpaceLaunchNowService.java index 89fd9ee5a..8e1a054f3 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/interfaces/SpaceLaunchNowService.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/interfaces/SpaceLaunchNowService.java @@ -3,6 +3,7 @@ import me.calebjones.spacelaunchnow.data.BuildConfig; import me.calebjones.spacelaunchnow.data.models.main.Launch; import me.calebjones.spacelaunchnow.data.networking.responses.base.AgencyResponse; +import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchListResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.OrbiterResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.VehicleResponse; @@ -14,7 +15,7 @@ public interface SpaceLaunchNowService { - String version = "3.0.0"; + String version = "3.2.0"; @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) @GET(version + "/orbiters/") @@ -24,6 +25,10 @@ public interface SpaceLaunchNowService { @GET(version + "/agencies/") Call getAgencies(@Query("featured") boolean featured, @Query("mode") String mode); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) + @GET(version + "/agencies/") + Call getAgenciesWithOrbiters(@Query("orbiters") boolean orbiters); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) @GET(version + "/launchers_string/") Call getVehiclesByAgency(@Query("launch_agency__name") String agency); @@ -49,6 +54,13 @@ Call getUpcomingLaunches(@Query("limit") int amount, @Query("off @Query("lsp__name") String lspName, @Query("launcher_config__id") Integer launcherId); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) + @GET(version + "/launch/upcoming/") + Call getUpcomingLaunchesMini(@Query("limit") int amount, @Query("offset") int offset, + @Query("mode") String mode, @Query("search") String search, + @Query("lsp__name") String lspName, @Query("serial_number") String serialNumber, + @Query("launcher_config__id") Integer launcherId); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) @GET(version + "/launch/upcoming/") Call getUpcomingLaunches(@Query("limit") int amount, @Query("offset") int offset, @@ -96,6 +108,13 @@ Call getPreviousLaunches(@Query("limit") int amount, @Query("off @Query("mode") String mode, @Query("search") String search, @Query("lsp__name") String lspName, @Query("launcher_config__id") Integer lspId); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) + @GET(version + "/launch/previous/") + Call getPreviousLaunchesMini(@Query("limit") int amount, @Query("offset") int offset, + @Query("mode") String mode, @Query("search") String search, + @Query("lsp__name") String lspName, @Query("serial_number") String serialNumber, + @Query("launcher_config__id") Integer lspId); + @Headers({"User-Agent: SpaceLaunchNow-" + BuildConfig.VERSION_NAME}) @GET(version + "/launch/previous/") Call getPreviousLaunchesByLauncherID(@Query("limit") int amount, @Query("offset") int offset, diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/LaunchListResponse.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/LaunchListResponse.java new file mode 100644 index 000000000..6c553e88b --- /dev/null +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/LaunchListResponse.java @@ -0,0 +1,17 @@ +package me.calebjones.spacelaunchnow.data.networking.responses.base; + +import com.google.gson.annotations.SerializedName; + +import java.util.List; + +import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; + +public class LaunchListResponse extends BaseResponse { + @SerializedName("results") + private List launches; + + public List getLaunches() { + return launches; + } +} diff --git a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/VehicleResponse.java b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/VehicleResponse.java index 5cb8b711a..5ad89c0f8 100644 --- a/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/VehicleResponse.java +++ b/data/src/main/java/me/calebjones/spacelaunchnow/data/networking/responses/base/VehicleResponse.java @@ -2,14 +2,14 @@ import com.google.gson.annotations.SerializedName; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; public class VehicleResponse extends BaseResponse { @SerializedName(value="results") - private Launcher[] vehicles; + private LauncherConfig[] vehicles; - public Launcher[] getVehicles() { + public LauncherConfig[] getVehicles() { return vehicles; } } diff --git a/mobile/build.gradle b/mobile/build.gradle index ef56ebcf8..38a83f070 100644 --- a/mobile/build.gradle +++ b/mobile/build.gradle @@ -201,7 +201,7 @@ dependencies { implementation files('libs/YouTubeAndroidPlayerApi.jar') // Android Official Libraries - implementation 'com.android.support.constraint:constraint-layout:1.1.1' + implementation 'com.android.support.constraint:constraint-layout:1.1.3' implementation "com.android.support:customtabs:$rootProject.supportLibraryVersion" implementation "com.android.support:cardview-v7:$rootProject.supportLibraryVersion" implementation "com.android.support:palette-v7:$rootProject.supportLibraryVersion" @@ -259,6 +259,8 @@ dependencies { implementation 'com.borax12.materialdaterangepicker:library:1.9' implementation 'com.simplecityapps:recyclerview-fastscroll:1.0.18' implementation 'jp.wasabeef:glide-transformations:3.0.1' + implementation 'net.cachapa.expandablelayout:expandablelayout:2.9.2' + implementation 'at.blogc:expandabletextview:1.0.5' // If you want to use the GPU Filters implementation 'jp.co.cyberagent.android.gpuimage:gpuimage-library:1.4.1' diff --git a/mobile/src/main/assets/CHANGELOG.md b/mobile/src/main/assets/CHANGELOG.md index a180712ac..b460fad13 100644 --- a/mobile/src/main/assets/CHANGELOG.md +++ b/mobile/src/main/assets/CHANGELOG.md @@ -1,17 +1,28 @@ # Space Launch Now -A space launch tracker for Android using data from the Launch Library API. +A space launch tracker for Android using data from the Launch Library API. [View the latest releases here.](https://github.com/ItsCalebJones/SpaceLaunchNow-Android/releases) ## Changelog #### Updated 6-11-2018 --- -### Version 2.6.0 (Latest) +### Version 2.6.2 (Latest) +#### Overview +Finally, SpaceX landing information! It's a long time coming but its finally here. + +#### Changelog +* Add labels for SpaceX landing information. +* Add labels to indicate status of the launch. +* Add labels to indicate intended orbit. +* Fix a whole lotta bugs. +* Remove the Google Map view from the home page due to performance issues rendering multiple maps. + +### Version 2.6.0 #### Overview Change over to using my own server to support future Blue Origin launches and additional data about SpaceX launches and LANDINGS. Coming soon! #### Changelog * Iconography changes to improve user experience. -* Added a 'View More' buttons for launchers and agencies. +* Added a 'View More' buttons for launcherConfigs and agencies. * Moved away from using Launch Library API to our own server. Special shoutout to the translators that have helped fully translate Space Launch Now into over five languages! @@ -121,7 +132,7 @@ Quick bug fix release - addressing a few issues. #### Changelog * Added an option to hide launches that have an unconfirmed date. * Fixed an issue with some users not receiving notifications. -* Fixed issue where the incorrect launcher data was being shown. +* Fixed issue where the incorrect launcherConfig data was being shown. * Fixed a few crashes. --- diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/LaunchApplication.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/LaunchApplication.java index 097923801..e29125c38 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/LaunchApplication.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/LaunchApplication.java @@ -99,12 +99,7 @@ private void setupTwitter() { .debug(true) .build(); Twitter.initialize(config); - new Thread() { - @Override - public void run() { - TweetUi.getInstance(); - } - }.start(); + new Thread(TweetUi::getInstance).start(); } private void setupNotificationChannels() { @@ -169,12 +164,15 @@ private void setupWebView() { private void setupData(final boolean update) { final String version; + boolean debug; if (sharedPreference.isDebugEnabled()) { version = "dev"; + debug = true; } else { version = "1.3"; + debug = false; } - DataClient.create(version, getString(R.string.sln_token)); + DataClient.create(version, getString(R.string.sln_token), debug); JobManager.create(context).addJobCreator(new DataJobCreator()); startJobs(); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/calendar/CalendarUtility.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/calendar/CalendarUtility.java index 54b8246b8..887ae5a2e 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/calendar/CalendarUtility.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/calendar/CalendarUtility.java @@ -85,7 +85,7 @@ public Integer addEvent(Context context, Launch launch) { event.calendarId = calendarItem.getId(); event.title = launch.getName(); event.description = description; - event.location = launch.getLocation().getName(); + event.location = launch.getPad().getLocation().getName(); if (startDate != null && endDate != null) { event.startDate = startDate.getTime(); event.endDate = endDate.getTime(); @@ -140,7 +140,7 @@ public boolean updateEvent(Context context, Launch launch) { Date endDate = launch.getWindowEnd(); calEvent.put(CalendarContract.Events.DESCRIPTION, description); - calEvent.put(CalendarContract.Events.EVENT_LOCATION, launch.getLocation().getName()); + calEvent.put(CalendarContract.Events.EVENT_LOCATION, launch.getPad().getLocation().getName()); if (startDate != null && endDate != null) { calEvent.put(CalendarContract.Events.DTSTART, startDate.getTime()); calEvent.put(CalendarContract.Events.DTEND, endDate.getTime()); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/common/RetroFitFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/common/RetroFitFragment.java index ab2acf1eb..61f6b4d82 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/common/RetroFitFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/common/RetroFitFragment.java @@ -5,11 +5,22 @@ import android.os.Build; import android.os.Bundle; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + import java.io.File; import java.io.IOException; +import java.lang.reflect.Type; +import java.util.Date; +import io.realm.RealmList; import me.calebjones.spacelaunchnow.content.database.ListPreferences; import me.calebjones.spacelaunchnow.data.models.Constants; +import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; import me.calebjones.spacelaunchnow.data.networking.RetrofitBuilder; import me.calebjones.spacelaunchnow.utils.Utils; import okhttp3.Cache; @@ -23,10 +34,46 @@ abstract public class RetroFitFragment extends BaseFragment { private OkHttpClient client; + private OkHttpClient newsClient; private Retrofit libraryRetrofit; private Retrofit spaceLaunchNowRetrofit; + private Retrofit newsRetrofit; private Context context; + private Interceptor NEWS_REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() { + @Override public okhttp3.Response intercept(Chain chain) throws IOException { + okhttp3.Response originalResponse = chain.proceed(chain.request()); + if (Utils.isNetworkAvailable(context)) { + int maxAge = 60 * 5; // Five minute Cache + return originalResponse.newBuilder() + .header("Cache-Control", "public, max-age=" + maxAge) + .build(); + } else { + int maxStale = 60 * 60 * 24; // one day + return originalResponse.newBuilder() + .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) + .build(); + } + } + }; + + private Interceptor REWRITE_CACHE_CONTROL_INTERCEPTOR = new Interceptor() { + @Override public okhttp3.Response intercept(Chain chain) throws IOException { + okhttp3.Response originalResponse = chain.proceed(chain.request()); + if (Utils.isNetworkAvailable(context)) { + int maxAge = 60 * 60; // Hour Cache + return originalResponse.newBuilder() + .header("Cache-Control", "public, max-age=" + maxAge) + .build(); + } else { + int maxStale = 60 * 60 * 24; // one day + return originalResponse.newBuilder() + .header("Cache-Control", "public, only-if-cached, max-stale=" + maxStale) + .build(); + } + } + }; + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); context = getActivity().getApplicationContext(); @@ -37,25 +84,44 @@ public void onCreate(Bundle savedInstanceState) { Cache cache = new Cache(httpCacheDirectory, cacheSize); client = new OkHttpClient() .newBuilder() + .addNetworkInterceptor(REWRITE_CACHE_CONTROL_INTERCEPTOR) + .cache(cache) + .build(); + + newsClient = new OkHttpClient() + .newBuilder() + .addNetworkInterceptor(NEWS_REWRITE_CACHE_CONTROL_INTERCEPTOR) .cache(cache) .build(); ListPreferences sharedPreference = ListPreferences.getInstance(context); String version; + String BASE_URL; + String NEWS_URL; if (sharedPreference.isDebugEnabled()) { + NEWS_URL = Constants.NEWS_BASE_URL; + BASE_URL = Constants.API_DEBUG_BASE_URL; version = "dev"; } else { version = "1.2.1"; + NEWS_URL = Constants.NEWS_BASE_URL; + BASE_URL = Constants.API_BASE_URL; } libraryRetrofit = RetrofitBuilder.getLibraryRetrofit(version); spaceLaunchNowRetrofit = new Retrofit.Builder() - .baseUrl(Constants.API_BASE_URL) + .baseUrl(BASE_URL) .client(client) .addConverterFactory(GsonConverterFactory.create(getGson())) .build(); + + newsRetrofit = new Retrofit.Builder() + .baseUrl(NEWS_URL) + .client(newsClient) + .addConverterFactory(GsonConverterFactory.create(getNewsGson())) + .build(); } public void startActivity(Intent intent, Bundle bundle) { @@ -77,4 +143,35 @@ public Retrofit getLibraryRetrofit() { public Retrofit getSpaceLaunchNowRetrofit() { return spaceLaunchNowRetrofit; } + + public Retrofit getNewsRetrofit() { return newsRetrofit;} + + public Gson getNewsGson() { + return new GsonBuilder() + .registerTypeAdapter(Date.class, new me.calebjones.spacelaunchnow.data.helpers.Utils.EpochDateConverter()) + .registerTypeAdapter(getToken(), new TypeAdapter>() { + + @Override + public void write(JsonWriter out, RealmList value) throws io.realm.internal.IOException { + // Ignore + } + + @Override + public RealmList read(JsonReader in) throws io.realm.internal.IOException, java.io.IOException { + RealmList list = new RealmList(); + in.beginArray(); + while (in.hasNext()) { + list.add(new RealmStr(in.nextString())); + } + in.endArray(); + return list; + } + }) + .create(); + } + + private static Type getToken(){ + return new TypeToken>() { + }.getType(); + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/DataSaver.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/DataSaver.java index 091125c33..dc37f479c 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/DataSaver.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/DataSaver.java @@ -101,9 +101,9 @@ public void saveLaunchesToRealm(final List launches, final boolean mini) } private static boolean isLaunchTimeChanged(Launch previous, Launch item) { - if ((Math.abs(previous.getNet().getTime() - item.getNet().getTime()) >= 3600)) { + if ((Math.abs(previous.getNet().getTime() - item.getNet().getTime()) >= 360)) { return true; - } else if (previous.getStatus() != null && item.getStatus() != null && previous.getStatus().intValue() != item.getStatus().intValue()) { + } else if (previous.getStatus() != null && item.getStatus() != null && previous.getStatus().getId().intValue() != item.getStatus().getId().intValue()) { return true; } return false; diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/LaunchStatus.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/LaunchStatus.java index e8e6a1de5..f3eff5ba9 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/LaunchStatus.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/LaunchStatus.java @@ -3,6 +3,7 @@ import android.content.Context; import me.calebjones.spacelaunchnow.R; +import me.calebjones.spacelaunchnow.data.models.main.Landing; public class LaunchStatus { @@ -34,4 +35,46 @@ public static String getLaunchStatusTitle(Context context, int statusId) { return "Unknown Launch Status"; } } + + public static int getLaunchStatusColor(Context context, Integer id) { + switch (id) { + case 1: + //GO for launch + return context.getResources().getColor(R.color.material_color_green_600); + case 2: + //TBD for launch + return context.getResources().getColor(R.color.material_color_red_500); + case 3: + //Success for launch + return context.getResources().getColor(R.color.material_color_green_800); + case 4: + //Failure to launch + return context.getResources().getColor((R.color.material_color_red_700)); + case 5: + //HOLD + return context.getResources().getColor((R.color.material_color_orange_500)); + case 6: + //In Flight + return context.getResources().getColor(R.color.material_color_blue_500); + case 7: + //Partial Failure + return context.getResources().getColor(R.color.material_color_blue_grey_500); + default: + return context.getResources().getColor(R.color.material_color_purple_800); + } + } + + public static int getLandingStatusColor(Context context, Integer landing) { + if (landing == null) { + return context.getResources().getColor(R.color.material_color_blue_500); + } else if (landing == 1) { + return context.getResources().getColor(R.color.material_color_green_800); + } else if (landing == 2) { + return context.getResources().getColor(R.color.material_color_red_700); + } else if (landing == 3) { + return context.getResources().getColor(R.color.material_color_blue_grey_500); + } else { + return context.getResources().getColor(R.color.material_color_blue_500); + } + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/ArticleRepository.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/ArticleRepository.java index a08351ba5..670bf38ee 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/ArticleRepository.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/ArticleRepository.java @@ -2,20 +2,16 @@ import android.content.Context; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; +import java.util.List; import io.realm.Realm; -import io.realm.RealmList; -import io.realm.Sort; import me.calebjones.spacelaunchnow.data.models.news.Article; -import me.calebjones.spacelaunchnow.data.models.news.NewsFeedResponse; import me.calebjones.spacelaunchnow.content.data.articles.network.NewsAPIClient; +import me.calebjones.spacelaunchnow.utils.Utils; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; +import retrofit2.Retrofit; import timber.log.Timber; public class ArticleRepository { @@ -24,71 +20,48 @@ public class ArticleRepository { private Realm realm; private NewsAPIClient newsAPIClient; - public ArticleRepository(Context context) { + public ArticleRepository(Context context, Retrofit newsRetrofit) { this.context = context; this.realm = Realm.getDefaultInstance(); - newsAPIClient = new NewsAPIClient(); + newsAPIClient = new NewsAPIClient(newsRetrofit); } public void getArticles(boolean forceRefresh, final GetArticlesCallback callback) { - Date currentDate = new Date(); - currentDate.setTime(currentDate.getTime() - 1000 * 60 * 60); - RealmList

articles = new RealmList(); - articles.addAll(realm.where(Article.class).sort("date", Sort.DESCENDING).findAll()); - - if (articles.size() == 0 || forceRefresh) { - newsAPIClient.getNews(new Callback() { - @Override - public void onResponse(Call call, Response response) { - Timber.v("Hello"); - if (response.isSuccessful()) { - final NewsFeedResponse newsResponse = response.body(); - if (newsResponse != null) { - realm.executeTransaction(realm -> { - RealmList
finalArticles = new RealmList(); - SimpleDateFormat inDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); - SimpleDateFormat altDateFormat = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm Z", Locale.US); - for (Article article: newsResponse.getChannel().getArticles()){ - try { - Date pubDate = inDateFormat.parse(article.getPubDate()); - article.setDate(pubDate); - finalArticles.add(article); - } catch (ParseException e) { - try { - Date pubDate = altDateFormat.parse(article.getPubDate()); - article.setDate(pubDate); - finalArticles.add(article); - } catch (ParseException f){ - Timber.e(f, "Unable to parse %s", article.getTitle()); - } - } - } - realm.copyToRealmOrUpdate(finalArticles); - callback.onSuccess(finalArticles); - }); - - } - } else { - callback.onNetworkFailure(); + newsAPIClient.getNews(30, new Callback>() { + @Override + public void onResponse(Call> call, Response> response) { + if (response.raw().cacheResponse() != null) { + Timber.v("Response pulled from cache."); + if (!Utils.isNetworkAvailable(context)) { + callback.onFailure("Offline: Showing cached results.", true); } } - @Override - public void onFailure(Call call, Throwable t) { - callback.onFailure(t); + if (response.raw().networkResponse() != null) { + Timber.v("Response pulled from network."); } - }); - } else { - callback.onSuccess(articles); - } - } + if (response.isSuccessful()) { + callback.onSuccess(response.body()); + + } else { + callback.onNetworkFailure(); + } + } + + @Override + public void onFailure(Call> call, Throwable t) { + callback.onFailure(t.getLocalizedMessage(), false); + } + }); + } + public interface GetArticlesCallback { - void onSuccess(RealmList
articles); + void onSuccess(List
articles); - void onFailure(Throwable throwable); + void onFailure(String error, boolean showContent); void onNetworkFailure(); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsAPIClient.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsAPIClient.java index 02e37cb4a..9ad633778 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsAPIClient.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsAPIClient.java @@ -1,39 +1,50 @@ package me.calebjones.spacelaunchnow.content.data.articles.network; +import com.google.gson.Gson; +import com.google.gson.GsonBuilder; +import com.google.gson.TypeAdapter; +import com.google.gson.reflect.TypeToken; +import com.google.gson.stream.JsonReader; +import com.google.gson.stream.JsonWriter; + +import java.lang.reflect.Type; +import java.util.Date; +import java.util.List; import java.util.concurrent.TimeUnit; -import me.calebjones.spacelaunchnow.data.models.news.NewsFeedResponse; +import io.realm.RealmList; +import me.calebjones.spacelaunchnow.data.helpers.Utils; +import me.calebjones.spacelaunchnow.data.models.news.Article; +import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; import okhttp3.OkHttpClient; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Retrofit; -import retrofit2.converter.simplexml.SimpleXmlConverterFactory; +import retrofit2.converter.gson.GsonConverterFactory; public class NewsAPIClient { private final NewsService newsService; private Retrofit newsRetrofit; - public NewsAPIClient(){ - OkHttpClient.Builder client = new OkHttpClient().newBuilder(); - client.connectTimeout(15, TimeUnit.SECONDS); - client.readTimeout(15, TimeUnit.SECONDS); - client.writeTimeout(15, TimeUnit.SECONDS); - - newsRetrofit = new Retrofit.Builder() - .baseUrl("https://feed.rssunify.com") - .client(client.build()) - .addConverterFactory(SimpleXmlConverterFactory.create()) - .build(); + public NewsAPIClient(Retrofit newsRetrofit){ + this.newsRetrofit = newsRetrofit; + newsService = this.newsRetrofit.create(NewsService.class); + } - newsService = newsRetrofit.create(NewsService.class); + public Call> getNews(int limit, Callback> callback) { + Call> call; + call = newsService.getNews(limit); + call.enqueue(callback); + return call; } - public Call getNews(Callback callback) { - Call call; - call = newsService.getNews(); + public Call
getArticle(Callback
callback) { + Call
call; + call = newsService.getArticle("5b98f79158ed93e183e0f834"); call.enqueue(callback); return call; } + } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsService.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsService.java index 816309e66..e8036eec5 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsService.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/articles/network/NewsService.java @@ -1,10 +1,19 @@ package me.calebjones.spacelaunchnow.content.data.articles.network; -import me.calebjones.spacelaunchnow.data.models.news.NewsFeedResponse; +import java.util.List; + +import me.calebjones.spacelaunchnow.data.models.news.Article; import retrofit2.Call; import retrofit2.http.GET; +import retrofit2.http.Path; +import retrofit2.http.Query; public interface NewsService { - @GET("5ac455da55299/rss.xml") - Call getNews(); + + @GET("/articles/") + Call> getNews(@Query("limit") int amount); + + @GET("/article/{id}") + Call
getArticle(@Path("id") String id); + } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/callbacks/Callbacks.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/callbacks/Callbacks.java index 1444b300c..ef77d3201 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/callbacks/Callbacks.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/callbacks/Callbacks.java @@ -6,6 +6,7 @@ import io.realm.RealmResults; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; public class Callbacks { @@ -27,9 +28,21 @@ public interface ListNetworkCallback { void onFailure(Throwable throwable); } + public interface ListNetworkCallbackMini { + void onSuccess(List launches, int next, int total); + void onNetworkFailure(int code); + void onFailure(Throwable throwable); + } + public interface ListCallback { void onLaunchesLoaded(List launches, int nextOffset); void onNetworkStateChanged(boolean refreshing); void onError(String message, @Nullable Throwable throwable); } + + public interface ListCallbackMini { + void onLaunchesLoaded(List launches, int nextOffset, int total); + void onNetworkStateChanged(boolean refreshing); + void onError(String message, @Nullable Throwable throwable); + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/next/NextLaunchDataLoader.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/next/NextLaunchDataLoader.java index 831aa68b5..85c41fad1 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/next/NextLaunchDataLoader.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/next/NextLaunchDataLoader.java @@ -31,7 +31,7 @@ public DataSaver getDataSaver() { } public void getNextUpcomingLaunches(int limit, Callbacks.NextNetworkCallback nextNetworkCallback) { - Timber.i("Running getUpcomingLaunches"); + Timber.i("Running getUpcomingLaunchesList"); DataClient.getInstance().getNextUpcomingLaunches(limit, 0, new Callback() { @Override public void onResponse(Call call, Response response) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataLoader.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataLoader.java index 532123c2e..37a571533 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataLoader.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataLoader.java @@ -10,6 +10,7 @@ import me.calebjones.spacelaunchnow.data.models.Result; import me.calebjones.spacelaunchnow.data.networking.DataClient; import me.calebjones.spacelaunchnow.data.networking.error.ErrorUtil; +import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchListResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchResponse; import retrofit2.Call; import retrofit2.Callback; @@ -30,13 +31,13 @@ public DataSaver getDataSaver() { return dataSaver; } - public void getPreviousLaunches(int limit, int offset, String search, String lspName, Integer launcherId, Callbacks.ListNetworkCallback networkCallback) { + public void getPreviousLaunches(int limit, int offset, String search, String lspName, String serialNumber, Integer launcherId, Callbacks.ListNetworkCallbackMini networkCallback) { Timber.i("Running getPreviousLaunches"); - DataClient.getInstance().getPreviousLaunches(limit, offset, search, lspName, launcherId, new Callback() { + DataClient.getInstance().getPreviousLaunchesMini(limit, offset, search, lspName, serialNumber, launcherId, new Callback() { @Override - public void onResponse(Call call, Response response) { + public void onResponse(Call call, Response response) { if (response.isSuccessful()) { - LaunchResponse launchResponse = response.body(); + LaunchListResponse launchResponse = response.body(); Timber.v("Previous Launch Count: %s", launchResponse.getCount()); @@ -45,9 +46,9 @@ public void onResponse(Call call, Response respo String limit = uri.getQueryParameter("limit"); String nextOffset = uri.getQueryParameter("offset"); int next = Integer.valueOf(nextOffset); - networkCallback.onSuccess(launchResponse.getLaunches(), next); + networkCallback.onSuccess(launchResponse.getLaunches(), next, launchResponse.getCount()); } else { - networkCallback.onSuccess(launchResponse.getLaunches(), 0); + networkCallback.onSuccess(launchResponse.getLaunches(), 0, launchResponse.getCount()); } } else { networkCallback.onNetworkFailure(response.code()); @@ -57,7 +58,7 @@ public void onResponse(Call call, Response respo } @Override - public void onFailure(Call call, Throwable t) { + public void onFailure(Call call, Throwable t) { networkCallback.onFailure(t); dataSaver.sendResult(new Result(Constants.ACTION_GET_NEXT_LAUNCHES, false, call, t.getLocalizedMessage())); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataRepository.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataRepository.java index bc1432512..46f624a6b 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataRepository.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/previous/PreviousDataRepository.java @@ -17,6 +17,7 @@ import me.calebjones.spacelaunchnow.data.models.Result; import me.calebjones.spacelaunchnow.data.models.UpdateRecord; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.data.networking.DataClient; import me.calebjones.spacelaunchnow.data.networking.error.ErrorUtil; import retrofit2.Call; @@ -42,19 +43,19 @@ public PreviousDataRepository(Context context, Realm realm) { } @UiThread - public void getPreviousLaunches(int count, String search, String lspName, Integer launchId, Callbacks.ListCallback launchCallback) { - getPreviousLaunchesFromNetwork(count, search, lspName, launchId, launchCallback); + public void getPreviousLaunches(int count, String search, String lspName, String serialNumber, Integer launchId, Callbacks.ListCallbackMini launchCallback) { + getPreviousLaunchesFromNetwork(count, search, lspName, serialNumber, launchId, launchCallback); } - private void getPreviousLaunchesFromNetwork(int count, String search, String lspName, Integer launcherId, Callbacks.ListCallback callback) { + private void getPreviousLaunchesFromNetwork(int count, String search, String lspName, String serialNumber, Integer launcherId, Callbacks.ListCallbackMini callback) { callback.onNetworkStateChanged(true); - dataLoader.getPreviousLaunches(30, count, search, lspName, launcherId, new Callbacks.ListNetworkCallback() { + dataLoader.getPreviousLaunches(30, count, search, lspName, serialNumber, launcherId, new Callbacks.ListNetworkCallbackMini() { @Override - public void onSuccess(List launches, int next) { + public void onSuccess(List launches, int next, int total) { callback.onNetworkStateChanged(false); - callback.onLaunchesLoaded(launches, next); + callback.onLaunchesLoaded(launches, next, total); } @Override diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataLoader.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataLoader.java index 71c23077a..3b6bf650a 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataLoader.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataLoader.java @@ -10,6 +10,7 @@ import me.calebjones.spacelaunchnow.data.models.Result; import me.calebjones.spacelaunchnow.data.networking.DataClient; import me.calebjones.spacelaunchnow.data.networking.error.ErrorUtil; +import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchListResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchResponse; import retrofit2.Call; import retrofit2.Callback; @@ -30,13 +31,13 @@ public DataSaver getDataSaver() { return dataSaver; } - public void getUpcomingLaunches(int limit, int offset, String search, String lspName, Integer launchId, Callbacks.ListNetworkCallback networkCallback) { - Timber.i("Running getUpcomingLaunches"); - DataClient.getInstance().getUpcomingLaunches(limit, offset, search, lspName, launchId, new Callback() { + public void getUpcomingLaunchesList(int limit, int offset, String search, String lspName, String serialNumber, Integer launchId, Callbacks.ListNetworkCallbackMini networkCallback) { + Timber.i("Running getUpcomingLaunchesList"); + DataClient.getInstance().getUpcomingLaunchesMini(limit, offset, search, lspName, serialNumber, launchId, new Callback() { @Override - public void onResponse(Call call, Response response) { + public void onResponse(Call call, Response response) { if (response.isSuccessful()) { - LaunchResponse launchResponse = response.body(); + LaunchListResponse launchResponse = response.body(); Timber.v("UpcomingLaunches Count: %s", launchResponse.getCount()); @@ -44,10 +45,11 @@ public void onResponse(Call call, Response respo Uri uri = Uri.parse(launchResponse.getNext()); String limit = uri.getQueryParameter("limit"); String nextOffset = uri.getQueryParameter("offset"); + String total = uri.getQueryParameter("offset"); int next = Integer.valueOf(nextOffset); - networkCallback.onSuccess(launchResponse.getLaunches(), next); + networkCallback.onSuccess(launchResponse.getLaunches(), next, launchResponse.getCount()); } else { - networkCallback.onSuccess(launchResponse.getLaunches(), 0); + networkCallback.onSuccess(launchResponse.getLaunches(), 0, launchResponse.getCount()); } } else { networkCallback.onNetworkFailure(response.code()); @@ -57,7 +59,7 @@ public void onResponse(Call call, Response respo } @Override - public void onFailure(Call call, Throwable t) { + public void onFailure(Call call, Throwable t) { networkCallback.onFailure(t); dataSaver.sendResult(new Result(Constants.ACTION_GET_NEXT_LAUNCHES, false, call, t.getLocalizedMessage())); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataRepository.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataRepository.java index 250409e74..4429e269d 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataRepository.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/data/upcoming/UpcomingDataRepository.java @@ -8,6 +8,7 @@ import io.realm.Realm; import me.calebjones.spacelaunchnow.content.data.callbacks.Callbacks; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; /** * Responsible for retrieving data from the Realm cache. @@ -28,18 +29,18 @@ public UpcomingDataRepository(Context context, Realm realm) { @UiThread - public void getUpcomingLaunches(int count, String search, String lspName, Integer launcherId, Callbacks.ListCallback launchCallback) { - getUpcomingLaunchesFromNetwork(count, search, lspName, launcherId, launchCallback); + public void getUpcomingLaunches(int count, String search, String lspName, String serialNumber, Integer launcherId, Callbacks.ListCallbackMini launchCallback) { + getUpcomingLaunchesFromNetwork(count, search, lspName, serialNumber, launcherId, launchCallback); } - private void getUpcomingLaunchesFromNetwork(int count, String search, String lspName, Integer launcherId, Callbacks.ListCallback callback) { + private void getUpcomingLaunchesFromNetwork(int count, String search, String lspName, String serialNumber, Integer launcherId, Callbacks.ListCallbackMini callback) { callback.onNetworkStateChanged(true); - dataLoader.getUpcomingLaunches(30, count, search, lspName, launcherId, new Callbacks.ListNetworkCallback() { + dataLoader.getUpcomingLaunchesList(30, count, search, lspName, serialNumber, launcherId, new Callbacks.ListNetworkCallbackMini() { @Override - public void onSuccess(List launches, int next) { + public void onSuccess(List launches, int next, int total) { callback.onNetworkStateChanged(false); - callback.onLaunchesLoaded(launches, next); + callback.onLaunchesLoaded(launches, next, total); } @Override diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/database/SwitchPreferences.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/database/SwitchPreferences.java index 1f3409dc3..dc6a98e65 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/database/SwitchPreferences.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/database/SwitchPreferences.java @@ -869,7 +869,7 @@ public void setWidgetID(int key) { this.prefsEditor.apply(); } - public boolean getNoGoSwitch() { + public boolean getTBDSwitch() { this.sharedPrefs = this.appContext.getSharedPreferences(PREFS_NAME, 0); return this.sharedPrefs.getBoolean(PREFS_NO_GO_SWITCH, true); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/notifications/NotificationBuilder.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/notifications/NotificationBuilder.java index 1c1a6a6f2..9848ebd75 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/notifications/NotificationBuilder.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/notifications/NotificationBuilder.java @@ -58,7 +58,7 @@ public static void notifyUser(Context context, Launch launch, long timeToFinish, String launchDate; String expandedText; String launchName = launch.getName(); - String launchPad = launch.getLocation().getName(); + String launchPad = launch.getPad().getLocation().getName(); boolean isDoNotDisturb = sharedPref.getBoolean("do_not_disturb_status", false); if (isDoNotDisturb) { @@ -106,10 +106,10 @@ public static void notifyUser(Context context, Launch launch, long timeToFinish, NotificationCompat.WearableExtender wearableExtender = new NotificationCompat.WearableExtender() .setHintHideIcon(true); - if (launch.getLauncher().getImageUrl() != null && launch.getLauncher().getImageUrl().length() > 0 && !launch.getLauncher().getImageUrl().contains("placeholder")) { + if (launch.getRocket().getConfiguration().getImageUrl() != null && launch.getRocket().getConfiguration().getImageUrl().length() > 0 && !launch.getRocket().getConfiguration().getImageUrl().contains("placeholder")) { Bitmap bitmap = null; try { - bitmap = Utils.getBitMapFromUrl(context, launch.getLauncher().getImageUrl()); + bitmap = Utils.getBitMapFromUrl(context, launch.getRocket().getConfiguration().getImageUrl()); } catch (ExecutionException | InterruptedException e) { Timber.e(e); Crashlytics.logException(e); @@ -192,10 +192,10 @@ public static void notifyUser(Context context, Launch launch, long timeToFinish, } - if (launch.getLauncher().getImageUrl() != null && launch.getLauncher().getImageUrl().length() > 0 && !launch.getLauncher().getImageUrl().contains("placeholder")) { + if (launch.getRocket().getConfiguration().getImageUrl() != null && launch.getRocket().getConfiguration().getImageUrl().length() > 0 && !launch.getRocket().getConfiguration().getImageUrl().contains("placeholder")) { Bitmap bitmap = null; try { - bitmap = Utils.getBitMapFromUrl(context, launch.getLauncher().getImageUrl()); + bitmap = Utils.getBitMapFromUrl(context, launch.getRocket().getConfiguration().getImageUrl()); } catch (ExecutionException | InterruptedException e) { Timber.e(e); Crashlytics.logException(e); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/services/AppFireBaseMessagingService.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/services/AppFireBaseMessagingService.java index 99fd96cbb..f55a82542 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/services/AppFireBaseMessagingService.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/services/AppFireBaseMessagingService.java @@ -18,8 +18,10 @@ import me.calebjones.spacelaunchnow.BuildConfig; import me.calebjones.spacelaunchnow.content.notifications.NotificationBuilder; import me.calebjones.spacelaunchnow.data.models.main.Launch; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.data.models.main.Location; +import me.calebjones.spacelaunchnow.data.models.main.Pad; +import me.calebjones.spacelaunchnow.data.models.main.Rocket; import me.calebjones.spacelaunchnow.utils.Utils; import timber.log.Timber; @@ -46,13 +48,17 @@ public void onMessageReceived(RemoteMessage remoteMessage) { launch.setNet(dateFormat.parse(data.getString("launch_net"))); launch.setName(data.getString("launch_name")); - Launcher launcher = new Launcher(); - launcher.setImageUrl(data.getString("launch_image")); - launch.setLauncher(launcher); + LauncherConfig launcherConfig = new LauncherConfig(); + launcherConfig.setImageUrl(data.getString("launch_image")); + Rocket rocket = new Rocket(); + rocket.setConfiguration(launcherConfig); + launch.setRocket(rocket); Location location = new Location(); location.setName(data.getString("launch_location")); - launch.setLocation(location); + Pad pad = new Pad(); + pad.setLocation(location); + launch.setPad(pad); if (background.contains("true")) { if (isNotificationEnabled(data.getString("notification_type"), data.getString("webcast").contains("true"))) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/util/QueryBuilder.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/util/QueryBuilder.java index e51ef1aff..9c4212ee9 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/util/QueryBuilder.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/util/QueryBuilder.java @@ -23,360 +23,6 @@ public class QueryBuilder { public static boolean first = true; - public static RealmResults buildPrevQueryAsync(Context context, Realm realm) throws ParseException { - SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); - ListPreferences listPreferences = ListPreferences.getInstance(context); - - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - - String start = listPreferences.getStartDate(); - String end = listPreferences.getEndDate(); - - Date sDate; - Date eDate; - - sDate = df.parse(start); - eDate = df.parse(end); - - RealmQuery query = realm.where(Launch.class).between("net", sDate, eDate).findAll().where(); - - Integer[] countryFilter = switchPreferences.getPrevCountryFiltered(); - Integer[] agencyFilter = switchPreferences.getPrevAgencyFiltered(); - Integer[] locationFilter = switchPreferences.getPrevLocationFiltered(); - Integer[] vehicleFilter = switchPreferences.getPrevVehicleFiltered(); - - if (countryFilter != null && countryFilter.length > 0) { - query = filterCountry(query, switchPreferences.getPrevCountryFilteredArray()).findAll().where(); - } - - if (agencyFilter != null && agencyFilter.length > 0) { - query = filterAgency(query, switchPreferences.getPrevAgencyFilteredArray()).findAll().where(); - } - - if (locationFilter != null && locationFilter.length > 0) { - query = filterLocation(query, switchPreferences.getPrevLocationFilteredArray()).findAll().where(); - } - - if (vehicleFilter != null && vehicleFilter.length > 0) { - query = filterVehicle(query, switchPreferences.getPrevVehicleFilteredArray()); - } - - Timber.v("Returning Query"); - query.sort("net", Sort.DESCENDING); - return query.findAllAsync(); - } - - public static RealmResults buildPrevQuery(Context context, Realm realm) throws ParseException { - SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); - ListPreferences listPreferences = ListPreferences.getInstance(context); - - SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd"); - - String start = listPreferences.getStartDate(); - String end = listPreferences.getEndDate(); - - Date sDate; - Date eDate; - - sDate = df.parse(start); - eDate = df.parse(end); - - RealmQuery query = realm.where(Launch.class).between("net", sDate, eDate).findAll().where(); - - Integer[] countryFilter = switchPreferences.getPrevCountryFiltered(); - Integer[] agencyFilter = switchPreferences.getPrevAgencyFiltered(); - Integer[] locationFilter = switchPreferences.getPrevLocationFiltered(); - Integer[] vehicleFilter = switchPreferences.getPrevVehicleFiltered(); - - if (countryFilter != null && countryFilter.length > 0) { - query = filterCountry(query, switchPreferences.getPrevCountryFilteredArray()).findAll().where(); - } - - if (agencyFilter != null && agencyFilter.length > 0) { - query = filterAgency(query, switchPreferences.getPrevAgencyFilteredArray()).findAll().where(); - } - - if (locationFilter != null && locationFilter.length > 0) { - query = filterLocation(query, switchPreferences.getPrevLocationFilteredArray()).findAll().where(); - } - - if (vehicleFilter != null && vehicleFilter.length > 0) { - query = filterVehicle(query, switchPreferences.getPrevVehicleFilteredArray()); - } - - Timber.v("Returning Query"); - query.sort("net", Sort.DESCENDING); - return query.findAll(); - } - - public static RealmResults buildUpQueryAsync(Context context, Realm realm) { - SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); - - Date date = new Date(); - - RealmQuery query = realm.where(Launch.class).greaterThanOrEqualTo("net", date).findAll().where(); - - verifyUpSwitches(context, switchPreferences); - - Integer[] countryFilter = switchPreferences.getUpCountryFiltered(); - Integer[] agencyFilter = switchPreferences.getUpAgencyFiltered(); - Integer[] locationFilter = switchPreferences.getUpLocationFiltered(); - Integer[] vehicleFilter = switchPreferences.getUpVehicleFiltered(); - - if (countryFilter != null && countryFilter.length > 0) { - ArrayList array = switchPreferences.getUpCountryFilteredArray(); - if (array != null && array.size() > 0) { - query = filterCountry(query, array).findAll().where(); - } else { - Crashlytics.logException(new Throwable("Error - array is null.")); - } - } - - if (agencyFilter != null && agencyFilter.length > 0) { - query = filterAgency(query, switchPreferences.getUpAgencyFilteredArray()).findAll().where(); - } - - if (locationFilter != null && locationFilter.length > 0) { - query = filterLocation(query, switchPreferences.getUpLocationFilteredArray()).findAll().where(); - } - - if (vehicleFilter != null && vehicleFilter.length > 0) { - query = filterVehicle(query, switchPreferences.getUpVehicleFilteredArray()); - - } - - Timber.v("Returning Query"); - query.sort("net", Sort.ASCENDING); - return query.findAllAsync(); - } - - private static void verifyUpSwitches(Context context, SwitchPreferences switchPreferences) { - Integer[] countryFilter = switchPreferences.getUpCountryFiltered(); - Integer[] agencyFilter = switchPreferences.getUpAgencyFiltered(); - Integer[] locationFilter = switchPreferences.getUpLocationFiltered(); - Integer[] vehicleFilter = switchPreferences.getUpVehicleFiltered(); - ArrayList agencyArray = switchPreferences.getUpAgencyFilteredArray(); - ArrayList countryArray = switchPreferences.getUpCountryFilteredArray(); - ArrayList locationArray = switchPreferences.getUpLocationFilteredArray(); - ArrayList vehicleArray = switchPreferences.getUpVehicleFilteredArray(); - - if (countryArray != null && countryFilter != null && countryArray.size() != countryFilter.length) { - Crashlytics.log("Country Array: " + countryArray + " Country Filter " + countryFilter); - Toast.makeText(context, "UNKNOWN ERROR - Resetting Country filter.", Toast.LENGTH_SHORT).show(); - switchPreferences.resetAllUpFilters(); - if (switchPreferences.isUpFiltered()) { - switchPreferences.setUpFiltered(false); - } - } - - if (agencyArray != null && agencyFilter != null && agencyArray.size() != agencyFilter.length) { - Crashlytics.log("LauncherAgency Array: " + agencyArray + " LauncherAgency Filter " + agencyFilter); - Toast.makeText(context, "UNKNOWN ERROR - Resetting LauncherAgency filter.", Toast.LENGTH_SHORT).show(); - switchPreferences.resetAllUpFilters(); - if (switchPreferences.isUpFiltered()) { - switchPreferences.setUpFiltered(false); - } - } - - if (locationArray != null && locationFilter != null && locationArray.size() != locationFilter.length) { - Crashlytics.log("Location Array: " + locationArray + " Location Filter " + locationFilter); - Toast.makeText(context, "UNKNOWN ERROR - Resetting Location filter.", Toast.LENGTH_SHORT).show(); - switchPreferences.resetAllUpFilters(); - if (switchPreferences.isUpFiltered()) { - switchPreferences.setUpFiltered(false); - } - } - - if (vehicleArray != null && vehicleFilter != null && vehicleArray.size() != vehicleFilter.length) { - Crashlytics.log("Vehicle Array: " + vehicleArray + " Vehicle Filter " + vehicleFilter); - Toast.makeText(context, "UNKNOWN ERROR - Resetting Vehicle filter.", Toast.LENGTH_SHORT).show(); - switchPreferences.resetAllUpFilters(); - if (switchPreferences.isUpFiltered()) { - switchPreferences.setUpFiltered(false); - } - } - } - - public static RealmResults buildUpQuery(Context context, Realm realm) { - SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); - - Date date = new Date(); - - RealmQuery query = realm.where(Launch.class).greaterThanOrEqualTo("net", date).findAll().where(); - - Integer[] countryFilter = switchPreferences.getUpCountryFiltered(); - Integer[] agencyFilter = switchPreferences.getUpAgencyFiltered(); - Integer[] locationFilter = switchPreferences.getUpLocationFiltered(); - Integer[] vehicleFilter = switchPreferences.getUpVehicleFiltered(); - - if (countryFilter != null && countryFilter.length > 0) { - ArrayList array = switchPreferences.getUpCountryFilteredArray(); - if (array != null && array.size() > 0) { - query = filterCountry(query, array).findAll().where(); - } else { - Crashlytics.logException(new Throwable("Error - array is null.")); - } - } - - if (agencyFilter != null && agencyFilter.length > 0) { - query = filterAgency(query, switchPreferences.getUpAgencyFilteredArray()).findAll().where(); - } - - if (locationFilter != null && locationFilter.length > 0) { - query = filterLocation(query, switchPreferences.getUpLocationFilteredArray()).findAll().where(); - } - - if (vehicleFilter != null && vehicleFilter.length > 0) { - query = filterVehicle(query, switchPreferences.getUpVehicleFilteredArray()); - - } - - Timber.v("Returning Query"); - query.sort("net", Sort.ASCENDING); - return query.findAllAsync(); - - } - - private static RealmQuery filterVehicle(RealmQuery query, ArrayList vehicleFilter) { - boolean firstGroup = true; - for (String key : vehicleFilter) { - if (key.contains("SLV")) { - key = "SLV"; - } - Timber.v("Vehicle key: %s", key); - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.contains("rocket.name", key); - } - return query; - } - - private static RealmQuery filterLocation(RealmQuery query, ArrayList locationFilter) { - boolean firstGroup = true; - for (String key : locationFilter) { - String[] parts = key.split(","); - key = parts[0]; - if (key.length() > 5) { - key = key.substring(0, 5); - } - Timber.v("Location key: %s", key); - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.beginsWith("location.name", key); - } - return query; - } - - private static RealmQuery filterAgency(RealmQuery query, ArrayList agencyFilter) { - boolean firstGroup = true; - for (String key : agencyFilter) { - Timber.v("LauncherAgency key: %s", key); - if (key.contains("NASA")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 44); - } else if (key.contains("SpaceX")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 121).or().contains("name", "Falcon"); - - } else if (key.contains("ROSCOSMOS")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 111) - .or() - .equalTo("lsp.id", 163) - .or() - .equalTo("lsp.id", 63); - - } else if (key.contains("ULA")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 124); - - } else if (key.contains("Arianespace")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 115); - - } else if (key.contains("CASC")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 88); - - } else if (key.contains("ISRO")) { - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.equalTo("lsp.id", 31); - } - } - return query; - } - - private static RealmQuery filterCountry(RealmQuery query, ArrayList countryFilter) { - boolean firstGroup = true; - for (String key : countryFilter) { - Timber.v("Country key: %s", key); - if (key.contains("China")) { - key = "CHN"; - } else if (key.contains("Russia")) { - key = "RUS"; - } else if (key.contains("India")) { - key = "IND"; - } else if (key.contains("Multi")) { - key = ","; - } - if (!firstGroup) { - query.or(); - } else { - firstGroup = false; - } - query.contains("location.countryCode", key); - query.or(); - query.contains("lsp.countryCode", key); - } - return query; - } - - - public static RealmResults buildUpcomingSwitchQueryAsync(Context context, Realm realm) { - SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); - RealmQuery query; - if (switchPreferences.getAllSwitch()) { - query = getAllUpcomingQuery(context, realm); - } else { - query = getSortedUpcomingQuery(context, realm); - } - return query.findAllAsync(); - } - public static RealmResults buildUpcomingSwitchQuery(Context context, Realm realm) { SwitchPreferences switchPreferences = SwitchPreferences.getInstance(context); RealmQuery query; @@ -397,12 +43,8 @@ private static RealmQuery getAllUpcomingQuery(Context context, Realm rea Date date = calendar.getTime(); RealmQuery query = realm.where(Launch.class) .greaterThanOrEqualTo("net", date); - if (switchPreferences.getNoGoSwitch()) { - query.notEqualTo("status", 2); - query.findAll(); - } - if (switchPreferences.getTBDLaunchSwitch()) { - query.equalTo("tbddate", false); + if (switchPreferences.getTBDSwitch()) { + query.notEqualTo("status.id", 2); query.findAll(); } query.sort("net", Sort.ASCENDING); @@ -422,18 +64,14 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm .greaterThanOrEqualTo("net", date); query.findAll(); - if (switchPreferences.getNoGoSwitch()) { - query.notEqualTo("status", 2).findAll(); - } - - if (switchPreferences.getTBDLaunchSwitch()) { - query.equalTo("tbddate", false).findAll(); + if (switchPreferences.getTBDSwitch()) { + query.notEqualTo("status.id", 2).findAll(); } query.beginGroup(); if (switchPreferences.getSwitchNasa()) { first = false; - query.equalTo("lsp.id", 44); + query.equalTo("rocket.configuration.launchServiceProvider.id", 44); } if (switchPreferences.getSwitchArianespace()) { @@ -442,7 +80,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 115); + query.equalTo("rocket.configuration.launchServiceProvider.id", 115); } if (switchPreferences.getSwitchSpaceX()) { @@ -451,7 +89,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 121); + query.equalTo("rocket.configuration.launchServiceProvider.id", 121); } if (switchPreferences.getSwitchULA()) { @@ -460,7 +98,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 124); + query.equalTo("rocket.configuration.launchServiceProvider.id", 124); } if (switchPreferences.getSwitchRoscosmos()) { @@ -469,11 +107,11 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 111) + query.equalTo("rocket.configuration.launchServiceProvider.id", 111) .or() - .equalTo("lsp.id", 163) + .equalTo("rocket.configuration.launchServiceProvider.id", 163) .or() - .equalTo("lsp.id", 63); + .equalTo("rocket.configuration.launchServiceProvider.id", 63); } if (switchPreferences.getSwitchCASC()) { if (!first) { @@ -481,7 +119,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 88); + query.equalTo("rocket.configuration.launchServiceProvider.id", 88); } if (switchPreferences.getSwitchISRO()) { @@ -490,7 +128,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("lsp.id", 31); + query.equalTo("rocket.configuration.launchServiceProvider.id", 31); } if (switchPreferences.getSwitchKSC()) { @@ -499,7 +137,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("location.id", 17); + query.equalTo("pad.location.id", 17); } if (switchPreferences.getSwitchKSC()) { @@ -508,7 +146,7 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("location.id", 16); + query.equalTo("pad.location.id", 16); } if (switchPreferences.getSwitchPles()) { @@ -517,14 +155,14 @@ private static RealmQuery getSortedUpcomingQuery(Context context, Realm } else { first = false; } - query.equalTo("location.id", 11); + query.equalTo("pad.location.id", 11); } if (switchPreferences.getSwitchVan()) { if (!first) { query.or(); } - query.equalTo("location.id", 18); + query.equalTo("pad.location.id", 18); } query.endGroup(); @@ -543,15 +181,15 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm query.findAll(); - if (switchPreferences.getNoGoSwitch()) { - query.notEqualTo("status", 2).findAll(); + if (switchPreferences.getTBDSwitch()) { + query.notEqualTo("status.id", 2).findAll(); } query.beginGroup(); if (switchPreferences.getSwitchNasa()) { first = false; - query.equalTo("lsp.id", 44); + query.equalTo("rocket.configuration.launchServiceProvider.id", 44); } if (switchPreferences.getSwitchArianespace()) { @@ -560,7 +198,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 115); + query.equalTo("rocket.configuration.launchServiceProvider.id", 115); } if (switchPreferences.getSwitchSpaceX()) { @@ -569,7 +207,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 121); + query.equalTo("rocket.configuration.launchServiceProvider.id", 121); } @@ -579,7 +217,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 124); + query.equalTo("rocket.configuration.launchServiceProvider.id", 124); } if (switchPreferences.getSwitchRoscosmos()) { @@ -588,11 +226,11 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 111) + query.equalTo("rocket.configuration.launchServiceProvider.id", 111) .or() - .equalTo("lsp.id", 163) + .equalTo("rocket.configuration.launchServiceProvider.id", 163) .or() - .equalTo("lsp.id", 63); + .equalTo("rocket.configuration.launchServiceProvider.id", 63); } if (switchPreferences.getSwitchCASC()) { if (!first) { @@ -600,7 +238,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 88); + query.equalTo("rocket.configuration.launchServiceProvider.id", 88); } if (switchPreferences.getSwitchISRO()) { @@ -609,7 +247,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 31); + query.equalTo("rocket.configuration.launchServiceProvider.id", 31); } if (switchPreferences.getSwitchKSC()) { @@ -618,7 +256,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 17); + query.equalTo("pad.location.id", 17); } if (switchPreferences.getSwitchKSC()) { @@ -627,7 +265,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 16); + query.equalTo("pad.location.id", 16); } if (switchPreferences.getSwitchPles()) { @@ -636,14 +274,14 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 11); + query.equalTo("pad.location.id", 11); } if (switchPreferences.getSwitchVan()) { if (!first) { query.or(); } - query.equalTo("location.id", 18); + query.equalTo("pad.location.id", 18); } query.endGroup(); @@ -659,15 +297,15 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm query.findAll(); - if (switchPreferences.getNoGoSwitch()) { - query.notEqualTo("status", 2).findAll(); + if (switchPreferences.getTBDSwitch()) { + query.notEqualTo("status.id", 2).findAll(); } query.beginGroup(); if (switchPreferences.getSwitchNasa()) { first = false; - query.equalTo("lsp.id", 44); + query.equalTo("rocket.configuration.launchServiceProvider.id", 44); } if (switchPreferences.getSwitchArianespace()) { @@ -676,7 +314,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 115); + query.equalTo("rocket.configuration.launchServiceProvider.id", 115); } if (switchPreferences.getSwitchSpaceX()) { @@ -685,7 +323,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 121); + query.equalTo("rocket.configuration.launchServiceProvider.id", 121); } if (switchPreferences.getSwitchULA()) { @@ -694,7 +332,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 124); + query.equalTo("rocket.configuration.launchServiceProvider.id", 124); } if (switchPreferences.getSwitchRoscosmos()) { @@ -703,11 +341,11 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 111) + query.equalTo("rocket.configuration.launchServiceProvider.id", 111) .or() - .equalTo("lsp.id", 163) + .equalTo("rocket.configuration.launchServiceProvider.id", 163) .or() - .equalTo("lsp.id", 63); + .equalTo("rocket.configuration.launchServiceProvider.id", 63); } if (switchPreferences.getSwitchCASC()) { if (!first) { @@ -715,7 +353,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 88); + query.equalTo("rocket.configuration.launchServiceProvider.id", 88); } if (switchPreferences.getSwitchISRO()) { @@ -724,7 +362,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("lsp.id", 31); + query.equalTo("rocket.configuration.launchServiceProvider.id", 31); } if (switchPreferences.getSwitchKSC()) { @@ -733,7 +371,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 17); + query.equalTo("pad.location.id", 17); } if (switchPreferences.getSwitchKSC()) { @@ -742,7 +380,7 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 16); + query.equalTo("pad.location.id", 16); } if (switchPreferences.getSwitchPles()) { @@ -751,14 +389,14 @@ public static RealmResults buildSwitchQuery(Context context, Realm realm } else { first = false; } - query.equalTo("location.id", 11); + query.equalTo("pad.location.id", 11); } if (switchPreferences.getSwitchVan()) { if (!first) { query.or(); } - query.equalTo("location.id", 18); + query.equalTo("pad.location.id", 18); } query.endGroup(); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/wear/WearWatchfaceManager.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/wear/WearWatchfaceManager.java index 2ef85c70a..a18dc4eeb 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/content/wear/WearWatchfaceManager.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/content/wear/WearWatchfaceManager.java @@ -32,7 +32,7 @@ import me.calebjones.spacelaunchnow.content.services.BaseManager; import me.calebjones.spacelaunchnow.content.util.QueryBuilder; import me.calebjones.spacelaunchnow.data.models.main.Launch; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.ui.supporter.SupporterHelper; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.transformations.SaturationTransformation; @@ -81,25 +81,25 @@ private void checkLaunch() { RealmResults launches = QueryBuilder.buildSwitchQuery(context, mRealm); Launch launch = launches.first(); // Launch launch = mRealm.where(Launch.class).greaterThan("net", new Date()).findAllSorted("net").first(); - if (launch != null && launch.getName() != null && launch.getNetstamp() != null) { + if (launch != null && launch.getName() != null && launch.getNet() != null) { Timber.v("Sending data to wear: %s", launch.getName()); boolean dynamic = sharedPref.getBoolean("supporter_dynamic_background", false); boolean modify = sharedPref.getBoolean("wear_background_blur", true); if (dynamic) { - if (launch.getLauncher().getName() != null) { - if (launch.getLauncher().getImageUrl() != null && launch.getLauncher().getImageUrl().length() > 0 && !launch.getLauncher().getImageUrl().contains("placeholder")) { - Timber.v("Sending image %s", launch.getLauncher().getImageUrl()); - sendDataToWear(launch.getLauncher().getImageUrl(), launch, modify); + if (launch.getRocket().getConfiguration().getName() != null) { + if (launch.getRocket().getConfiguration().getImageUrl() != null && launch.getRocket().getConfiguration().getImageUrl().length() > 0 && !launch.getRocket().getConfiguration().getImageUrl().contains("placeholder")) { + Timber.v("Sending image %s", launch.getRocket().getConfiguration().getImageUrl()); + sendDataToWear(launch.getRocket().getConfiguration().getImageUrl(), launch, modify); } else { String query; - if (launch.getLauncher().getName().contains("Space Shuttle")) { + if (launch.getRocket().getConfiguration().getName().contains("Space Shuttle")) { query = "Space Shuttle"; } else { - query = launch.getLauncher().getName(); + query = launch.getRocket().getConfiguration().getName(); } - Launcher launchVehicle = mRealm.where(Launcher.class) + LauncherConfig launchVehicle = mRealm.where(LauncherConfig.class) .contains("name", query) .findFirst(); if (launchVehicle != null && launchVehicle.getImageUrl() != null && launchVehicle.getImageUrl().length() > 0) { @@ -172,8 +172,9 @@ private void sendDataToWear(String image, final Launch launch, boolean modify) { Asset asset = createAssetFromBitmap(resource); + int i = (int) (new Date().getTime()/1000); putImageReq.getDataMap().putString(NAME_KEY, launch.getName()); - putImageReq.getDataMap().putInt(TIME_KEY, launch.getNetstamp()); + putImageReq.getDataMap().putLong(TIME_KEY, (int) launch.getNet().getTime()/1000); putImageReq.getDataMap().putLong(DATE_KEY, launch.getNet().getTime()); putImageReq.getDataMap().putLong("time", new Date().getTime()); putImageReq.getDataMap().putAsset(BACKGROUND_KEY, asset); @@ -198,7 +199,7 @@ private void sendDataToWear(String image, final Launch launch, boolean modify) { Asset asset = createAssetFromBitmap(resource); putImageReq.getDataMap().putString(NAME_KEY, launch.getName()); - putImageReq.getDataMap().putInt(TIME_KEY, launch.getNetstamp()); + putImageReq.getDataMap().putLong(TIME_KEY, (int) launch.getNet().getTime()/1000); putImageReq.getDataMap().putLong(DATE_KEY, launch.getNet().getTime()); putImageReq.getDataMap().putLong("time", new Date().getTime()); putImageReq.getDataMap().putAsset(BACKGROUND_KEY, asset); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/debug/DebugPresenter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/debug/DebugPresenter.java index 51c42f348..56c70ca6d 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/debug/DebugPresenter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/debug/DebugPresenter.java @@ -95,25 +95,19 @@ public void toggleDebugLaunchesClicked(boolean selected, final Context context) sharedPreference.setDebugLaunch(selected); if (selected) { sharedPreference.setDebugLaunch(true); - DataClient.create("dev", context.getString(R.string.sln_token)); + DataClient.create("dev", context.getString(R.string.sln_token), true); } else { sharedPreference.setDebugLaunch(false); - DataClient.create("1.3", context.getString(R.string.sln_token)); + DataClient.create("1.3", context.getString(R.string.sln_token), false); } //Delete from Database realm = Realm.getDefaultInstance(); - realm.executeTransactionAsync(new Realm.Transaction() { - @Override - public void execute(Realm realm) { - RealmResults results = realm.where(Launch.class).findAll(); - results.deleteAllFromRealm(); - } - }, new Realm.Transaction.OnSuccess() { - @Override - public void onSuccess() { - } + realm.executeTransactionAsync(realm -> { + RealmResults results = realm.where(Launch.class).findAll(); + results.deleteAllFromRealm(); + }, () -> { }); realm.close(); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/OnFragmentInteractionListener.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/OnFragmentInteractionListener.java new file mode 100644 index 000000000..96becfa91 --- /dev/null +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/OnFragmentInteractionListener.java @@ -0,0 +1,11 @@ +package me.calebjones.spacelaunchnow.ui.launchdetail; + +public interface OnFragmentInteractionListener { + + int AGENCY = 0; + int SUMMARY = 1; + int MISSION = 2; + + void sendLaunchToFragment(int fragment); + +} diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/TabsAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/TabsAdapter.java index 344509eff..fbb07b90d 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/TabsAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/TabsAdapter.java @@ -4,17 +4,21 @@ import android.support.v4.app.Fragment; import android.support.v4.app.FragmentManager; import android.support.v4.app.FragmentPagerAdapter; +import android.view.ViewGroup; import me.calebjones.spacelaunchnow.R; +import me.calebjones.spacelaunchnow.data.models.main.Launch; import me.calebjones.spacelaunchnow.ui.launchdetail.fragments.AgencyDetailFragment; -import me.calebjones.spacelaunchnow.ui.launchdetail.fragments.MissionDetailFragment; +import me.calebjones.spacelaunchnow.ui.launchdetail.fragments.mission.MissionDetailFragment; import me.calebjones.spacelaunchnow.ui.launchdetail.fragments.SummaryDetailFragment; +import me.calebjones.spacelaunchnow.ui.launches.launcher.PreviousLauncherLaunchesFragment; +import me.calebjones.spacelaunchnow.ui.launches.launcher.UpcomingLauncherLaunchesFragment; public class TabsAdapter extends FragmentPagerAdapter { - private SummaryDetailFragment summaryFragment = SummaryDetailFragment.newInstance(); - private MissionDetailFragment missionFragment = MissionDetailFragment.newInstance(); - private AgencyDetailFragment agencyFragment = AgencyDetailFragment.newInstance(); + public SummaryDetailFragment summaryFragment; + public MissionDetailFragment missionFragment; + public AgencyDetailFragment agencyFragment; private Context context; public TabsAdapter(FragmentManager fragmentManager, Context context) { @@ -22,24 +26,78 @@ public TabsAdapter(FragmentManager fragmentManager, Context context) { this.context = context; } + public void updateLaunches(Launch launch) { + if (summaryFragment != null) { + summaryFragment.setLaunch(launch); + } + if (missionFragment != null) { + missionFragment.setLaunch(launch); + } + if (agencyFragment != null) { + agencyFragment.setLaunch(launch); + } + } + + public void updateSummaryLaunch(Launch launch) { + if (summaryFragment != null) { + summaryFragment.setLaunch(launch); + } + } + + public void updatAgencyLaunch(Launch launch) { + if (agencyFragment != null) { + agencyFragment.setLaunch(launch); + } + } + + + public void updateMissionLaunch(Launch launch) { + if (missionFragment != null) { + missionFragment.setLaunch(launch); + } + } + @Override public int getCount() { return 3; } @Override - public Fragment getItem(int i) { - switch (i) { + public Fragment getItem(int position) { + switch (position) { case 0: - return summaryFragment; + return SummaryDetailFragment.newInstance(); case 1: - return missionFragment; + return MissionDetailFragment.newInstance(); case 2: - return agencyFragment; + return AgencyDetailFragment.newInstance(); } return null; } + // Here we can finally safely save a reference to the created + // Fragment, no matter where it came from (either getItem() or + // FragmentManger). Simply save the returned Fragment from + // super.instantiateItem() into an appropriate reference depending + // on the ViewPager position. + @Override + public Object instantiateItem(ViewGroup container, int position) { + Fragment createdFragment = (Fragment) super.instantiateItem(container, position); + // save the appropriate reference depending on position + switch (position) { + case 0: + summaryFragment = (SummaryDetailFragment) createdFragment; + break; + case 1: + missionFragment = (MissionDetailFragment) createdFragment; + break; + case 2: + agencyFragment = (AgencyDetailFragment) createdFragment; + break; + } + return createdFragment; + } + @Override public CharSequence getPageTitle(int position) { switch (position) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/activity/LaunchDetailActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/activity/LaunchDetailActivity.java index 2a5a8891f..40609daba 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/activity/LaunchDetailActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/activity/LaunchDetailActivity.java @@ -39,13 +39,8 @@ import com.mikepenz.fontawesome_typeface_library.FontAwesome; import com.mikepenz.iconics.IconicsDrawable; -import org.greenrobot.eventbus.EventBus; -import org.greenrobot.eventbus.Subscribe; -import org.greenrobot.eventbus.ThreadMode; - import java.text.SimpleDateFormat; import java.util.Date; -import java.util.List; import java.util.Scanner; import java.util.concurrent.TimeUnit; @@ -62,12 +57,12 @@ import me.calebjones.spacelaunchnow.content.events.LaunchEvent; import me.calebjones.spacelaunchnow.content.events.LaunchRequestEvent; import me.calebjones.spacelaunchnow.data.models.main.Launch; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.data.networking.DataClient; import me.calebjones.spacelaunchnow.data.networking.error.ErrorUtil; import me.calebjones.spacelaunchnow.data.networking.error.LibraryError; -import me.calebjones.spacelaunchnow.data.networking.responses.base.LaunchResponse; import me.calebjones.spacelaunchnow.ui.imageviewer.FullscreenImageActivity; +import me.calebjones.spacelaunchnow.ui.launchdetail.OnFragmentInteractionListener; import me.calebjones.spacelaunchnow.ui.launchdetail.TabsAdapter; import me.calebjones.spacelaunchnow.ui.main.MainActivity; import me.calebjones.spacelaunchnow.ui.settings.SettingsActivity; @@ -84,7 +79,7 @@ import timber.log.Timber; public class LaunchDetailActivity extends BaseActivity - implements AppBarLayout.OnOffsetChangedListener { + implements AppBarLayout.OnOffsetChangedListener, OnFragmentInteractionListener { private static final int PERCENTAGE_TO_ANIMATE_AVATAR = 20; @BindView(R.id.fab_share) @@ -203,6 +198,17 @@ public void onAdFailedToLoad(int error) { Window window = getWindow(); window.addFlags(WindowManager.LayoutParams.FLAG_TRANSLUCENT_STATUS); + appBarLayout.addOnOffsetChangedListener(new CustomOnOffsetChangedListener(statusColor, getWindow())); + appBarLayout.addOnOffsetChangedListener(this); + mMaxScrollSize = appBarLayout.getTotalScrollRange(); + + tabAdapter = new TabsAdapter(getSupportFragmentManager(), context); + + viewPager.setAdapter(tabAdapter); + viewPager.setOffscreenPageLimit(3); + + tabLayout.setupWithViewPager(viewPager); + //Grab information from Intent Intent mIntent = getIntent(); String type = mIntent.getStringExtra("TYPE"); @@ -268,16 +274,9 @@ public void onFailure(Call call, Throwable t) { getSupportActionBar().setDisplayShowTitleEnabled(false); } } - appBarLayout.addOnOffsetChangedListener(new CustomOnOffsetChangedListener(statusColor, getWindow())); - appBarLayout.addOnOffsetChangedListener(this); - mMaxScrollSize = appBarLayout.getTotalScrollRange(); - tabAdapter = new TabsAdapter(getSupportFragmentManager(), context); - viewPager.setAdapter(tabAdapter); - viewPager.setOffscreenPageLimit(3); - tabLayout.setupWithViewPager(viewPager); } private void showFeedback() { @@ -367,15 +366,15 @@ private void updateViews(Launch launch) { try { this.launch = launch; - EventBus.getDefault().post(new LaunchEvent(launch)); - if (!this.isDestroyed() && launch != null && launch.getLauncher() != null) { + tabAdapter.updateLaunches(launch); + if (!this.isDestroyed() && launch != null && launch.getRocket().getConfiguration() != null) { Timber.v("Loading detailLaunch %s", launch.getId()); findProfileLogo(); - if (launch.getLauncher().getName() != null) { - if (launch.getLauncher().getImageUrl() != null - && launch.getLauncher().getImageUrl().length() > 0 - && !launch.getLauncher().getImageUrl().contains("placeholder")) { - final String image = launch.getLauncher().getImageUrl(); + if (launch.getRocket().getConfiguration().getName() != null) { + if (launch.getRocket().getConfiguration().getImageUrl() != null + && launch.getRocket().getConfiguration().getImageUrl().length() > 0 + && !launch.getRocket().getConfiguration().getImageUrl().contains("placeholder")) { + final String image = launch.getRocket().getConfiguration().getImageUrl(); GlideApp.with(this) .load(image) .placeholder(R.drawable.placeholder) @@ -412,17 +411,17 @@ private void findProfileLogo() { String agencyName = null; //This checks to see if a location is available - if (launch.getLsp() != null) { - locationCountryCode = launch.getLsp().getCountryCode(); - agencyName = launch.getLsp().getName(); + if (launch.getRocket().getConfiguration().getLaunchServiceProvider() != null) { + locationCountryCode = launch.getRocket().getConfiguration().getLaunchServiceProvider().getCountryCode(); + agencyName = launch.getRocket().getConfiguration().getLaunchServiceProvider().getName(); //Go through various CountryCodes and assign flag. - if (launch.getLsp().getAbbrev().contains("ASA")) { + if (launch.getRocket().getConfiguration().getLaunchServiceProvider().getAbbrev().contains("ASA")) { applyProfileLogo(getString(R.string.ariane_logo)); - } else if (launch.getLsp().getAbbrev().contains("SpX")) { + } else if (launch.getRocket().getConfiguration().getLaunchServiceProvider().getAbbrev().contains("SpX")) { applyProfileLogo(getString(R.string.spacex_logo)); - } else if (launch.getLsp().getAbbrev().contains("BA")) { + } else if (launch.getRocket().getConfiguration().getLaunchServiceProvider().getAbbrev().contains("BA")) { applyProfileLogo(getString(R.string.Yuzhnoye_logo)); - } else if (launch.getLsp().getAbbrev().contains("ULA")) { + } else if (launch.getRocket().getConfiguration().getLaunchServiceProvider().getAbbrev().contains("ULA")) { applyProfileLogo(getString(R.string.ula_logo)); } else if (locationCountryCode.length() == 3) { if (locationCountryCode.contains("USA")) { @@ -464,12 +463,12 @@ public void onResume() { private void getLaunchVehicle(Launch result, boolean setImage) { String query; - if (result.getLauncher().getName().contains("Space Shuttle")) { + if (result.getRocket().getConfiguration().getName().contains("Space Shuttle")) { query = "Space Shuttle"; } else { - query = result.getLauncher().getName(); + query = result.getRocket().getConfiguration().getName(); } - Launcher launchVehicle = getRealm().where(Launcher.class) + LauncherConfig launchVehicle = getRealm().where(LauncherConfig.class) .contains("name", query) .findFirst(); if (setImage) { @@ -494,8 +493,20 @@ public void setData(String data) { scanner.close(); } - public Launch getLaunch() { - return launch; + public void sendLaunchToFragment(int fragment) { + if (launch != null) { + switch (fragment) { + case OnFragmentInteractionListener.AGENCY: + tabAdapter.updatAgencyLaunch(launch); + break; + case OnFragmentInteractionListener.MISSION: + tabAdapter.updateMissionLaunch(launch); + break; + case OnFragmentInteractionListener.SUMMARY: + tabAdapter.updateSummaryLaunch(launch); + break; + } + } } @Override @@ -532,14 +543,12 @@ public void onOffsetChanged(AppBarLayout appBarLayout, int verticalOffset) { @Override public void onStart() { super.onStart(); - EventBus.getDefault().register(this); Timber.v("LaunchDetailActivity onStart!"); customTabActivityHelper.bindCustomTabsService(this); } @Override public void onStop() { - EventBus.getDefault().unregister(this); Timber.v("LaunchDetailActivity onStop!"); customTabActivityHelper.unbindCustomTabsService(this); super.onStop(); @@ -564,14 +573,14 @@ public void onViewClicked() { df.toLocalizedPattern(); launchDate = df.format(date); } - if (launch.getLocation() != null) { + if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; - } else if (launch.getLocation() != null) { + } else if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; } else { message = launch.getName() @@ -593,11 +602,6 @@ public void onViewClicked() { } } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(LaunchRequestEvent event) { - EventBus.getDefault().post(new LaunchEvent(launch)); - } - @Override protected void onSaveInstanceState(final Bundle outState) { super.onSaveInstanceState(outState); @@ -631,8 +635,7 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } if (id == android.R.id.home) { - Intent intent = new Intent(context, MainActivity.class); - startActivity(intent); + onBackPressed(); return true; } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/AgencyDetailFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/AgencyDetailFragment.java index cd2f6aa4b..4c0095621 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/AgencyDetailFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/AgencyDetailFragment.java @@ -27,6 +27,7 @@ import me.calebjones.spacelaunchnow.content.database.ListPreferences; import me.calebjones.spacelaunchnow.content.events.LaunchEvent; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.ui.launchdetail.OnFragmentInteractionListener; import me.calebjones.spacelaunchnow.ui.launches.agency.AgencyLaunchActivity; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.Utils; @@ -57,6 +58,7 @@ public class AgencyDetailFragment extends BaseFragment { private SharedPreferences sharedPref; private static ListPreferences sharedPreference; private Context context; + private OnFragmentInteractionListener mListener; public static Launch detailLaunch; @@ -86,6 +88,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa if (detailLaunch != null && detailLaunch.isValid()) { setUpViews(detailLaunch); + } else { + mListener.sendLaunchToFragment(OnFragmentInteractionListener.AGENCY); } return view; @@ -95,16 +99,17 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle sa public void onResume() { if (detailLaunch != null && detailLaunch.isValid()) { setUpViews(detailLaunch); + } else { + mListener.sendLaunchToFragment(OnFragmentInteractionListener.AGENCY); } super.onResume(); } - private void setLaunch(Launch launch) { + public void setLaunch(Launch launch) { detailLaunch = launch; setUpViews(launch); } - // TODO redo for payloads private void setUpViews(Launch launch) { try { detailLaunch = launch; @@ -112,31 +117,32 @@ private void setUpViews(Launch launch) { Timber.v("Setting up views..."); lspCard.setVisibility(View.VISIBLE); - if (detailLaunch.getLsp().getLogoUrl() != null) { + lspAgency.setText(String.format(this.getString(R.string.view_rocket_launches), launch.getRocket().getConfiguration().getLaunchServiceProvider().getName())); + if (detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getLogoUrl() != null) { lspLogo.setVisibility(View.VISIBLE); GlideApp.with(context) - .load(detailLaunch.getLsp().getLogoUrl()) + .load(detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getLogoUrl()) .centerInside() .into(lspLogo); } - lspName.setText(detailLaunch.getLsp().getName()); - lspType.setText(detailLaunch.getLsp().getType()); - if (detailLaunch.getLsp().getAdministrator() != null) { - lspAdministrator.setText(String.format("%s", detailLaunch.getLsp().getAdministrator())); + lspName.setText(detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getName()); + lspType.setText(detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getType()); + if (detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getAdministrator() != null) { + lspAdministrator.setText(String.format("%s", detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getAdministrator())); } else { lspAdministrator.setText(R.string.unknown_administrator); } - if (detailLaunch.getLsp().getFoundingYear() != null) { - lspFoundedYear.setText(String.format(getString(R.string.founded_in), detailLaunch.getLsp().getFoundingYear())); + if (detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getFoundingYear() != null) { + lspFoundedYear.setText(String.format(getString(R.string.founded_in), detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getFoundingYear())); } else { lspFoundedYear.setText(R.string.unknown_year); } - lspSummary.setText(detailLaunch.getLsp().getDescription()); - if (detailLaunch.getLsp().getInfoUrl() == null) { + lspSummary.setText(detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getDescription()); + if (detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getInfoUrl() == null) { lspInfoButtonOne.setVisibility(View.GONE); } - if (detailLaunch.getLsp().getWikiUrl() == null) { + if (detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getWikiUrl() == null) { lspWikiButtonOne.setVisibility(View.GONE); } lspAgency.setVisibility(View.VISIBLE); @@ -156,41 +162,39 @@ public static AgencyDetailFragment newInstance() { return new AgencyDetailFragment(); } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(LaunchEvent event) { - setLaunch(event.launch); - } - - @Override - public void onStart() { - super.onStart(); - Timber.v("On Start"); - EventBus.getDefault().register(this); - } - - @Override - public void onStop() { - Timber.v("On Stop"); - EventBus.getDefault().unregister(this); - super.onStop(); - } - @OnClick(R.id.lsp_infoButton_one) public void onLspInfoButtonOneClicked() { Activity activity = (Activity) context; - Utils.openCustomTab(activity, context, detailLaunch.getLsp().getInfoUrl()); + Utils.openCustomTab(activity, context, detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getInfoUrl()); } @OnClick(R.id.lsp_wikiButton_one) public void onLspWikiButtonOneClicked() { Activity activity = (Activity) context; - Utils.openCustomTab(activity, context, detailLaunch.getLsp().getWikiUrl()); + Utils.openCustomTab(activity, context, detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getWikiUrl()); } @OnClick(R.id.lsp_agency) public void onViewClicked() { Intent intent = new Intent(context, AgencyLaunchActivity.class); - intent.putExtra("lspName", detailLaunch.getLsp().getName()); + intent.putExtra("lspName", detailLaunch.getRocket().getConfiguration().getLaunchServiceProvider().getName()); startActivity(intent); } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/SummaryDetailFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/SummaryDetailFragment.java index 3a6f8d08a..7eb5641d8 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/SummaryDetailFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/SummaryDetailFragment.java @@ -38,6 +38,8 @@ import com.google.android.youtube.player.YouTubePlayerSupportFragment; import com.mypopsy.maps.StaticMap; +import net.cachapa.expandablelayout.ExpandableLayout; + import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; @@ -49,12 +51,16 @@ import java.util.List; import java.util.Locale; import java.util.TimeZone; +import java.util.concurrent.TimeUnit; import java.util.regex.Matcher; import java.util.regex.Pattern; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; import io.realm.Realm; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.calendar.CalendarSyncManager; @@ -65,10 +71,14 @@ import me.calebjones.spacelaunchnow.content.database.SwitchPreferences; import me.calebjones.spacelaunchnow.content.events.LaunchEvent; import me.calebjones.spacelaunchnow.content.util.DialogAdapter; +import me.calebjones.spacelaunchnow.data.models.main.Landing; import me.calebjones.spacelaunchnow.data.models.main.Launch; import me.calebjones.spacelaunchnow.data.models.main.Pad; import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; +import me.calebjones.spacelaunchnow.ui.launchdetail.OnFragmentInteractionListener; import me.calebjones.spacelaunchnow.ui.launchdetail.activity.LaunchDetailActivity; +import me.calebjones.spacelaunchnow.ui.launches.launcher.UpcomingLauncherLaunchesFragment; +import me.calebjones.spacelaunchnow.ui.main.next.CardAdapter; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.Utils; import me.calebjones.spacelaunchnow.utils.analytics.Analytics; @@ -81,11 +91,6 @@ public class SummaryDetailFragment extends BaseFragment implements YouTubePlayer.OnInitializedListener { - - @BindView(R.id.youTube_viewHolder) - LinearLayout youTubeViewHolder; - @BindView(R.id.countdown_separator) - View countdownSeparator; private SharedPreferences sharedPref; private ListPreferences sharedPreference; private Context context; @@ -98,7 +103,14 @@ public class SummaryDetailFragment extends BaseFragment implements YouTubePlayer private Dialog dialog; private boolean youTubePlaying = false; private int youTubeProgress = 0; + private OnFragmentInteractionListener mListener; + @BindView(R.id.weather_title) + TextView weatherTitle; + @BindView(R.id.countdown_status) + TextView countdownStatus; + @BindView(R.id.countdown_separator) + View countdownSeparator; @BindView(R.id.content_TMinus_status) TextView contentTMinusStatus; @BindView(R.id.countdown_days) @@ -110,13 +122,7 @@ public class SummaryDetailFragment extends BaseFragment implements YouTubePlayer @BindView(R.id.countdown_seconds) TextView countdownSeconds; @BindView(R.id.countdown_layout) - LinearLayout countdownLayout; - @BindView(R.id.day_two) - LinearLayout dayTwo; - @BindView(R.id.day_three) - LinearLayout dayThree; - @BindView(R.id.day_four) - LinearLayout dayFour; + View countdownLayout; @BindView(R.id.launch_summary) NestedScrollView launchSummary; @BindView(R.id.map_view_summary) @@ -178,7 +184,7 @@ public class SummaryDetailFragment extends BaseFragment implements YouTubePlayer @BindView(R.id.day_four_day) TextView dayFourDay; @BindView(R.id.three_day_forecast) - LinearLayout threeDayForecast; + View threeDayForecast; @BindView(R.id.day_two_weather_wind_speed_icon) WeatherIconView dayTwoWeatherWindIcon; @BindView(R.id.day_three_weather_wind_speed_icon) @@ -202,6 +208,8 @@ public class SummaryDetailFragment extends BaseFragment implements YouTubePlayer @BindView(R.id.youtube_view) View youTubeView; + public Disposable var; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -249,6 +257,8 @@ public void onResume() { } if (detailLaunch != null && detailLaunch.isValid()) { setUpViews(detailLaunch); + } else { + mListener.sendLaunchToFragment(OnFragmentInteractionListener.SUMMARY); } super.onResume(); } @@ -259,6 +269,7 @@ public void setLaunch(Launch launch) { } private void fetchPastWeather() { + weatherTitle.setText("Launch Day Weather"); if (detailLaunch.getPad() != null) { Pad pad = detailLaunch.getPad(); @@ -274,28 +285,27 @@ private void fetchPastWeather() { unit = Unit.SI; } - ForecastClient.getInstance() - .getForecast(latitude, longitude, detailLaunch.getNetstamp(), null, unit, null, false, new Callback() { - @Override - public void onResponse(Call forecastCall, Response response) { - if (response.isSuccessful()) { - Forecast forecast = response.body(); - if (SummaryDetailFragment.this.isVisible()) { - Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), true, "Success"); - updateWeatherView(forecast); - } - } else { - Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), false, response.errorBody().toString()); - Timber.e("Error: %s", response.errorBody()); - } + ForecastClient.getInstance().getForecast(latitude, longitude, (int) detailLaunch.getNet().getTime() / 1000, null, unit, null, false, new Callback() { + @Override + public void onResponse(Call forecastCall, Response response) { + if (response.isSuccessful()) { + Forecast forecast = response.body(); + if (SummaryDetailFragment.this.isVisible()) { + Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), true, "Success"); + updateWeatherView(forecast); } + } else { + Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), false, response.errorBody().toString()); + Timber.e("Error: %s", response.errorBody()); + } + } - @Override - public void onFailure(Call forecastCall, Throwable t) { - Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), false, t.getLocalizedMessage()); - Timber.e("ERROR: %s", t.getLocalizedMessage()); - } - }); + @Override + public void onFailure(Call forecastCall, Throwable t) { + Analytics.getInstance().sendWeatherEvent(detailLaunch.getName(), false, t.getLocalizedMessage()); + Timber.e("ERROR: %s", t.getLocalizedMessage()); + } + }); } } @@ -481,7 +491,7 @@ private void updateWeatherView(Forecast forecast) { weatherSummaryDay.setVisibility(View.GONE); } - weatherLocation.setText(detailLaunch.getLocation().getName()); + weatherLocation.setText(detailLaunch.getPad().getLocation().getName()); weatherCard.setVisibility(View.VISIBLE); if (nightMode) { @@ -613,7 +623,7 @@ public boolean onPreDraw() { Date mDate; String dateText = null; - if (launch.getStatus() == 1){ + if (launch.getStatus().getId() == 1) { String go = context.getResources().getString(R.string.status_go); if (detailLaunch.getProbability() != null && detailLaunch.getProbability() > 0) { go = String.format("%s | Forecast - %s%%", go, detailLaunch.getProbability()); @@ -621,7 +631,7 @@ public boolean onPreDraw() { //GO for launch launch_status.setText(go); } else { - launch_status.setText(LaunchStatus.getLaunchStatusTitle(context, detailLaunch.getStatus())); + launch_status.setText(LaunchStatus.getLaunchStatusTitle(context, detailLaunch.getStatus().getId())); } if (detailLaunch.getVidURLs() != null && detailLaunch.getVidURLs().size() > 0) { @@ -634,7 +644,8 @@ public boolean onPreDraw() { if (youTubeURL != null) { Timber.v("Loading %s", youTubeURL); mapView.setVisibility(View.GONE); - youTubeViewHolder.setVisibility(View.VISIBLE); + youTubeView.setVisibility(View.VISIBLE); + errorMessage.setVisibility(View.GONE); final LaunchDetailActivity mainActivity = (LaunchDetailActivity) getActivity(); youTubePlayerFragment.initialize(context.getResources().getString(R.string.GoogleMapsKey), new YouTubePlayer.OnInitializedListener() { @Override @@ -707,6 +718,8 @@ public void onLoaded(String s) { if (youTubeURL.contains("live")) { errorMessage.setVisibility(View.VISIBLE); errorMessage.setText(String.format("Live Broadcast %s", s)); + } else { + errorMessage.setVisibility(View.GONE); } checkState(); } @@ -732,6 +745,8 @@ public void onError(YouTubePlayer.ErrorReason errorReason) { if (youTubeURL.contains("live")) { errorMessage.setVisibility(View.VISIBLE); errorMessage.setText("Broadcast may not be live."); + } else { + errorMessage.setVisibility(View.GONE); } if (errorReason.ordinal() == 4) { Toast.makeText(mainActivity, "Playback paused by YouTube while view is obstructed.", Toast.LENGTH_SHORT).show(); @@ -823,6 +838,7 @@ public void onListItemSelected(int index, MaterialSimpleListItem item, boolean l } else { launchWindowText.setVisibility(View.GONE); } + } catch (NullPointerException e) { Timber.e(e); } @@ -851,9 +867,8 @@ private String getYouTubeID(String vidURL) { private void setupCountdownTimer(Launch launch) { //If timestamp is available calculate TMinus and date. - if (launch.getNetstamp() > 0 && (launch.getStatus() == 1 || launch.getStatus() == 2)) { - long longdate = launch.getNetstamp(); - longdate = longdate * 1000; + if (launch.getNet() != null && (launch.getStatus().getId() == 1 || launch.getStatus().getId() == 2)) { + long longdate = launch.getNet().getTime(); final Date date = new Date(longdate); Calendar future = Utils.DateToCalendar(date); @@ -865,158 +880,175 @@ private void setupCountdownTimer(Launch launch) { timer.cancel(); } - final int status = launch.getStatus(); + final int status = launch.getStatus().getId(); final String hold = launch.getHoldreason(); final int nightColor = ContextCompat.getColor(context, R.color.dark_theme_secondary_text_color); final int color = ContextCompat.getColor(context, R.color.colorTextSecondary); final int accentColor = ContextCompat.getColor(context, R.color.colorAccent); - contentTMinusStatus.setTypeface(Typeface.SANS_SERIF); - contentTMinusStatus.setTextColor(accentColor); - - countdownLayout.setVisibility(View.VISIBLE); + contentTMinusStatus.setVisibility(View.GONE); long timeToFinish = future.getTimeInMillis() - now.getTimeInMillis(); - if (timeToFinish > 0) { + if (timeToFinish > 0 && launch.getStatus().getId() == 1) { timer = new CountDownTimer(timeToFinish, 1000) { StringBuilder time = new StringBuilder(); @Override public void onFinish() { Timber.v("Countdown finished."); - contentTMinusStatus.setTypeface(Typeface.DEFAULT); - if (sharedPreference.isNightModeActive(context)) { - contentTMinusStatus.setTextColor(nightColor); - } else { - contentTMinusStatus.setTextColor(color); - } - if (status == 1) { - contentTMinusStatus.setText("Watch Live webcast for up to date status."); - - } else { - if (hold != null && hold.length() > 1) { - contentTMinusStatus.setText(hold); - } else { - contentTMinusStatus.setText("Watch Live webcast for up to date status."); - } - } - contentTMinusStatus.setVisibility(View.VISIBLE); countdownDays.setText("00"); countdownHours.setText("00"); countdownMinutes.setText("00"); countdownSeconds.setText("00"); + countdownStatus.setVisibility(View.VISIBLE); + countdownStatus.setText("+"); + countUpTimer(longdate); } @Override public void onTick(long millisUntilFinished) { time.setLength(0); + setCountdownView(millisUntilFinished); + } + }.start(); + } else if (launch.getStatus().getId() == 3 || launch.getStatus().getId() == 4 || launch.getStatus().getId() == 7) { + countdownDays.setText("00"); + countdownHours.setText("00"); + countdownMinutes.setText("00"); + countdownSeconds.setText("00"); + showStatusDescription(launch); + } else if (launch.getStatus().getId() == 6 || launch.getStatus().getId() == 1) { + countdownStatus.setVisibility(View.VISIBLE); + countdownStatus.setText("+"); + countUpTimer(longdate); + } else { + countdownDays.setText("- -"); + countdownHours.setText("- -"); + countdownMinutes.setText("- -"); + countdownSeconds.setText("- -"); + showStatusDescription(launch); + } + } else { + showStatusDescription(launch); + } + } - // Calculate the Days/Hours/Mins/Seconds numerically. - long longDays = millisUntilFinished / 86400000; - long longHours = (millisUntilFinished / 3600000) % 24; - long longMins = (millisUntilFinished / 60000) % 60; - long longSeconds = (millisUntilFinished / 1000) % 60; - - String days = String.valueOf(longDays); - String hours; - String minutes; - String seconds; - - // Translate those numerical values to string values. - if (longHours < 10) { - hours = "0" + String.valueOf(longHours); - } else { - hours = String.valueOf(longHours); - } + private void countUpTimer(long longdate) { + var = Observable + .interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) + .subscribe( + time -> { + Calendar currentTime = Calendar.getInstance(); + long timeSince = currentTime.getTimeInMillis() - longdate; + setCountdownView(timeSince); + }); + } - if (longMins < 10) { - minutes = "0" + String.valueOf(longMins); - } else { - minutes = String.valueOf(longMins); - } + private void setCountdownView(long millisUntilFinished) { + // Calculate the Days/Hours/Mins/Seconds numerically. + long longDays = millisUntilFinished / 86400000; + long longHours = (millisUntilFinished / 3600000) % 24; + long longMins = (millisUntilFinished / 60000) % 60; + long longSeconds = (millisUntilFinished / 1000) % 60; - if (longSeconds < 10) { - seconds = "0" + String.valueOf(longSeconds); - } else { - seconds = String.valueOf(longSeconds); - } + String days; + String hours; + String minutes; + String seconds; + if (longDays < 10) { + days = "0" + String.valueOf(longDays); + } else { + days = String.valueOf(longDays); + } - // Update the views - if (Integer.valueOf(days) > 0) { - countdownDays.setText(days); - } else { - countdownDays.setText("00"); - } - if (Integer.valueOf(hours) > 0) { - countdownHours.setText(hours); - } else if (Integer.valueOf(days) > 0) { - countdownHours.setText("00"); - } else { - countdownHours.setText("00"); - } + // Translate those numerical values to string values. + if (longHours < 10) { + hours = "0" + String.valueOf(longHours); + } else { + hours = String.valueOf(longHours); + } - if (Integer.valueOf(minutes) > 0) { - countdownMinutes.setText(minutes); - } else if (Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { - countdownMinutes.setText("00"); - } else { - countdownMinutes.setText("00"); - } + if (longMins < 10) { + minutes = "0" + String.valueOf(longMins); + } else { + minutes = String.valueOf(longMins); + } - if (Integer.valueOf(seconds) > 0) { - countdownSeconds.setText(seconds); - } else if (Integer.valueOf(minutes) > 0 || Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { - countdownSeconds.setText("00"); - } else { - countdownSeconds.setText("00"); - } + if (longSeconds < 10) { + seconds = "0" + String.valueOf(longSeconds); + } else { + seconds = String.valueOf(longSeconds); + } - // Hide status if countdown is active. - contentTMinusStatus.setVisibility(View.GONE); - } - }.start(); - } else { - showStatusDescription(launch); - } + + // Update the views + if (Integer.valueOf(days) > 0) { + countdownDays.setText(days); } else { - showStatusDescription(launch); + countdownDays.setText("00"); + } + + if (Integer.valueOf(hours) > 0) { + countdownHours.setText(hours); + } else if (Integer.valueOf(days) > 0) { + countdownHours.setText("00"); + } else { + countdownHours.setText("00"); + } + + if (Integer.valueOf(minutes) > 0) { + countdownMinutes.setText(minutes); + } else if (Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { + countdownMinutes.setText("00"); + } else { + countdownMinutes.setText("00"); + } + + if (Integer.valueOf(seconds) > 0) { + countdownSeconds.setText(seconds); + } else if (Integer.valueOf(minutes) > 0 || Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { + countdownSeconds.setText("00"); + } else { + countdownSeconds.setText("00"); } } + private void showStatusDescription(Launch launchItem) { contentTMinusStatus.setVisibility(View.VISIBLE); - contentTMinusStatus.setTypeface(Typeface.DEFAULT); - if (sharedPreference.isNightModeActive(context)) { - contentTMinusStatus.setTextColor(ContextCompat.getColor(context, R.color.dark_theme_secondary_text_color)); - } else { - contentTMinusStatus.setTextColor(ContextCompat.getColor(context, R.color.colorTextSecondary)); - } - if (launchItem.getStatus() == 2) { - countdownLayout.setVisibility(View.GONE); - if (launchItem.getLsp() != null) { - contentTMinusStatus.setText(String.format(context.getString(R.string.pending_confirmed_go_specific), launchItem.getLsp().getName())); + if (launchItem.getStatus().getId() == 2) { + if (launchItem.getRocket().getConfiguration().getLaunchServiceProvider() != null) { + contentTMinusStatus.setText(String.format(context.getString(R.string.pending_confirmed_go_specific), launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getName())); } else { contentTMinusStatus.setText(R.string.pending_confirmed_go); } - } else if (launchItem.getStatus() == 3) { - countdownLayout.setVisibility(View.GONE); + } else if (launchItem.getStatus().getId() == 3) { contentTMinusStatus.setText("Launch was a success!"); - } else if (launchItem.getStatus() == 4) { + } else if (launchItem.getStatus().getId() == 4) { countdownLayout.setVisibility(View.GONE); - contentTMinusStatus.setText("A launch failure has occurred."); - } else if (launchItem.getStatus() == 5) { - contentTMinusStatus.setText("A hold has been placed on the launch."); - } else if (launchItem.getStatus() == 6) { - countdownDays.setText("00"); - countdownHours.setText("00"); - countdownMinutes.setText("00"); - countdownSeconds.setText("00"); - contentTMinusStatus.setText("The launch is currently in flight."); - } else if (launchItem.getStatus() == 7) { + + if (launchItem.getFailreason() != null){ + contentTMinusStatus.setText(launchItem.getFailreason()); + } else { + contentTMinusStatus.setText("A launch failure has occurred."); + } + } else if (launchItem.getStatus().getId() == 5) { + if (launchItem.getHoldreason() != null){ + contentTMinusStatus.setText(launchItem.getHoldreason()); + } else { + contentTMinusStatus.setText("A hold has been placed on the launch."); + } + } else if (launchItem.getStatus().getId() == 6) { + contentTMinusStatus.setText("Launch is in flight."); + } else if (launchItem.getStatus().getId() == 7) { countdownLayout.setVisibility(View.GONE); - contentTMinusStatus.setText("Launch was a partial failure, payload separated into an incorrect orbit."); + if (launchItem.getFailreason() != null){ + contentTMinusStatus.setText(launchItem.getFailreason()); + } else { + contentTMinusStatus.setText("A partial launch failure has occurred."); + } } } @@ -1104,27 +1136,10 @@ public static SummaryDetailFragment newInstance() { return new SummaryDetailFragment(); } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(LaunchEvent event) { - setLaunch(event.launch); - } - - @Override - public void onStart() { - super.onStart(); - EventBus.getDefault().register(this); - } - - @Override - public void onStop() { - EventBus.getDefault().unregister(this); - super.onStop(); - } - @OnClick(R.id.map_view_summary) public void onViewClicked() { - if (detailLaunch != null && detailLaunch.isValid() && detailLaunch.getLocation() != null) { - String location = detailLaunch.getLocation().getName(); + if (detailLaunch != null && detailLaunch.isValid() && detailLaunch.getPad().getLocation() != null) { + String location = detailLaunch.getPad().getLocation().getName(); location = (location.substring(location.indexOf(",") + 1)); Timber.d("FAB: %s ", location); @@ -1160,4 +1175,21 @@ public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInit youTubeView.setVisibility(View.GONE); } } + + @Override + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } + } + + @Override + public void onDetach() { + super.onDetach(); + mListener = null; + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/MissionDetailFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/MissionDetailFragment.java similarity index 72% rename from mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/MissionDetailFragment.java rename to mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/MissionDetailFragment.java index e4d27316f..10e4451ad 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/MissionDetailFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/MissionDetailFragment.java @@ -1,4 +1,4 @@ -package me.calebjones.spacelaunchnow.ui.launchdetail.fragments; +package me.calebjones.spacelaunchnow.ui.launchdetail.fragments.mission; import android.annotation.SuppressLint; import android.app.Activity; @@ -6,41 +6,51 @@ import android.content.Intent; import android.os.Bundle; import android.support.annotation.Nullable; +import android.support.constraint.Group; import android.support.v7.widget.AppCompatButton; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.ImageView; import android.widget.TextView; import com.crashlytics.android.Crashlytics; +import net.cachapa.expandablelayout.ExpandableLayout; + import org.greenrobot.eventbus.EventBus; import org.greenrobot.eventbus.Subscribe; import org.greenrobot.eventbus.ThreadMode; import butterknife.BindView; import butterknife.ButterKnife; +import butterknife.OnClick; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.RetroFitFragment; import me.calebjones.spacelaunchnow.content.events.LaunchEvent; import me.calebjones.spacelaunchnow.data.models.main.Launch; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.data.models.main.Mission; +import me.calebjones.spacelaunchnow.ui.launchdetail.OnFragmentInteractionListener; import me.calebjones.spacelaunchnow.ui.launches.launcher.LauncherLaunchActivity; -import me.calebjones.spacelaunchnow.utils.analytics.Analytics; import me.calebjones.spacelaunchnow.utils.Utils; +import me.calebjones.spacelaunchnow.utils.analytics.Analytics; import timber.log.Timber; public class MissionDetailFragment extends RetroFitFragment { - private Context context; - public Launch detailLaunch; + @BindView(R.id.coreRecyclerView) + RecyclerView coreRecyclerView; @BindView(R.id.vehicle_spec_view) - View vehicleSpecView; + Group vehicleSpecView; @BindView(R.id.payload_type) TextView payloadType; @BindView(R.id.payload_description) TextView payloadDescription; + @BindView(R.id.orbit) + TextView orbit; @BindView(R.id.payload_status) TextView payloadStatus; @BindView(R.id.payload_infoButton) @@ -76,6 +86,10 @@ public class MissionDetailFragment extends RetroFitFragment { @BindView(R.id.launcher_launches) AppCompatButton launchesButton; + private OnFragmentInteractionListener mListener; + private Context context; + public Launch detailLaunch; + @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -100,6 +114,8 @@ public View onCreateView(LayoutInflater inflater, final ViewGroup container, Bun public void onResume() { if (detailLaunch != null && detailLaunch.isValid()) { setUpViews(detailLaunch); + } else { + mListener.sendLaunchToFragment(OnFragmentInteractionListener.MISSION); } super.onResume(); } @@ -119,6 +135,12 @@ private void setUpViews(Launch launch) { payloadStatus.setText(mission.getName()); payloadDescription.setText(mission.getDescription()); payloadType.setText(mission.getTypeName()); + if (mission.getOrbit() != null && mission.getOrbitAbbrev() != null) { + orbit.setVisibility(View.VISIBLE); + orbit.setText(String.format("%s (%s)", mission.getOrbit(), mission.getOrbitAbbrev())); + } else { + orbit.setVisibility(View.GONE); + } payloadInfoButton.setVisibility(View.GONE); payloadWikiButton.setVisibility(View.GONE); } else { @@ -128,38 +150,50 @@ private void setUpViews(Launch launch) { payloadWikiButton.setVisibility(View.GONE); } - launchVehicleView.setText(detailLaunch.getLauncher().getFullName()); - launchConfiguration.setText(detailLaunch.getLauncher().getVariant()); - launchFamily.setText(detailLaunch.getLauncher().getFamily()); - if (detailLaunch.getLauncher().getInfoUrl() != null && detailLaunch.getLauncher().getInfoUrl().length() > 0){ + launchVehicleView.setText(detailLaunch.getRocket().getConfiguration().getFullName()); + launchConfiguration.setText(detailLaunch.getRocket().getConfiguration().getVariant()); + launchFamily.setText(detailLaunch.getRocket().getConfiguration().getFamily()); + if (detailLaunch.getRocket().getConfiguration().getInfoUrl() != null && detailLaunch.getRocket().getConfiguration().getInfoUrl().length() > 0) { vehicleInfoButton.setOnClickListener(view -> { Activity activity = (Activity) context; - Utils.openCustomTab(activity, context, detailLaunch.getLauncher().getInfoUrl()); + Utils.openCustomTab(activity, context, detailLaunch.getRocket().getConfiguration().getInfoUrl()); Analytics.getInstance().sendButtonClickedWithURL("Vehicle Info", - detailLaunch.getLauncher().getInfoUrl()); + detailLaunch.getRocket().getConfiguration().getInfoUrl()); }); } else { vehicleInfoButton.setVisibility(View.GONE); } - if (detailLaunch.getLauncher().getWikiUrl() != null && detailLaunch.getLauncher().getWikiUrl().length() > 0){ + if (detailLaunch.getRocket().getConfiguration().getWikiUrl() != null && detailLaunch.getRocket().getConfiguration().getWikiUrl().length() > 0) { vehicleWikiButton.setOnClickListener(view -> { Activity activity = (Activity) context; - Utils.openCustomTab(activity, context, detailLaunch.getLauncher().getWikiUrl()); + Utils.openCustomTab(activity, context, detailLaunch.getRocket().getConfiguration().getWikiUrl()); Analytics.getInstance().sendButtonClickedWithURL("Vehicle Wiki", - detailLaunch.getLauncher().getWikiUrl()); + detailLaunch.getRocket().getConfiguration().getWikiUrl()); }); } else { vehicleWikiButton.setVisibility(View.GONE); } - configureLaunchVehicle(launch.getLauncher()); + configureLaunchVehicle(launch.getRocket().getConfiguration()); + + if (launch.getRocket().getFirstStage() != null && launch.getRocket().getFirstStage().size() > 0){ + coreRecyclerView.setVisibility(View.VISIBLE); + LinearLayoutManager layoutManager = new LinearLayoutManager(context); + coreRecyclerView.setLayoutManager(layoutManager); + StageInformationAdapter stageInformationAdapter = new StageInformationAdapter(launch.getRocket().getFirstStage(), context); + coreRecyclerView.setAdapter(stageInformationAdapter); + coreRecyclerView.setHasFixedSize(true); + } else { + coreRecyclerView.setVisibility(View.GONE); + } + + } catch (NullPointerException e) { Timber.e(e); } } - @SuppressLint("StringFormatMatches") - private void configureLaunchVehicle(Launcher launchVehicle) { + private void configureLaunchVehicle(LauncherConfig launchVehicle) { if (launchVehicle != null) { vehicleSpecView.setVisibility(View.VISIBLE); try { @@ -230,20 +264,21 @@ public static MissionDetailFragment newInstance() { return new MissionDetailFragment(); } - @Subscribe(threadMode = ThreadMode.MAIN) - public void onMessageEvent(LaunchEvent event) { - setLaunch(event.launch); - } - @Override - public void onStart() { - super.onStart(); - EventBus.getDefault().register(this); + public void onAttach(Context context) { + super.onAttach(context); + if (context instanceof OnFragmentInteractionListener) { + mListener = (OnFragmentInteractionListener) context; + } else { + throw new RuntimeException(context.toString() + + " must implement OnFragmentInteractionListener"); + } } @Override - public void onStop() { - EventBus.getDefault().unregister(this); - super.onStop(); + public void onDetach() { + super.onDetach(); + mListener = null; } + } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/StageInformationAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/StageInformationAdapter.java new file mode 100644 index 000000000..9f5670fcf --- /dev/null +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launchdetail/fragments/mission/StageInformationAdapter.java @@ -0,0 +1,233 @@ +package me.calebjones.spacelaunchnow.ui.launchdetail.fragments.mission; + +import android.content.Context; +import android.content.Intent; +import android.support.constraint.Group; +import android.support.v7.widget.AppCompatButton; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.Button; +import android.widget.ImageView; +import android.widget.TextView; + +import com.afollestad.materialdialogs.MaterialDialog; + +import java.util.List; + +import at.blogc.android.views.ExpandableTextView; +import butterknife.BindView; +import butterknife.ButterKnife; +import me.calebjones.spacelaunchnow.R; +import me.calebjones.spacelaunchnow.data.models.main.Landing; +import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.Stage; +import me.calebjones.spacelaunchnow.ui.launches.launcher.LauncherLaunchActivity; +import timber.log.Timber; + +/** + * This adapter takes data from ListPreferences/LoaderService and applies it to RecyclerView + */ +public class StageInformationAdapter extends RecyclerView.Adapter { + public int position; + private List launcherList; + private Context context; + + public StageInformationAdapter(List launchers, Context context) { + launcherList = launchers; + this.context = context; + notifyDataSetChanged(); + } + + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + Timber.v("onCreate ViewHolder."); + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.core_information, viewGroup, false); + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(final ViewHolder holder, int position) { + Stage stage = launcherList.get(position); + if (stage.getLauncher() != null) { + Launcher launcher = stage.getLauncher(); + holder.viewCoreLaunches.setVisibility(View.VISIBLE); + holder.viewCoreLaunches.setText(String.format("View %s Launches", stage.getLauncher().getSerialNumber())); + holder.viewCoreLaunches.setOnClickListener(v -> { + Intent launches = new Intent(context, LauncherLaunchActivity.class); + launches.putExtra("serialNumber", launcher.getSerialNumber()); + context.startActivity(launches); + }); + holder.coreInformation.setText(String.format("%s Information", launcher.getSerialNumber())); + if (stage.getType() != null) { + holder.coreInformationSubtitle.setText(String.format("First Stage - %s", stage.getType())); + } + holder.details.setText(launcher.getDetails()); + holder.serialNumberText.setText(stage.getLauncher().getSerialNumber()); + String cap = launcher.getStatus().substring(0, 1).toUpperCase() + stage.getLauncher().getStatus().substring(1); + holder.statusText.setText(cap); + holder.previousText.setText(""); + if (launcher.getFlightProven() == null) { + holder.flightProven.setImageResource(R.drawable.ic_question_mark); + } else if (launcher.getFlightProven()) { + holder.flightProven.setImageResource(R.drawable.ic_checkmark); + } else if (!launcher.getFlightProven()) { + holder.flightProven.setImageResource(R.drawable.ic_failed); + } + holder.previousText.setText(String.format("%d", stage.getLauncher().getPreviousFlights())); + } else { + holder.viewCoreLaunches.setVisibility(View.GONE); + } + + holder.landingGroup.setVisibility(View.GONE); + holder.landingLocationGroup.setVisibility(View.GONE); + holder.landingTypeGroup.setVisibility(View.GONE); + holder.landingMore.setVisibility(View.GONE); + + if (stage.getLanding() != null) { + holder.landingGroup.setVisibility(View.VISIBLE); + Landing landing = stage.getLanding(); + + if (landing.getAttempt() == null) { + holder.flightProven.setImageResource(R.drawable.ic_question_mark); + } else if (landing.getAttempt()) { + holder.flightProven.setImageResource(R.drawable.ic_checkmark); + } else if (!landing.getAttempt()) { + holder.flightProven.setImageResource(R.drawable.ic_failed); + } + + if (landing.getSuccess() == null) { + holder.flightProven.setImageResource(R.drawable.ic_question_mark); + } else if (landing.getSuccess()) { + holder.flightProven.setImageResource(R.drawable.ic_checkmark); + } else if (!landing.getSuccess()) { + holder.flightProven.setImageResource(R.drawable.ic_failed); + } + + if (landing.getDescription().length() != 0) { + holder.landingDescription.setText(landing.getDescription()); + holder.landingDescription.setOnClickListener(v -> { + if (!holder.landingDescription.isExpanded()) { + holder.landingDescription.expand(); + } + }); + } else { + holder.landingDescription.setVisibility(View.GONE); + } + + if (landing.getLandingType() != null && landing.getLandingType().getName() != null) { + holder.landingType.setText(landing.getLandingType().getName()); + holder.landingLocationGroup.setVisibility(View.VISIBLE); + } + + if (landing.getLandingLocation() != null && landing.getLandingLocation().getName() != null) { + holder.landingLocation.setText(landing.getLandingLocation().getName()); + holder.landingTypeGroup.setVisibility(View.VISIBLE); + } + + if (landing.getLandingLocation() != null + && landing.getLandingLocation().getName() != null + && landing.getLandingLocation().getDescription() != null + && landing.getLandingType() != null + && landing.getLandingType().getName() != null + && landing.getLandingType().getDescription() != null) { + holder.landingMore.setVisibility(View.VISIBLE); + holder.landingMore.setOnClickListener((View v) -> { + MaterialDialog dialog = new MaterialDialog.Builder(context) + .title("Additional Landing Information") + .customView(R.layout.landing_information, true) + .positiveText("Close") + .show(); + View view = dialog.getCustomView(); + + TextView landingType = view.findViewById(R.id.landing_type); + TextView landingTypeDescription = view.findViewById(R.id.landing_type_description); + TextView landingLocation = view.findViewById(R.id.landing_location); + TextView landingLocationDescription = view.findViewById(R.id.landing_location_description); + + landingType.setText(landing.getLandingType().getName()); + landingTypeDescription.setText(landing.getLandingType().getDescription()); + landingLocation.setText(landing.getLandingLocation().getName()); + landingLocationDescription.setText(landing.getLandingLocation().getDescription()); + }); + } else { + holder.landingMore.setVisibility(View.GONE); + } + + } else { + holder.landingGroup.setVisibility(View.GONE); + holder.landingLocationGroup.setVisibility(View.GONE); + holder.landingTypeGroup.setVisibility(View.GONE); + holder.landingMore.setVisibility(View.GONE); + } + } + + + @Override + public int getItemCount() { + return launcherList.size(); + } + + public class ViewHolder extends RecyclerView.ViewHolder { + + @BindView(R.id.core_information) + TextView coreInformation; + @BindView(R.id.core_information_subtitle) + TextView coreInformationSubtitle; + @BindView(R.id.serial_number_title) + TextView serialNumberTitle; + @BindView(R.id.serial_number_text) + TextView serialNumberText; + @BindView(R.id.status_title) + TextView statusTitle; + @BindView(R.id.status_text) + TextView statusText; + @BindView(R.id.previous_title) + TextView previousTitle; + @BindView(R.id.previous_text) + TextView previousText; + @BindView(R.id.flight_proven) + ImageView flightProven; + @BindView(R.id.flight_proven_title) + TextView flightProvenTitle; + @BindView(R.id.landing_attempt_title) + TextView landingAttemptTitle; + @BindView(R.id.attempt_icon) + ImageView attemptIcon; + @BindView(R.id.landing_success_title) + TextView landingSuccessTitle; + @BindView(R.id.success_icon) + ImageView successIcon; + @BindView(R.id.landing_description) + ExpandableTextView landingDescription; + @BindView(R.id.landing_type) + TextView landingType; + @BindView(R.id.landing_type_title) + TextView landingTypeTitle; + @BindView(R.id.landing_location) + TextView landingLocation; + @BindView(R.id.landing_location_title) + TextView landingLocationTitle; + @BindView(R.id.landing_more) + Button landingMore; + @BindView(R.id.view_core_launches) + Button viewCoreLaunches; + @BindView(R.id.landing_group) + Group landingGroup; + @BindView(R.id.landing_group_landingtype) + Group landingLocationGroup; + @BindView(R.id.landing_group_landinglocation) + Group landingTypeGroup; + @BindView(R.id.details) + TextView details; + + + //Add content to the card + public ViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); + } + } +} diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/LauncherDetailActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/LauncherDetailActivity.java index e9ad31ff9..814150de7 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/LauncherDetailActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/LauncherDetailActivity.java @@ -30,24 +30,16 @@ import de.hdodenhof.circleimageview.CircleImageView; import io.realm.RealmResults; -import jonathanfinerty.once.Once; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.BaseActivity; -import me.calebjones.spacelaunchnow.content.data.DataSaver; import me.calebjones.spacelaunchnow.content.database.ListPreferences; import me.calebjones.spacelaunchnow.data.models.main.Agency; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; -import me.calebjones.spacelaunchnow.data.networking.DataClient; -import me.calebjones.spacelaunchnow.data.networking.responses.base.VehicleResponse; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.ui.main.MainActivity; import me.calebjones.spacelaunchnow.ui.settings.SettingsActivity; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.Utils; import me.calebjones.spacelaunchnow.utils.views.CustomOnOffsetChangedListener; -import me.calebjones.spacelaunchnow.utils.views.SnackbarHandler; -import retrofit2.Call; -import retrofit2.Callback; -import retrofit2.Response; import timber.log.Timber; public class LauncherDetailActivity extends BaseActivity implements AppBarLayout.OnOffsetChangedListener { @@ -60,7 +52,7 @@ public class LauncherDetailActivity extends BaseActivity implements AppBarLayout private ImageView detail_profile_backdrop; private CircleImageView detail_profile_image; private VehicleDetailAdapter adapter; - private RealmResults rocketLaunches; + private RealmResults rocketLaunches; private AppBarLayout appBarLayout; private CollapsingToolbarLayout collapsingToolbar; private int mMaxScrollSize; @@ -155,9 +147,9 @@ public void displayRockets() { detail_rocket.setText(name); detail_vehicle_agency.setText(agencyName); - if (agency.getLaunchers() != null) { + if (agency.getLauncherConfigs() != null) { adapter.clear(); - adapter.addItems(agency.getLaunchers()); + adapter.addItems(agency.getLauncherConfigs()); } applyProfileBackdrop(agency.getImageUrl()); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/VehicleDetailAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/VehicleDetailAdapter.java index d30d96397..10c0615e1 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/VehicleDetailAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launcher/VehicleDetailAdapter.java @@ -5,7 +5,11 @@ import android.content.Context; import android.content.Intent; import android.os.Build; +import android.support.constraint.ConstraintLayout; +import android.support.constraint.Group; +import android.support.design.widget.CoordinatorLayout; import android.support.v7.widget.AppCompatButton; +import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -18,9 +22,11 @@ import java.util.ArrayList; import java.util.List; +import butterknife.BindView; +import butterknife.ButterKnife; import io.realm.RealmList; import me.calebjones.spacelaunchnow.R; -import me.calebjones.spacelaunchnow.data.models.main.Launcher; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.ui.imageviewer.FullscreenImageActivity; import me.calebjones.spacelaunchnow.ui.launches.launcher.LauncherLaunchActivity; import me.calebjones.spacelaunchnow.utils.GlideApp; @@ -31,7 +37,7 @@ public class VehicleDetailAdapter extends RecyclerView.Adapter items; + private List items; private RequestOptions requestOptions; private int backgroundColor = 0; @@ -44,7 +50,7 @@ public VehicleDetailAdapter(Context context, Activity activity) { this.activity = activity; } - public void addItems(List items) { + public void addItems(List items) { if (this.items != null) { this.items.addAll(items); } else { @@ -68,9 +74,11 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { @Override public void onBindViewHolder(final ViewHolder holder, int i) { - Launcher launchVehicle = items.get(holder.getAdapterPosition()); + LauncherConfig launchVehicle = items.get(holder.getAdapterPosition()); if (launchVehicle != null) { + + holder.launchesButton.setText(String.format(mContext.getString(R.string.view_rocket_launches), launchVehicle.getFullName())); holder.vehicleSpecView.setVisibility(View.VISIBLE); if (launchVehicle.getDescription() != null && launchVehicle.getDescription().length() > 0) { holder.vehicleDescription.setVisibility(View.VISIBLE); @@ -118,12 +126,13 @@ public void onBindViewHolder(final ViewHolder holder, int i) { if (launchVehicle.getToThrust() != null) { holder.vehicleSpecsThrust.setText(String.format(mContext.getString(R.string.thrust_full), launchVehicle.getToThrust())); } else { - holder.vehicleSpecsHeight.setText(mContext.getString(R.string.height)); + holder.vehicleSpecsThrust.setText(mContext.getString(R.string.height)); } if (backgroundColor != 0) { - holder.titleContainer.setBackgroundColor(backgroundColor); + holder.vehicleName.setBackgroundColor(backgroundColor); + holder.vehicleFamily.setBackgroundColor(backgroundColor); } if (launchVehicle.getImageUrl() != null && launchVehicle.getImageUrl().length() > 0) { holder.vehicleImage.setVisibility(View.VISIBLE); @@ -154,12 +163,6 @@ public void onBindViewHolder(final ViewHolder holder, int i) { } else { holder.wikiButton.setVisibility(View.GONE); } - - if (holder.infoButton.getVisibility() == View.GONE && holder.wikiButton.getVisibility() == View.GONE) { - holder.button_layout.setVisibility(View.GONE); - } else { - holder.button_layout.setVisibility(View.VISIBLE); - } } } @@ -171,53 +174,51 @@ public int getItemCount() { public void updateColor(int color) { - backgroundColor = color; + backgroundColor = color; - backgroundColor = color; + backgroundColor = color; } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - public ImageView vehicleImage; - public View vehicleSpecView, vehicleContainer, button_layout; - public TextView vehicleName; - public TextView vehicleFamily; - public TextView vehicleSpecsHeight; - public TextView vehicleSpecsDiameter; - public TextView vehicleSpecsStages; - public TextView vehicleSpecsLeo; - public TextView vehicleSpecsGto; - public TextView vehicleSpecsLaunchMass; - public TextView vehicleSpecsThrust; - public View titleContainer; - public AppCompatButton infoButton; - public AppCompatButton wikiButton; - public TextView vehicleDescription; - public AppCompatButton launchesButton; + + @BindView(R.id.imageView) + ImageView vehicleImage; + @BindView(R.id.launch_vehicle_title) + TextView vehicleName; + @BindView(R.id.launch_vehicle) + TextView vehicleFamily; + @BindView(R.id.launch_vehicle_description) + TextView vehicleDescription; + + @BindView(R.id.launch_vehicle_specs_height) + TextView vehicleSpecsHeight; + @BindView(R.id.launch_vehicle_specs_diameter) + TextView vehicleSpecsDiameter; + @BindView(R.id.launch_vehicle_specs_stages) + TextView vehicleSpecsStages; + @BindView(R.id.launch_vehicle_specs_leo) + TextView vehicleSpecsLeo; + @BindView(R.id.launch_vehicle_specs_gto) + TextView vehicleSpecsGto; + @BindView(R.id.launch_vehicle_specs_launch_mass) + TextView vehicleSpecsLaunchMass; + @BindView(R.id.launch_vehicle_specs_thrust) + TextView vehicleSpecsThrust; + @BindView(R.id.vehicle_infoButton) + AppCompatButton infoButton; + @BindView(R.id.vehicle_wikiButton) + AppCompatButton wikiButton; + @BindView(R.id.vehicle_spec_view) + Group vehicleSpecView; + @BindView(R.id.launcher_launches) + AppCompatButton launchesButton; //Add content to the card public ViewHolder(View view) { super(view); - + ButterKnife.bind(this, view); view.setOnClickListener(this); - vehicleContainer = view.findViewById(R.id.vehicle_container); - vehicleSpecView = view.findViewById(R.id.vehicle_spec_view); - vehicleImage = view.findViewById(R.id.item_icon); - vehicleName = view.findViewById(R.id.item_title); - vehicleFamily = view.findViewById(R.id.text_subtitle); - vehicleSpecsStages = view.findViewById(R.id.launch_vehicle_specs_stages); - vehicleSpecsHeight = view.findViewById(R.id.launch_vehicle_specs_height); - vehicleSpecsDiameter = view.findViewById(R.id.launch_vehicle_specs_diameter); - vehicleSpecsLeo = view.findViewById(R.id.launch_vehicle_specs_leo); - vehicleSpecsGto = view.findViewById(R.id.launch_vehicle_specs_gto); - vehicleSpecsLaunchMass = view.findViewById(R.id.launch_vehicle_specs_launch_mass); - vehicleSpecsThrust = view.findViewById(R.id.launch_vehicle_specs_thrust); - vehicleDescription = view.findViewById(R.id.launch_vehicle_description); - button_layout = view.findViewById(R.id.button_layout); - titleContainer = view.findViewById(R.id.text_container); - infoButton = view.findViewById(R.id.infoButton); - wikiButton = view.findViewById(R.id.wikiButton); - launchesButton = view.findViewById(R.id.launcher_launches); launchesButton.setOnClickListener(this); infoButton.setOnClickListener(this); @@ -236,7 +237,7 @@ public void onClick(View v) { case R.id.wikiButton: Utils.openCustomTab(activity, mContext, items.get(position).getWikiUrl()); break; - case R.id.item_icon: + case R.id.imageView: Intent animateIntent = new Intent(activity, FullscreenImageActivity.class); animateIntent.putExtra("imageURL", items.get(position).getImageUrl()); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/AgencyLaunchActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/AgencyLaunchActivity.java index 42dad21f2..befb91973 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/AgencyLaunchActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/AgencyLaunchActivity.java @@ -14,13 +14,13 @@ import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; import android.view.ViewGroup; import com.afollestad.materialdialogs.MaterialDialog; - import java.util.ArrayList; import java.util.List; @@ -33,18 +33,20 @@ import me.calebjones.spacelaunchnow.data.networking.responses.base.AgencyResponse; import me.calebjones.spacelaunchnow.ui.settings.SettingsActivity; import me.calebjones.spacelaunchnow.ui.supporter.SupporterActivity; +import me.calebjones.spacelaunchnow.utils.views.BadgeTabLayout; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; import timber.log.Timber; -public class AgencyLaunchActivity extends AppCompatActivity implements UpcomingAgencyLaunchesFragment.OnFragmentInteractionListener, PreviousAgencyLaunchesFragment.OnFragmentInteractionListener, SwipeRefreshLayout.OnRefreshListener { +public class AgencyLaunchActivity extends AppCompatActivity implements UpcomingAgencyLaunchesFragment.OnFragmentInteractionListener, + PreviousAgencyLaunchesFragment.OnFragmentInteractionListener, SwipeRefreshLayout.OnRefreshListener { @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.tabs) - TabLayout tabLayout; + BadgeTabLayout tabLayout; @BindView(R.id.appbar) AppBarLayout appbar; @BindView(R.id.container) @@ -88,10 +90,8 @@ protected void onCreate(Bundle savedInstanceState) { // Set up the ViewPager with the sections adapter. viewPager.setAdapter(mSectionsPagerAdapter); + tabLayout.setupWithViewPager(viewPager); swipeRefresh.setOnRefreshListener(this); - - viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); - tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(viewPager)); getFeaturedAgencies(); } @@ -124,6 +124,20 @@ public void onFailure(Call call, Throwable t) { }); } + @Override + public void setUpcomingBadge(int count) { + if (tabLayout != null && count > 0) { + tabLayout.with(0).badge(true).badgeCount(count).name("UPCOMING").build(); + } + } + + @Override + public void setPreviousBadge(int count) { + if (tabLayout != null && count > 0) { + tabLayout.with(1).badge(true).badgeCount(count).name("PREVIOUS").build(); + } + } + private void showAgencyDialog() { new MaterialDialog.Builder(this) .title(R.string.select_launch_agency) @@ -271,6 +285,17 @@ public Object instantiateItem(ViewGroup container, int position) { return createdFragment; } + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return getApplicationContext().getString(R.string.upcoming); + case 1: + return getApplicationContext().getString(R.string.previous); + } + return null; + } + @Override public int getCount() { return 2; diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/PreviousAgencyLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/PreviousAgencyLaunchesFragment.java index d6cb54dd2..8e0cdb61a 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/PreviousAgencyLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/PreviousAgencyLaunchesFragment.java @@ -22,6 +22,7 @@ import me.calebjones.spacelaunchnow.content.data.callbacks.Callbacks; import me.calebjones.spacelaunchnow.content.data.previous.PreviousDataRepository; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.main.launches.ListAdapter; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; import timber.log.Timber; @@ -104,6 +105,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, recyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); recyclerView.setAdapter(adapter); statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { @@ -112,6 +114,7 @@ public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { if (canLoadMore) { fetchData(false); mListener.showPreviousLoading(true); + } } }; @@ -144,13 +147,15 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, lspName, null, new Callbacks.ListCallback() { + + previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, lspName, null, null, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; canLoadMore = next > 0; updateAdapter(launches); + mListener.setPreviousBadge(total); } @Override @@ -161,6 +166,8 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; if (throwable != null) { Timber.e(throwable); } else { @@ -170,7 +177,7 @@ public void onError(String message, @Nullable Throwable throwable) { }); } - private void updateAdapter(List launches) { + private void updateAdapter(List launches) { if (launches.size() > 0) { if (!statefulStateContentShow) { @@ -210,5 +217,7 @@ public interface OnFragmentInteractionListener { void showPreviousLoading(boolean loading); + void setPreviousBadge(int count); + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/UpcomingAgencyLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/UpcomingAgencyLaunchesFragment.java index f2d4906e0..622403e9a 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/UpcomingAgencyLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/agency/UpcomingAgencyLaunchesFragment.java @@ -24,6 +24,7 @@ import me.calebjones.spacelaunchnow.content.data.upcoming.UpcomingDataRepository; import me.calebjones.spacelaunchnow.data.models.main.Agency; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.main.launches.ListAdapter; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; import timber.log.Timber; @@ -101,6 +102,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, recyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); recyclerView.setAdapter(adapter); statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { @@ -142,13 +144,14 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, lspName, null, new Callbacks.ListCallback() { + upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, lspName, null, null, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; canLoadMore = next > 0; updateAdapter(launches); + mListener.setUpcomingBadge(total); } @Override @@ -158,6 +161,8 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; if (throwable != null) { Timber.e(throwable); } else { @@ -167,7 +172,7 @@ public void onError(String message, @Nullable Throwable throwable) { }); } - private void updateAdapter(List launches) { + private void updateAdapter(List launches) { if (launches.size() > 0) { if (!statefulStateContentShow) { @@ -207,5 +212,7 @@ public interface OnFragmentInteractionListener { void showUpcomingLoading(boolean loading); + void setUpcomingBadge(int count); + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/LauncherLaunchActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/LauncherLaunchActivity.java index 92ff13ef6..706ec77ed 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/LauncherLaunchActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/LauncherLaunchActivity.java @@ -14,6 +14,7 @@ import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.app.AppCompatActivity; import android.support.v7.widget.Toolbar; +import android.text.TextUtils; import android.view.Menu; import android.view.MenuItem; import android.view.View; @@ -27,6 +28,7 @@ import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; +import cn.nekocode.badge.BadgeDrawable; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.data.models.main.Agency; import me.calebjones.spacelaunchnow.data.networking.DataClient; @@ -35,6 +37,7 @@ import me.calebjones.spacelaunchnow.ui.launches.agency.UpcomingAgencyLaunchesFragment; import me.calebjones.spacelaunchnow.ui.settings.SettingsActivity; import me.calebjones.spacelaunchnow.ui.supporter.SupporterActivity; +import me.calebjones.spacelaunchnow.utils.views.BadgeTabLayout; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -46,7 +49,7 @@ public class LauncherLaunchActivity extends AppCompatActivity implements Upcomin @BindView(R.id.toolbar) Toolbar toolbar; @BindView(R.id.tabs) - TabLayout tabLayout; + BadgeTabLayout tabLayout; @BindView(R.id.appbar) AppBarLayout appbar; @BindView(R.id.container) @@ -68,7 +71,9 @@ public class LauncherLaunchActivity extends AppCompatActivity implements Upcomin private String searchTerm = null; private String lspName = null; private String launcherName = null; + private String serialNumber = null; private Integer launcherId = null; + private int color; @Override @@ -76,12 +81,13 @@ protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_agency_launch); ButterKnife.bind(this); - + color = ContextCompat.getColor(this, R.color.accent); Bundle extras = getIntent().getExtras(); if (extras != null) { lspName = extras.getString("lspName"); launcherName = extras.getString("launcherName"); launcherId = extras.getInt("launcherId"); + serialNumber = extras.getString("serialNumber"); } setTitle(); @@ -94,6 +100,7 @@ protected void onCreate(Bundle savedInstanceState) { // Set up the ViewPager with the sections adapter. viewPager.setAdapter(mSectionsPagerAdapter); + tabLayout.setupWithViewPager(viewPager); swipeRefresh.setOnRefreshListener(this); viewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout)); @@ -159,15 +166,16 @@ public void showPreviousLoading(boolean loading) { public void onRefresh() { lspName = null; searchTerm = null; + serialNumber = null; refresh(); } private void refresh() { if (upcomingFragment != null) { - upcomingFragment.onRefresh(lspName, searchTerm); + upcomingFragment.onRefresh(lspName, searchTerm, serialNumber); } if (previousFragment != null) { - previousFragment.onRefresh(lspName, searchTerm); + previousFragment.onRefresh(lspName, searchTerm, serialNumber); } setTitle(); } @@ -175,6 +183,8 @@ private void refresh() { private void setTitle() { if (launcherName != null) { toolbar.setTitle(launcherName); + } else if (serialNumber != null) { + toolbar.setTitle(serialNumber); } else { toolbar.setTitle("Launches"); } @@ -198,6 +208,38 @@ private void hideLoading() { swipeRefresh.post(() -> swipeRefresh.setRefreshing(false)); } + @Override + public void setUpcomingBadge(int count) { + if (tabLayout != null && count > 0) { + final BadgeDrawable drawable = + new BadgeDrawable.Builder() + .type(BadgeDrawable.TYPE_NUMBER) + .badgeColor(color) + .number(count) + .padding(8, 8, 8, 8, 8) + .strokeWidth(16) + .build(); + + tabLayout.getTabAt(0).setText(TextUtils.concat(getString(R.string.upcoming_with_space), drawable.toSpannable())); + } + } + + @Override + public void setPreviousBadge(int count) { + if (tabLayout != null && count > 0) { + final BadgeDrawable drawable = + new BadgeDrawable.Builder() + .type(BadgeDrawable.TYPE_NUMBER) + .badgeColor(color) + .number(count) + .padding(8, 8, 8, 8, 8) + .strokeWidth(16) + .build(); + + tabLayout.getTabAt(1).setText(TextUtils.concat(getString(R.string.previous_with_space), drawable.toSpannable())); + } + } + public class SectionsPagerAdapter extends FragmentPagerAdapter { @@ -210,9 +252,9 @@ public Fragment getItem(int position) { switch (position) { case 0: - return UpcomingLauncherLaunchesFragment.newInstance(searchTerm, lspName, launcherId); + return UpcomingLauncherLaunchesFragment.newInstance(searchTerm, lspName, launcherId, serialNumber); case 1: - return PreviousLauncherLaunchesFragment.newInstance(searchTerm, lspName, launcherId); + return PreviousLauncherLaunchesFragment.newInstance(searchTerm, lspName, launcherId, serialNumber); default: return null; } @@ -238,6 +280,17 @@ public Object instantiateItem(ViewGroup container, int position) { return createdFragment; } + @Override + public CharSequence getPageTitle(int position) { + switch (position) { + case 0: + return getApplicationContext().getString(R.string.upcoming); + case 1: + return getApplicationContext().getString(R.string.previous); + } + return null; + } + @Override public int getCount() { return 2; diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/PreviousLauncherLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/PreviousLauncherLaunchesFragment.java index c68394d52..954a40cf4 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/PreviousLauncherLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/PreviousLauncherLaunchesFragment.java @@ -22,6 +22,7 @@ import me.calebjones.spacelaunchnow.content.data.callbacks.Callbacks; import me.calebjones.spacelaunchnow.content.data.previous.PreviousDataRepository; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.main.launches.ListAdapter; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; import timber.log.Timber; @@ -38,6 +39,7 @@ public class PreviousLauncherLaunchesFragment extends BaseFragment { private static final String SEARCH_TERM = "searchTerm"; private static final String LSP_NAME = "lspName"; + private static final String SERIAL_NUMBER = "serialNumber"; private static final String LAUNCHER_ID = "launcherId"; @BindView(R.id.recycler_view) @@ -51,6 +53,7 @@ public class PreviousLauncherLaunchesFragment extends BaseFragment { private ListAdapter adapter; private String searchTerm = null; private String lspName = null; + private String serialNumber = null; private PreviousDataRepository previousDataRepository; private int nextOffset = 0; private EndlessRecyclerViewScrollListener scrollListener; @@ -74,11 +77,12 @@ public PreviousLauncherLaunchesFragment() { * @return A new instance of fragment PreviousLauncherLaunchesFragment. */ // TODO: Rename and change types and number of parameters - public static PreviousLauncherLaunchesFragment newInstance(String searchTerm, String lspName, Integer launcherId) { + public static PreviousLauncherLaunchesFragment newInstance(String searchTerm, String lspName, Integer launcherId, String serialNumber) { PreviousLauncherLaunchesFragment fragment = new PreviousLauncherLaunchesFragment(); Bundle args = new Bundle(); args.putString(SEARCH_TERM, searchTerm); args.putString(LSP_NAME, lspName); + args.putString(SERIAL_NUMBER, serialNumber); args.putInt(LAUNCHER_ID, launcherId); fragment.setArguments(args); return fragment; @@ -91,6 +95,7 @@ public void onCreate(Bundle savedInstanceState) { searchTerm = getArguments().getString(SEARCH_TERM); lspName = getArguments().getString(LSP_NAME); launcherId = getArguments().getInt(LAUNCHER_ID); + serialNumber = getArguments().getString(SERIAL_NUMBER); } context = getActivity(); previousDataRepository = new PreviousDataRepository(context, getRealm()); @@ -108,6 +113,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, recyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); recyclerView.setAdapter(adapter); statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { @@ -148,13 +154,14 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, lspName, launcherId, new Callbacks.ListCallback() { + previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, lspName, serialNumber, launcherId, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; canLoadMore = next > 0; updateAdapter(launches); + mListener.setPreviousBadge(total); } @Override @@ -165,6 +172,8 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; if (throwable != null) { Timber.e(throwable); } else { @@ -174,7 +183,7 @@ public void onError(String message, @Nullable Throwable throwable) { }); } - private void updateAdapter(List launches) { + private void updateAdapter(List launches) { if (launches.size() > 0) { if (!statefulStateContentShow) { @@ -194,9 +203,10 @@ private void updateAdapter(List launches) { scrollListener.resetState(); } - public void onRefresh(String lspName, String searchTerm) { + public void onRefresh(String lspName, String searchTerm, String serialNumber) { this.searchTerm = searchTerm; this.lspName = lspName; + this.serialNumber = serialNumber; fetchData(true); } @@ -214,5 +224,6 @@ public interface OnFragmentInteractionListener { void showPreviousLoading(boolean loading); + void setPreviousBadge(int count); } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/UpcomingLauncherLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/UpcomingLauncherLaunchesFragment.java index 5828132b8..8d38b4fea 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/UpcomingLauncherLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/launches/launcher/UpcomingLauncherLaunchesFragment.java @@ -24,6 +24,7 @@ import me.calebjones.spacelaunchnow.content.data.upcoming.UpcomingDataRepository; import me.calebjones.spacelaunchnow.data.models.main.Agency; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.main.launches.ListAdapter; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; import timber.log.Timber; @@ -33,6 +34,7 @@ public class UpcomingLauncherLaunchesFragment extends BaseFragment { private static final String SEARCH_TERM = "searchTerm"; private static final String LSP_NAME = "lspName"; + private static final String SERIAL_NUMBER = "serialNumber"; private static final String LAUNCHER_ID = "launcherId"; @BindView(R.id.recycler_view) @@ -46,6 +48,7 @@ public class UpcomingLauncherLaunchesFragment extends BaseFragment { private ListAdapter adapter; private String searchTerm = null; private String lspName = null; + private String serialNumber = null; private UpcomingDataRepository upcomingDataRepository; private int nextOffset = 0; private EndlessRecyclerViewScrollListener scrollListener; @@ -71,11 +74,13 @@ public UpcomingLauncherLaunchesFragment() { * @return A new instance of fragment PreviousLauncherLaunchesFragment. */ // TODO: Rename and change types and number of parameters - public static UpcomingLauncherLaunchesFragment newInstance(String searchTerm, String lspName, Integer launcherId) { + public static UpcomingLauncherLaunchesFragment newInstance(String searchTerm, String lspName, + Integer launcherId, String serialNumber) { UpcomingLauncherLaunchesFragment fragment = new UpcomingLauncherLaunchesFragment(); Bundle args = new Bundle(); args.putString(SEARCH_TERM, searchTerm); args.putString(LSP_NAME, lspName); + args.putString(SERIAL_NUMBER, serialNumber); args.putInt(LAUNCHER_ID, launcherId); fragment.setArguments(args); return fragment; @@ -88,6 +93,7 @@ public void onCreate(Bundle savedInstanceState) { searchTerm = getArguments().getString(SEARCH_TERM); lspName = getArguments().getString(LSP_NAME); launcherId = getArguments().getInt(LAUNCHER_ID); + serialNumber = getArguments().getString(SERIAL_NUMBER); } context = getActivity(); upcomingDataRepository = new UpcomingDataRepository(context, getRealm()); @@ -105,6 +111,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, recyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); recyclerView.setAdapter(adapter); statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); scrollListener = new EndlessRecyclerViewScrollListener(linearLayoutManager) { @Override public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { @@ -146,13 +153,14 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, lspName, launcherId, new Callbacks.ListCallback() { + upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, lspName, serialNumber, launcherId, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; canLoadMore = next > 0; updateAdapter(launches); + mListener.setUpcomingBadge(total); } @Override @@ -162,6 +170,8 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; if (throwable != null) { Timber.e(throwable); } else { @@ -171,7 +181,7 @@ public void onError(String message, @Nullable Throwable throwable) { }); } - private void updateAdapter(List launches) { + private void updateAdapter(List launches) { if (launches.size() > 0) { if (!statefulStateContentShow) { @@ -191,9 +201,10 @@ private void updateAdapter(List launches) { scrollListener.resetState(); } - public void onRefresh(String lspName, String searchTerm) { + public void onRefresh(String lspName, String searchTerm, String serialNumber) { this.searchTerm = searchTerm; this.lspName = lspName; + this.serialNumber = serialNumber; fetchData(true); } @@ -211,5 +222,7 @@ public interface OnFragmentInteractionListener { void showUpcomingLoading(boolean loading); + void setUpcomingBadge(int count); + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/MainActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/MainActivity.java index 887b59a9a..873122512 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/MainActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/MainActivity.java @@ -221,12 +221,7 @@ protected void onCreate(Bundle savedInstanceState) { .setTriggerCount(10) .setMinimumInstallTime(TimeUnit.DAYS.toMillis(3)) .setMessage(R.string.please_rate_short) - .setFeedbackAction(new OnFeedbackListener() { - @Override - public void onFeedbackTapped() { - showFeedback(); - } - }) + .setFeedbackAction(() -> showFeedback()) .setSnackBarParent(coordinatorLayout) .build(); @@ -247,10 +242,6 @@ public void onFeedbackTapped() { .withIcon(GoogleMaterial.Icon.gmd_assignment) .withIdentifier(R.id.menu_launches) .withSelectable(true), -// new PrimaryDrawerItem().withName(R.string.missions) -// .withIcon(GoogleMaterial.Icon.gmd_satellite) -// .withIdentifier(R.id.menu_missions) -// .withSelectable(true), new PrimaryDrawerItem().withName(R.string.news) .withIcon(CommunityMaterial.Icon.cmd_newspaper) .withIdentifier(R.id.menu_news) @@ -264,37 +255,6 @@ public void onFeedbackTapped() { .withName(R.string.discord) .withIdentifier(R.id.menu_discord) .withSelectable(false), -// new DividerDrawerItem(), -// new ExpandableDrawerItem().withName(R.string.stay_connected).withIcon(CommunityMaterial.Icon.cmd_account).withDescription(R.string.connect_description).withIdentifier(19).withSelectable(false).withSubItems( -// new SecondaryDrawerItem() -// .withIcon(CommunityMaterial.Icon.cmd_discord) -// .withLevel(2) -// .withName(R.string.discord) -// .withDescription(R.string.discord_subtitle) -// .withIdentifier(R.id.menu_discord) -// .withSelectable(false), -// new SecondaryDrawerItem() -// .withIcon(CommunityMaterial.Icon.cmd_twitter) -// .withLevel(2) -// .withName(R.string.twitter) -// .withDescription(R.string.twitter_subtitle) -// .withIdentifier(R.id.menu_twitter) -// .withSelectable(false), -// new SecondaryDrawerItem() -// .withIcon(CommunityMaterial.Icon.cmd_facebook) -// .withLevel(2) -// .withName(R.string.facebook) -// .withDescription(R.string.facebook_subtitle) -// .withIdentifier(R.id.menu_facebook) -// .withSelectable(false), -// new SecondaryDrawerItem() -// .withIcon(CommunityMaterial.Icon.cmd_web) -// .withLevel(2) -// .withName(R.string.website) -// .withDescription(R.string.website_subtitle) -// .withIdentifier(R.id.menu_website) -// .withSelectable(false) -// ), new DividerDrawerItem(), new ExpandableDrawerItem().withName(R.string.get_help).withIcon(GoogleMaterial.Icon.gmd_account_box).withDescription(R.string.help_description).withIdentifier(20).withSelectable(false).withSubItems( new SecondaryDrawerItem() diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/ListAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/ListAdapter.java index 47102cf69..d84368872 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/ListAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/ListAdapter.java @@ -4,7 +4,7 @@ import android.content.Intent; import android.content.SharedPreferences; import android.preference.PreferenceManager; -import android.support.annotation.NonNull; +import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; import android.view.View; @@ -12,18 +12,18 @@ import android.widget.ImageView; import android.widget.TextView; -import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; - import java.text.SimpleDateFormat; import java.util.Calendar; -import java.util.Date; import java.util.List; import java.util.TimeZone; +import butterknife.BindView; +import butterknife.ButterKnife; import io.realm.RealmList; import me.calebjones.spacelaunchnow.R; +import me.calebjones.spacelaunchnow.content.data.LaunchStatus; import me.calebjones.spacelaunchnow.content.database.ListPreferences; -import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.launchdetail.activity.LaunchDetailActivity; import me.calebjones.spacelaunchnow.utils.Utils; import timber.log.Timber; @@ -33,7 +33,7 @@ */ public class ListAdapter extends RecyclerView.Adapter { public int position; - private RealmList launchList; + private RealmList launchList; private Context mContext; private Calendar rightNow; private SharedPreferences sharedPref; @@ -65,7 +65,7 @@ public ListAdapter(Context context) { night = sharedPreference.isNightModeActive(mContext); } - public void addItems(List launchList) { + public void addItems(List launchList) { if (this.launchList != null) { this.launchList.addAll(launchList); @@ -90,7 +90,7 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { @Override public void onBindViewHolder(final ViewHolder holder, int i) { - final Launch launchItem = launchList.get(i); + final LaunchList launchItem = launchList.get(i); String[] title; String launchDate; @@ -99,7 +99,7 @@ public void onBindViewHolder(final ViewHolder holder, int i) { //Retrieve missionType if (launchItem.getMission() != null) { - Utils.setCategoryIcon(holder.categoryIcon, launchItem.getMission().getTypeName(), night); + Utils.setCategoryIcon(holder.categoryIcon, launchItem.getMissionType(), night); } else { if (night) { holder.categoryIcon.setImageResource(R.drawable.ic_unknown_white); @@ -108,7 +108,7 @@ public void onBindViewHolder(final ViewHolder holder, int i) { } } - if (launchItem.getStatus() != null && launchItem.getStatus() == 2) { + if (launchItem.getStatus() != null && launchItem.getStatus().getId() == 2) { //Get launch date launchDate = sdf.format(launchItem.getNet()); @@ -120,7 +120,7 @@ public void onBindViewHolder(final ViewHolder holder, int i) { //If pad and agency exist add it to location, otherwise get whats always available if (launchItem.getLocation() != null) { - holder.location.setText(launchItem.getLocation().getName()); + holder.location.setText(launchItem.getLocation()); } else { holder.location.setText("Click for more information."); } @@ -134,21 +134,36 @@ public void onBindViewHolder(final ViewHolder holder, int i) { } else { holder.title.setText(launchItem.getName()); if (launchItem.getMission() != null) { - holder.title.setText(launchItem.getMission().getName()); + holder.title.setText(launchItem.getMission()); } } } catch (ArrayIndexOutOfBoundsException exception) { holder.title.setText(launchItem.getName()); if (launchItem.getMission() != null) { - holder.title.setText(launchItem.getMission().getName()); + holder.title.setText(launchItem.getMission()); } } } - } - public String parseDateToMMyyyy(Date date) { - return new SimpleDateFormat("MMM yyyy").format(date); + if (launchItem.getLanding() != null) { + holder.landingCard.setVisibility(View.VISIBLE); + holder.landingLocation.setText(launchItem.getLanding()); + holder.landingCard.setCardBackgroundColor(LaunchStatus.getLandingStatusColor(mContext, launchItem.getLandingSuccess())); + } else { + holder.landingCard.setVisibility(View.GONE); + } + + if (launchItem.getOrbit() != null) { + holder.orbitCard.setVisibility(View.VISIBLE); + holder.orbitName.setText(launchItem.getOrbit()); + } else { + holder.orbitCard.setVisibility(View.GONE); + } + + holder.status.setText(launchItem.getStatus().getName()); + holder.statusCard.setCardBackgroundColor(LaunchStatus.getLaunchStatusColor(mContext, launchItem.getStatus().getId())); + } @Override @@ -157,18 +172,34 @@ public int getItemCount() { } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { - public TextView title, content, location, launch_date, mission; - public ImageView categoryIcon; + @BindView(R.id.status) + TextView status; + @BindView(R.id.status_pill_mini) + CardView statusCard; + @BindView(R.id.landing) + TextView landingLocation; + @BindView(R.id.landing_pill_mini) + CardView landingCard; + @BindView(R.id.launcher) + TextView orbitName; + @BindView(R.id.launcher_pill_mini) + CardView orbitCard; + @BindView(R.id.launch_rocket) + TextView title; + @BindView(R.id.location) + TextView location; + @BindView(R.id.launch_date) + TextView launch_date; + @BindView(R.id.mission) + TextView mission; + @BindView(R.id.categoryIcon) + ImageView categoryIcon; + //Add content to the card public ViewHolder(View view) { super(view); - - categoryIcon = view.findViewById(R.id.categoryIcon); - title = view.findViewById(R.id.launch_rocket); - location = view.findViewById(R.id.location); - launch_date = view.findViewById(R.id.launch_date); - mission = view.findViewById(R.id.mission); + ButterKnife.bind(this, view); title.setOnClickListener(this); location.setOnClickListener(this); @@ -179,7 +210,7 @@ public ViewHolder(View view) { //React to click events. @Override public void onClick(View v) { - final Launch launch = launchList.get(getAdapterPosition()); + final LaunchList launch = launchList.get(getAdapterPosition()); Intent intent = new Intent(mContext, LaunchDetailActivity.class); intent.putExtra("TYPE", "launch"); @@ -188,13 +219,13 @@ public void onClick(View v) { } } - public void animateTo(List models) { + public void animateTo(List models) { applyAndAnimateRemovals(models); applyAndAnimateAdditions(models); applyAndAnimateMovedItems(models); } - private void applyAndAnimateRemovals(List newModels) { + private void applyAndAnimateRemovals(List newModels) { for (int i = launchList.size() - 1; i >= 0; i--) { if (!newModels.contains(launchList.get(i))) { removeItem(i); @@ -202,18 +233,18 @@ private void applyAndAnimateRemovals(List newModels) { } } - private void applyAndAnimateAdditions(List newModels) { + private void applyAndAnimateAdditions(List newModels) { for (int i = 0, count = newModels.size(); i < count; i++) { - final Launch model = newModels.get(i); + final LaunchList model = newModels.get(i); if (!launchList.contains(model)) { addItem(i, model); } } } - private void applyAndAnimateMovedItems(List newModels) { + private void applyAndAnimateMovedItems(List newModels) { for (int toPosition = newModels.size() - 1; toPosition >= 0; toPosition--) { - final Launch model = newModels.get(toPosition); + final LaunchList model = newModels.get(toPosition); final int fromPosition = launchList.indexOf(model); if (fromPosition >= 0 && fromPosition != toPosition) { moveItem(fromPosition, toPosition); @@ -221,13 +252,13 @@ private void applyAndAnimateMovedItems(List newModels) { } } - public Launch removeItem(int position) { - Launch model = launchList.remove(position); + public LaunchList removeItem(int position) { + LaunchList model = launchList.remove(position); notifyItemRemoved(position); return model; } - public void addItem(int position, Launch model) { + public void addItem(int position, LaunchList model) { launchList.add(position, model); notifyItemInserted(position); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/PreviousLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/PreviousLaunchesFragment.java index 0b16ef3fc..be2583716 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/PreviousLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/PreviousLaunchesFragment.java @@ -1,9 +1,7 @@ package me.calebjones.spacelaunchnow.ui.main.launches; import android.content.Context; -import android.content.SharedPreferences; import android.os.Bundle; -import android.preference.PreferenceManager; import android.support.annotation.Nullable; import android.support.design.widget.CoordinatorLayout; import android.support.v4.app.Fragment; @@ -20,22 +18,19 @@ import android.view.ViewGroup; import com.crashlytics.android.Crashlytics; -import com.github.clans.fab.FloatingActionButton; -import com.github.clans.fab.FloatingActionMenu; -import com.simplecityapps.recyclerview_fastscroll.views.FastScrollRecyclerView; import java.util.List; -import io.realm.RealmResults; +import butterknife.BindView; +import butterknife.ButterKnife; +import cz.kinst.jakub.view.SimpleStatefulLayout; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.BaseFragment; import me.calebjones.spacelaunchnow.common.customviews.SimpleDividerItemDecoration; import me.calebjones.spacelaunchnow.content.data.callbacks.Callbacks; import me.calebjones.spacelaunchnow.content.data.previous.PreviousDataRepository; -import me.calebjones.spacelaunchnow.content.database.ListPreferences; -import me.calebjones.spacelaunchnow.content.database.SwitchPreferences; import me.calebjones.spacelaunchnow.data.models.main.Launch; -import me.calebjones.spacelaunchnow.ui.main.MainActivity; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.supporter.SupporterHelper; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; import me.calebjones.spacelaunchnow.utils.views.SnackbarHandler; @@ -45,19 +40,26 @@ public class PreviousLaunchesFragment extends BaseFragment implements SearchView.OnQueryTextListener, SwipeRefreshLayout.OnRefreshListener { private View view; - private RecyclerView mRecyclerView; private ListAdapter adapter; private LinearLayoutManager layoutManager; - private SwipeRefreshLayout mSwipeRefreshLayout; private Context context; - private CoordinatorLayout coordinatorLayout; private PreviousDataRepository previousDataRepository; private int nextOffset = 0; private EndlessRecyclerViewScrollListener scrollListener; private String searchTerm = null; - public boolean canLoadMore; + @BindView(R.id.stateful_view) + SimpleStatefulLayout statefulView; + @BindView(R.id.recycler_view) + RecyclerView mRecyclerView; + @BindView(R.id.swipe_refresh_layout) + SwipeRefreshLayout mSwipeRefreshLayout; + @BindView(R.id.coordinatorLayout) + CoordinatorLayout coordinatorLayout; + private SearchView searchView; + public boolean canLoadMore; + private boolean statefulStateContentShow = false; private static final Field sChildFragmentManagerField; @Override @@ -71,26 +73,15 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.context = getContext(); - canLoadMore = true; - - super.onCreateView(inflater, container, savedInstanceState); - setHasOptionsMenu(true); adapter = new ListAdapter(getContext()); - LayoutInflater lf = getActivity().getLayoutInflater(); - - view = lf.inflate(R.layout.fragment_launches, container, false); + view = inflater.inflate(R.layout.fragment_launches, container, false); + ButterKnife.bind(this, view); - coordinatorLayout = view.findViewById(R.id.coordinatorLayout); - - - /*Set up Pull to refresh*/ - mSwipeRefreshLayout = view.findViewById(R.id.launches_swipe_refresh_layout); mSwipeRefreshLayout.setOnRefreshListener(this); - mRecyclerView = view.findViewById(R.id.recycler_view); layoutManager = new LinearLayoutManager(getContext()); mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); @@ -101,13 +92,17 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { // Triggered only when new data needs to be appended to the list // Add whatever code is needed to append new items to the bottom of the list - if (canLoadMore) { + Timber.v("onLoadMore - page: %s totalItemsCount: %s nextOffset: %s", page, totalItemsCount, nextOffset); + if (canLoadMore && nextOffset > 0) { + Timber.v("onLoadMore - adding more!"); fetchData(false); mSwipeRefreshLayout.setRefreshing(true); } } }; mRecyclerView.addOnScrollListener(scrollListener); + statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); return view; } @@ -132,19 +127,23 @@ public void onStop() { super.onStop(); } - private void updateAdapter(List launches) { - + private void updateAdapter(List launches) { if (launches.size() > 0) { + if (!statefulStateContentShow) { + statefulView.showContent(); + statefulStateContentShow = true; + } adapter.addItems(launches); adapter.notifyDataSetChanged(); } else { + statefulView.showEmpty(); + statefulStateContentShow = false; if (adapter != null) { adapter.clear(); } } scrollListener.resetState(); - } public void fetchData(boolean forceRefresh) { @@ -153,12 +152,12 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, null, null, new Callbacks.ListCallback() { + previousDataRepository.getPreviousLaunches(nextOffset, searchTerm, null, null, null, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; - canLoadMore = next > 0; + canLoadMore = nextOffset > 0; updateAdapter(launches); } @@ -169,6 +168,9 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; + showNetworkLoading(false); if (throwable != null) { Timber.e(throwable); } else { @@ -252,7 +254,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { } final MenuItem item = menu.findItem(R.id.action_search); - final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); + searchView = (SearchView) MenuItemCompat.getActionView(item); searchView.setOnQueryTextListener(this); } @@ -277,8 +279,10 @@ public boolean onQueryTextChange(String query) { @Override public boolean onQueryTextSubmit(String query) { + Timber.v("onQueryTextSubmit - %s", query); searchTerm = query; fetchData(true); + searchView.clearFocus(); return false; } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/UpcomingLaunchesFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/UpcomingLaunchesFragment.java index 8f8c37e53..bf4ce2836 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/UpcomingLaunchesFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/launches/UpcomingLaunchesFragment.java @@ -29,6 +29,9 @@ import java.util.ArrayList; import java.util.List; +import butterknife.BindView; +import butterknife.ButterKnife; +import cz.kinst.jakub.view.SimpleStatefulLayout; import io.realm.RealmResults; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.BaseFragment; @@ -39,6 +42,7 @@ import me.calebjones.spacelaunchnow.content.database.ListPreferences; import me.calebjones.spacelaunchnow.content.database.SwitchPreferences; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.LaunchList; import me.calebjones.spacelaunchnow.ui.main.MainActivity; import me.calebjones.spacelaunchnow.ui.supporter.SupporterHelper; import me.calebjones.spacelaunchnow.utils.views.EndlessRecyclerViewScrollListener; @@ -51,19 +55,26 @@ public class UpcomingLaunchesFragment extends BaseFragment implements SearchView.OnQueryTextListener, SwipeRefreshLayout.OnRefreshListener { private View view; - private RecyclerView mRecyclerView; private ListAdapter adapter; private LinearLayoutManager layoutManager; - private SwipeRefreshLayout mSwipeRefreshLayout; private Context context; - private CoordinatorLayout coordinatorLayout; private UpcomingDataRepository upcomingDataRepository; private int nextOffset = 0; private EndlessRecyclerViewScrollListener scrollListener; private String searchTerm = null; - public boolean canLoadMore; + @BindView(R.id.stateful_view) + SimpleStatefulLayout statefulView; + @BindView(R.id.recycler_view) + RecyclerView mRecyclerView; + @BindView(R.id.swipe_refresh_layout) + SwipeRefreshLayout mSwipeRefreshLayout; + @BindView(R.id.coordinatorLayout) + CoordinatorLayout coordinatorLayout; + private SearchView searchView; + public boolean canLoadMore; + private boolean statefulStateContentShow = false; private static final Field sChildFragmentManagerField; @Override @@ -77,25 +88,14 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { this.context = getContext(); - canLoadMore = true; - - super.onCreateView(inflater, container, savedInstanceState); - setHasOptionsMenu(true); adapter = new ListAdapter(getContext()); - LayoutInflater lf = getActivity().getLayoutInflater(); - - view = lf.inflate(R.layout.fragment_launches, container, false); + view = inflater.inflate(R.layout.fragment_launches, container, false); + ButterKnife.bind(this, view); - coordinatorLayout = view.findViewById(R.id.coordinatorLayout); - - /*Set up Pull to refresh*/ - mSwipeRefreshLayout = view.findViewById(R.id.launches_swipe_refresh_layout); mSwipeRefreshLayout.setOnRefreshListener(this); - - mRecyclerView = view.findViewById(R.id.recycler_view); layoutManager = new LinearLayoutManager(getContext()); mRecyclerView.setLayoutManager(layoutManager); mRecyclerView.addItemDecoration(new SimpleDividerItemDecoration(context)); @@ -113,6 +113,8 @@ public void onLoadMore(int page, int totalItemsCount, RecyclerView view) { } }; mRecyclerView.addOnScrollListener(scrollListener); + statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> fetchData(true)); return view; } @@ -137,19 +139,23 @@ public void onStop() { super.onStop(); } - private void updateAdapter(List launches) { - + private void updateAdapter(List launches) { if (launches.size() > 0) { + if (!statefulStateContentShow) { + statefulView.showContent(); + statefulStateContentShow = true; + } adapter.addItems(launches); adapter.notifyDataSetChanged(); } else { + statefulView.showEmpty(); + statefulStateContentShow = false; if (adapter != null) { adapter.clear(); } } scrollListener.resetState(); - } public void fetchData(boolean forceRefresh) { @@ -158,9 +164,9 @@ public void fetchData(boolean forceRefresh) { nextOffset = 0; adapter.clear(); } - upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, null, null, new Callbacks.ListCallback() { + upcomingDataRepository.getUpcomingLaunches(nextOffset, searchTerm, null, null,null, new Callbacks.ListCallbackMini() { @Override - public void onLaunchesLoaded(List launches, int next) { + public void onLaunchesLoaded(List launches, int next, int total) { Timber.v("Offset - %s", next); nextOffset = next; canLoadMore = next > 0; @@ -174,6 +180,9 @@ public void onNetworkStateChanged(boolean refreshing) { @Override public void onError(String message, @Nullable Throwable throwable) { + statefulView.showOffline(); + statefulStateContentShow = false; + showNetworkLoading(false); if (throwable != null) { Timber.e(throwable); } else { @@ -257,7 +266,7 @@ public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { } final MenuItem item = menu.findItem(R.id.action_search); - final SearchView searchView = (SearchView) MenuItemCompat.getActionView(item); + searchView = (SearchView) MenuItemCompat.getActionView(item); searchView.setOnQueryTextListener(this); } @@ -284,6 +293,7 @@ public boolean onQueryTextChange(String query) { public boolean onQueryTextSubmit(String query) { searchTerm = query; fetchData(true); + searchView.clearFocus(); return false; } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/NewsViewPager.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/NewsViewPager.java index f7bac9fc0..61b21f8ab 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/NewsViewPager.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/NewsViewPager.java @@ -40,8 +40,8 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, View inflatedView = inflater.inflate(R.layout.fragment_view_pager, container, false); tabLayout = inflatedView.findViewById(R.id.tabLayout); - tabLayout.addTab(tabLayout.newTab().setText("Twitter")); - tabLayout.addTab(tabLayout.newTab().setText("Web")); + tabLayout.addTab(tabLayout.newTab().setText(R.string.news)); + tabLayout.addTab(tabLayout.newTab().setText(R.string.twitter)); viewPager = inflatedView.findViewById(R.id.viewpager); pagerAdapter = new PagerAdapter @@ -82,8 +82,8 @@ public PagerAdapter(FragmentManager fm, int NumOfTabs) { public Fragment getItem(int position) { switch (position) { - case 0: return new TwitterFragment(); - case 1: return new WebNewsFragment(); + case 0: return new WebNewsFragment(); + case 1: return new TwitterFragment(); default: return null; } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/twitter/TwitterFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/twitter/TwitterFragment.java index c2e33a36e..537115e37 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/twitter/TwitterFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/twitter/TwitterFragment.java @@ -47,25 +47,20 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { context = getActivity(); setHasOptionsMenu(true); - View view = inflater.inflate(R.layout.fragment_news, container, false); + View view = inflater.inflate(R.layout.fragment_twitter, container, false); ButterKnife.bind(this, view); getTwitterTimeline(); - swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { + swipeRefreshLayout.setOnRefreshListener(() -> timelineAdapter.refresh(new Callback>() { @Override - public void onRefresh() { - timelineAdapter.refresh(new Callback>() { - @Override - public void success(Result> result) { - swipeRefreshLayout.setRefreshing(false); - } - - @Override - public void failure(TwitterException exception) { - swipeRefreshLayout.setRefreshing(false); - } - }); + public void success(Result> result) { + swipeRefreshLayout.setRefreshing(false); } - }); + + @Override + public void failure(TwitterException exception) { + swipeRefreshLayout.setRefreshing(false); + } + })); return view; } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/ArticleAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/ArticleAdapter.java index b016627d1..b75b5da26 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/ArticleAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/ArticleAdapter.java @@ -2,11 +2,13 @@ import android.app.Activity; import android.content.Context; +import android.content.res.Resources; import android.support.annotation.NonNull; import android.support.design.widget.CoordinatorLayout; import android.support.v4.content.ContextCompat; import android.support.v7.widget.RecyclerView; import android.text.format.DateFormat; +import android.util.TypedValue; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -20,6 +22,7 @@ import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Date; +import java.util.List; import java.util.Locale; import butterknife.BindView; @@ -38,8 +41,8 @@ public class ArticleAdapter extends RecyclerView.Adapter { private Context context; - private RealmList
articles; - private int color; + private List
articles; + private int color, altColor; private SimpleDateFormat inDateFormat; private SimpleDateFormat outDateFormat; private Activity activity; @@ -48,12 +51,15 @@ public ArticleAdapter(Context context, Activity activity) { this.context = context; this.activity = activity; color = ContextCompat.getColor(context, R.color.accent); - inDateFormat = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.US); - String format = DateFormat.getBestDateTimePattern(Locale.getDefault(), "h:mm a - MMMM d, yyyy"); + TypedValue typedValue = new TypedValue(); + Resources.Theme theme = context.getTheme(); + theme.resolveAttribute(R.attr.titleBarColor, typedValue, true); + altColor = typedValue.data; + String format = DateFormat.getBestDateTimePattern(Locale.getDefault(), "MMMM d, yyyy"); outDateFormat = new SimpleDateFormat(format, Locale.getDefault()); } - public void addItems(final RealmList
articles) { + public void addItems(final List
articles) { this.articles = articles; notifyDataSetChanged(); } @@ -103,43 +109,66 @@ public void onBindViewHolder(@NonNull final ViewHolder holder, int position) { if (article != null) { holder.titleText.setText(article.getTitle()); - tryDefault(article.getLink(), holder.imageView); + if (article.getFeaturedImage() != null) { + GlideApp.with(context) + .load(article.getFeaturedImage()) + .centerCrop() + .placeholder(R.drawable.placeholder) + .into(holder.imageView); + } else { + tryDefault(article.getUrl(), holder.imageView); + } BadgeDrawable.Builder siteDrawable = new BadgeDrawable.Builder() .type(BadgeDrawable.TYPE_ONLY_ONE_TEXT) .badgeColor(color) - .textSize(40) - .padding(16, 16, 16, 16, 16) + .padding(8, 8, 8, 8, 8) .strokeWidth(16); - String link = article.getLink(); - - if (link.contains("spaceflightnow")) { - siteDrawable.text1("Space Flight Now"); - } else if (link.contains("spaceflight101")) { - siteDrawable.text1("Space Flight 101"); - } else if (link.contains("spacenews")) { - siteDrawable.text1("Space News"); - } else if (link.contains("nasaspaceflight")) { - siteDrawable.text1("NASA Spaceflight"); - } else if (link.contains("nasa.gov")) { - siteDrawable.text1("NASA.Gov"); - } else if (link.contains("spacex.com")) { - siteDrawable.text1("SpaceX"); + BadgeDrawable.Builder tagDrawable = + new BadgeDrawable.Builder() + .type(BadgeDrawable.TYPE_ONLY_ONE_TEXT) + .badgeColor(altColor) + .padding(16, 8, 16, 8, 8) + .strokeWidth(16); + + BadgeDrawable.Builder altTagDrawable = + new BadgeDrawable.Builder() + .type(BadgeDrawable.TYPE_ONLY_ONE_TEXT) + .badgeColor(altColor) + .padding(16, 8, 16, 8, 8) + .strokeWidth(16); + + + + siteDrawable.text1(article.getNewsSite()); + + if (article.getTags() != null && article.getTags().size() > 0) { + holder.tagText.setVisibility(View.VISIBLE); + String upperString = article.getTags().get(0).substring(0, 1).toUpperCase() + + article.getTags().get(0).substring(1); + upperString = Utils.ellipsize(upperString, 15); + tagDrawable.text1(upperString); + holder.tagText.setText(tagDrawable.build().toSpannable()); } else { - siteDrawable.text1("Unknown"); + holder.tagText.setVisibility(View.GONE); + } + + if (article.getTags() != null && article.getTags().size() > 1) { + holder.tagTextAlt.setVisibility(View.VISIBLE); + String upperString = article.getTags().get(1).substring(0, 1).toUpperCase() + + article.getTags().get(1).substring(1); + upperString = Utils.ellipsize(upperString, 15); + altTagDrawable.text1(upperString); + holder.tagTextAlt.setText(altTagDrawable.build().toSpannable()); + } else { + holder.tagTextAlt.setVisibility(View.GONE); } holder.siteText.setText(siteDrawable.build().toSpannable()); - try { - Date pubDate = inDateFormat.parse(article.getPubDate()); - holder.publicationDate.setText(outDateFormat.format(pubDate)); - } catch (ParseException e) { - e.printStackTrace(); - holder.publicationDate.setText(article.getPubDate()); - } + holder.publicationDate.setText(outDateFormat.format(article.getDatePublished())); } } @@ -206,6 +235,10 @@ public class ViewHolder extends RecyclerView.ViewHolder { TextView titleText; @BindView(R.id.article_site) TextView siteText; + @BindView(R.id.article_tag) + TextView tagText; + @BindView(R.id.article_tag_alt) + TextView tagTextAlt; @BindView(R.id.article_publication_date) TextView publicationDate; @BindView(R.id.article_image) @@ -215,7 +248,7 @@ public class ViewHolder extends RecyclerView.ViewHolder { @OnClick(R.id.rootview) void onClick() { - Utils.openCustomTab(activity, context, articles.get(getAdapterPosition()).getLink()); + Utils.openCustomTab(activity, context, articles.get(getAdapterPosition()).getUrl()); } public ViewHolder(View itemView) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/WebNewsFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/WebNewsFragment.java index 36eaaffa9..2486e54e4 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/WebNewsFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/news/web/WebNewsFragment.java @@ -2,10 +2,12 @@ import android.content.Context; import android.os.Bundle; +import android.support.design.widget.CoordinatorLayout; import android.support.v4.app.Fragment; import android.support.v4.widget.SwipeRefreshLayout; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.support.v7.widget.StaggeredGridLayoutManager; import android.view.LayoutInflater; import android.view.Menu; import android.view.MenuInflater; @@ -13,55 +15,59 @@ import android.view.View; import android.view.ViewGroup; - -import com.leocardz.link.preview.library.LinkPreviewCallback; -import com.leocardz.link.preview.library.SourceContent; -import com.leocardz.link.preview.library.TextCrawler; +import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; -import io.realm.Realm; +import cz.kinst.jakub.view.SimpleStatefulLayout; import io.realm.RealmList; import me.calebjones.spacelaunchnow.R; -import me.calebjones.spacelaunchnow.data.models.news.Article; +import me.calebjones.spacelaunchnow.common.RetroFitFragment; import me.calebjones.spacelaunchnow.content.data.articles.ArticleRepository; +import me.calebjones.spacelaunchnow.data.models.news.Article; import me.calebjones.spacelaunchnow.ui.supporter.SupporterHelper; +import me.calebjones.spacelaunchnow.utils.views.SnackbarHandler; -public class WebNewsFragment extends Fragment { +public class WebNewsFragment extends RetroFitFragment { @BindView(R.id.recycler_view) RecyclerView recyclerView; @BindView(R.id.swiperefresh) SwipeRefreshLayout swipeRefreshLayout; + @BindView(R.id.stateful_view) + SimpleStatefulLayout statefulView; + @BindView(R.id.coordinatorLayout) + CoordinatorLayout coordinatorLayout; private Context context; private ArticleRepository articleRepository; private ArticleAdapter articleAdapter; private LinearLayoutManager linearLayoutManager; - private RealmList
articles; + private StaggeredGridLayoutManager layoutManager; + private List
articles; @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { context = getActivity(); - articleRepository = new ArticleRepository(context); + articleRepository = new ArticleRepository(context, getNewsRetrofit()); setHasOptionsMenu(true); View view = inflater.inflate(R.layout.fragment_news, container, false); ButterKnife.bind(this, view); - - - linearLayoutManager = new LinearLayoutManager(context); - recyclerView.setLayoutManager(linearLayoutManager); articleAdapter = new ArticleAdapter(context, getActivity()); + if (getResources().getBoolean(R.bool.landscape) && getResources().getBoolean(R.bool.isTablet)) { + layoutManager = new StaggeredGridLayoutManager(2, StaggeredGridLayoutManager.VERTICAL); + recyclerView.setLayoutManager(layoutManager); + } else { + linearLayoutManager = new LinearLayoutManager(context.getApplicationContext(), LinearLayoutManager.VERTICAL, false); + recyclerView.setLayoutManager(linearLayoutManager); + } recyclerView.setAdapter(articleAdapter); getArticles(false); - swipeRefreshLayout.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { - @Override - public void onRefresh() { - getArticles(true); - } - }); + swipeRefreshLayout.setOnRefreshListener(() -> getArticles(true)); + statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> getArticles(true)); return view; } @@ -92,19 +98,25 @@ public void getArticles(boolean forced) { swipeRefreshLayout.setRefreshing(true); articleRepository.getArticles(forced, new ArticleRepository.GetArticlesCallback() { @Override - public void onSuccess(RealmList
newArticles) { + public void onSuccess(List
newArticles) { articles = newArticles; + statefulView.showContent(); articleAdapter.addItems(articles); swipeRefreshLayout.setRefreshing(false); } @Override - public void onFailure(Throwable throwable) { + public void onFailure(String error, boolean showContent) { + if (!showContent) { + statefulView.showEmpty(); + } + SnackbarHandler.showInfoSnackbar(context, coordinatorLayout, error); swipeRefreshLayout.setRefreshing(false); } @Override public void onNetworkFailure() { + statefulView.showOffline(); swipeRefreshLayout.setRefreshing(false); } }); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/CardAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/CardAdapter.java index 0d0d154a7..c3882a2b7 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/CardAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/CardAdapter.java @@ -5,17 +5,24 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.graphics.Bitmap; +import android.graphics.Color; import android.graphics.Typeface; import android.net.Uri; -import android.os.Build; +import android.os.SystemClock; import android.preference.PreferenceManager; +import android.support.constraint.ConstraintLayout; import android.support.v4.app.ShareCompat; import android.support.v4.content.ContextCompat; import android.support.v7.widget.CardView; import android.support.v7.widget.RecyclerView; +import android.text.format.DateFormat; +import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; +import android.widget.Button; +import android.widget.Chronometer; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.SectionIndexer; @@ -24,34 +31,45 @@ import com.afollestad.materialdialogs.MaterialDialog; import com.afollestad.materialdialogs.simplelist.MaterialSimpleListItem; +import com.bumptech.glide.load.MultiTransformation; +import com.bumptech.glide.load.engine.DiskCacheStrategy; +import com.bumptech.glide.request.RequestOptions; import com.crashlytics.android.Crashlytics; -import com.google.android.gms.maps.CameraUpdateFactory; -import com.google.android.gms.maps.model.BitmapDescriptorFactory; +import com.google.android.gms.maps.OnMapReadyCallback; import com.google.android.gms.maps.model.LatLng; -import com.google.android.gms.maps.model.MarkerOptions; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.List; -import java.util.TimeZone; +import java.util.concurrent.TimeUnit; +import butterknife.BindView; +import butterknife.ButterKnife; +import io.reactivex.Observable; +import io.reactivex.android.schedulers.AndroidSchedulers; +import io.reactivex.disposables.Disposable; import io.realm.RealmList; +import jp.wasabeef.glide.transformations.BlurTransformation; +import jp.wasabeef.glide.transformations.ColorFilterTransformation; +import jp.wasabeef.glide.transformations.gpu.BrightnessFilterTransformation; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.content.data.LaunchStatus; import me.calebjones.spacelaunchnow.content.database.ListPreferences; import me.calebjones.spacelaunchnow.content.util.DialogAdapter; +import me.calebjones.spacelaunchnow.data.models.main.Landing; import me.calebjones.spacelaunchnow.data.models.main.Launch; +import me.calebjones.spacelaunchnow.data.models.main.Stage; import me.calebjones.spacelaunchnow.data.models.realm.RealmStr; import me.calebjones.spacelaunchnow.ui.launchdetail.activity.LaunchDetailActivity; +import me.calebjones.spacelaunchnow.utils.GlideApp; +import me.calebjones.spacelaunchnow.utils.Utils; import me.calebjones.spacelaunchnow.utils.analytics.Analytics; +import me.calebjones.spacelaunchnow.utils.transformations.SaturationTransformation; import me.calebjones.spacelaunchnow.utils.views.CountDownTimer; -import me.calebjones.spacelaunchnow.utils.Utils; import timber.log.Timber; -import com.google.android.gms.maps.GoogleMap; -import com.google.android.gms.maps.MapView; -import com.google.android.gms.maps.MapsInitializer; -import com.google.android.gms.maps.OnMapReadyCallback; + +import static me.calebjones.spacelaunchnow.utils.GlideOptions.bitmapTransform; /** * Adapts UpcomingLaunch data to the LaunchFragment @@ -60,7 +78,6 @@ public class CardAdapter extends RecyclerView.Adapter im private static ListPreferences sharedPreference; public int position; - private String launchTime; private RealmList launchList; private Context context; private Calendar rightNow; @@ -111,7 +128,7 @@ public void clear() { @Override public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { - View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.content_card_item, viewGroup, false); + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.content_card, viewGroup, false); return new ViewHolder(v); } @@ -120,17 +137,14 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { public void onBindViewHolder(final ViewHolder holder, int i) { Launch launchItem = launchList.get(i); Timber.i("Binding %s", launchItem.getName()); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - holder.cardView.setElevation(7); - } String title; try { if (launchItem.isValid()) { - if (launchItem.getLauncher() != null) { - if (launchItem.getLsp() != null) { - title = launchItem.getLsp().getName() + " | " + (launchItem.getLauncher().getName()); + if (launchItem.getRocket().getConfiguration() != null) { + if (launchItem.getRocket().getConfiguration().getLaunchServiceProvider() != null) { + title = launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getName() + " | " + (launchItem.getRocket().getConfiguration().getName()); } else { - title = launchItem.getLauncher().getName(); + title = launchItem.getRocket().getConfiguration().getName(); } } else if (launchItem.getName() != null) { title = launchItem.getName(); @@ -155,32 +169,62 @@ public void onBindViewHolder(final ViewHolder holder, int i) { dlon = Double.parseDouble(launchItem.getPad().getLongitude()); } - // Getting status - if (dlat == 0 && dlon == 0 || Double.isNaN(dlat) || Double.isNaN(dlon) || dlat == Double.NaN || dlon == Double.NaN) { - if (holder.map_view != null) { - holder.map_view.setVisibility(View.GONE); + holder.landingView.setVisibility(View.INVISIBLE); + if (launchItem.getRocket().getFirstStage() != null && launchItem.getRocket().getFirstStage().size() >= 1){ + if (launchItem.getRocket().getFirstStage().size() > 1){ + String stagesText = ""; + for (Stage stage : launchItem.getRocket().getFirstStage()){ + if (stage.getLanding().getLandingLocation() != null) { + stagesText = stagesText + stage.getLanding().getLandingLocation().getAbbrev() + " "; + } + } + holder.landingView.setVisibility(View.VISIBLE); + holder.landing.setText(stagesText); + } else if (launchItem.getRocket().getFirstStage().size() == 1){ + if (launchItem.getRocket().getFirstStage().first().getLanding() != null){ + Landing landing = launchItem.getRocket().getFirstStage().first().getLanding(); + if (landing.getLandingLocation() != null) { + holder.landingView.setVisibility(View.VISIBLE); + holder.landing.setText(landing.getLandingLocation().getAbbrev()); + } + } } - } else { - holder.map_view.setVisibility(View.VISIBLE); - holder.bindView(new LaunchLocation(launchItem, new LatLng(dlat, dlon))); } - if (launchItem.getProbability() != null && launchItem.getProbability() > 0) { - holder.contentForecast.setText(String.format(context.getString(R.string.weather_favorable), launchItem.getProbability())); - holder.contentForecast.setVisibility(View.VISIBLE); + if (launchItem.getRocket().getConfiguration().getImageUrl() != null) { + holder.launchImage.setVisibility(View.VISIBLE); + GlideApp.with(context) + .load(launchItem.getRocket().getConfiguration().getImageUrl()) + .placeholder(R.drawable.placeholder) + .into(holder.launchImage); + } else if (launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getImageUrl() != null) { + holder.launchImage.setVisibility(View.VISIBLE); + GlideApp.with(context) + .load(launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getImageUrl()) + .placeholder(R.drawable.placeholder) + .into(holder.launchImage); + } else if (launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getLogoUrl() != null) { + holder.launchImage.setVisibility(View.VISIBLE); + GlideApp.with(context) + .load(launchItem.getRocket().getConfiguration().getLaunchServiceProvider().getLogoUrl()) + .placeholder(R.drawable.placeholder) + .into(holder.launchImage); } else { - holder.contentForecast.setVisibility(View.GONE); + holder.launchImage.setVisibility(View.GONE); } - holder.content_status.setText(LaunchStatus.getLaunchStatusTitle(context, launchItem.getStatus())); + holder.status.setText(LaunchStatus.getLaunchStatusTitle(context, launchItem.getStatus().getId())); + holder.statusPill.setCardBackgroundColor(LaunchStatus.getLaunchStatusColor(context, launchItem.getStatus().getId())); //If timestamp is available calculate TMinus and date. - if (launchItem.getNetstamp() > 0 && (launchItem.getStatus() == 1 || launchItem.getStatus() == 2)) { - long longdate = launchItem.getNetstamp(); - longdate = longdate * 1000; + holder.countdownStatus.setText(""); + holder.countdownStatus.setVisibility(View.GONE); + if (launchItem.getNet().getTime() > 0) { + //TODO VERIFY THIS STILL WORKS + long longdate = launchItem.getNet().getTime(); final Date date = new Date(longdate); - Calendar future = DateToCalendar(date); + Calendar launchDate = DateToCalendar(date); Calendar now = rightNow; now.setTimeInMillis(System.currentTimeMillis()); @@ -189,171 +233,78 @@ public void onBindViewHolder(final ViewHolder holder, int i) { holder.timer.cancel(); } - final int status = launchItem.getStatus(); + if (holder.var != null){ + holder.var.dispose(); + } + + final int status = launchItem.getStatus().getId(); final String hold = launchItem.getHoldreason(); - holder.content_TMinus_status.setTypeface(Typeface.SANS_SERIF); - holder.content_TMinus_status.setTextColor(accentColor); + long timeToFinish = launchDate.getTimeInMillis() - now.getTimeInMillis(); -// holder.countdownView.setVisibility(View.VISIBLE); - long timeToFinish = future.getTimeInMillis() - now.getTimeInMillis(); - if (timeToFinish > 0) { + if (timeToFinish > 0 && launchItem.getStatus().getId() == 1) { holder.timer = new CountDownTimer(timeToFinish, 1000) { StringBuilder time = new StringBuilder(); @Override public void onFinish() { Timber.v("Countdown finished."); - holder.content_TMinus_status.setTypeface(Typeface.DEFAULT); - if (night) { - holder.content_TMinus_status.setTextColor(nightColor); - } else { - holder.content_TMinus_status.setTextColor(color); - } - if (status == 1) { - holder.content_TMinus_status.setText(R.string.watch_webcast); - - } else { - if (hold != null && hold.length() > 1) { - holder.content_TMinus_status.setText(hold); - } else { - holder.content_TMinus_status.setText(R.string.watch_webcast); - } - } - holder.content_TMinus_status.setVisibility(View.VISIBLE); holder.countdownDays.setText("00"); holder.countdownHours.setText("00"); holder.countdownMinutes.setText("00"); holder.countdownSeconds.setText("00"); + holder.countdownStatus.setVisibility(View.VISIBLE); + holder.countdownStatus.setText("+"); + countUpTimer(holder, longdate); } @Override public void onTick(long millisUntilFinished) { time.setLength(0); - - // Calculate the Days/Hours/Mins/Seconds numerically. - long longDays = millisUntilFinished / 86400000; - long longHours = (millisUntilFinished / 3600000) % 24; - long longMins = (millisUntilFinished / 60000) % 60; - long longSeconds = (millisUntilFinished / 1000) % 60; - - String days = String.valueOf(longDays); - String hours; - String minutes; - String seconds; - - // Translate those numerical values to string values. - if (longHours < 10) { - hours = "0" + String.valueOf(longHours); - } else { - hours = String.valueOf(longHours); - } - - if (longMins < 10) { - minutes = "0" + String.valueOf(longMins); - } else { - minutes = String.valueOf(longMins); - } - - if (longSeconds < 10) { - seconds = "0" + String.valueOf(longSeconds); - } else { - seconds = String.valueOf(longSeconds); - } - - - // Update the views - if (Integer.valueOf(days) > 0) { - holder.countdownDays.setText(days); - } else { - holder.countdownDays.setText("00"); - } - - if (Integer.valueOf(hours) > 0) { - holder.countdownHours.setText(hours); - } else if (Integer.valueOf(days) > 0) { - holder.countdownHours.setText("00"); - } else { - holder.countdownHours.setText("00"); - } - - if (Integer.valueOf(minutes) > 0) { - holder.countdownMinutes.setText(minutes); - } else if (Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { - holder.countdownMinutes.setText("00"); - } else { - holder.countdownMinutes.setText("00"); - } - - if (Integer.valueOf(seconds) > 0) { - holder.countdownSeconds.setText(seconds); - } else if (Integer.valueOf(minutes) > 0 || Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { - holder.countdownSeconds.setText("00"); - } else { - holder.countdownSeconds.setText("00"); - } - - // Hide status if countdown is active. - holder.content_TMinus_status.setVisibility(View.GONE); + setCountdownView(millisUntilFinished, holder); } }.start(); + } else if (launchItem.getStatus().getId() == 3 || launchItem.getStatus().getId() == 4 || launchItem.getStatus().getId() == 7) { + holder.countdownDays.setText("00"); + holder.countdownHours.setText("00"); + holder.countdownMinutes.setText("00"); + holder.countdownSeconds.setText("00"); + } else if (launchItem.getStatus().getId() == 6 || launchItem.getStatus().getId() == 1) { + holder.countdownStatus.setVisibility(View.VISIBLE); + holder.countdownStatus.setText("+"); + countUpTimer(holder, longdate); } else { - showStatusDescription(launchItem, holder); + holder.countdownDays.setText("- -"); + holder.countdownHours.setText("- -"); + holder.countdownMinutes.setText("- -"); + holder.countdownSeconds.setText("- -"); } - - } else { - showStatusDescription(launchItem, holder); } //Get launch date - if (launchItem.getStatus() == 2) { + if (launchItem.getStatus().getId() == 2) { if (launchItem.getNet() != null) { //Get launch date SimpleDateFormat sdf = Utils.getSimpleDateFormatForUI("MMMM d, yyyy"); - sdf.toLocalizedPattern(); Date date = launchItem.getNet(); String launchTime = sdf.format(date); - if (launchItem.getTbddate()){ - launchTime = launchTime + context.getString(R.string.unconfirmed); + if (launchItem.getTbddate()) { + launchTime = launchTime + " " + context.getString(R.string.unconfirmed); } - holder.launch_date_compact.setText(launchTime); - holder.launch_time.setVisibility(View.GONE); + holder.launchDateCompact.setText(launchTime); } } else { - if (launchItem.getNet() != null) { - if (sharedPref.getBoolean("local_time", true)) { - SimpleDateFormat sdf; - if (sharedPref.getBoolean("24_hour_mode", false)) { - sdf = new SimpleDateFormat("HH:mm zzz"); - } else { - sdf = new SimpleDateFormat("h:mm a zzz"); - } - sdf.toLocalizedPattern(); - Date date = launchItem.getNet(); - launchTime = sdf.format(date); - } else { - SimpleDateFormat sdf; - if (sharedPref.getBoolean("24_hour_mode", false)) { - sdf = new SimpleDateFormat("HH:mm zzz"); - } else { - sdf = new SimpleDateFormat("h:mm a zzz"); - } - Date date = launchItem.getNet(); - sdf.setTimeZone(TimeZone.getTimeZone("UTC")); - launchTime = sdf.format(date); - } + SimpleDateFormat sdf; + if (DateFormat.is24HourFormat(context)) { + sdf = Utils.getSimpleDateFormatForUI("MMMM d, yyyy HH:mm zzz"); } else { - launchTime = "To be determined... "; + sdf = Utils.getSimpleDateFormatForUI("MMMM d, yyyy h:mm a zzz"); } - SimpleDateFormat sdf = Utils.getSimpleDateFormatForUI("MMMM d, yyyy"); sdf.toLocalizedPattern(); Date date = launchItem.getNet(); - holder.launch_date_compact.setText(sdf.format(date)); - holder.launch_time.setVisibility(View.GONE); - holder.launch_time.setText("NET: " + launchTime); - holder.launch_time.setVisibility(View.VISIBLE); + holder.launchDateCompact.setText(sdf.format(date)); } if (launchItem.getVidURLs() != null) { @@ -368,29 +319,27 @@ public void onTick(long millisUntilFinished) { if (launchItem.getMission() != null) { - holder.content_mission.setText(launchItem.getMission().getName()); + holder.contentMission.setText(launchItem.getMission().getName()); String description = launchItem.getMission().getDescription(); if (description.length() > 0) { - holder.content_mission_description_view.setVisibility(View.VISIBLE); - holder.content_mission_description.setText(description); + holder.contentMissionDescription.setText(description); } } else { String[] separated = launchItem.getName().split(" \\| "); try { if (separated.length > 0 && separated[1].length() > 4) { - holder.content_mission.setText(separated[1].trim()); + holder.contentMission.setText(separated[1].trim()); } else { - holder.content_mission.setText("Unknown Mission"); + holder.contentMission.setText("Unknown Mission"); } } catch (ArrayIndexOutOfBoundsException exception) { - holder.content_mission.setText("Unknown Mission"); + holder.contentMission.setText("Unknown Mission"); } - holder.content_mission_description_view.setVisibility(View.GONE); } //If pad and agency_menu exist add it to location, otherwise get whats always available - if (launchItem.getLocation() != null) { - holder.location.setText(launchItem.getLocation().getName()); + if (launchItem.getPad().getLocation() != null) { + holder.location.setText(launchItem.getPad().getLocation().getName()); } else { holder.location.setText(""); } @@ -400,41 +349,85 @@ public void onTick(long millisUntilFinished) { } } - private void showStatusDescription(Launch launchItem, ViewHolder holder) { - holder.content_TMinus_status.setVisibility(View.VISIBLE); - holder.content_TMinus_status.setTypeface(Typeface.DEFAULT); - if (night) { - holder.content_TMinus_status.setTextColor(ContextCompat.getColor(context, R.color.dark_theme_secondary_text_color)); + private void countUpTimer(ViewHolder holder, long longdate) { + holder.var = Observable + .interval(1, TimeUnit.SECONDS, AndroidSchedulers.mainThread()) + .subscribe( + time -> { + Calendar currentTime = Calendar.getInstance(); + long timeSince = currentTime.getTimeInMillis() - longdate; + setCountdownView(timeSince, holder); + }); + } + + private void setCountdownView(long millisUntilFinished, ViewHolder holder) { + // Calculate the Days/Hours/Mins/Seconds numerically. + long longDays = millisUntilFinished / 86400000; + long longHours = (millisUntilFinished / 3600000) % 24; + long longMins = (millisUntilFinished / 60000) % 60; + long longSeconds = (millisUntilFinished / 1000) % 60; + + String days; + String hours; + String minutes; + String seconds; + + if (longDays < 10) { + days = "0" + String.valueOf(longDays); + } else { + days = String.valueOf(longDays); + } + + + // Translate those numerical values to string values. + if (longHours < 10) { + hours = "0" + String.valueOf(longHours); } else { - holder.content_TMinus_status.setTextColor(ContextCompat.getColor(context, R.color.colorTextSecondary)); + hours = String.valueOf(longHours); } - if (holder.timer != null) { - holder.timer.cancel(); + + if (longMins < 10) { + minutes = "0" + String.valueOf(longMins); + } else { + minutes = String.valueOf(longMins); } - if (launchItem.getStatus() == 2) { - holder.countdownView.setVisibility(View.GONE); - if (launchItem.getLsp() != null) { - holder.content_TMinus_status.setText(String.format(context.getString(R.string.pending_confirmed_go_specific), launchItem.getLsp().getName())); - } else { - holder.content_TMinus_status.setText(R.string.pending_confirmed_go); - } - } else if (launchItem.getStatus() == 3) { - holder.countdownView.setVisibility(View.GONE); - holder.content_TMinus_status.setText("Launch was a success!"); - } else if (launchItem.getStatus() == 4) { - holder.countdownView.setVisibility(View.GONE); - holder.content_TMinus_status.setText("A launch failure has occurred."); - } else if (launchItem.getStatus() == 5) { - holder.content_TMinus_status.setText("A hold has been placed on the launch."); - } else if (launchItem.getStatus() == 6) { + + if (longSeconds < 10) { + seconds = "0" + String.valueOf(longSeconds); + } else { + seconds = String.valueOf(longSeconds); + } + + + // Update the views + if (Integer.valueOf(days) > 0) { + holder.countdownDays.setText(days); + } else { holder.countdownDays.setText("00"); + } + + if (Integer.valueOf(hours) > 0) { + holder.countdownHours.setText(hours); + } else if (Integer.valueOf(days) > 0) { holder.countdownHours.setText("00"); + } else { + holder.countdownHours.setText("00"); + } + + if (Integer.valueOf(minutes) > 0) { + holder.countdownMinutes.setText(minutes); + } else if (Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { holder.countdownMinutes.setText("00"); + } else { + holder.countdownMinutes.setText("00"); + } + + if (Integer.valueOf(seconds) > 0) { + holder.countdownSeconds.setText(seconds); + } else if (Integer.valueOf(minutes) > 0 || Integer.valueOf(hours) > 0 || Integer.valueOf(days) > 0) { + holder.countdownSeconds.setText("00"); + } else { holder.countdownSeconds.setText("00"); - holder.content_TMinus_status.setText("The launch is currently in flight."); - } else if (launchItem.getStatus() == 7) { - holder.countdownView.setVisibility(View.GONE); - holder.content_TMinus_status.setText("Launch was a partial failure, payload separated into an incorrect orbit."); } } @@ -462,79 +455,61 @@ public int getSectionForPosition(int position) { return 0; } - public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener, OnMapReadyCallback { - public TextView title; - public TextView content; - public TextView location; - public TextView content_mission; - public TextView content_mission_description; - public TextView launch_date_compact; - public TextView launch_time; - public TextView content_status; - public TextView content_TMinus_status; - public TextView watchButton; - public TextView shareButton; - public TextView exploreButton; - public TextView countdownDays; - public TextView countdownHours; - public TextView countdownMinutes; - public TextView countdownSeconds; - public LinearLayout content_mission_description_view; - public ImageView categoryIcon; - public GoogleMap map; - public CountDownTimer timer; - public View countdownView; - public View titleCard; - public TextView contentForecast; - public CardView cardView; + public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { + + @BindView(R.id.categoryIcon) + ImageView categoryIcon; + @BindView(R.id.launch_rocket) + TextView title; + @BindView(R.id.location) + TextView location; + @BindView(R.id.launch_date_compact) + TextView launchDateCompact; + @BindView(R.id.launch_image) + ImageView launchImage; + @BindView(R.id.countdown_days) + TextView countdownDays; + @BindView(R.id.countdown_hours) + TextView countdownHours; + @BindView(R.id.countdown_minutes) + TextView countdownMinutes; + @BindView(R.id.countdown_seconds) + TextView countdownSeconds; + @BindView(R.id.countdown_status) + TextView countdownStatus; + @BindView(R.id.status) + TextView status; + @BindView(R.id.watchButton) + Button watchButton; + @BindView(R.id.shareButton) + Button shareButton; + @BindView(R.id.exploreButton) + Button exploreButton; + @BindView(R.id.content_mission) + TextView contentMission; + @BindView(R.id.content_mission_description) + TextView contentMissionDescription; + @BindView(R.id.landing_icon) + ImageView landingIcon; + @BindView(R.id.landing) + TextView landing; + @BindView(R.id.landing_pill) + View landingView; + @BindView(R.id.status_pill) + CardView statusPill; public View layout; - public MapView map_view; + public CountDownTimer timer; + public Disposable var; //Add content to the card public ViewHolder(View view) { super(view); layout = view; - categoryIcon = view.findViewById(R.id.categoryIcon); - exploreButton = view.findViewById(R.id.exploreButton); - shareButton = view.findViewById(R.id.shareButton); - watchButton = view.findViewById(R.id.watchButton); - title = view.findViewById(R.id.launch_rocket); - location = view.findViewById(R.id.location); - content_mission = view.findViewById(R.id.content_mission); - content_mission_description = view.findViewById( - R.id.content_mission_description); - launch_date_compact = view.findViewById(R.id.launch_date_compact); - launch_time = view.findViewById(R.id.launch_date_full); - content_status = view.findViewById(R.id.content_status); - content_TMinus_status = view.findViewById(R.id.content_TMinus_status); - content_mission_description_view = view.findViewById(R.id.content_mission_description_view); - - countdownDays = view.findViewById(R.id.countdown_days); - countdownHours = view.findViewById(R.id.countdown_hours); - countdownMinutes = view.findViewById(R.id.countdown_minutes); - countdownSeconds = view.findViewById(R.id.countdown_seconds); - countdownView = view.findViewById(R.id.countdown_layout); - cardView = view.findViewById(R.id.card_view); - titleCard = view.findViewById(R.id.TitleCard); - - contentForecast = view.findViewById(R.id.content_forecast); - - map_view = view.findViewById(R.id.map_view); - map_view.setClickable(false); - - titleCard.setOnClickListener(this); + ButterKnife.bind(this, view); + shareButton.setOnClickListener(this); exploreButton.setOnClickListener(this); watchButton.setOnClickListener(this); - map_view.setOnClickListener(this); - - if (map_view != null) { - // Initialise the MapView - map_view.onCreate(null); - // Set the map ready callback to receive the GoogleMap object - map_view.getMapAsync(this); - map_view.setVisibility(View.INVISIBLE); - } } //React to click events. @@ -604,14 +579,14 @@ public void onClick(View v) { case R.id.shareButton: String message; if (launch.getVidURLs().size() > 0) { - if (launch.getLocation() != null) { + if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; - } else if (launch.getLocation() != null) { + } else if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; } else { message = launch.getName() @@ -619,14 +594,14 @@ public void onClick(View v) { + launchDate; } } else { - if (launch.getLocation() != null) { + if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; - } else if (launch.getLocation() != null) { + } else if (launch.getPad().getLocation() != null) { message = launch.getName() + " launching from " - + launch.getLocation().getName() + "\n\n" + + launch.getPad().getLocation().getName() + "\n\n" + launchDate; } else { message = launch.getName() @@ -641,26 +616,6 @@ public void onClick(View v) { .startChooser(); Analytics.getInstance().sendLaunchShared("Explore Button", launch.getName() + "-" + launch.getId().toString()); break; - case R.id.map_view: - String location = launchList.get(position).getLocation().getName(); - location = (location.substring(location.indexOf(",") + 1)); - - Timber.d("FAB: %s ", location); - - double dlat = Double.parseDouble(launchList.get(position).getPad().getLatitude()); - double dlon = Double.parseDouble(launchList.get(position).getPad().getLongitude()); - - Uri gmmIntentUri = Uri.parse("geo:" + dlat + ", " + dlon + "?z=12&q=" + dlat + ", " + dlon); - Intent mapIntent = new Intent(Intent.ACTION_VIEW, gmmIntentUri); - mapIntent.setPackage("com.google.android.apps.maps"); - - Analytics.getInstance().sendLaunchMapClicked(launch.getName()); - - if (mapIntent.resolveActivity(context.getPackageManager()) != null) { - Toast.makeText(context, "Loading " + launchList.get(position).getPad().getName(), Toast.LENGTH_LONG).show(); - context.startActivity(mapIntent); - } - break; case R.id.TitleCard: Timber.d("Explore: %s", launchList.get(position).getId()); Analytics.getInstance().sendButtonClicked("Title Card", launch.getName()); @@ -672,86 +627,5 @@ public void onClick(View v) { break; } } - - @Override - public void onMapReady(GoogleMap googleMap) { - Timber.v("onMapReady called."); - MapsInitializer.initialize(context); - map = googleMap; - setMapLocation(); - } - - private void setMapLocation() { - if (map == null) { - Timber.d("setMapLocation - map is null"); - return; - } - - LaunchLocation data = (LaunchLocation) map_view.getTag(); - if (data == null) { - Timber.d("setMapLocation - data is null"); - return; - } - - map_view.setVisibility(View.VISIBLE); - map.getUiSettings().setMapToolbarEnabled(true); - map.getUiSettings().setZoomGesturesEnabled(false); - map.getUiSettings().setScrollGesturesEnabled(false); - Timber.d("setMapLocation - Moving the camera."); - // Add a marker for this item and set the camera - map.moveCamera(CameraUpdateFactory.newLatLngZoom(data.location, 7f)); - map.addMarker(new MarkerOptions() - .position(data.location) - .title(data.launch.getLocation().getName()) - .snippet(data.launch.getPad().getName()) - .infoWindowAnchor(0.5f, 0.5f)); - - // Set the map type back to normal. - map.setMapType(GoogleMap.MAP_TYPE_NORMAL); - } - - private void bindView(LaunchLocation item) { - Timber.d("bindView - %s", item.launch.getName()); - // Store a reference of the ViewHolder object in the layout. - layout.setTag(this); - // Store a reference to the item in the mapView's tag. We use it to get the - // coordinate of a location, when setting the map location. - map_view.setTag(item); - map_view.onResume(); - setMapLocation(); - } - } - - private static class LaunchLocation { - - public final Launch launch; - public final LatLng location; - - LaunchLocation(Launch launch, LatLng location) { - this.launch = launch; - this.location = location; - } } - - /** - * RecycleListener that completely clears the {@link com.google.android.gms.maps.GoogleMap} - * attached to a row in the RecyclerView. - * Sets the map type to {@link com.google.android.gms.maps.GoogleMap#MAP_TYPE_NONE} and clears - * the map. - */ - public RecyclerView.RecyclerListener mRecycleListener = new RecyclerView.RecyclerListener() { - - @Override - public void onViewRecycled(RecyclerView.ViewHolder holder) { - CardAdapter.ViewHolder mapHolder = (CardAdapter.ViewHolder) holder; - if (mapHolder != null && mapHolder.map != null) { - Timber.d("Clearing map!"); - // Clear the map and free up resources by changing the map type to none. - // Also reset the map when it gets reattached to layout, so the previous map would - // not be displayed. - mapHolder.map.clear(); - mapHolder.map.setMapType(GoogleMap.MAP_TYPE_NONE); - } - } - }; } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/NextLaunchFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/NextLaunchFragment.java index c6b15a9b8..d15db5695 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/NextLaunchFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/next/NextLaunchFragment.java @@ -90,14 +90,10 @@ public class NextLaunchFragment extends BaseFragment implements SwipeRefreshLayo AppCompatCheckBox customSwitch; @BindView(R.id.tbd_launch) SwitchCompat tbdLaunchSwitch; - @BindView(R.id.no_go_launch) - SwitchCompat noGoSwitch; @BindView(R.id.persist_last_launch) SwitchCompat persistLastSwitch; - @BindView(R.id.no_go_info) - AppCompatImageView noGoInfo; @BindView(R.id.tbd_info) - AppCompatImageView tbdInfo; + AppCompatImageView noGoInfo; @BindView(R.id.last_launch_info) AppCompatImageView lastLaunchInfo; @BindView(R.id.action_notification_settings) @@ -133,7 +129,6 @@ public void onCreate(Bundle savedInstanceState) { sharedPref = PreferenceManager.getDefaultSharedPreferences(context); switchPreferences = SwitchPreferences.getInstance(context); nextLaunchDataRepository = new NextLaunchDataRepository(context, getRealm()); - preferredCount = Integer.parseInt(sharedPref.getString("upcoming_value", "5")); setScreenName("Next Launch Fragment"); } @@ -176,21 +171,6 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, mRecyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); mRecyclerView.setHasFixedSize(true); - mRecyclerView.setRecyclerListener(adapter.mRecycleListener); - mRecyclerView.setOnScrollListener(new RecyclerView.OnScrollListener() { - @Override - public void onScrolled(RecyclerView recyclerView, int dx, int dy) { - int topRowVerticalPosition = - (recyclerView == null || recyclerView.getChildCount() == 0) ? 0 : recyclerView.getChildAt(0).getTop(); - mSwipeRefreshLayout.setEnabled(topRowVerticalPosition >= 0); - - } - - @Override - public void onScrollStateChanged(RecyclerView recyclerView, int newState) { - super.onScrollStateChanged(recyclerView, newState); - } - }); //If preference is for small card, landscape tablets get three others get two. if (getResources().getBoolean(R.bool.landscape) && getResources().getBoolean(R.bool.isTablet)) { @@ -255,8 +235,7 @@ private void setUpSwitches() { plesSwitch.setChecked(switchPreferences.getSwitchPles()); vanSwitch.setChecked(switchPreferences.getSwitchVan()); kscSwitch.setChecked(switchPreferences.getSwitchKSC()); - noGoSwitch.setChecked(switchPreferences.getNoGoSwitch()); - tbdLaunchSwitch.setChecked(switchPreferences.getTBDLaunchSwitch()); + tbdLaunchSwitch.setChecked(switchPreferences.getTBDSwitch()); persistLastSwitch.setChecked(switchPreferences.getPersistSwitch()); } @@ -313,6 +292,7 @@ public void onAnimationEnd(Animator animation) { public void fetchData(boolean forceRefresh) { Timber.v("Sending GET_UP_LAUNCHES"); + preferredCount = Integer.parseInt(sharedPref.getString("upcoming_value", "5")); nextLaunchDataRepository.getNextUpcomingLaunches(preferredCount, forceRefresh, new Callbacks.NextLaunchesCallback() { @Override public void onLaunchesLoaded(RealmResults launches) { @@ -338,7 +318,7 @@ public void onError(String message, @Nullable Throwable throwable) { private void updateAdapter(RealmResults launches) { adapter.clear(); - + preferredCount = Integer.parseInt(sharedPref.getString("upcoming_value", "5")); if (launches.size() >= preferredCount) { no_data.setVisibility(View.GONE); setLayoutManager(preferredCount); @@ -615,16 +595,10 @@ public void all_switch() { setUpSwitches(); } - @OnClick(R.id.no_go_launch) - public void noGoSwitch() { - confirm(); - switchPreferences.setNoGoSwitch(noGoSwitch.isChecked()); - } - @OnClick(R.id.tbd_launch) - public void tbdLaunchSwitch() { + public void noGoSwitch() { confirm(); - switchPreferences.setTBDLaunchSwitch(tbdLaunchSwitch.isChecked()); + switchPreferences.setNoGoSwitch(tbdLaunchSwitch.isChecked()); } @OnClick(R.id.persist_last_launch) @@ -641,16 +615,13 @@ public void onNotificationSettingsClicked() { startActivity(intent); } - @OnClick({R.id.no_go_info, R.id.tbd_info, R.id.last_launch_info}) + @OnClick({R.id.tbd_info, R.id.last_launch_info}) public void onViewClicked(View view) { MaterialDialog.Builder dialog = new MaterialDialog.Builder(context); dialog.positiveText("Ok"); switch (view.getId()) { - case R.id.no_go_info: - dialog.title(R.string.no_go).content(R.string.no_go_description).show(); - break; case R.id.tbd_info: - dialog.title(R.string.to_be_determined).content(R.string.to_be_determined_description).show(); + dialog.title(R.string.no_go).content(R.string.no_go_description).show(); break; case R.id.last_launch_info: dialog.title(R.string.launch_info).content(R.string.launch_info_description).show(); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/LauncherFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/LauncherFragment.java index 7f0199ea8..eb495fdfe 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/LauncherFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/LauncherFragment.java @@ -19,6 +19,9 @@ import java.util.Arrays; import java.util.List; +import butterknife.BindView; +import butterknife.ButterKnife; +import cz.kinst.jakub.view.SimpleStatefulLayout; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.RetroFitFragment; import me.calebjones.spacelaunchnow.data.models.main.Agency; @@ -29,6 +32,7 @@ import me.calebjones.spacelaunchnow.utils.analytics.Analytics; import me.calebjones.spacelaunchnow.utils.OnItemClickListener; import me.calebjones.spacelaunchnow.utils.views.SnackbarHandler; +import okhttp3.CacheControl; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -41,9 +45,14 @@ public class LauncherFragment extends RetroFitFragment implements SwipeRefreshLa private List items = new ArrayList<>(); private Context context; private View view; - private RecyclerView mRecyclerView; - private CoordinatorLayout coordinatorLayout; - private SwipeRefreshLayout swipeRefreshLayout; + @BindView(R.id.stateful_view) + SimpleStatefulLayout statefulView; + @BindView(R.id.vehicle_detail_list) + RecyclerView mRecyclerView; + @BindView(R.id.vehicle_coordinator) + CoordinatorLayout coordinatorLayout; + @BindView(R.id.swiperefresh) + SwipeRefreshLayout swipeRefreshLayout; @Override @@ -59,6 +68,7 @@ public View onCreateView(LayoutInflater inflater, ViewGroup container, super.onCreateView(inflater, container, savedInstanceState); view = inflater.inflate(R.layout.fragment_launch_vehicles, container, false); + ButterKnife.bind(this, view); mRecyclerView = view.findViewById(R.id.vehicle_detail_list); coordinatorLayout = view.findViewById(R.id.vehicle_coordinator); @@ -91,6 +101,8 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { adapter.setOnItemClickListener(recyclerRowClickListener); mRecyclerView.setAdapter(adapter); Timber.v("Returning view."); + statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> loadJSON(false)); return view; } @@ -100,21 +112,15 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { public void onResume() { super.onResume(); Timber.v("onResume"); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - loadJSON(); - } - }, 100); + new Handler().postDelayed(() -> loadJSON(false), 100); } - private void loadJSON() { + private void loadJSON(boolean forceRefresh) { Timber.v("Loading vehicles..."); showLoading(); SpaceLaunchNowService request = getSpaceLaunchNowRetrofit().create(SpaceLaunchNowService.class); Call call = request.getAgencies(true, "detailed"); - call.enqueue(new Callback() { @Override public void onResponse(Call call, Response response) { @@ -132,9 +138,11 @@ public void onResponse(Call call, Response respo Timber.v("Success %s", response.message()); items = jsonResponse.getAgencies(); adapter.addItems(items); + statefulView.showContent(); Analytics.getInstance().sendNetworkEvent("LAUNCHER_INFORMATION", call.request().url().toString(), true); } else { + statefulView.showEmpty(); Timber.e(ErrorUtil.parseSpaceLaunchNowError(response).message()); SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, ErrorUtil.parseSpaceLaunchNowError(response).message()); } @@ -145,6 +153,7 @@ public void onResponse(Call call, Response respo public void onFailure(Call call, Throwable t) { Timber.e(t.getMessage()); hideLoading(); + statefulView.showOffline(); SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, t.getLocalizedMessage()); Analytics.getInstance().sendNetworkEvent("VEHICLE_INFORMATION", call.request().url().toString(), false, t.getLocalizedMessage()); } @@ -177,6 +186,6 @@ private void showLoading() { @Override public void onRefresh() { Analytics.getInstance().sendButtonClicked("Launcher Refresh"); - loadJSON(); + loadJSON(true); } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/VehicleAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/VehicleAdapter.java index c8470bfa6..ac9548250 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/VehicleAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/launcher/VehicleAdapter.java @@ -1,7 +1,6 @@ package me.calebjones.spacelaunchnow.ui.main.vehicles.launcher; import android.content.Context; -import android.support.annotation.Nullable; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -11,7 +10,6 @@ import android.widget.TextView; import com.bumptech.glide.request.RequestOptions; -import com.github.florent37.glidepalette.BitmapPalette; import com.github.florent37.glidepalette.GlidePalette; import java.util.ArrayList; @@ -31,14 +29,14 @@ public class VehicleAdapter extends RecyclerView.Adapter launchers = new ArrayList<>(); + private List agencies = new ArrayList<>(); private OnItemClickListener onItemClickListener; private boolean night = false; private RequestOptions requestOptions; private int palette; public VehicleAdapter(Context context) { - launchers = new ArrayList(); + agencies = new ArrayList(); this.mContext = context; night = ListPreferences.getInstance(mContext).isNightModeActive(mContext); @@ -55,13 +53,13 @@ public VehicleAdapter(Context context) { } public void addItems(List items) { - if (this.launchers == null) { - this.launchers = items; - } else if (this.launchers.size() == 0) { - this.launchers.addAll(items); + if (this.agencies == null) { + this.agencies = items; + } else if (this.agencies.size() == 0) { + this.agencies.addAll(items); } else { - this.launchers.clear(); - this.launchers.addAll(items); + this.agencies.clear(); + this.agencies.addAll(items); } notifyDataSetChanged(); } @@ -79,7 +77,7 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { @Override public void onBindViewHolder(final ViewHolder holder, int i) { - Agency launcher = launchers.get(i); + Agency launcher = agencies.get(i); Timber.v("onBindViewHolder %s", launcher.getName()); GlideApp.with(mContext) @@ -87,40 +85,37 @@ public void onBindViewHolder(final ViewHolder holder, int i) { .apply(requestOptions) .listener(GlidePalette.with(launcher.getImageUrl()) .use(palette) - .intoCallBack(new BitmapPalette.CallBack() { - @Override - public void onPaletteLoaded(@Nullable Palette palette) { - Palette.Swatch color = null; - if (palette != null) { - if (night) { - if (palette.getDarkMutedSwatch() != null) { - color = palette.getDarkMutedSwatch(); - } else if (palette.getDarkVibrantSwatch() != null) { - color = palette.getDarkVibrantSwatch(); - } - } else { - if (palette.getVibrantSwatch() != null) { - color = palette.getVibrantSwatch(); - } else if (palette.getMutedSwatch() != null) { - color = palette.getMutedSwatch(); - } + .intoCallBack(palette -> { + Palette.Swatch color = null; + if (palette != null) { + if (night) { + if (palette.getDarkMutedSwatch() != null) { + color = palette.getDarkMutedSwatch(); + } else if (palette.getDarkVibrantSwatch() != null) { + color = palette.getDarkVibrantSwatch(); } - if (color != null) { - holder.textContainer.setBackgroundColor(color.getRgb()); + } else { + if (palette.getVibrantSwatch() != null) { + color = palette.getVibrantSwatch(); + } else if (palette.getMutedSwatch() != null) { + color = palette.getMutedSwatch(); } } + if (color != null) { + holder.textContainer.setBackgroundColor(color.getRgb()); + } } }) .intoBackground(holder.textContainer, GlidePalette.Swatch.RGB) .crossfade(true)) .into(holder.picture); - holder.subTitle.setText(launcher.getLaunchers_string()); + holder.subTitle.setText(launcher.getType()); holder.name.setText(launcher.getName()); } @Override public int getItemCount() { - return launchers.size(); + return agencies.size(); } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { @@ -151,6 +146,4 @@ public void onClick(View v) { onItemClickListener.onClick(v, getAdapterPosition()); } } - - } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterAdapter.java index ae13bdf2f..1ba7fa3d4 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterAdapter.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterAdapter.java @@ -1,7 +1,6 @@ package me.calebjones.spacelaunchnow.ui.main.vehicles.orbiter; import android.content.Context; -import android.support.annotation.Nullable; import android.support.v7.graphics.Palette; import android.support.v7.widget.RecyclerView; import android.view.LayoutInflater; @@ -11,7 +10,6 @@ import android.widget.TextView; import com.bumptech.glide.request.RequestOptions; -import com.github.florent37.glidepalette.BitmapPalette; import com.github.florent37.glidepalette.GlidePalette; import java.util.ArrayList; @@ -19,6 +17,7 @@ import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.content.database.ListPreferences; +import me.calebjones.spacelaunchnow.data.models.main.Agency; import me.calebjones.spacelaunchnow.data.models.main.Orbiter; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.OnItemClickListener; @@ -31,14 +30,14 @@ public class OrbiterAdapter extends RecyclerView.Adapter orbiters = new ArrayList(); + private List agencies = new ArrayList(); private OnItemClickListener onItemClickListener; private boolean night = false; private RequestOptions requestOptions; private int palette; public OrbiterAdapter(Context context) { - orbiters = new ArrayList(); + agencies = new ArrayList(); this.mContext = context; night = ListPreferences.getInstance(mContext).isNightModeActive(mContext); @@ -54,14 +53,14 @@ public OrbiterAdapter(Context context) { .centerCrop(); } - public void addItems(List items) { - if (this.orbiters == null) { - this.orbiters = items; - } else if (this.orbiters.size() == 0) { - this.orbiters.addAll(items); + public void addItems(List items) { + if (this.agencies == null) { + this.agencies = items; + } else if (this.agencies.size() == 0) { + this.agencies.addAll(items); } else { - this.orbiters.clear(); - this.orbiters.addAll(items); + this.agencies.clear(); + this.agencies.addAll(items); } notifyDataSetChanged(); } @@ -79,47 +78,53 @@ public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { @Override public void onBindViewHolder(final ViewHolder holder, int i) { - final Orbiter orbiter = orbiters.get(i); - Timber.v("onBindViewHolder %s", orbiter.getName()); - - GlideApp.with(mContext) - .load(orbiter.getImageURL()) - .apply(requestOptions) - .listener(GlidePalette.with(orbiter.getImageURL()) - .use(palette) - .intoCallBack(new BitmapPalette.CallBack() { - @Override - public void onPaletteLoaded(@Nullable Palette palette) { - Palette.Swatch color = null; - if (palette != null) { - if (night) { - if (palette.getDarkMutedSwatch() != null) { - color = palette.getDarkMutedSwatch(); - } else if (palette.getDarkVibrantSwatch() != null) { - color = palette.getDarkVibrantSwatch(); + final Agency agency = agencies.get(i); + Timber.v("onBindViewHolder %s", agency.getName()); + + holder.name.setText(agency.getName()); + holder.subTitle.setText(agency.getType()); + + if (agency.getOrbiters() != null && agency.getOrbiters().size() > 0) { + Orbiter firstOrbiter = agency.getOrbiters().get(0); + + if (firstOrbiter.getImageURL() != null) { + GlideApp.with(mContext) + .load(firstOrbiter.getImageURL()) + .apply(requestOptions) + .listener(GlidePalette.with(firstOrbiter.getImageURL()) + .use(palette) + .intoCallBack(palette -> { + Palette.Swatch color = null; + if (palette != null) { + if (night) { + if (palette.getDarkMutedSwatch() != null) { + color = palette.getDarkMutedSwatch(); + } else if (palette.getDarkVibrantSwatch() != null) { + color = palette.getDarkVibrantSwatch(); + } + } else { + if (palette.getVibrantSwatch() != null) { + color = palette.getVibrantSwatch(); + } else if (palette.getMutedSwatch() != null) { + color = palette.getMutedSwatch(); + } } - } else { - if (palette.getVibrantSwatch() != null) { - color = palette.getVibrantSwatch(); - } else if (palette.getMutedSwatch() != null) { - color = palette.getMutedSwatch(); + if (color != null) { + holder.textContainer.setBackgroundColor(color.getRgb()); } } - if (color != null) { - holder.textContainer.setBackgroundColor(color.getRgb()); - } - } - } - }) - .crossfade(true)) - .into(holder.picture); - holder.name.setText(orbiter.getName()); - holder.subTitle.setText(orbiter.getAgency()); + }) + .crossfade(true)) + .into(holder.picture); + } + holder.subTitle.setText(firstOrbiter.getName()); + } + } @Override public int getItemCount() { - return orbiters.size(); + return agencies.size(); } public class ViewHolder extends RecyclerView.ViewHolder implements View.OnClickListener { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterFragment.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterFragment.java index b07f6324d..faf6a5610 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterFragment.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/main/vehicles/orbiter/OrbiterFragment.java @@ -23,12 +23,18 @@ import java.util.Arrays; import java.util.List; +import butterknife.BindView; +import butterknife.ButterKnife; +import cz.kinst.jakub.view.SimpleStatefulLayout; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.RetroFitFragment; +import me.calebjones.spacelaunchnow.data.models.main.Agency; import me.calebjones.spacelaunchnow.data.models.main.Orbiter; import me.calebjones.spacelaunchnow.data.networking.error.ErrorUtil; import me.calebjones.spacelaunchnow.data.networking.interfaces.SpaceLaunchNowService; +import me.calebjones.spacelaunchnow.data.networking.responses.base.AgencyResponse; import me.calebjones.spacelaunchnow.data.networking.responses.base.OrbiterResponse; +import me.calebjones.spacelaunchnow.ui.launcher.LauncherDetailActivity; import me.calebjones.spacelaunchnow.ui.orbiter.OrbiterDetailActivity; import me.calebjones.spacelaunchnow.utils.analytics.Analytics; import me.calebjones.spacelaunchnow.utils.OnItemClickListener; @@ -43,13 +49,18 @@ public class OrbiterFragment extends RetroFitFragment implements SwipeRefreshLay private Context context; private View view; private OrbiterAdapter adapter; - private RecyclerView mRecyclerView; private GridLayoutManager layoutManager; - private CoordinatorLayout coordinatorLayout; - private SwipeRefreshLayout swipeRefreshLayout; + private List items = new ArrayList(); - private List items = new ArrayList(); - public static SparseArray photoCache = new SparseArray(1); + + @BindView(R.id.stateful_view) + SimpleStatefulLayout statefulView; + @BindView(R.id.vehicle_detail_list) + RecyclerView mRecyclerView; + @BindView(R.id.vehicle_coordinator) + CoordinatorLayout coordinatorLayout; + @BindView(R.id.swiperefresh) + SwipeRefreshLayout swipeRefreshLayout; @Override public void onCreate(Bundle savedInstanceState) { @@ -62,21 +73,17 @@ public void onCreate(Bundle savedInstanceState) { public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { super.onCreateView(inflater, container, savedInstanceState); - view = inflater.inflate(R.layout.fragment_launch_vehicles, container, false); - - mRecyclerView = (RecyclerView) view.findViewById(R.id.vehicle_detail_list); - coordinatorLayout = (CoordinatorLayout) view.findViewById(R.id.vehicle_coordinator); - swipeRefreshLayout = (SwipeRefreshLayout) view.findViewById(R.id.swiperefresh); + ButterKnife.bind(this, view); swipeRefreshLayout.setOnRefreshListener(this); if (getResources().getBoolean(R.bool.landscape) && getResources().getBoolean(R.bool.isTablet)) { - layoutManager = new GridLayoutManager(getActivity().getApplicationContext(), 3); + layoutManager = new GridLayoutManager(context, 3); } else if (getResources().getBoolean(R.bool.landscape) || getResources().getBoolean(R.bool.isTablet)) { - layoutManager = new GridLayoutManager(getActivity().getApplicationContext(), 2); + layoutManager = new GridLayoutManager(context, 2); } else { - layoutManager = new GridLayoutManager(getActivity().getApplicationContext(), 1); + layoutManager = new GridLayoutManager(context, 1); } mRecyclerView.setLayoutManager(layoutManager); @@ -96,18 +103,15 @@ public void onScrollStateChanged(RecyclerView recyclerView, int newState) { }); adapter.setOnItemClickListener(recyclerRowClickListener); mRecyclerView.setAdapter(adapter); + statefulView.showProgress(); + statefulView.setOfflineRetryOnClickListener(v -> loadJSON()); return view; } @Override public void onResume() { if (adapter.getItemCount() == 0) { - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - loadJSON(); - } - }, 100); + new Handler().postDelayed(() -> loadJSON(), 100); } super.onResume(); } @@ -117,33 +121,43 @@ private void loadJSON() { showLoading(); SpaceLaunchNowService request = getSpaceLaunchNowRetrofit().create(SpaceLaunchNowService.class); - Call call = request.getOrbiter(); - call.enqueue(new Callback() { + Call call = request.getAgenciesWithOrbiters(true); + call.enqueue(new Callback() { @Override - public void onResponse(Call call, Response response) { + public void onResponse(Call call, Response response) { + Timber.v("onResponse"); + if (response.raw().cacheResponse() != null) { + Timber.v("Response pulled from cache."); + } + + if (response.raw().networkResponse() != null) { + Timber.v("Response pulled from network."); + } + if (response.isSuccessful()) { + AgencyResponse jsonResponse = response.body(); Timber.v("Success %s", response.message()); - OrbiterResponse jsonResponse = response.body(); - items = new ArrayList<>(Arrays.asList(jsonResponse.getOrbiters())); + items = jsonResponse.getAgencies(); + statefulView.showContent(); adapter.addItems(items); - Analytics.getInstance().sendNetworkEvent("ORBITER_INFORMATION", call.request().url().toString(), true); + Analytics.getInstance().sendNetworkEvent("LAUNCHER_INFORMATION", call.request().url().toString(), true); + } else { + statefulView.showEmpty(); Timber.e(ErrorUtil.parseSpaceLaunchNowError(response).message()); - if (OrbiterFragment.this.getUserVisibleHint()) { - SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, ErrorUtil.parseSpaceLaunchNowError(response).message()); - } + SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, ErrorUtil.parseSpaceLaunchNowError(response).message()); } hideLoading(); + } @Override - public void onFailure(Call call, Throwable t) { + public void onFailure(Call call, Throwable t) { Timber.e(t.getMessage()); + statefulView.showOffline(); hideLoading(); - if (OrbiterFragment.this.getUserVisibleHint()) { - SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, t.getLocalizedMessage()); - } - Analytics.getInstance().sendNetworkEvent("ORBITER_INFORMATION", call.request().url().toString(), false, t.getLocalizedMessage()); + SnackbarHandler.showErrorSnackbar(context, coordinatorLayout, t.getLocalizedMessage()); + Analytics.getInstance().sendNetworkEvent("VEHICLE_INFORMATION", call.request().url().toString(), false, t.getLocalizedMessage()); } }); } @@ -160,41 +174,15 @@ private void showLoading() { } } - private OnItemClickListener recyclerRowClickListener = new OnItemClickListener() { - - @Override - public void onClick(View v, int position) { - - Gson gson = new Gson(); - String jsonItem = gson.toJson(items.get(position)); - Analytics.getInstance().sendButtonClicked("Orbiter clicked", items.get(position).getName()); - - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { - Timber.d("Starting Activity at %s", position); - - Intent detailIntent = new Intent(getActivity(), OrbiterDetailActivity.class); - detailIntent.putExtra("position", position + 1); - detailIntent.putExtra("family", items.get(position).getName()); - detailIntent.putExtra("agency", items.get(position).getAgency()); - detailIntent.putExtra("json", jsonItem); + private OnItemClickListener recyclerRowClickListener = (v, position) -> { + Analytics.getInstance().sendButtonClicked("Launcher clicked", items.get(position).getName()); + Gson gson = new Gson(); + String jsonItem = gson.toJson(items.get(position)); - ImageView coverImage = (ImageView) v.findViewById(R.id.picture); - ((ViewGroup) coverImage.getParent()).setTransitionGroup(false); - photoCache.put(position, coverImage.getDrawingCache()); - - // Setup the transition to the detail activity - ActivityOptions options = ActivityOptions.makeSceneTransitionAnimation(getActivity(), - new Pair(coverImage, "cover" + position + 1)); - - startActivity(detailIntent, options.toBundle()); - } else { - Intent intent = new Intent(getActivity(), OrbiterDetailActivity.class); - intent.putExtra("family", items.get(position).getName()); - intent.putExtra("agency", items.get(position).getAgency()); - intent.putExtra("json", jsonItem); - startActivity(intent); - } - } + Intent intent = new Intent(getActivity(), OrbiterDetailActivity.class); + intent.putExtra("name", items.get(position).getName()); + intent.putExtra("json", jsonItem); + startActivity(intent); }; @Override diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailActivity.java index f22949984..914a4ca13 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailActivity.java @@ -1,40 +1,44 @@ package me.calebjones.spacelaunchnow.ui.orbiter; -import android.annotation.TargetApi; -import android.app.Activity; import android.content.Context; import android.content.Intent; +import android.graphics.Color; +import android.net.Uri; import android.os.Build; import android.os.Bundle; -import android.support.annotation.Nullable; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CollapsingToolbarLayout; +import android.support.design.widget.CoordinatorLayout; import android.support.v4.content.ContextCompat; import android.support.v7.graphics.Palette; +import android.support.v7.widget.LinearLayoutManager; +import android.support.v7.widget.RecyclerView; import android.support.v7.widget.Toolbar; -import android.transition.Slide; import android.view.Menu; +import android.view.MenuInflater; import android.view.MenuItem; -import android.view.View; import android.view.ViewPropertyAnimator; import android.widget.ImageView; import android.widget.TextView; import android.widget.Toast; -import com.github.florent37.glidepalette.BitmapPalette; +import com.afollestad.materialdialogs.MaterialDialog; import com.github.florent37.glidepalette.GlidePalette; import com.google.gson.Gson; +import com.mikepenz.fontawesome_typeface_library.FontAwesome; +import com.mikepenz.iconics.IconicsDrawable; import de.hdodenhof.circleimageview.CircleImageView; +import io.realm.RealmResults; import me.calebjones.spacelaunchnow.R; import me.calebjones.spacelaunchnow.common.BaseActivity; import me.calebjones.spacelaunchnow.content.database.ListPreferences; -import me.calebjones.spacelaunchnow.data.models.main.Orbiter; +import me.calebjones.spacelaunchnow.data.models.main.Agency; +import me.calebjones.spacelaunchnow.data.models.main.LauncherConfig; import me.calebjones.spacelaunchnow.ui.main.MainActivity; import me.calebjones.spacelaunchnow.ui.settings.SettingsActivity; import me.calebjones.spacelaunchnow.utils.GlideApp; import me.calebjones.spacelaunchnow.utils.Utils; -import me.calebjones.spacelaunchnow.utils.customtab.CustomTabActivityHelper; import me.calebjones.spacelaunchnow.utils.views.CustomOnOffsetChangedListener; import timber.log.Timber; @@ -42,34 +46,33 @@ public class OrbiterDetailActivity extends BaseActivity implements AppBarLayout. private static final int PERCENTAGE_TO_ANIMATE_AVATAR = 20; private boolean mIsAvatarShown = true; - - private ListPreferences sharedPreference; - private android.content.SharedPreferences SharedPreferences; - private CustomTabActivityHelper customTabActivityHelper; - private View view, title_container, gridview; private Context context; - private TextView toolbarTitle, detail_rocket, detail_vehicle_agency, - orbiter_title, orbiter_description, wikiButton, orbiter_history, orbiter_history_description; - private View orbiter_vehicle_card; + private RecyclerView mRecyclerView; + private TextView toolbarSubTitle, toolbarTitle; private ImageView detail_profile_backdrop; private CircleImageView detail_profile_image; + private OrbiterDetailAdapter adapter; + private RealmResults rocketLaunches; private AppBarLayout appBarLayout; - private CollapsingToolbarLayout collapsingToolbarLayout; + private CollapsingToolbarLayout collapsingToolbar; private int mMaxScrollSize; + private ListPreferences sharedPreference; + private int statusColor; + private CoordinatorLayout coordinatorLayout; private CustomOnOffsetChangedListener customOnOffsetChangedListener; public OrbiterDetailActivity() { - super("Orbiter Detail Activity"); + super("Launcher Detail Activity"); } @Override protected void onCreate(Bundle savedInstanceState) { - int m_theme; - final int statusColor; this.context = getApplicationContext(); + setTheme(R.style.BaseAppTheme); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_vehicle_list); sharedPreference = ListPreferences.getInstance(this.context); - customTabActivityHelper = new CustomTabActivityHelper(); if (sharedPreference.isNightModeActive(this)) { statusColor = ContextCompat.getColor(context, R.color.darkPrimary_dark); @@ -77,54 +80,33 @@ protected void onCreate(Bundle savedInstanceState) { statusColor = ContextCompat.getColor(context, R.color.colorPrimaryDark); } - m_theme = R.style.BaseAppTheme; - - setTheme(m_theme); - - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_orbiter_detail); - - Toolbar toolbar = (Toolbar) findViewById(R.id.detail_toolbar); - toolbarTitle = (TextView) findViewById(R.id.title_text); - detail_rocket = (TextView) findViewById(R.id.detail_title); - detail_vehicle_agency = (TextView) findViewById(R.id.detail_sub_title); - detail_profile_image = (CircleImageView) findViewById(R.id.detail_profile_image); - detail_profile_backdrop = (ImageView) findViewById(R.id.detail_profile_backdrop); - orbiter_title = (TextView) findViewById(R.id.orbiter_title); - orbiter_description = (TextView) findViewById(R.id.orbiter_description); - wikiButton = (TextView) findViewById(R.id.wikiButton); - appBarLayout = (AppBarLayout) findViewById(R.id.detail_appbar); - orbiter_history = (TextView) findViewById(R.id.orbiter_history); - orbiter_history_description = (TextView) findViewById(R.id.orbiter_history_description); - orbiter_vehicle_card = findViewById(R.id.orbiter_vehicle_card); - title_container = findViewById(R.id.detail_title_container); - collapsingToolbarLayout = findViewById(R.id.collapsing); - gridview = findViewById(R.id.vehicle_detail_list); + Toolbar toolbar = findViewById(R.id.detail_toolbar); + toolbarSubTitle = findViewById(R.id.detail_sub_title); + toolbarTitle = findViewById(R.id.detail_title); + detail_profile_image = findViewById(R.id.detail_profile_image); + detail_profile_backdrop = findViewById(R.id.detail_profile_backdrop); + collapsingToolbar = findViewById(R.id.main_collapsing_bar); + coordinatorLayout = findViewById(R.id.coordinatorLayout); + appBarLayout = findViewById(R.id.detail_appbar); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { // Fab button detail_profile_image.setScaleX(0); detail_profile_image.setScaleY(0); -// setupWindowAnimations(); - - // Recover items from the intent - final int position = getIntent().getIntExtra("position", 0); - Timber.d("Position %s", position); - // Add a listener to get noticed when the transition ends to animate the view ViewPropertyAnimator showTitleAnimator = Utils.showViewByScale(detail_profile_image); showTitleAnimator.setStartDelay(500); } else { detail_profile_image.setScaleX(1); detail_profile_image.setScaleY(1); } - customOnOffsetChangedListener = new CustomOnOffsetChangedListener(statusColor, getWindow()); appBarLayout.addOnOffsetChangedListener(this); appBarLayout.addOnOffsetChangedListener(customOnOffsetChangedListener); mMaxScrollSize = appBarLayout.getTotalScrollRange(); + if (toolbar != null) { setSupportActionBar(toolbar); if (getSupportActionBar() != null) { @@ -133,74 +115,82 @@ protected void onCreate(Bundle savedInstanceState) { getSupportActionBar().setDisplayShowTitleEnabled(false); } } - displayOrbiterDetails(); + adapter = new OrbiterDetailAdapter(context, this); + mRecyclerView = findViewById(R.id.vehicle_detail_list); + LinearLayoutManager linearLayoutManager = new LinearLayoutManager(this, LinearLayoutManager.VERTICAL, false); + mRecyclerView.setLayoutManager(linearLayoutManager); + mRecyclerView.setAdapter(adapter); + displayRockets(); } - public void displayOrbiterDetails() { - final Activity activity = this; - final Context context = this; - + public void displayRockets() { Intent intent = getIntent(); Gson gson = new Gson(); - final Orbiter orbiter = gson.fromJson(intent.getStringExtra("json"), Orbiter.class); + final Agency agency = gson.fromJson(intent.getStringExtra("json"), Agency.class); - if (orbiter == null){ - Toast.makeText(context, R.string.error_orbiter_details, Toast.LENGTH_SHORT).show(); + if (agency == null) { + Toast.makeText(context, R.string.error_launch_details, Toast.LENGTH_SHORT).show(); Timber.e("Error - Unable to load launch details."); Intent homeIntent = new Intent(this, MainActivity.class); startActivity(homeIntent); } - detail_rocket.setText(String.format("%s Spacecraft", orbiter.getName())); - detail_vehicle_agency.setText(orbiter.getName()); + toolbarSubTitle.setText(agency.getType()); + toolbarTitle.setText(agency.getName()); - GlideApp.with(this) - .load(orbiter.getImageURL()) - .centerCrop() - .into(detail_profile_backdrop); + if (agency.getOrbiters() != null) { + adapter.clear(); + adapter.addItems(agency.getOrbiters()); + } + applyProfileBackdrop(agency.getImageUrl()); + applyProfileLogo(agency.getNationUrl()); + } + + private void applyProfileBackdrop(String drawableURL) { + Timber.d("OrbiterDetailActivity - Loading Backdrop Image url: %s ", drawableURL); int palette; if (ListPreferences.getInstance(context).isNightModeActive(context)) { palette = GlidePalette.Profile.MUTED_DARK; } else { palette = GlidePalette.Profile.VIBRANT; } - GlideApp.with(this) - .load(orbiter.getImageURL()) + .load(drawableURL) .centerCrop() - .listener(GlidePalette.with(orbiter.getImageURL()) + .listener(GlidePalette.with(drawableURL) .use(palette) - .intoCallBack(new BitmapPalette.CallBack() { - @Override - public void onPaletteLoaded(@Nullable Palette palette) { - if (ListPreferences.getInstance(context).isNightModeActive(context)) { - if (palette != null) { - Palette.Swatch color = null; - if (palette.getDarkMutedSwatch() != null) { - color = palette.getDarkMutedSwatch(); - } else if (palette.getDarkVibrantSwatch() != null){ - color = palette.getDarkVibrantSwatch(); - } - if (color != null) { - collapsingToolbarLayout.setContentScrimColor(color.getRgb()); - customOnOffsetChangedListener.updateStatusColor(color.getRgb()); - appBarLayout.setBackgroundColor(color.getRgb()); - } + .intoCallBack(palette1 -> { + if (ListPreferences.getInstance(context).isNightModeActive(context)) { + if (palette1 != null) { + Palette.Swatch color = null; + if (palette1.getDarkMutedSwatch() != null) { + color = palette1.getDarkMutedSwatch(); + } else if (palette1.getDarkVibrantSwatch() != null) { + color = palette1.getDarkVibrantSwatch(); } - } else { - if (palette != null) { - Palette.Swatch color = null; - if (palette.getVibrantSwatch() != null) { - color = palette.getVibrantSwatch(); - } else if (palette.getMutedSwatch() != null){ - color = palette.getMutedSwatch(); - } - if (color != null) { - collapsingToolbarLayout.setContentScrimColor(color.getRgb()); - customOnOffsetChangedListener.updateStatusColor(color.getRgb()); - appBarLayout.setBackgroundColor(color.getRgb()); - } + if (color != null) { + collapsingToolbar.setContentScrimColor(color.getRgb()); + customOnOffsetChangedListener.updateStatusColor(color.getRgb()); + appBarLayout.setBackgroundColor(color.getRgb()); + adapter.updateColor(color.getRgb()); + adapter.notifyDataSetChanged(); + } + } + } else { + if (palette1 != null) { + Palette.Swatch color = null; + if (palette1.getVibrantSwatch() != null) { + color = palette1.getVibrantSwatch(); + } else if (palette1.getMutedSwatch() != null) { + color = palette1.getMutedSwatch(); + } + if (color != null) { + collapsingToolbar.setContentScrimColor(color.getRgb()); + customOnOffsetChangedListener.updateStatusColor(color.getRgb()); + appBarLayout.setBackgroundColor(color.getRgb()); + adapter.updateColor(color.getRgb()); + adapter.notifyDataSetChanged(); } } } @@ -208,58 +198,24 @@ public void onPaletteLoaded(@Nullable Palette palette) { .crossfade(true)) .into(detail_profile_backdrop); + } + + private void applyProfileLogo(String url) { + Timber.d("OrbiterDetailActivity - Loading Profile Image url: %s ", url); + GlideApp.with(this) - .load(orbiter.getNationURL()) + .load(url) .centerCrop() .placeholder(R.drawable.icon_international) .into(detail_profile_image); - - //Set up history information - orbiter_history.setText(String.format(getString(R.string.spacecraft_history), orbiter.getName())); - orbiter_history_description.setText(orbiter.getHistory()); - - if (orbiter.getWikiLink() != null && orbiter.getWikiLink().length() > 0) { - wikiButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - Utils.openCustomTab(activity, context, orbiter.getWikiLink()); - } - }); - } else { - wikiButton.setVisibility(View.INVISIBLE); - } - - //Set up vehicle card Information - orbiter_title.setText(String.format(getString(R.string.spacecraft_details), orbiter.getName())); - orbiter_description.setText(orbiter.getDetails()); - } - - public void onStart() { - super.onStart(); - Timber.v("LaunchDetailActivity onStart!"); - customTabActivityHelper.bindCustomTabsService(this); - } - - public void onStop() { - super.onStop(); - Timber.v("LaunchDetailActivity onStop!"); - customTabActivityHelper.unbindCustomTabsService(this); - } - - - @TargetApi(Build.VERSION_CODES.LOLLIPOP) - private void setupWindowAnimations() { - Slide slide = new Slide(); - slide.setDuration(1000); - getWindow().setReturnTransition(slide); - getWindow().setEnterTransition(slide); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. - getMenuInflater().inflate(R.menu.main_menu, menu); + MenuInflater inflater = getMenuInflater(); + inflater.inflate(R.menu.info_menu, menu); return true; } @@ -282,6 +238,26 @@ public boolean onOptionsItemSelected(MenuItem item) { return true; } + if (id == R.id.info) { + new MaterialDialog.Builder(this) + .title(R.string.improve_our_data) + .icon(new IconicsDrawable(this) + .icon(FontAwesome.Icon.faw_discord) + .color(Color.rgb(114, 137, 218)) + .sizeDp(24)) + .content(R.string.improve_our_data_content) + .negativeText(R.string.button_no) + .positiveText(R.string.ok) + .onNegative((dialog, which) -> dialog.dismiss()) + .onPositive((dialog, which) -> { + String discordUrl = getString(R.string.discord_url); + Intent discordIntent = new Intent(Intent.ACTION_VIEW); + discordIntent.setData(Uri.parse(discordUrl)); + startActivity(discordIntent); + }) + .show(); + } + return super.onOptionsItemSelected(item); } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailAdapter.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailAdapter.java new file mode 100644 index 000000000..b5d16e0b7 --- /dev/null +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/orbiter/OrbiterDetailAdapter.java @@ -0,0 +1,265 @@ +package me.calebjones.spacelaunchnow.ui.orbiter; + +import android.app.Activity; +import android.content.Context; +import android.graphics.drawable.Drawable; +import android.support.annotation.Nullable; +import android.support.v7.widget.AppCompatButton; +import android.support.v7.widget.RecyclerView; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; +import android.widget.ImageView; +import android.widget.TextView; + +import com.bumptech.glide.load.DataSource; +import com.bumptech.glide.load.engine.GlideException; +import com.bumptech.glide.request.RequestListener; +import com.bumptech.glide.request.RequestOptions; +import com.bumptech.glide.request.target.Target; + +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; + +import at.blogc.android.views.ExpandableTextView; +import butterknife.BindView; +import butterknife.ButterKnife; +import butterknife.OnClick; +import io.realm.RealmList; +import me.calebjones.spacelaunchnow.R; +import me.calebjones.spacelaunchnow.data.models.main.Orbiter; +import me.calebjones.spacelaunchnow.utils.GlideApp; +import me.calebjones.spacelaunchnow.utils.Utils; + +public class OrbiterDetailAdapter extends RecyclerView.Adapter { + + public int position; + private Context context; + private Activity activity; + private List items; + private RequestOptions requestOptions; + private int backgroundColor = 0; + private SimpleDateFormat sdf; + + public OrbiterDetailAdapter(Context context, Activity activity) { + items = new ArrayList<>(); + requestOptions = new RequestOptions() + .placeholder(R.drawable.placeholder) + .centerCrop(); + this.context = context; + this.activity = activity; + sdf = Utils.getSimpleDateFormatForUI("MMMM yyyy"); + sdf.toLocalizedPattern(); + } + + public void addItems(List items) { + if (this.items != null) { + this.items.addAll(items); + } else { + this.items = new RealmList<>(); + this.items.addAll(items); + } + notifyDataSetChanged(); + } + + public void clear() { + items.clear(); + notifyDataSetChanged(); + } + + + @Override + public ViewHolder onCreateViewHolder(ViewGroup viewGroup, int i) { + View v = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.orbiter_list_item, viewGroup, false); + return new ViewHolder(v); + } + + @Override + public void onBindViewHolder(final ViewHolder holder, int i) { + Orbiter orbiter = items.get(holder.getAdapterPosition()); + + //Set up vehicle card Information + holder.orbiterTitle.setText(orbiter.getName()); + holder.orbiterSubtitle.setText(orbiter.getCapability()); + + holder.orbiterName.setText(String.format(context.getString(R.string.spacecraft_details), orbiter.getName())); + holder.orbiterDescription.setText(orbiter.getDetails()); + + holder.orbiterHistory.setText(String.format(context.getString(R.string.spacecraft_history), orbiter.getName())); + holder.orbiterHistoryDescription.setText(orbiter.getHistory()); + + if (backgroundColor != 0) { + holder.orbiterTitle.setBackgroundColor(backgroundColor); + holder.orbiterSubtitle.setBackgroundColor(backgroundColor); + } + + if (orbiter.getDiameter() != null) { + holder.diameter.setText(String.format(context.getString(R.string.diameter_full), orbiter.getDiameter())); + } + if (orbiter.getHeight() != null) { + holder.height.setText(String.format(context.getString(R.string.height_full), orbiter.getHeight())); + } + if (orbiter.getPayloadCapacity() != null) { + holder.payload.setText(String.format(context.getString(R.string.payload), orbiter.getPayloadCapacity())); + } + + if (orbiter.getFlightLife() != null) { + holder.flightLife.setVisibility(View.VISIBLE); + holder.flightLife.setText(orbiter.getFlightLife()); + } else { + holder.flightLife.setVisibility(View.GONE); + } + + if (orbiter.getInUse()){ + GlideApp.with(context) + .load(R.drawable.ic_checkmark) + .into(holder.activeIcon); + } else { + GlideApp.with(context) + .load(R.drawable.ic_failed) + .into(holder.activeIcon); + } + + if (orbiter.getHumanRated() == null ){ + GlideApp.with(context) + .load(R.drawable.ic_question_mark) + .into(holder.crewIcon); + holder.crewCapacity.setVisibility(View.GONE); + } else if (orbiter.getHumanRated()){ + GlideApp.with(context) + .load(R.drawable.ic_checkmark) + .into(holder.crewIcon); + holder.crewCapacity.setVisibility(View.VISIBLE); + holder.crewCapacity.setText(String.format(context.getString(R.string.crew_capacity), orbiter.getCrewCapacity())); + } else { + holder.crewCapacity.setVisibility(View.GONE); + GlideApp.with(context) + .load(R.drawable.ic_failed) + .into(holder.crewIcon); + } + + if (orbiter.getMaidenFlight() != null) { + holder.firstFlight.setText(sdf.format(orbiter.getMaidenFlight())); + } else { + holder.firstFlight.setText(R.string.unknown); + } + + GlideApp.with(context) + .load(orbiter.getImageURL()) + .placeholder(R.drawable.placeholder) + .centerCrop() + .listener(new RequestListener() { + @Override + public boolean onLoadFailed(@Nullable GlideException e, Object model, Target target, boolean isFirstResource) { + holder.orbiterImage.setVisibility(View.GONE); + return false; + } + + @Override + public boolean onResourceReady(Drawable resource, Object model, Target target, DataSource dataSource, boolean isFirstResource) { + holder.orbiterImage.setVisibility(View.VISIBLE); + return false; + } + }) + .into(holder.orbiterImage); + + + if (orbiter.getWikiLink() != null && orbiter.getWikiLink().length() > 0) { + holder.wikiButton.setVisibility(View.VISIBLE); + holder.wikiButton.setOnClickListener(v -> Utils.openCustomTab(activity, context, orbiter.getWikiLink())); + } else { + holder.wikiButton.setVisibility(View.GONE); + } + + if (orbiter.getInfoLink() != null && orbiter.getInfoLink().length() > 0) { + holder.infoButton.setVisibility(View.VISIBLE); + holder.infoButton.setOnClickListener(v -> Utils.openCustomTab(activity, context, orbiter.getInfoLink())); + } else { + holder.infoButton.setVisibility(View.GONE); + } + } + + + @Override + public int getItemCount() { + return items.size(); + } + + public void updateColor(int color) { + + backgroundColor = color; + + backgroundColor = color; + + } + + + public class ViewHolder extends RecyclerView.ViewHolder { + + @BindView(R.id.orbiter_image) + ImageView orbiterImage; + @BindView(R.id.in_use_icon) + ImageView activeIcon; + @BindView(R.id.human_rated_icon) + ImageView crewIcon; + @BindView(R.id.orbiter_title) + TextView orbiterTitle; + @BindView(R.id.orbiter_subtitle) + TextView orbiterSubtitle; + @BindView(R.id.orbiter_name) + TextView orbiterName; + @BindView(R.id.orbiter_description_expand) + View orbiterDescriptionExpand; + @BindView(R.id.orbiter_description) + ExpandableTextView orbiterDescription; + @BindView(R.id.orbiter_history) + TextView orbiterHistory; + @BindView(R.id.orbiter_history_description) + ExpandableTextView orbiterHistoryDescription; + @BindView(R.id.orbiter_history_expand) + View orbiterHistoryExpand; + @BindView(R.id.wikiButton) + AppCompatButton wikiButton; + @BindView(R.id.infoButton) + AppCompatButton infoButton; + @BindView(R.id.diameter) + TextView diameter; + @BindView(R.id.height) + TextView height; + @BindView(R.id.payload) + TextView payload; + @BindView(R.id.crew_capacity) + TextView crewCapacity; + @BindView(R.id.flight_life) + TextView flightLife; + @BindView(R.id.first_flight_text) + TextView firstFlight; + + //Add content to the card + public ViewHolder(View view) { + super(view); + ButterKnife.bind(this, view); + } + + @OnClick(R.id.orbiter_history_expand) + public void onHistoryViewClicked() { + orbiterHistoryDescription.toggle(); + if (orbiterHistoryDescription.isExpanded()) { + orbiterHistoryExpand.animate().rotation(0).start(); + } else { + orbiterHistoryExpand.animate().rotation(180).start(); + } + } + + @OnClick(R.id.orbiter_description_expand) + public void onDescriptionViewClicked() { + orbiterDescription.toggle(); + if (orbiterDescription.isExpanded()) { + orbiterDescriptionExpand.animate().rotation(0).start(); + } else { + orbiterDescriptionExpand.animate().rotation(180).start(); + } + } + } +} diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/settings/AboutActivity.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/settings/AboutActivity.java index fd092fb43..3bc569c53 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/settings/AboutActivity.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/ui/settings/AboutActivity.java @@ -76,27 +76,22 @@ private void loadAbout() { .addAction(new IconicsDrawable(this) .icon(CommunityMaterial.Icon.cmd_android_debug_bridge) .sizeDp(24).toBitmap(), - "Debug", new View.OnClickListener() { - @Override - public void onClick(View view) { - new MaterialDialog.Builder(context) - .title("Enter Support Code") - .content("To debug the application - please enter the code from support.") - .inputType(InputType.TYPE_CLASS_NUMBER) - .inputRangeRes(1,100, R.color.accent) - .input("Support Code", null, new MaterialDialog.InputCallback() { - @Override - public void onInput(MaterialDialog dialog, CharSequence input) { - // Do something - if(!input.equals("") && DebugAuthManager.getAuthResult(input)){ - goToDebug(); - } else { - Toast.makeText(context, "Error - code was invalid.", Toast.LENGTH_LONG).show(); - } - } - }).show(); - } - } + "Debug", view -> new MaterialDialog.Builder(context) + .title("Enter Support Code") + .content("To debug the application - please enter the code from support.") + .inputType(InputType.TYPE_CLASS_NUMBER) + .inputRangeRes(1,100, R.color.accent) + .input("Support Code", null, new MaterialDialog.InputCallback() { + @Override + public void onInput(MaterialDialog dialog, CharSequence input) { + // Do something + if(!input.equals("") && DebugAuthManager.getAuthResult(input)){ + goToDebug(); + } else { + Toast.makeText(context, "Error - code was invalid.", Toast.LENGTH_LONG).show(); + } + } + }).show() ) .addShareAction("Checkout " + R.string.app_name) .addUpdateAction() @@ -112,58 +107,52 @@ public void onInput(MaterialDialog dialog, CharSequence input) { .sizeDp(24) .toBitmap(), "Privacy Policy", - new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - StringBuilder buf = new StringBuilder(); - InputStream json = context.getAssets().open("PRIVACY.md"); - BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8")); - - String str; - while((str = in.readLine()) != null) { - buf.append(str).append("\n"); - } - - in.close(); - new MaterialDialog.Builder(context) - .title("Privacy Policy") - .content(buf.toString()) - .positiveText("Got it.") - .show(); - } catch (IOException var6) { - var6.printStackTrace(); + view -> { + try { + StringBuilder buf = new StringBuilder(); + InputStream json = context.getAssets().open("PRIVACY.md"); + BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8")); + + String str; + while((str = in.readLine()) != null) { + buf.append(str).append("\n"); } + in.close(); + new MaterialDialog.Builder(context) + .title("Privacy Policy") + .content(buf.toString()) + .positiveText("Got it.") + .show(); + } catch (IOException var6) { + var6.printStackTrace(); } + }) .addAction(new IconicsDrawable(this) .icon(CommunityMaterial.Icon.cmd_file_check) .sizeDp(24) .toBitmap(), "Terms of Use", - new View.OnClickListener() { - @Override - public void onClick(View view) { - try { - StringBuilder buf = new StringBuilder(); - InputStream json = context.getAssets().open("TERMS.md"); - BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8")); - - String str; - while((str = in.readLine()) != null) { - buf.append(str).append("\n"); - } - - in.close(); - new MaterialDialog.Builder(context) - .title("Terms of Use") - .content(buf.toString()) - .positiveText("Got it.") - .show(); - } catch (IOException var6) { - var6.printStackTrace(); + view -> { + try { + StringBuilder buf = new StringBuilder(); + InputStream json = context.getAssets().open("TERMS.md"); + BufferedReader in = new BufferedReader(new InputStreamReader(json, "UTF-8")); + + String str; + while((str = in.readLine()) != null) { + buf.append(str).append("\n"); } + + in.close(); + new MaterialDialog.Builder(context) + .title("Terms of Use") + .content(buf.toString()) + .positiveText("Got it.") + .show(); + } catch (IOException var6) { + var6.printStackTrace(); } }) .setWrapScrollView(true) diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/Utils.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/Utils.java index a357d49d3..60dd4a415 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/Utils.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/Utils.java @@ -150,6 +150,8 @@ public static void openCustomTab(Activity activity, Context context, String url) PendingIntent actionPendingIntent = createPendingShareIntent(context, url); intentBuilder.setActionButton(BitmapFactory.decodeResource(context.getResources(), R.drawable.ic_menu_share_white), "Share", actionPendingIntent); + intentBuilder.setCloseButtonIcon(BitmapFactory.decodeResource( + context.getResources(), R.drawable.ic_arrow_back)); intentBuilder.setStartAnimations(activity, @@ -391,5 +393,39 @@ public static int sp2px(Context context, float spValue) { final float fontScale = context.getResources().getDisplayMetrics().scaledDensity; return (int) (spValue * fontScale + 0.5f); } + + private final static String NON_THIN = "[^iIl1\\.,']"; + + private static int textWidth(String str) { + return (int) (str.length() - str.replaceAll(NON_THIN, "").length() / 2); + } + + public static String ellipsize(String text, int max) { + + if (textWidth(text) <= max) + return text; + + // Start by chopping off at the word before max + // This is an over-approximation due to thin-characters... + int end = text.lastIndexOf(' ', max - 3); + + // Just one long word. Chop it off. + if (end == -1) + return text.substring(0, max-3) + "..."; + + // Step forward as long as textWidth allows. + int newEnd = end; + do { + end = newEnd; + newEnd = text.indexOf(' ', end + 1); + + // No more spaces. + if (newEnd == -1) + newEnd = text.length(); + + } while (textWidth(text.substring(0, newEnd) + "...") < max); + + return text.substring(0, end) + "..."; + } } diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/views/BadgeTabLayout.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/views/BadgeTabLayout.java new file mode 100644 index 000000000..d1eb753b9 --- /dev/null +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/utils/views/BadgeTabLayout.java @@ -0,0 +1,245 @@ +package me.calebjones.spacelaunchnow.utils.views; + +import android.content.Context; +import android.graphics.PorterDuff; +import android.graphics.drawable.Drawable; +import android.os.Build; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; +import android.support.design.widget.TabLayout; +import android.util.AttributeSet; +import android.util.SparseArray; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.TextView; + +import me.calebjones.spacelaunchnow.R; + + +public class BadgeTabLayout extends TabLayout { + private final SparseArray mTabBuilders = new SparseArray<>(); + + public BadgeTabLayout(Context context) { + super(context); + } + + public BadgeTabLayout(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BadgeTabLayout(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public Builder with(int position) { + Tab tab = getTabAt(position); + return with(tab); + } + + /** + * Apply a builder for this tab. + * + * @param tab for which we create a new builder or retrieve its builder if existed. + * @return the required Builder. + */ + public Builder with(Tab tab) { + if (tab == null) { + throw new IllegalArgumentException("Tab must not be null"); + } + + Builder builder = mTabBuilders.get(tab.getPosition()); + if (builder == null) { + builder = new Builder(this, tab); + mTabBuilders.put(tab.getPosition(), builder); + } + + return builder; + } + + public static final class Builder { + + /** + * This badge widget must not support this value. + */ + private static final int INVALID_NUMBER = Integer.MIN_VALUE; + + @Nullable final View mView; + final Context mContext; + final TabLayout.Tab mTab; + @Nullable TextView mBadgeTextView; + @Nullable TextView mTextView; + String mTabName; + int mBadgeCount = Integer.MIN_VALUE; + + boolean mHasBadge = false; + + /** + * This construct take a TabLayout parent to have its context and other attributes sets. And + * the tab whose icon will be updated. + * + * @param parent + * @param tab + */ + private Builder(TabLayout parent, @NonNull TabLayout.Tab tab) { + super(); + this.mContext = parent.getContext(); + this.mTab = tab; + // initialize current tab's custom view. + if (tab.getCustomView() != null) { + this.mView = tab.getCustomView(); + } else { + this.mView = LayoutInflater.from(parent.getContext()).inflate(R.layout.tab_custom_icon, parent, false); + } + + if (mView != null) { + this.mTextView = mView.findViewById(R.id.tv_title); + this.mBadgeTextView = mView.findViewById(R.id.tv_count); + } + + if (this.mBadgeTextView != null) { + this.mHasBadge = mBadgeTextView.getVisibility() == View.VISIBLE; + try { + this.mBadgeCount = Integer.parseInt(mBadgeTextView.getText().toString()); + } catch (NumberFormatException er) { + er.printStackTrace(); + this.mBadgeCount = INVALID_NUMBER; + } + } + + if (this.mTextView != null) { + mTabName = String.valueOf(mTextView.getText()); + } + } + + /** + * The related Tab is about to have a badge + * + * @return this builder + */ + public Builder hasBadge() { + mHasBadge = true; + return this; + } + + /** + * The related Tab is not about to have a badge + * + * @return this builder + */ + public Builder noBadge() { + mHasBadge = false; + return this; + } + + /** + * Dynamically set the availability of tab's badge + * + * @param hasBadge + * @return this builder + */ + // This method is used for DEBUG purpose only + /*hide*/ + public Builder badge(boolean hasBadge) { + mHasBadge = hasBadge; + return this; + } + + /** + * Set icon custom drawable by Resource ID; + * + * @param tabName + * @return this builder + */ + public Builder name(String tabName) { + mTabName = tabName; + return this; + } + + /** + * increase current badge by 1 + * + * @return this builder + */ + public Builder increase() { + mBadgeCount = + mBadgeTextView == null ? + INVALID_NUMBER + : + Integer.parseInt(mBadgeTextView.getText().toString()) + 1; + return this; + } + + /** + * decrease current badge by 1 + * + * @return + */ + public Builder decrease() { + mBadgeCount = + mBadgeTextView == null ? + INVALID_NUMBER + : + Integer.parseInt(mBadgeTextView.getText().toString()) - 1; + return this; + } + + /** + * set badge count + * + * @param count expected badge number + * @return this builder + */ + public Builder badgeCount(int count) { + mBadgeCount = count; + return this; + } + + /** + * Build the current Tab icon's custom view + */ + public void build() { + if (mView == null) { + return; + } + + // update badge counter + if (mBadgeTextView != null) { + mBadgeTextView.setText(formatBadgeNumber(mBadgeCount)); + + if (mHasBadge) { + mBadgeTextView.setVisibility(View.VISIBLE); + } else { + // set to View#INVISIBLE to not screw up the layout + mBadgeTextView.setVisibility(View.INVISIBLE); + } + } + + // update icon drawable + if (mTextView != null && mTabName != null) { + mTextView.setText(mTabName); + } + + mTab.setCustomView(mView); + } + } + + /** + * This format must follow User's badge policy. + * + * @param value of current badge + * @return corresponding badge number. TextView need to be passed by a String/CharSequence + */ + private static String formatBadgeNumber(int value) { + if (value < 0) { + return "-" + formatBadgeNumber(-value); + } + + if (value < 1000) { + // equivalent to String#valueOf(int); + return Integer.toString(value); + } + + // my own policy + return "999"; + } +} diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchcard/LaunchCardCompactManager.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchcard/LaunchCardCompactManager.java index 6863868c7..7516fd924 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchcard/LaunchCardCompactManager.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchcard/LaunchCardCompactManager.java @@ -57,8 +57,8 @@ private Launch getLaunch() { if (switchPreferences.getAllSwitch()) { RealmQuery query = mRealm.where(Launch.class) .greaterThanOrEqualTo("net", date); - if (switchPreferences.getNoGoSwitch()) { - query.equalTo("status", 1); + if (switchPreferences.getTBDSwitch()) { + query.equalTo("status.id", 1); } launchRealms = query.sort("net", Sort.ASCENDING).findAll(); Timber.v("loadLaunches - Realm query created."); @@ -166,8 +166,8 @@ private void setWidgetStyle() { private void setLocationName(Launch launchRealm) { String locationName = null; - if (launchRealm.getLocation() != null && launchRealm.getLocation().getName() != null) { - locationName = launchRealm.getLocation().getName(); + if (launchRealm.getPad().getLocation() != null && launchRealm.getPad().getLocation().getName() != null) { + locationName = launchRealm.getPad().getLocation().getName(); } if (locationName != null) { diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchlist/LaunchListFactory.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchlist/LaunchListFactory.java index 8437883ce..4eef65537 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchlist/LaunchListFactory.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/launchlist/LaunchListFactory.java @@ -62,8 +62,8 @@ private List getLaunches(Realm mRealm) { if (switchPreferences.getAllSwitch()) { RealmQuery query = mRealm.where(Launch.class) .greaterThanOrEqualTo("net", date); - if (switchPreferences.getNoGoSwitch()) { - query.equalTo("status", 1); + if (switchPreferences.getTBDSwitch()) { + query.equalTo("status.id", 1); } launchRealms = query.sort("net", Sort.ASCENDING).findAll(); Timber.v("loadLaunches - Realm query created."); @@ -132,7 +132,7 @@ public RemoteViews getViewAt(int position) { row.setTextColor(R.id.launch_date, widgetSecondaryTextColor); row.setTextColor(R.id.location, widgetSecondaryTextColor); - if (launch.getStatus() != null && launch.getStatus() == 2) { + if (launch.getStatus() != null && launch.getStatus().getId() == 2) { //Get launch date sdf.setTimeZone(TimeZone.getTimeZone("UTC")); Date date = launch.getNet(); @@ -176,12 +176,12 @@ public RemoteViews getViewAt(int position) { } //If pad and agency exist add it to location, otherwise get whats always available - if (launch.getLocation() != null) { - row.setTextViewText(R.id.location, launch.getLocation().getName()); + if (launch.getPad().getLocation() != null) { + row.setTextViewText(R.id.location, launch.getPad().getLocation().getName()); } else { row.setTextViewText(R.id.location, "Click for more information."); } - row.setTextViewText(R.id.location, launch.getLocation().getName()); + row.setTextViewText(R.id.location, launch.getPad().getLocation().getName()); Intent exploreIntent = new Intent(context, LaunchDetailActivity.class); exploreIntent.putExtra("TYPE", "launch"); diff --git a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/wordtimer/LaunchWordTimerManager.java b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/wordtimer/LaunchWordTimerManager.java index 209059f79..d0a101c97 100644 --- a/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/wordtimer/LaunchWordTimerManager.java +++ b/mobile/src/main/java/me/calebjones/spacelaunchnow/widget/wordtimer/LaunchWordTimerManager.java @@ -95,8 +95,8 @@ private Launch getLaunch(Context context) { if (switchPreferences.getAllSwitch()) { RealmQuery query = mRealm.where(Launch.class) .greaterThanOrEqualTo("net", date); - if (switchPreferences.getNoGoSwitch()) { - query.equalTo("status", 1); + if (switchPreferences.getTBDSwitch()) { + query.equalTo("status.id", 1); } launchRealms = query.findAll().sort("net", Sort.ASCENDING); Timber.v("loadLaunches - Realm query created."); @@ -202,9 +202,9 @@ private void setLaunchName(Launch launchRealm) { private String getLaunchName(Launch launchRealm) { //Replace with launch - if (launchRealm.getLauncher() != null) { + if (launchRealm.getRocket().getConfiguration() != null) { //Replace with mission name - return launchRealm.getLauncher().getName(); + return launchRealm.getRocket().getConfiguration().getName(); } else { return null; } diff --git a/mobile/src/main/res/drawable/badge_background.xml b/mobile/src/main/res/drawable/badge_background.xml new file mode 100644 index 000000000..ba2c156b0 --- /dev/null +++ b/mobile/src/main/res/drawable/badge_background.xml @@ -0,0 +1,8 @@ + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/ic_badge.xml b/mobile/src/main/res/drawable/ic_badge.xml new file mode 100644 index 000000000..258f44630 --- /dev/null +++ b/mobile/src/main/res/drawable/ic_badge.xml @@ -0,0 +1,7 @@ + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/ic_checkmark.xml b/mobile/src/main/res/drawable/ic_checkmark.xml new file mode 100644 index 000000000..27ad458ff --- /dev/null +++ b/mobile/src/main/res/drawable/ic_checkmark.xml @@ -0,0 +1,4 @@ + + + diff --git a/mobile/src/main/res/drawable/ic_failed.xml b/mobile/src/main/res/drawable/ic_failed.xml new file mode 100644 index 000000000..36b011498 --- /dev/null +++ b/mobile/src/main/res/drawable/ic_failed.xml @@ -0,0 +1,5 @@ + + + + diff --git a/mobile/src/main/res/drawable/ic_landing.xml b/mobile/src/main/res/drawable/ic_landing.xml new file mode 100644 index 000000000..25502c70d --- /dev/null +++ b/mobile/src/main/res/drawable/ic_landing.xml @@ -0,0 +1,15 @@ + + + + + + diff --git a/mobile/src/main/res/drawable/ic_question_mark.xml b/mobile/src/main/res/drawable/ic_question_mark.xml new file mode 100644 index 000000000..37dee8e1d --- /dev/null +++ b/mobile/src/main/res/drawable/ic_question_mark.xml @@ -0,0 +1,4 @@ + + + diff --git a/mobile/src/main/res/drawable/rounded_colored.xml b/mobile/src/main/res/drawable/rounded_colored.xml new file mode 100644 index 000000000..e71122f3e --- /dev/null +++ b/mobile/src/main/res/drawable/rounded_colored.xml @@ -0,0 +1,7 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/tab_text_color_selector.xml b/mobile/src/main/res/drawable/tab_text_color_selector.xml new file mode 100644 index 000000000..8a00fa8cc --- /dev/null +++ b/mobile/src/main/res/drawable/tab_text_color_selector.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/drawable/triangle.xml b/mobile/src/main/res/drawable/triangle.xml new file mode 100644 index 000000000..6d7059964 --- /dev/null +++ b/mobile/src/main/res/drawable/triangle.xml @@ -0,0 +1,14 @@ + + + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/layout-night/gridview_item.xml b/mobile/src/main/res/layout-night/gridview_item.xml deleted file mode 100644 index dcdc0a6e7..000000000 --- a/mobile/src/main/res/layout-night/gridview_item.xml +++ /dev/null @@ -1,58 +0,0 @@ - - - - - - - - - - - - - - - diff --git a/mobile/src/main/res/layout-w500dp/article_item.xml b/mobile/src/main/res/layout-w500dp/article_item.xml new file mode 100644 index 000000000..c78800ded --- /dev/null +++ b/mobile/src/main/res/layout-w500dp/article_item.xml @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/mobile/src/main/res/layout-w500dp/content_card.xml b/mobile/src/main/res/layout-w500dp/content_card.xml new file mode 100644 index 000000000..13898a5ca --- /dev/null +++ b/mobile/src/main/res/layout-w500dp/content_card.xml @@ -0,0 +1,275 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +