This is a full Proof of Concept to show how React Native could rock the foodsharing world.
The app is optimized for iOS and Android - one code, one love!
Timeframe: 2 weeks from scratch to production π
-
iOS
- Install TestFlight
- Tap on this invitation link
-
Android
- Choose a minimized version for your platform
- or just install the universal APK
-
Login
- Full login / reauthentication / logout flows from cold and warm start
- Restores session if previously logged in - even if device offline
- Using device's keychain to store credentials in a secure location
- Auth form for email and password
- Buttons -> navigate to web based register & password restore
- Loading indication inside login button
- Notification of failed login
- Display of the current build version
-
Drawer
- Icon badge of unread notification count
- Display of logo and name of user
- Button -> navigation to notifications
- Badge next to button in case of unread notifications
- Button -> navigation to own profile
- Button -> send lovely feedback during beta
- Button -> Logout
- Display of the current build version
-
Conversations
- Send and receive messages
- Highlight/unhighlight of unread messages (sending 'read' signal to backend)
- Unlimitted scroll and pagination for conversation messages
- Activity indicator for all interactions
- Badge in the tab bar signalizing the unread count
- Conversation overview limited to the 50 latest conversations for now - because.. so much to do.. :)
- Connect to and handle WebSocket chat interface
- Local Notifications while app runs in the background
- Touch on Notification directly brings you to corresponding conversation (iOS only for now)
- Background conversations list pull every 15 minutes (iOS only for now)
- Display number of unread conversations as icon badge on home screen (iOS and some Android)
- Persist message drafts (per conversation)
- Shorten very long messages and display a 'read more' button
- Group chats (incl. multiple avatars displayed)
- Named chats (= title changed via web UI)
- Disable sending button while sending
- Tap on group conversation title -> navigate to list of members
- Tap on personal conversation title -> navigate to profile page
- Today -> Yesterday -> $Date labeling in conversation list
- Today -> Yesterday -> $Date seperators in conversation
- Detect URLs to foodsharing* in messages and make them clickable
- Pull to refresh
-
Group Conversation members
- Photo and name of group members
- Tap on list item -> navigate to profile of foodsaver
-
Notifications (bells)
- Handle/display all supported bell types in (bilingual)
- Pull to refresh
- Refreshed as well via Websocket signal
- Swipe right to display delete button
- Delete button -> triggers delete via API and removes bell
- Touch -> opens correlating URL in Browser (or in-app profile if friend request)
- As soon as item got touched, read notification is sent via API
-
Profile
- Screen scrape (until rest interface exists) of stats/information
- Image of foodsaver, paralax style
- Loading indicator
- Statistic circles
- Banana support! Button -> jump to Bananas scene
- Friendship button - signals friendship-offered status
- Send friendship request by touching friendship button (incl. loading indicator)
- Message button -> initiate conversation and jump to Conversation scene (incl. loading indicator)
- Report button -> jump to Report scene -> jump back (incl. loading indicator)
- Information segments parsed from the profile page
-
Bananas
- List of all received bananas and corresponding banana texts
-
Violation Report
- Wait, what? There's an API for it? Yep, at least to send them in :)
- Fully translated German <> English reporting system
- Picker(s) for report reason(s)
- Dynamic checkbox displaying of nested options
- Text entry for report text, autoscaling to fullscreen on text focus
- Hooking into Android's back button & blur event to leave fullscreen
- Sending/Success indicator on Profile scene
-
Baskets
- List of your own and nearby baskets
- Scene to view basket with creator, info, map
- Buttons to either message user or directly call phone
- Buttons to either edit or delete as the creator of the basket
- Image of basket - in list and detail view
- Create Basket scene
- Dynamic form to enter details, time frame and desired way of contact
- Camera button -> Camera scene to take picture
- Display of taken picture (currently not uploaded)
- Mini map with marker at currently choosen location
- Tap on mini map -> Location picker scene with current location preselected
- Possibility to set marker on current location
- Universal Linking of basket URLs (iOS)
- Share extension - 'Share' any image system wide directly into a new basket (iOS)
-
Camera
- Permission management - prompting on first use
- If permission denied, info and button leading to system settings
- If permission granted, take picture button
- Automatic rescale to backends 'normal' 800x before upload
-
Map
- Embedded map based on system (iOS: Apple Maps, Android: Google Maps)
- Clustering of markers
- Showing fairteiler and baskets
- Layer filter
- Tracking/centering of the user's current location on demand
- Button to zoom back to initial region
- Prompt for location permission on demand
- Reusing marker icons from Android version
-
Fairteiler
- Adress, picture and information
- Posts made to the Fairteilers wall (incl. images)
- Share button to copy or forward public Fairteiler URL
- Swipeable layout, number of comments in tab
- Navigate to profile on foodsaver image touch
-
Persisted central data (redux) store
- Persistence of conversations, messages, foodsavers, ...
- Full reset on logout
- Full offline read-only capability
- Caching of downloaded images via native libraries
-
UI / UX
- Custom fonts / 'foodsharing identity'
- All strings mapped to i18n files
-
Deployment, reporting, testing and CI
- Full sentry.io ingetration with censored redux log (auth, session and personal information removed)
- Detox & Mocha E2E UI test framework
- Over 60 test cases incl. auth, messaging, baskets, map, fairteiler, ...
- Travis CI
- Linting and test compilation of TypeScript
- Native compile and E2E simulator tests
- Fastlane iOS
- app icon generation
- app icon badge generation (version & build number)
- certificate handling
- testflight/appstore deployment
-
Tech stack
- React Native
- redux / redux-saga for js generator magic β€οΈ
- see package.json for complete package list
Setup your React Native environment by following the Getting started guide (React Native CLI Quickstart).
After cloning the project, initialize its node environment, compile the TypeScript and finally the native version:
$> yarn
$> tsc
# then for iOS
$> cd ios
$> pod install
$> cd ..
$> react-native run-ios
# or for Android - make sure to have your emulator running or phone connected in developer mode
$> react-native run-android
To get an insight into the redux action flow, state and log, use react-native-debugger
and the Debug
mode via React Native's shaking menu.
To let it use your local docker development environment instead of production endpoints, set PRODUCTION
to false
in the configuration file.
Setup your detox environment by following the Step 1 of detox's documentation.
Afterwards, first compile the test version (only needed once per native breaking change) and start the tests afterwards:
$> detox build --configuration ios.sim.debug
$> detox test --configuration ios.sim.debug
-
Should have
- Optimize and benchmark rendering
- Android
- Camera, when first blocking permissions, going to settings, granting them, return -> overlay stays visible
- Map markers on location selector scene is lagging behind movement
- Reflect REQUEST_ERROR errors in the seperate UIs instead of silently canceling the loading/sending
- Pull conversation again when open and coming from background to make sure its marked as read
- Notifications after background pull / detect new conversations - even pull pull conversations? Delta algo!
- Handle WebSocket reconnect after long inactivity
- Clean up old navigation state system - only needed to track if and which conversation a user is watching atm
- If both mobile and landline numbers are defined for a basket to request, ask the user which to call
-
Nice to have
- Make sure there is no gap between old store and long-time-no-see message list request -> hotfix: logout-in
- Settings screen to setup background pull / notifications?
- Use
CONVERSATIONS_SUCCESS
to warm up conversation's message (at least one) - State for loading conversations overview for loading indicator
-
Feature creep
- Edit profile information / MΓΌtze :)
While the app and its screens are fully i18n translated, a few foorsharing endpoints deserve some love by someone motivated. Information like the profile details are returned by the backend in German only - fix it, and i will adapt it!