plante-app-team / plante Goto Github PK
View Code? Open in Web Editor NEWCommunity-based vegan groceries map
Home Page: https://planteapp.com
License: GNU General Public License v3.0
Community-based vegan groceries map
Home Page: https://planteapp.com
License: GNU General Public License v3.0
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2194%3A43274
The button should:
ShopProductRangePage
,The Suggestions Settings Subpage should function similarly to how SettingsCachePage
works - the main settings page should have a button "Products suggestions settings", which would open it.
The new settings subpage should have toggles/checkboxes to enable/disable the according suggestions (OFF and Radius suggestions).
Checkboxe's values should be stored in Settings
.
When suggestions of a type are disabled (by value stored in Settings
), then ShopProductRangePage
:
ShopProductRangePage
, the page would hide already loaded suggestions.ShopProductRangePage
must be covered with tests:
We should store the list of products for a country persistently (when the list is loaded user’s country should be taken into account).
We should make a SQLite DB with pairs of “ShopUID” - “product barcode”.
The persistent data should be loaded before the network data.
Both types of data (list of shops and suggested pairs) should have a lifetime - after a month of storage they should be invalidated and then downloaded again.
The avatar would need to be downloaded and put to a local temporary file.
The editing page should have restorable fields, and should itself be restorably pushed to navigator.
See if other such pages are tested.
Manual testing is mandatory.
Markers are here: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=796%3A1690
The color of the circle at MapShopsFilterCheckbox
should be same as on the new markers.
Progress bar should be at the bottom:
Figma: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2194%3A42214
Because now they're separated, they should be in 2 separate widget with similar logic. E.g. the hints widget can be named TimedHints
.
We should try to reuse the GradientSpinner
as a progress bar widget. To reuse it, make it so that it would accept custom colors
and borderRadius
in its constructor.
If it's not possible, a new widget should be created with a logic similar to GradientSpinner
.
The new progress bar widget should be at the bottom of the page.
TimedHints
should be just below the search bar (find Column
which contains the search bar in MapPage
).
New design should not be applied yet.
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2109%3A30271
The Profile page should contain a pager with 2 products lists and 2 check-buttons which should allow to switch between the lists.
When lists are switched, the checked button also switches. When a button is checked, lists switch.
The "My products" list should not yet be implemented.
The "History" page should contain same products as ViewedProductsHistoryPage
does. ViewedProductsHistoryPage
should be removed.
Ensure the products are not loaded when a list is not displayed (use VisibilityDetectorPlante
).
Depends on: #79
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2293%3A30110
Describe the bug
When user starts the app for the first time and clicks the "Where am I" button, it takes the app too much of time to show user's location, and while app's figuring out the location, it doesn't show any kind of loading spinner, doesn't let the user know it didn't forget about the button press.
To Reproduce
Steps to reproduce the behavior:
Expected behavior
The app should either:
The 1st behavior would be much more preferred of course.
Maybe it can be done by:
Maybe there's a better way to do that, but it needs to be researched.
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2027%3A30674
Create EditUserDataPage
.
When the "Edit profile" button is clicked in the Profile page, the new page should be opened.
The new page should use EditUserDataWidget
, created in #99
The new page should has similar logic to what's implemented in #99 - it should allow to edit user's data and send it to the backend when the "Save" button is clicked.
Also, similarly to the Init User page, inserted data should be validated - too short user names shouldn't be allowed.
When map's shop creation mode is started manually by a call to the MapPage class, back press should cancel the mode.
Figma: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2109%3A30271
The Profile page should be empty for now.
The Plus button should do nothing for now.
There should be no News button, the Plus button should be at far-right.
UPD: Disregard all of the below, just show empty shops by default.
After cold start, when the first shops area is loaded - display empty stores if the loaded area has <5 of shops with products.
Currently map filtering options are managed in lib/ui/map/map_page/map_page_mode_default.dart
.
The options are stored in shared preferences, and can be safely moved to a new singleton (and should be).
The singleton should be named MapFiltersManager
, its file should be put into the lib/ui/map/map_page
dir.
Nearby should be created a new enum MapFilter
, with values NOT_EMPTY_SHOPS
, SHOPS_WITH_SUGGESTIONS
, EMPTY_SHOPS
.
MapFiltersManager
should have next methods:
/// Whether the [setValue] method was called with `byUser == true`.
Future<bool> wasValueSetByUser(MapFilter filter);
/// Stores value for the filter persistently (into shared prefs)
Future<void> setValue(MapFilter filter, bool value, bool byUser);
/// Returns stored value, or some default value if nothing is stored yet.
Future<bool> getValue(MapFilter filter);
MapFiltersManager
should store and retrieve persistent values in the same way map_page_mode_default.dart
currently does.
The byUser
value should be stored separately for each of the MapFilter
entries.
MapFiltersManager
should observe the ShopsManager
singleton.
When first shops area is loaded, MapFiltersManager
should check if MapFilter.EMPTY_SHOPS
wasn't set by user yet, and if it wasn't:
NOTE: feel free to tweak the description above if needed
Feedback:
Nice User — 01/14/2022
Creating new products is really slow for me. I can fill text fields and take pictures normally, but after clicking "submit" it will usually take 3 minutes to upload.I think it's because of a combination of slow Internet (1Mbps upload) and very large filesizes. It's a bug of a pain in the butt because it means I can't easily scan products. Are there any plans to implement some form of image compression (prior to the upload of a new product)? Or does it already exist and my issue is happening for another reason?
It happens both on my Mi A3 and my Redmi Note 10 Pro - Android 11 for both - and it's been happening since I downloaded the app (i.e. since I joined the server). :P
Nice User — 01/14/2022
(Assuming 16MB/picture and two pictures - one for the front and one for the ingredients - and a stable connection of 1Mbps, it does check out. It's about 4 minutes and 15 seconds)
Uploading 16MB images is not good.
What needs to be done.
Add this package to the app: https://pub.dev/packages/flutter_image_compress
Apply it to the code - compress images before they're sent to Open Food Facts.
Experiment with image sizes and compression levels:
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2293%3A29896
When the button is clicked, it should have a spinner inside of it.
When a loading was not caused by the button click, there should be no spinner, the button should disappear immediately (or not appear if it wasn't displayed before).
When the map is scrolled to an already loaded area, the button should disappear, even if it still has the spinner inside.
Map progress bar is a part of a column aligned to widget's bottom, because of this it forces other UI elements (which are in the same column) to move when it appears and disappears.
It looks janky and should be fixed.
To fix it, the progress bar should be put into some some Stack, completely separate from the Column described above. And should be aligned to bottom.
The resulted widgets structure probably will be similar to the structure which existed back then when the progress bar was aligned to top.
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2037%3A30314
New features should not be implemented, only new design should be applied to the existing settings.
Depends on: #79
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2194%3A42237
Use the ContributionsStorage
class to display the "My products" list.
While the products are being still loaded, show a spinner.
On loading errors, display error text with a Retry button.
Ensure the products are not loaded when a list is not displayed (use VisibilityDetectorPlante
).
Param is added here: plante-app-team/plante_server#7
The param should be set to true
if the create_update_product
cmd is sent from the Init Product page.
The parameter can be absent if the cmd is sent from other places.
Working prototype: blazern@9e8c7b9
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2194%3A42059
The CheckButtonPlante
widget should probably be used - it was created precisely to be a "checkbox, but it's a button".
Although current design of CheckButtonPlante
does not match the design of new buttons in Figma.
To solve it, the CheckButtonPlante
class should be changed to be more customizable - this way we would be able to use this widget for new filters and still use it where it's used at the moment.
Behavior:
Describe the bug
When we try to fetch offshops while we are in GB the request fails. We use countrycode GB instead while OFF expects a uk.openfoodfacts.org/shops
To Reproduce
Steps to reproduce the behavior:
Expected behavior
Offshops should be loaded for UK
Add to History all scanned products, even if the Product Display Page wasn't opened for them.
If the scanned product does not has all data yet, still add it to History.
When the Product Display Page is opened, still add the product to History - History will have 2 sources of products.
Write a script which will:
Send Shop info to OFF when a product is added to a shop:
Currently if an Android user uses the app without enabled geolocation services, the app prompts user to enable the services each time app's code tries to obtain user's current location.
The prompt dialog is shown by the OS.
This is bad - makes using the app harder.
To fix it, the UserLocationManager.currentPosition()
function should accept a {required bool userRequest}
parameter, which would signal whether the position was requested by user directly (e.g. they clicked the "Where am I" button), or by other places.
When userRequest == false
, UserLocationManager
should check if geolocation services are enabled on devices (not the permission, but the services), and return null
if they're disabled.
NOTE: it's possible the prompt wouldn't be shown if not-the-best accuracy would be requested from the OS.
If that's so, instead of returning null
the app should request such an accuracy from the OS (see GeolocatorWrapper.getCurrentPosition
).
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2122%3A30576
It should contain:
The Settings button should be removed from the Scan page. The Flashlight button should be moved to the right, where the Settings button was located before.
Presently ViewedProductsHistoryPage
loads products immediately after it's created. And the page can have a lot of products in it.
The page is rare opened though, but causes a lot of loadings on startups.
The products should start loading only when the page is opened. To achieve it, VisibilityDetectorPlante
should be used.
Put a product into the shop when a user clicks “Yes this suggested product is sold here”.
Extract edit-user-name widget into a EditUserDataWidget
, just like langs editing is extracted into UserLangsWidget
.
Just like UserLangsWidget
, EditUserDataWidget
should not send data to the backend itself. It should be only the representative of data added to it, accept callbacks and/or controllers (like TextField
does).
When the avatar in EditUserDataWidget
is clicked, the app should initiate photo selection process. The primary goal of such selection is to let user select a photo from their phone's gallery, not to take a new picture.
Once the photo is taken, ImageCropPage
should immediately be opened. ImageCropPage
must force the cropped area to be a square, user should see it's a square.
Once the photo is cropped, it should be downsized (if too big) according to the size figured out in plante-app-team/plante_server#5.
Once the photo is downsized, it should be set as the selected image of EditUserDataWidget
.
Maybe it makes sense to create a AvatarSelectionHelper
, which would: initiate photo selection, cropping, then would downsize the image.
When user clicks "Done" on the page after the avatar is chosen, the avatar is sent to the backend. The Backend
class should support that.
Avatar selection is optional, not mandatory. This should be explicitly mentioned in the UI.
This issue depends on: #65
See also: #67
The filters are managed by MapPageModeDefault
.
The map filters for suggestions must be removed - instead of 2 separate filters for OFF and Radius suggestions, there should be just 0 filter-checkmark saying "Products seen in similar stores".
The "Stores with products" filter now performs the work previously done by the 2 removed filters - when "Stores with products" is checked, then shops with suggested products are shown on the map (and not shown if it's not checked).
MapPageModeDefault.filter
should use values from settings - it should filter out shops (with suggestions) that are disabled by the settings (#65)
Of course, MapPageModeDefault.filter
shouldn't filter out a shop with suggestions if the shop satisfies some other condition (the empty/not-empty filtering).
The changes must be covered with tests in map_page_map_filters_test.dart
.
To do that, make an enum with list of places which cause photo selection. Accept an item of the enum when both selecting and retrieving a lost photo. Store the item persistently (shared prefs) and check which item is stored when retrieving a lost photo.
Cover with tests.
On ShopCard
display same label "products listed" for shops with suggestions only.
It should have both same text and same color as the label for sops with confirmed products.
It should be just same label.
When a new territory is just loaded, suggestions-markers start loading only when the camera moves.
Suggestions must start loading immediately after the territory is loaded.
Main usage:
When a user clicks “No it’s not sold here” on a suggested products, we should remove the suggested product from the list and stop asking the user about this product in this shop. For this, we should make an SQLite DB.
The DB should be made with keeping in mind its usefulness for other purposes. For example, in the future we should also store information about whether the user clicked the “It’s (not) sold here” button of main products list to not ask the user about same product again until it’s time.
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2109%3A30346
When pressed, shows a popup with "Add a product" and "Add a store" buttons.
When the "Add a product" button is clicked, barcode-scanning page is opened.
When the "Add a store" button is clicked, map is opened and the mode is switched to MapPageModeCreateShop
.
Tests:
If the image is smaller than min size, Open Food Facts rejects it, the app shows an error to the user.
This confuses users who want to send an image of a product to OFF.
It's not a very easy task because it requires the developer:
to be familiar with how Isolates in Dart works (or to learn it)
to investigate how image size can be obtained from either its binary data or from the image on the files system
ImageCropPage
should accept min Size
.
Min size for Open Food Facts is: width = 640
, height = 160
.
When user clicks "Done" in ImageCropPage
, the page should check the image size and show a user-friendly message if it's too small.
Tests are appreciated, but at the same time it's not going to be easy to cover this functionality with tests, so they're not necessary.
Problem
Shops in OFF can have slightly wrong names, and OSM can have slightly wrong names for shops.
When searching for products suggestions for a certain store, we should compare names not directly, but with fuzzy compare.
For example, if stores chain is named "Albert Heijn", and this store has products both in OFF (OffShopsManager
) and in Plante (RadiusProductsSuggestionsManager
), then all stores with very similar names should get products suggestions from both OFF and Plante.
A couple of examples of slightly differently named "Albert Heijn":
Solution description
shops_comparator.dart
file should be created in lib/outside/products/suggestions/
.bool areShopsNamesSimilar(String name1, String name2)
.areShopsNamesSimilar
function should either:
FuzzySearch
class,fuzzywuzzy
library directly,FuzzySearch
should be updated with new functionality which the areShopsNamesSimilar
would use.areShopsNamesSimilar
function should be used to compare stores in next places:
RadiusProductsSuggestionsManager
class (Plante's radius based suggestions),OffShopsListWrapper._backgroundFindAppropriateShop
method (OFF suggestions).areShopsNamesSimilar
),RadiusProductsSuggestionsManager
class (to ensure it uses the function),OffShopsListWrapper
class (to ensure it uses the function).DisplayProductPage
add a new item into the page's top-right menu: "See barcode".'send report'
in display_product_page_test.dart
(opens the menu and clicks an item in it).Steps to reproduce:
The problem is most likely in RadiusProductsSuggestionsManager.getSuggestedBarcodesByRadius
- it's code is not optimized for cities with enormous amounts of shops.
As much as possible of the code should be moved to a background isolate.
This issue depends on: #65
See also: #66
When all types of suggested products are disabled, ShopProductRangePage
should display a "Products suggestions settings" button at the bottom of the list.
The button should open products suggestions settings subpage (added in #65).
If ShopProductRangePage
didn't have any suggestions loaded when it was opened, then user opened the settings by the button, enabled suggestions and returned back to ShopProductRangePage
- it should load the enabled suggestions.
The button should be covered with tests.
What does "similar store" means on the labels of products in ShopProductRangePage
? ("Seen in similar store")
The word "similar" doesn't give an idea that the product was seen in a store with the same name.
It looks like it means "seen in a store, that visually looks similar" or something like that.
We should try the label: "Seen in other <storename> stores"
.
Design: https://www.figma.com/file/lHqzwSaWfsBiWNj9iyOaoh/plante-UI?node-id=2194%3A43274
No white background for the header and the titles:
(Probably 197c86a need to be partially reverted)
The button should not yet be added:
The header should be scrollable - when user scrolls products, the header should be scrolled together with them, so that more products would fit to the screen.
An "up" FAB should appear when the list is scrolled down a bit, and disappear when the list is being scrolled back up. When button is clicked, the list should scroll back to the top (preferably with animation).
Add all countrycodes and translations to country.dart
and change countries_lang_codes_table.dart to use country.dart as key
Create a ContributionsStorage
class.
The class should be lazy - it should retrieve list of user's contributions from the backend (using the user_contributions_data
cmd (plante-app-team/plante_server#7)) only when asked for the first time.
After the class is (lazily) inited, it should start observing ShopsManager
, and add to its local cache products which the user adds to shops.
It also should add to its local cache products created by the user.
When user clicks the appropriate button, send a cmd to the server to delete user's avatar (through UserAvatarManager
).
On success, delete the avatar locally.
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.