google / ground-android Goto Github PK
View Code? Open in Web Editor NEWGround mobile data collection app for Android
Home Page: http://groundplatform.org
License: Apache License 2.0
Ground mobile data collection app for Android
Home Page: http://groundplatform.org
License: Apache License 2.0
Multiple warnings appear in log when strict mode is enabled that Firebase is being run on wrong thread. This could lead to sluggishness on older devices, or worse, force quits. Should be fixed ASAP.
Project definitions would need to be explicitly stored locally so user can switch projects when offline.
Blocked by #19.
Once we've determined the best process for creating new issues, we should document it in CONTRIBUTING.md (On the issues page, a message from github recommends reading this file prior to creating an issue, so it makes sense to include issue creation guidelines here).
Should we decide not to document this process, we can capture discussions on the matter here and close this issue once it's settled.
We sometimes use "labels" plural vs. "title" singular, for ex, to describe localized string maps. We should always use the plural here for clarity and consistency.
DataRepository currently receives full Feature objects on create and converts them to FeatureMutations itself. Since update feature will create FeatureMutations, API would be simpler to always use FeatureMutations directly.
Will need to use Room 2.1.0 to allow Room annotations on AutoValue value objects. This may require updating to Android X:
https://stackoverflow.com/questions/44869545/android-room-persistence-library-entity-with-autovalue
Repro:
Results don't show, clicking add record adds the wrong form (form 0).
Needed to help scale the effort and collaborate
Once "view observation" intents are supported, the user will also need the map to have some context.
There are some instances in the code in which we rely on doOnNext
, doOnSuccess
and other RX side effect operators.
In general, we should either avoid side effects entirely or ensure their usage is carefully prescribed.
Personally, I like treating anything that does not have to do with the direct manipulation of data (emitted items) as a side effect. For example, logging and UI changes would both be considered side effects from this perspective. I think this approach enables us to maintain clear separation between the actual 'transformation'/ data-manipulating code and 'side-effecting' code like logging.
For our purposes, we only need to treat logging as a side-effect, since display related code is handled by fragments (and ideally live-data binding). The majority of cases in which we manipulate some piece of data in a doOn
function can be expressed using transformations instead.
@scolsen listened to this podcast after our chat. I agree with most of the suggestions there. Key takeaways (mixed with my own observations):
getFoo()
pattern is dated, a relic of JavaBeans naming conventions.Some ideas/suggestions:
foo()
for immutable synchronous accessors (e.g. User user()
).. There's also precedent for this in JDK methods like values()
.fooOnce()
for Rx types that return a single value and complete (usually Single<>
).fooStream()
for Rx types that are expected to not complete while the application is in a normal state.
fooOnceAndStream()` for Rx types that return a single value (the latest?) ASAP and then continue to stream updates while the application is in a normal state.A similar approach is also described here.
Wdyt? No need to change existing uses now, but new code could use the convention, and we can update existing code once V0 is ready.
@navinsivakumar FYI.
There are a number of TODOs lying around regarding VM simplification. We should address these! Creating an issue so that we can reference it in each TODO.
When many users are adding data, "Save" button sometimes stops working. Users observed this at G4G18 when editing the 'frogs' test project.
Backpeddling on this one after looking at other related tools and after feedback at G4G18. "Feature" is also more correct, since it includes any type of entity on a map, whereas "Place" can be misunderstood as a single point instead of any arbitrary feature (polygons, polylines, etc.).
In many cases we subscribe to a Completable, Single, or Maybe, and keeping around the Disposable for the lifetime of the component (ViewModel, View), leaking memory.
Rather than subscribing to the returned Maybe returned by getRecordDetails() and calling setValue on the MutableLiveData, is it possible to merge the Maybe into a existing stream in a such way that subscription is properly managed? If not, how should short-lived Single/Maybe/Completable subscriptions be disposed? I've seen conflicting suggestions online, from keeping them around in a CompositeDisposable (for the lifetime of the View?) to assuming Rx automatically disposes of them.
Mentioning that PRs are automatically updated when pushing to a branch with an active PR.
Currently, local db impl using Room lives in com.google.android.gnd.repository.local
.
The remote db interface is in com.google.android.gnd.service.RemoteDataService
, with Firestore impl under com.google.android.gnd.service.firestore
.
This is inconsistent and arbitrary. I would suggest renaming and moving as follows:
com.google.android.gnd.service.remotedb.RemoteDbService
com.google.android.gnd.service.remotedb.firestore.*
com.google.android.gnd.service.localdb.LocalDbService
(TBD)com.google.android.gnd.service.localdb.room.*
@scolsen, @navinsivakumar, any thoughts?
We can rename Result
to something like ValueOrError
, and wrap the value at the source, obviating the need to wrap/unwrap at arbitrary steps in the stream.
@scolsen FYI.
In emulator with Nexus 5X, Play Services 14.7.99
Whenever I set the state of the Bottom Sheet to expand mode then it gets expanded too fast.
Is there any way to control the expanding and collapsing animation speed?
Observed in branches in issue-57/
Yet another stylistic/preferential question--forgive me for having so many of these but once they're firmly answered I'll move forward without causing any trouble!
We've recently had some discussions about naming subjects that track user interactions appropriately such as (addFeatureClicks) etc. Most of these currently (or will) live in viewmodels as subjects. However, I think it may be more appropriate to track interactions (clicks, etc) in the fragment, granting the view models some level of independence.
This is already the case in some sense, but we currently often mix RX methods and approaches with more traditional direct VM method calls etc. Instead, we can stick to RX as much as possible, creating observables/subjects to track fragment interactions and capturing responses to view model data as transformations on these interactions.
see 4491816 experimental/scolsen/observable-views for an example using this approach.
For reference, here's a relevant snippet from the previously mentioned commit:
First, we specify the appropriate fragment reaction in the onCreate method and subscribe to the stream:
@Override
public void onCreate(@androidx.annotation.Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
saveClicks = PublishSubject.create();
singleSelectDialogFactory = new SingleSelectDialogFactory(getContext());
multiSelectDialogFactory = new MultiSelectDialogFactory(getContext());
viewModel = getViewModel(EditRecordViewModel.class);
Observable<Boolean> saveClickReactions =
saveClicks
.map(__ -> viewModel.onSaveClick())
.doOnNext(
result -> {
if (!result) {
EphemeralPopups.showFyi(getContext(), R.string.no_changes_to_save);
navigator.navigateUp();
}
});
saveClickReactions.subscribe();
Second, when a user clicks, drags, w/e, we emit:
@OnClick(R.id.save_record_btn)
void onSaveClick() {
saveClicks.onNext(new Object());
}
Note that this is mostly a stylistic difference and it may be totally unnecessary if we're able to switch every fragment/VM data coupling to LiveData
bindings. This approach does grant us some additional flexibility in that it's now fairly straightforward to accumulate further transformations/interactions on the initial stream, and it eliminates the need to track any state for dependent reactions (if any exist, we can simply model them as transformations, merges, etc.).
It also frees up
..and handle "loading" and "saving" in progress states in the UI layer instead of upstream.
@scolsen FYI.
..and remove individual latitude
and longitude
fields. This won't change the structure of the database since @Embedded
flattens objects into columns in the same table, but would prevent us from needing to copy the two fields between Coordinates
and FeatureEntity
.
Map becomes unusable since map is never unlocked
At the moment, there are some places in which streams and so called "side effects" (operations that use some value from the stream but don't modify the stream's contents i.e. aren't operations like map, and co.) are intermingled. For example, the addFeatureDialogFragment.show
function:
Observable<Feature> featureStream =
showFeatureDialogRequests.flatMapMaybe(
fragmentManager -> addFeatureDialogFragment.show(fragmentManager));
does two things: it calls show on the fragmentManager, and returns an entirely new PublishSubject:
public Maybe<Feature> show(FragmentManager fragmentManager) {
addFeatureRequestSubject = MaybeSubject.create();
show(fragmentManager, TAG);
return addFeatureRequestSubject;
}
This obfuscates the semantics somewhat and makes reading some functions difficult. For example, I would expect show
to be "effectful" only, and not to return a new Maybe.
Instead we can refactor this to use RX semantics to achieve the same thing.
Observable<Feature> featureStream =
showFeatureDialogRequests.doOnNext(fragmentManager -> show(fragmentManager, TAG)).flatMapMaybe(__ -> addFeatureDialogFragment.toSubject());
An approach like this keeps side effects and transformations separate and immediately obvious when reading the sequence of stream operations. This way we can essentially keep data transformations and ui actions 'distinct'.
This is preferential of course, so please let me know if you disagree!
Allows download of selected mbtiles for offline use. Related to #113.
This will facilitate testing and improve consistency across UI implementations.
create() method is currently required by room. Filed an FR against Room FR to use the builder directly:
https://issuetracker.google.com/issues/129183837
We're currently using google-java-format in Android Studio.
Set up lint or compile errors
The prototype currently requests sign-in when opening the app. If the user signs out while offline, the app currently becomes unusable, since there's no way to log back in. In order to properly support offline use, account tokens will likely need to be stored locally.
Blocked by google/ground-platform#17
Motivation: Once first Android binaries are rolled out, we won't be able to make breaking changes to the database. Making client more resilient to invalid or missing data in Firebase will allow us more flexibility in adding and deprecating features in the db
Blocked by #17.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.