├── app
├── .gitignore
├── src
│ ├── main
│ │ ├── res
│ │ │ ├── mipmap-hdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-mdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxhdpi
│ │ │ │ └── ic_launcher.png
│ │ │ ├── mipmap-xxxhdpi
│ │ │ │ ├── icon_large.png
│ │ │ │ └── ic_launcher.png
│ │ │ ├── drawable
│ │ │ │ ├── scrim_top.xml
│ │ │ │ ├── shape_circle.xml
│ │ │ │ ├── line_divider.xml
│ │ │ │ ├── ic_send.xml
│ │ │ │ ├── ic_arrow_upward.xml
│ │ │ │ ├── ic_terrain.xml
│ │ │ │ ├── ic_compass.xml
│ │ │ │ ├── ic_map.xml
│ │ │ │ ├── ic_archive.xml
│ │ │ │ ├── ic_pencil_box.xml
│ │ │ │ ├── ic_extension.xml
│ │ │ │ ├── ic_cube.xml
│ │ │ │ └── ic_speedometer.xml
│ │ │ ├── anim
│ │ │ │ └── rotation.xml
│ │ │ ├── values-w820dp
│ │ │ │ └── dimens.xml
│ │ │ ├── menu
│ │ │ │ ├── menu_cache_detail.xml
│ │ │ │ └── menu_cache_list.xml
│ │ │ ├── values
│ │ │ │ ├── dimens.xml
│ │ │ │ ├── colors.xml
│ │ │ │ └── styles.xml
│ │ │ ├── values-v21
│ │ │ │ └── styles.xml
│ │ │ └── layout
│ │ │ │ ├── fragment_cache_list.xml
│ │ │ │ ├── library_item.xml
│ │ │ │ ├── empty_view.xml
│ │ │ │ ├── activity_cache_list.xml
│ │ │ │ ├── content_compass_loading.xml
│ │ │ │ ├── activity_compass.xml
│ │ │ │ ├── activity_map.xml
│ │ │ │ └── content_compass.xml
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ ├── ForApplication.java
│ │ │ ├── data
│ │ │ ├── local
│ │ │ │ ├── RealmInitWrapper.java
│ │ │ │ ├── pref
│ │ │ │ │ ├── SharedPrefConstants.java
│ │ │ │ │ ├── OAuthUserToken.java
│ │ │ │ │ ├── OAuthUserTokenSecret.java
│ │ │ │ │ ├── PrefsModule.java
│ │ │ │ │ └── StringPreference.java
│ │ │ │ ├── RealmInitWrapperImpl.java
│ │ │ │ ├── model
│ │ │ │ │ ├── RealmLocation.java
│ │ │ │ │ └── Cache.java
│ │ │ │ └── DatabaseModule.java
│ │ │ ├── api
│ │ │ │ ├── EndpointQualifier.java
│ │ │ │ ├── response
│ │ │ │ │ └── SubmitLogResponse.java
│ │ │ │ ├── ApiConstants.java
│ │ │ │ ├── gson
│ │ │ │ │ ├── HtmlAdapter.java
│ │ │ │ │ ├── StringCapitalizerAdapter.java
│ │ │ │ │ ├── RealmLocationAdapter.java
│ │ │ │ │ ├── ListTypeAdapterFactory.java
│ │ │ │ │ └── ListTypeAdapter.java
│ │ │ │ ├── HostSelectionInterceptor.java
│ │ │ │ ├── OkApiService.java
│ │ │ │ ├── auth
│ │ │ │ │ └── OAuthSigningInterceptor.java
│ │ │ │ └── OkApiInteractor.java
│ │ │ ├── network
│ │ │ │ ├── NetworkUnavailableException.java
│ │ │ │ ├── NetworkModule.java
│ │ │ │ └── NetworkInteractor.java
│ │ │ ├── location
│ │ │ │ ├── LocationUnavailableException.java
│ │ │ │ ├── LocationModule.java
│ │ │ │ └── LocationAsyncEmitter.java
│ │ │ └── sensor
│ │ │ │ ├── SensorUnavailableException.java
│ │ │ │ ├── SensorModule.java
│ │ │ │ ├── AzimuthInteractor.java
│ │ │ │ └── AzimuthAsyncEmitter.java
│ │ │ ├── dev_tools
│ │ │ └── DevMetricsProxy.java
│ │ │ ├── ui
│ │ │ ├── ActivityScope.java
│ │ │ ├── FragmentScope.java
│ │ │ ├── navigate
│ │ │ │ ├── NavigateView.java
│ │ │ │ ├── NavigateComponent.java
│ │ │ │ ├── NavigateModule.java
│ │ │ │ ├── NavigatePresenter.java
│ │ │ │ └── NavigateActivity.java
│ │ │ ├── log
│ │ │ │ ├── LogComponent.java
│ │ │ │ ├── LogModule.java
│ │ │ │ └── LogView.java
│ │ │ ├── login
│ │ │ │ ├── LoginComponent.java
│ │ │ │ ├── LoginView.java
│ │ │ │ └── LoginModule.java
│ │ │ ├── cachelist
│ │ │ │ ├── CacheListView.java
│ │ │ │ ├── CacheListComponent.java
│ │ │ │ ├── CacheListModule.java
│ │ │ │ └── CacheAdapter.java
│ │ │ ├── map
│ │ │ │ ├── MapComponent.java
│ │ │ │ ├── MapActivityView.java
│ │ │ │ ├── MapModule.java
│ │ │ │ └── MapPresenter.java
│ │ │ ├── cachedetail
│ │ │ │ ├── CacheDetailView.java
│ │ │ │ ├── CacheDetailComponent.java
│ │ │ │ ├── CacheDetailModule.java
│ │ │ │ └── CacheDetailPresenter.java
│ │ │ ├── compass
│ │ │ │ ├── CompassView.java
│ │ │ │ ├── CompassComponent.java
│ │ │ │ ├── CompassModule.java
│ │ │ │ └── LocationUnavailableDialog.java
│ │ │ ├── base
│ │ │ │ ├── FragmentModule.java
│ │ │ │ ├── ActivityModule.java
│ │ │ │ ├── Presenter.java
│ │ │ │ ├── BaseActivity.java
│ │ │ │ ├── PresenterLoader.java
│ │ │ │ ├── BaseFragment.java
│ │ │ │ ├── PresenterFragment.java
│ │ │ │ ├── PresenterActivity.java
│ │ │ │ └── RxPresenter.java
│ │ │ ├── misc
│ │ │ │ ├── SimpleDividerItemDecoration.java
│ │ │ │ └── PermissionRationaleDialog.java
│ │ │ └── about
│ │ │ │ └── AboutActivity.java
│ │ │ ├── util
│ │ │ ├── ViewUtils.java
│ │ │ ├── MenuUtils.java
│ │ │ ├── UnitUtils.java
│ │ │ ├── AngleUtils.java
│ │ │ ├── PermissionUtils.java
│ │ │ ├── StringUtils.java
│ │ │ └── ActivityUtils.java
│ │ │ ├── ApplicationModule.java
│ │ │ └── ForageApplication.java
│ ├── unitTests
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ ├── data
│ │ │ ├── local
│ │ │ │ ├── DatabaseModuleForTest.java
│ │ │ │ ├── DatabaseInteractorTest.java
│ │ │ │ └── RealmLocationTest.java
│ │ │ ├── api
│ │ │ │ ├── gson
│ │ │ │ │ ├── HtmlAdapterTest.java
│ │ │ │ │ ├── StringCaptializerTest.java
│ │ │ │ │ └── RealmLocationAdapterTest.java
│ │ │ │ └── HostSelectionInterceptorTest.java
│ │ │ ├── location
│ │ │ │ └── LocationInteractorTest.java
│ │ │ └── network
│ │ │ │ └── NetworkInteractorTest.java
│ │ │ ├── ui
│ │ │ ├── base
│ │ │ │ ├── BaseActivityTest.java
│ │ │ │ └── PresenterTest.java
│ │ │ ├── cachedetail
│ │ │ │ └── CacheDetailPresenterTest.java
│ │ │ └── navigate
│ │ │ │ └── NavigatePresenterTest.java
│ │ │ ├── util
│ │ │ ├── ViewUtilsTest.java
│ │ │ ├── UnitUtilsTest.java
│ │ │ ├── PermissionUtilsTest.java
│ │ │ ├── ActivityUtilsTest.java
│ │ │ ├── AngleUtilsTest.java
│ │ │ └── RxUtilsTest.java
│ │ │ ├── ForageUnitTestApplication.java
│ │ │ └── ForageRoboelectricUnitTestRunner.java
│ ├── androidTest
│ │ ├── AndroidManifest.xml
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ ├── util
│ │ │ ├── TestUtils.java
│ │ │ └── UiAutomatorUtils.java
│ │ │ ├── ForageFunctionalTestRunner.java
│ │ │ ├── ForageFunctionalTestApplication.java
│ │ │ ├── screens
│ │ │ ├── MapScreen.java
│ │ │ ├── NavigateScreen.java
│ │ │ └── CacheListScreen.java
│ │ │ ├── rules
│ │ │ ├── NeedsMockWebServer.java
│ │ │ └── MockWebServerRule.java
│ │ │ └── espresso
│ │ │ └── ViewMatchers.java
│ ├── debug
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ └── dev_tools
│ │ │ ├── DebugToolsModule.java
│ │ │ └── DevMetricsProxyImpl.java
│ ├── release
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ └── dev_tools
│ │ │ └── DebugToolsModule.java
│ ├── integrationTests
│ │ └── java
│ │ │ └── io
│ │ │ └── github
│ │ │ └── plastix
│ │ │ └── forage
│ │ │ ├── ForageIntegrationTestApplication.java
│ │ │ ├── ForageRoboelectricIntegrationTestRunner.java
│ │ │ └── data
│ │ │ ├── local
│ │ │ └── CacheTest.java
│ │ │ └── api
│ │ │ └── HttpCodes.java
│ └── releaseUnitTests
│ │ └── java
│ │ └── io
│ │ └── github
│ │ └── plastix
│ │ └── forage
│ │ └── permission
│ │ └── PermissionsTest.java
└── proguard-rules.pro
├── settings.gradle
├── art
├── screenshots
│ ├── Screenshot_20160804-074527_framed.png
│ ├── forage_map.png
│ ├── forage_detail.png
│ ├── forage_cache_list.png
│ └── forage_cache_list_empty.png
└── logo.ai
├── gradle
└── wrapper
│ ├── gradle-wrapper.jar
│ └── gradle-wrapper.properties
├── signing.properties.sample
├── ci.sh
├── circle.yml
├── gradle.properties
├── environmentSetup.sh
├── gradlew.bat
└── .gitignore
/app/.gitignore:
--------------------------------------------------------------------------------
1 | /build
2 |
--------------------------------------------------------------------------------
/settings.gradle:
--------------------------------------------------------------------------------
1 | include ':app'
2 |
--------------------------------------------------------------------------------
/art/screenshots/Screenshot_20160804-074527_framed.png:
--------------------------------------------------------------------------------
1 |
--------------------------------------------------------------------------------
/art/logo.ai:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/art/logo.ai
--------------------------------------------------------------------------------
/art/screenshots/forage_map.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/art/screenshots/forage_map.png
--------------------------------------------------------------------------------
/art/screenshots/forage_detail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/art/screenshots/forage_detail.png
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.jar:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/gradle/wrapper/gradle-wrapper.jar
--------------------------------------------------------------------------------
/art/screenshots/forage_cache_list.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/art/screenshots/forage_cache_list.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-hdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-hdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-mdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-mdpi/ic_launcher.png
--------------------------------------------------------------------------------
/art/screenshots/forage_cache_list_empty.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/art/screenshots/forage_cache_list_empty.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-xhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/icon_large.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-xxxhdpi/icon_large.png
--------------------------------------------------------------------------------
/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Plastix/Forage/HEAD/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
--------------------------------------------------------------------------------
/signing.properties.sample:
--------------------------------------------------------------------------------
1 | STORE_FILE=/path/to/your.keystore
2 | STORE_PASSWORD=yourkeystorepass
3 | KEY_ALIAS=projectkeyalias
4 | KEY_PASSWORD=keyaliaspassword
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/ForApplication.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage;
2 |
3 | import javax.inject.Qualifier;
4 |
5 | @Qualifier
6 | public @interface ForApplication {
7 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/data/local/RealmInitWrapper.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.data.local;
2 |
3 | public interface RealmInitWrapper {
4 |
5 | void init();
6 | }
7 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/data/api/EndpointQualifier.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.data.api;
2 |
3 | import javax.inject.Qualifier;
4 |
5 | @Qualifier
6 | public @interface EndpointQualifier {
7 | }
8 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/dev_tools/DevMetricsProxy.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.dev_tools;
2 |
3 | public interface DevMetricsProxy {
4 | /**
5 | * Applies performance metrics library.
6 | */
7 | void apply();
8 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/ui/ActivityScope.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.ui;
2 |
3 | import javax.inject.Scope;
4 |
5 | /**
6 | * Custom Dagger 2 scope for Activities
7 | */
8 | @Scope
9 | public @interface ActivityScope {
10 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/ui/FragmentScope.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.ui;
2 |
3 | import javax.inject.Scope;
4 |
5 | /**
6 | * Custom Dagger 2 scope for Fragments
7 | */
8 | @Scope
9 | public @interface FragmentScope {
10 | }
--------------------------------------------------------------------------------
/gradle/wrapper/gradle-wrapper.properties:
--------------------------------------------------------------------------------
1 | #Sat Mar 04 08:33:35 EST 2017
2 | distributionBase=GRADLE_USER_HOME
3 | distributionPath=wrapper/dists
4 | zipStoreBase=GRADLE_USER_HOME
5 | zipStorePath=wrapper/dists
6 | distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip
7 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/ui/navigate/NavigateView.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.ui.navigate;
2 |
3 | public interface NavigateView {
4 |
5 | void errorParsingLatitude();
6 |
7 | void errorParsingLongitude();
8 |
9 | void openCompassScreen(double lat, double lon);
10 | }
11 |
--------------------------------------------------------------------------------
/app/src/main/res/drawable/scrim_top.xml:
--------------------------------------------------------------------------------
1 |
2 |
22 | * Useful for setting up responses that you simply can not define in the test code because app already hit the server.
23 | *
24 | * @return Empty string if no method invocation required or public method name that needs to be called.
25 | */
26 | @NonNull String setupMethod() default "";
27 | }
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/data/sensor/AzimuthInteractor.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.data.sensor;
2 |
3 | import android.support.annotation.NonNull;
4 |
5 | import javax.inject.Inject;
6 | import javax.inject.Provider;
7 |
8 | import rx.AsyncEmitter;
9 | import rx.Observable;
10 |
11 |
12 | /**
13 | * A Reactive wrapper around the Android compass sensor.
14 | */
15 | public class AzimuthInteractor {
16 |
17 | private Provider
18 | * This adapter converts the OkApi JSON object format to a nice list.
19 | *
20 | * @param HTML Description
12 | * Slightly adapted Code from https://github.com/alapshin/arctor
13 | *
14 | * @param
42 | * Based on http://stackoverflow.com/questions/8560045/android-getting-obj-using-textview-settextcharactersequence
43 | */
44 | @NonNull
45 | public static String stripHtml(@NonNull String input) {
46 | return Html.fromHtml(input).toString()
47 | .replace((char) 160, (char) 32).replace((char) 65532, (char) 32).trim();
48 | }
49 |
50 | /**
51 | * Capitalizes the first character of the given string.
52 | *
53 | * @param input String to capitalize.
54 | * @return Capitalized string.
55 | */
56 | public static String capitalize(@NonNull String input) {
57 | // Don't process empty strings
58 | if (input.length() == 0) {
59 | return input;
60 | }
61 |
62 | return input.substring(0, 1).toUpperCase(Locale.getDefault()) + input.substring(1);
63 | }
64 |
65 | /**
66 | * Turns the distance in miles to a human-readable String. For example:
67 | *
68 | * 5.2 -> 5.2 mi
69 | * 0.3 -> 5280 ft
70 | *
71 | * @param resources Resources object to fetch the string resources.
72 | * @param miles Miles to convert.
73 | * @return Human readable string.
74 | */
75 | @NonNull
76 | public static String humanReadableImperialDistance(@NonNull Resources resources, double miles) {
77 | String distance;
78 | String units;
79 |
80 | if (miles > 1) {
81 | distance = String.format(Locale.getDefault(), "%.2f", miles);
82 | units = resources.getString(R.string.unit_miles);
83 | } else {
84 | distance = String.format(Locale.getDefault(), "%.2f", UnitUtils.milesToFeet(miles));
85 | units = resources.getString(R.string.unit_feet);
86 | }
87 |
88 | return distance + " " + units;
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/app/src/main/java/io/github/plastix/forage/ui/cachelist/CacheAdapter.java:
--------------------------------------------------------------------------------
1 | package io.github.plastix.forage.ui.cachelist;
2 |
3 | import android.content.Context;
4 | import android.content.Intent;
5 | import android.content.res.Resources;
6 | import android.support.v7.widget.RecyclerView;
7 | import android.view.LayoutInflater;
8 | import android.view.View;
9 | import android.view.ViewGroup;
10 | import android.widget.TextView;
11 |
12 | import butterknife.BindView;
13 | import butterknife.ButterKnife;
14 | import io.github.plastix.forage.R;
15 | import io.github.plastix.forage.data.local.model.Cache;
16 | import io.github.plastix.forage.ui.cachedetail.CacheDetailActivity;
17 | import io.realm.OrderedRealmCollection;
18 | import io.realm.RealmRecyclerViewAdapter;
19 |
20 | /**
21 | * RecyclerView adapter to get {@link Cache}s from Realm and display them.
22 | */
23 | public class CacheAdapter extends RealmRecyclerViewAdapter> searchAndRetrieve(@Query("search_method") String searchMethod,
20 | @Query("search_params") String searchParams,
21 | @Query("retr_method") String retrMethod,
22 | @Query("retr_params") String retrParams,
23 | @Query("wrap") boolean wrap,
24 | @Query("consumer_key") String consumerKey
25 | );
26 |
27 | @Headers("OAuth: ENABLED")
28 | @GET("/okapi/services/logs/submit")
29 | Single
> {
23 |
24 | private TypeAdapter
> getNearbyCaches(double lat, double lon, double radius) {
43 |
44 | JsonObject searchParams = new JsonObject();
45 | searchParams.addProperty("center", String.format("%s|%s", lat, lon));
46 | searchParams.addProperty("radius", UnitUtils.milesToKilometer(radius));
47 |
48 | JsonObject returnParams = new JsonObject();
49 | returnParams.addProperty("fields", StringUtils.join("|", geocacheFields));
50 |
51 | return apiService.get().searchAndRetrieve(
52 | ApiConstants.ENDPOINT_NEAREST,
53 | searchParams.toString(),
54 | ApiConstants.ENDPOINT_GEOCACHES,
55 | returnParams.toString(),
56 | false,
57 | BuildConfig.OKAPI_US_CONSUMER_KEY
58 | )
59 | .compose(RxUtils.
>subscribeOnIoThreadTransformerSingle())
60 | .compose(RxUtils.
>observeOnUIThreadTransformerSingle());
61 | }
62 |
63 | public Single