Skip to content
This repository has been archived by the owner on Apr 1, 2023. It is now read-only.

PR for 30 location picker - Phase 1 #81

Merged
merged 42 commits into from Jan 13, 2017
Merged

Conversation

lemonboston
Copy link
Contributor

For #30.

This first phase of the location picker screen contains the replacement of the Google provider location picker UI overlay with our own minimal screen.

@dmfs Please review.

Things left from implementing the full location picker (we will create new stories where appropriate as agreed):

  • Event list screen: drop down arrow instead of location menu icon
  • Location picker screen:
  • 'x' cancel button at the right side of EditText (or using SearchView which has it but harder to customize)
  • icons next to suggestions and icon to the search bar (?)
  • Current location
  • Recent locations
  • Top city suggestions

Technical notes:

  • The second Place API call to get the actual Place by the id is now wired back to the controller that handles the list, it could be implemented as loader microfragment possibly. Or we could also consider prefetching them from the suggestions, but it is probably not worth it or not that important.
    (Error handling flow would need to be considered as well with the loader fragment.)
  • The errors related to Places API are not handled currently, I suggest a new story for them. There are TODOs left in the code, 2 for the tasks and one more difficult for the google api client error handling.
  • The new GeoPlace type is now composed of NamedPlace and GeoLocation, it could also just extend them. I started to refactor that way but realized that GeoLocation equals() is used in EventListControllerImpl, so that would mean we may need to provide equals() in all GeoPlace or maybe use a Equalable decorator within the controller? It seems like a little bit to me that there might be some general conflict or difficulty with Value objects and polymorphism because of the need to always provide equals().
    Anyway, please check if you think GeoPlace would be better as extending the interfaces instead of composed from them. I have a feeling that that might be a better design.

About implementing the list modules in the next phase:
I have a plan already in mind, it would be like something as follows (names are just indications):
Each module will have a PlaceListController that receives the query text changes and can initiate background tasks and update the list. They will each have a ListItems kind of object which they can add and remove items to and from, it will be a proxy to the real ListItems that will hold the full list. That will be a Sectionable extension, so each proxy can have an id automatically assigned for them for example and this SectionableListItems can add/remove items to sections based on these ids. Or there is another alternative as well, but basically the important part would be that the module Controllers will not need to know anything about the full list.
The fragment could be parameterized if needed by sending in factories that create these controllers.
The current callback on the PlaceListController would be removed, any action would be initialized by the controllers themselves, for example in this case possibly loading a loader microfragment for the place by id call as mentioned earlier.
(As you can see I changed the names from Provider to Controller for this components for the lists, I think they fit better to what they do now.)

Gabor Keszthelyi added 30 commits January 2, 2017 18:32
…n. Some refactor and improvements around location selection types.
…e in with the actual api calls initiated by the text input.
…scarding to not show intermediary results when user types fast.
…n, and returning it to EventList screen. Some other related refactors.
…s() by using the suggestion's extraContext.
…ng states. Create PlaceSuggestionListItems that can be used by the controller.
… enabling automanage or adding manual error handling.
 Conflicts:
	eventdiscovery-sdk/src/main/AndroidManifest.xml
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/eventlist/itemsprovider/EventListController.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/eventlist/itemsprovider/EventListControllerImpl.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/eventlist/itemsprovider/EventListItemsProvider.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/eventlist/itemsprovider/EventListItemsProviderImpl.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/eventlist/view/EventListView.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/activities/MicroFragmentHostActivity.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/adapter/ListItems.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/eventlist/EventListActivity.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/eventlist/EventListFragment.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/eventlist/itemsprovider/EventListItemsProvider.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/eventlist/itemsprovider/EventListItemsProviderImpl.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/LastSelectedLocation.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/LocationSelection.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/LocationSelectionResult.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/NoLocationSelected.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/PlacesApiLocationSelection.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/PlacesApiLocationSelectionResult.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/SharedPrefLastSelectedLocation.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/location/StructuredLocationSelectionResult.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/framework/microfragments/eventdetails/fragments/EventDetailFragment.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/LastSelectedLocation.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/LastSelectedPlace.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/LocationSelection.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/LocationSelectionResult.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/NoLocationSelected.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/PlaceSelection.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/SharedPrefLastSelectedLocation.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/SharedPrefLastSelectedPlace.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/StructuredLocationSelectionResult.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/model/GeoPlace.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/model/GooglePredictionNamedPlace.java
	eventdiscovery-sdk/src/main/java/com/schedjoules/eventdiscovery/location/model/StructuredGeoPlace.java
	eventdiscovery-sdk/src/main/res/layout/schedjoules_activity_microfragment_host.xml
	eventdiscovery-sdk/src/main/res/values/strings.xml
Copy link
Contributor

@dmfs dmfs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No code comments yet, just one about the UX so far. Please remove the flicker when a new character is entered. At present the items in the list flicker when the new results are available. I would expect a proper animation that removes all elements, that are no longer among the results. Just like with the original Google picker.

@lemonboston
Copy link
Contributor Author

lemonboston commented Jan 11, 2017

I didn't notice it, but yes, that clearly wasn't nice that way.

I've made the update to animate the changes and also started to introduce a general design for list change updates, and I really like it at the moment, I think it may be very useful in the future.
It is inspired in part by what you mentioned once about creating a change set and then applying it.
Calculating changes in the background might need to be figured out later, but here it is fine to make it on main thread because there are only 6 items in the list.

edit: (Calculating in background will have challenges on synchronizing to the list, or having some queue to not allow the next calculation begin until the previous is finished and applied on the main thred.)

Copy link
Contributor

@dmfs dmfs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I have a few general concerns regarding the architecture, but I would rather refactor the entire thing once the other modules have been implemented than doing this now.

*
* @author Gabor Keszthelyi
*/
public class EventListItemsProviderImpl implements EventListItemsProvider, EventListBackgroundMessage.OnClickListener
public class EventListControllerImpl implements EventListController, EventListBackgroundMessage.OnClickListener
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class not final?

@@ -1,5 +1,5 @@
/*
* Copyright 2017 SchedJoules
* Copyright 2016 SchedJoules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright date reverted

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The year is still not updated.

*
* @author Gabor Keszthelyi
*/
public class PlaceSuggestionItem implements ListItem<LocationSuggestionItemView>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class not final

@@ -1,5 +1,5 @@
/*
* Copyright 2017 SchedJoules
* Copyright 2016 SchedJoules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copyright date reverted

}


public void setTitle(CharSequence title)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Which interface does this implement?

We talked about this before (in the "smart views" vs. "presenters" discussion).
This View is called LocationSuggestionItemView, which is a very specific name. Why has it methods like setTitle and setSubTitle with very generic names? You could should call it TwoLineItemView instead (or give the methods more specific names).

However, I'd prefer the "smart view" version which could implement an interface like this

public interface SmartView<T>
{
   void  update(T data);
}

With T being NamedPlace in that case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right that it wasn't clear how I would approach this smart or dumb view for the list items, because I felt that the ListItem itself usually need to hold the data anyway, item views are also recycled, so it might be better to keep data and logic there. But I like that SmartView interfaces as well, also to be coherent with other (not list item) views, this would be a clearer approach.
I've added it and I see that it can lead to more generalization of the ListItems, I will look into that in the next round. Namely to check if ListItem<V extends View> can be changed to ListItem<V extends SmartView> and also to check how to handle callback if needed.
A SmartView can of course execute stuff itself, but I am not sure if it should execute something async and then act on the result, that clearly seems too much, so in some cases we might still need callback from it. It depends also on whether that loading can be done in a new MicroFragment, then it's not a problem. For now, I left the callbacks in, which also meant that PlaceSuggestionItem is still very specific.

About making PlaceSuggestionItemView TwoLineItemView, I think the layout will be usually specific to the actual place of usage, so my feeling is that it's probably not worth trying to create something general, it might just cause problem if we used something like that for multiple places and couple them that way, we couldn't change one without changing the other.

@Override
public NamedPlace namedPlace()
{
return mAnywhereNamedPlace;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Did you consider to create AnywhereNamedPlace lazily? You would have to store an ApplicationContext but that's not an issue IMO.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You are right, keeping app context should not be a problem, so we can possibly use that inside lazy declarations more. I've updated it.

*
* @author Gabor Keszthelyi
*/
public class HideKeyboardActionListener implements TextView.OnEditorActionListener
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

class not final

*
* @author Gabor Keszthelyi
*/
public abstract class SimpleTextWatcher implements TextWatcher
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Always call abstract classes like Abstract…, i.e. AbstractTextWatcher or AbstractDefaultTextWatcher

private final CharSequence mName;


private AnywhereNamedPlace(CharSequence name)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this lazy. Pass an ApplicationContext and let name() return context.getString(R.string.schedjoules_default_location_placeholder_name).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@lemonboston lemonboston assigned lemonboston and unassigned dmfs Jan 12, 2017
@lemonboston
Copy link
Contributor Author

I've made the requested changes.

@lemonboston lemonboston assigned dmfs and unassigned lemonboston Jan 12, 2017
Copy link
Contributor

@dmfs dmfs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I've spotted a few more minor issues.

@@ -1,5 +1,5 @@
/*
* Copyright 2017 SchedJoules
* Copyright 2016 SchedJoules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The year is still not updated.

@@ -1,5 +1,5 @@
/*
* Copyright 2017 SchedJoules
* Copyright 2016 SchedJoules
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Another wrong year.

}


private static class EqualsDiffUtilCallback<T> extends DiffUtil.Callback
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make inner classes final too.

}


private static class AnywhereNamedPlace implements NamedPlace
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please make it final

}


private class PlaceSuggestionQueryTaskClient implements PlaceSuggestionQueryTask.Client
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this class final.

}


private class PlaceByIdTaskClient implements PlaceByIdTask.Client
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Make this class final.

*/
public final class BasicChangeableListItems implements ChangeableListItems
{
private List<ListItem> mItems = new ArrayList<>();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any reason this is not final?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, I actually remembered that I missed it but forgot to go back, thanks for spotting it, I've made it final.

@lemonboston
Copy link
Contributor Author

I've change all classes to final in the codebase that hadn't been and updated all copyrights to 2017.

@dmfs dmfs merged commit 2621580 into master Jan 13, 2017
@dmfs dmfs deleted the stories/30-location-picker-2 branch January 13, 2017 15:03
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants