zaniluca / ping-4-gitlab Goto Github PK
View Code? Open in Web Editor NEWMultiplatform react-native app that sends you instant notifications about gitlab activities
Multiplatform react-native app that sends you instant notifications about gitlab activities
We will add Sentry to our app for error and crash tracing.
For this scope, we'll use the provided expo-sentry
package.
Follow the docs for more info on how to setup the project with sentry
.env
.env.example
and expo.dev
None
Expo Sentry Docs: https://docs.expo.dev/guides/using-sentry/
We should sanitize the HTML message from the notification document, mainly to remove the footer used in the emails to unsubscribe
sanitizeHtml
in InboxItem.tsx
/<div class="footer"(.*)\/div>/g
None
None
Add password auto-fill for ios devices, allowing ios users to store passwords in the keychain and get suggestions when creating a new account and logging in
From what I can tell this will need to have a website, something that at the moment we don't have
app.json
add the associated domain for webcredentials"ios": {
"bundleIdentifier": "com.zaniluca.ping4gitlab",
"associatedDomains": ["webcredentials:www.pfg.app"]
},
com.zaniluca.ping4gitlab
bundle and add the Associated Domains capabilitiesOld Gist: https://gist.github.com/amcvitty/42cbe072184fe72485ad17cd7120bb89
How to add associated domains to website: https://developer.apple.com/documentation/xcode/supporting-associated-domains
Implement a dark theme for the whole app.
For now the theme will match the system one
"userInterfaceStyle": "automatic"
to app.json
and install expo-system-ui
import { Appearance, useColorScheme } from 'react-native';
function MyComponent() {
let colorScheme = useColorScheme();
if (colorScheme === 'dark') {
// render some dark thing
} else {
// render some light thing
}
}
theme.ts
to include a darkTheme
which will be an object that overrides the current theme
, spreading everything except colors that will be modified like this:export const darkTheme = createTheme({
...theme,
colors: {
...theme.colors,
primary: 'insert new color',
},
});
DarkTheme
for dark mode in react-native-navigation
check this out.theme
to lightTheme
Check that the dark style is conforming everywhere
Expo Docs: https://docs.expo.dev/guides/color-schemes/
React Native Navigation: https://reactnavigation.org/docs/themes/
The input on forms auto-capitalizes the text inside which is not the intended behavior when working with emails.
We should also add some settings to the input to allow autocomplete and some props to improve login and signup ux
Input props: https://reactnative.dev/docs/textinput
Password rules: https://reactnative.dev/docs/textinput#passwordrules-ios
Rename grays to primary
, secondary
, tertiary
, and quaternary
.
These names fit better with the future implementation of dark mode which will involve changing these colors, and it makes much more sense to name them this way instead of the actual way (gray900
, ...)
If the find and replace goes fine it should go as planned otherwise probably typescript is going to error out thanks to restyle
None
Integrate Firebase Performance & Crashlytics to monitor app status and get more info about crashes and malfunctioning
Maybe the build could be impacted because we will have to rebuild the native code via expo prebuild
to add the react-native-firebase
plugins which these modules need.
We should have everything we need in the already added react-native-firebase
, check the docs for more info
We should add an .nvmrc
file to track the current version of node for the project
.nvmrc
with the correct version of node: v14.19.1
Configure a CI/CD environment to build (eventually test) and deploy to the stores all via a push to the production
branch
eas-build.yml
file which triggers the build in easeas-build
workflow which deploys the latest build for both ios and androidIn the build job at the end commit changes to both production and master branches, they will only include a version bump for both ios and android.
To do this we will need to add the commit action proposed in this issue
tag
; we might want to use that to mirror the app version in app.json
and have the current version tracked in Github.app.json
which because it is just a JSON file should be pretty easyIf we don't commit app.json
changes after the build, which automatically increments the build number for both platforms, we'll run into inconsistencies because the build number will always be the same.
Guide: https://techblog.geekyants.com/github-actions-for-automating-builds-for-your-app
How to commit from Github Action: https://github.com/stefanzweifel/git-auto-commit-action
Integrate the web SDK for firebase.
This has to be done because rn there are some bugs with the react-native-firebase
module and to test the server integration we might as well start with the non-native solution provided by firebase that is also compatible with react-native
.
The idea is that when the app is in a more advanced state we can swap the firebase web module in favor of the react-native-firebase
one.
We'll follow the expo using firebase guide
expo install firebase
firebase.ts
where we will export every native module component, for now, we might probably switch to a more modular approach where we separate every module In its own file with its own functions and stuff.firestore
works correctly because it wasn't in react-native-firebase
None
The development build fails because the expo-firebase-core
can't load the firebase configurations files and therefore the whole build fails.
Error: Firebase wasn't correctly initialized! Remember to add google-services.json and GoogleService-info.plist to the root folder
at node_modules\react-native\Libraries\LogBox\LogBox.js:149:8 in registerError
at node_modules\react-native\Libraries\LogBox\LogBox.js:60:8 in errorImpl
- ... 9 more stack frames from framework internals
Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.
at node_modules\react-native\Libraries\LogBox\LogBox.js:149:8 in registerError
at node_modules\react-native\Libraries\LogBox\LogBox.js:60:8 in errorImpl
at node_modules\react-native\Libraries\LogBox\LogBox.js:34:4 in console.error
at node_modules\expo\build\environment\react-native-logs.fx.js:27:4 in error
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:104:6 in reportException
at node_modules\react-native\Libraries\Core\ExceptionsManager.js:172:19 in handleException
at node_modules\react-native\Libraries\Core\setUpErrorHandling.js:24:6 in handleError
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:367:8 in __guard
at node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:112:4 in callFunctionReturnFlushedQueue
This seems to be a regression with #42 that wasn't ever built for development but just for production.
The main problem resides in app.json
with the expo.updates.url
field breaking something with firebase. removing the line fixes the problem but this will not allow us to remotely update the app via eas-update (which at the time of writing is in beta for pro users only so we wouldn't use it anyway)
While debugging this issue, something that came out was a way to move the app entry point to another folder or component. this will allow us to move App.tsx
to src/App.tsx
for a more cleaner folder structure with the function registerRootComponent
(more info here)
Fix warning on the console:
AsyncStorage has been extracted from react-native core and will be removed in a future release. It can now be installed and imported from '@react-native-async-storage/async-storage' instead of 'react-native'. See https://github.com/react-native-async-storage/async-storage
We should export a pre-typed hook for accessing the theme instead of defining the type in each component
useTheme = () => useRestyleTheme<Theme>()
so that the exported hook will be automatically typed, useRestyleTheme
will be an alias to the useTheme
provided by restyle
to prevent name conflictsNone
None
Right now when the user presses "Let's Get Started" a modal with the guide on how to set up ping for gitlab opens up.
We want to allow the user with a simple call to action to go back to the landing page (and delete the newly created anonymous user)
AuthContext.tsx
add a function to delete a userGetStartedScreen.tsx
add a CTA that when pressed deletes the user and navigates it back to the Landing PageMaybe reset the navigation history so that with android it can't press the hardware back button to go back
Let's make sure that there is no regression In the setup flow
None
Expo offers a way to integrate native SDK in a managed project with expo-firebase-core
.
We should test if this is beneficial to us, primarily this would be useful if by using the native SDK we can distinguish between Android and iOS users;
expo-firebase-core
.GoogleService-Info.plist
file from firebase console and add it into the project.expo.dev
for eas
to pick it up.GoogleService-Info.plist
file for ios:echo $GOOGLE_SERVICES_ANDROID_BASE64 | base64 --decode > ./google-services.json && echo $GOOGLE_SERVICES_IOS_BASE64 | base64 --decode > ./GoogleService-Info.plist
ios.googleServicesFile
key to app.json
pointing to ./GoogleService-Info.plist
firebase.ts
eas
and when builded for preview
This will impact almost every firebase flow in the app, a rough testing round will be required
Using the native Firebase SDK: https://docs.expo.dev/guides/setup-native-firebase/#create-firebase-project
FirebaseCore: https://docs.expo.dev/versions/v44.0.0/sdk/firebase-core/
As stated here by apple app that allows the user to login will have to also allow the complete deletion of the user's account and their related data
We already have a function in the AuthContext
that allows deleting the user in firebase auth, also on firebase we have an extension in place to automatically delete the user's data from firestore
chevron-right
icon on the right and on the left user
AccountSettingsScreen.tsx
SettingsList.tsx
with only one row which says "Delete account" in a red textdeleteUser()
function in the AuthContext
None
Apple Requirements: https://developer.apple.com/news/?id=12m75xbj#:~:text=As%20a%20reminder%2C%20apps%20that,5.1.1(v).
React Native Alert:
https://reactnative.dev/docs/alert
Add swipe actions to InboxList.tsx
and InboxItem.tsx
to allow the user to mark notifications as read; this functionality will be extended to marking them as done or saving them later.
For doing this we should try to use the react-native-gesture-handler
library which we should already have installed (I think)
None
Swipable Demo with Expo: https://snack.expo.dev/@adamgrzybowski/react-native-gesture-handler-demo
We will add a way for the user to specify the work hours, this will him to choose when he wants to receive notifications like it's done on slack.
WorkHoursSettingsScreen.tsx
The action will have
chevron-right
icon to the right andclock
icon to the left
WorkHoursSettingsPage.tsx
add a sectioned list like the one in SettingsList.tsx
(consider refactoring it to make it reusable)This section will be used to create multiple sections in our "form"
@react-native-community/datetimepicker
TBD
DateTimePicker: https://docs.expo.dev/versions/latest/sdk/date-time-picker/
When a login fails (for example when the user loses internet connection) the app goes back to the GetStartedPage
; ultimately when the login succeded if tried a second time (turning wi-fi on for example) the user's hook_id gets reset to a random one generated when we went back to the GetStartedPage
None
Integrate the Firebase SDK into the app to access the auth, database, and notifications services.
For this, we should use this great library react-native-firebase
which provides everything we need and has also compatibility with expo which is greater because it seems to be usable without ejecting from the managed workflow.
After fast compatibility check we should be able to quickly setup a basic integration with auth
, firestore
and cloud-messaging
plugins
None
None
App badge never resets, make that it resets every time the user opens the app
None
When notifications are 0 (which as of now will never happen) we need to show a banner to the user which says "You've read all your notifications, good job!" or something like that.
We can use the ListEmptyComponent
from FlatList
(see this)
This will need to be introduced along whit the "Done" notification feature
Create a style catalog in the theme.ts to adopt common styles throughout the app; this will be more maintainable and also less confusing to work with.
It could be easy to add a dark mode in the future too.
IDK if we should use a library for this, it seems such an easy task but we'll see.
Warning
This issue is blocked by #98
We'll improve the current work hours settings by letting the user specify custom work hours for each day of the week
TBD
TBD
Field Array Example: https://formik.org/docs/examples/field-arrays
The key feature of the app should be implemented as soon as possible to get to that MVP state, the easiest way to implement push notifications seems to be by using the expo-notifications
library that does everything we need.
This is handy because it also has a server SDK for node which we can use with firebase functions.
Ref: https://github.com/zaniluca/ping-4-gitlab-functions/issues/2
For testing purposes we can use a curl via postman on cmd:
curl --location --request POST 'https://exp.host/--/api/v2/push/send' \
--header 'Content-Type: application/json' \
--data-raw '{
"to": "ExponentPushToken[rqIw6TMNgRZJrOqCXqyanu]",
"title":"hello",
"body": "world",
"badge": 1,
"sound": "default"
}'
Or simply use expo playground: https://expo.dev/notifications
expo-notifications
ExpoToken
to servergoogle-services.json
file"eas-build-pre-install": "echo $GOOGLE_SERVICES_ANDROID_BASE64 | base64 --decode > ./google-services.json"
None
Pusher video: https://www.youtube.com/watch?v=OLXw0X6dlnM
Expo Docs: https://docs.expo.dev/versions/latest/sdk/notifications/
We want to remove the device's expo push token from the user document in firestore when the user logs out
None
Make button more dynamic and more adaptable by taking advantage of the newly added restyle library
None
None
We will add a way for users to disable notifications temporarily.
The work will all be done by the server who's not going to send new notifications pushes when the user has explicitly said they don't want to be notified.
This ref: https://github.com/zaniluca/ping-4-gitlab-firebase/issues/16
UserData
to allow this new prop hasDisabledNotifications
userData.hasDisabledNotifications
and changes it on clickNone
None
Seems like notifications that are older and so they're displayed in their inbox row with a date containing the month (that should be like "A" for "April" "J" for "January" and so on) don't display the right months
dd M
formatNone
We need to add a pagination system for the Inbox in order to show more than 50 notifications. We're going to use the infinite query provided by react-query
Paginated Query: https://tanstack.com/query/v4/docs/guides/paginated-queries
Right now the way we handle forms with the Formik Library is via the component <Formik />
, this is not the best looking approach so we should consider switching to the hook approach by using the useFormik()
hook
<Formik>
to hook.<Formik>
add a form component and pass down the onsubmit
from formik.This will impact the login flow and the custom Input
component, we'll need to properly test that everything works as it was before
useFormik Docs: https://formik.org/docs/api/useFormik
Formik react-native Docs: https://formik.org/docs/guides/react-native
Useful video: https://www.youtube.com/watch?v=jP5VKH-Um7U
Jared Palmer Talk about use with react-native: https://www.youtube.com/watch?v=C1dHjIFjl6k
Migrate the notifications list to use Shopify's FlashList
FlatList
in InboxList.tsx
by changing it to FlashList
FlashList
Flashlist: https://github.com/Shopify/flash-list
TBD
TBD
TBD
As a user I must be able to receive notifications on multiple devices, to do so we just need to upload the device expo push token to firebase if it's not already present in the array.
Relates to: https://github.com/zaniluca/ping-4-gitlab-functions/issues/7
In the app this shouldn't impact anything
None
When users sign up for a new account and then go back to the landing page, their account gets deleted, we want to prevent that for a permanent user and keep this behavior only for anonymous ones.
None
We'll change the notification toggle (#52) behavior to allow the silencing of notifications for a certain amount of time like:
This will be done through an option sheet opened when tapping the new Silence settings row, we'll send to the backend an update to the user document with:
{
"muteUntil": date
}
Where date
will be a datetime object computed on the client side:
var today = new Date();
today.setHours(today.getHours() + 8);
const today= new Date()
today .setDate(today.getDate() + 1)
const today= new Date()
today .setDate(today.getYear() + 99)
TBD
Action Sheet: https://github.com/expo/react-native-action-sheet
ATM we're rendering notifications HTML content in a web view, that's great because it's faster for rendering purposes and easier to manage.
This solution is not really customizable as we don't have access to the single components inside the browser.
We Shouldn't try to include the react-native-render-html
library which renders HTML code as react-native components and so it looks better and its more customizable.
The drawback is that when implementing it the diff visualization in HTML is broken; there is probably a tweak in the library options to fix that but I haven't found it.
Add a feature toggle to use emulator data instead of production data.
Depends on: https://github.com/zaniluca/ping-4-gitlab-firebase/issues/8
None
None
Configure eslint
to allow for automatic code linting and style enforcement
eslint-config-universe: https://github.com/expo/expo/tree/master/packages/eslint-config-universe
Add various utilities to help enforce code style and standards adopted by the app
None
Medium Article: https://zaferayan.medium.com/how-to-configure-eslint-and-prettier-for-expo-projects-fd78d4158590
Eslint: https://gist.github.com/yovany-lg/104ed47e74d1ba64f68d79a3e5f76e91
We should export a pre-typed version of the useNavigation()
hook provided by react-native-navigation
to allow for fewer imports and complexities in components
Also, we should expose some types for components that are navigation items like this:
type RootStackScreenProps = NativeStackScreenProps<RootStackParamList, T>;
Or something like this
useRootStackNavigation()
in RootStackNavigation.tsx
useNavigation()
with this new hook throughout the appNone
None
TLDR we need to keep google services files private; how do we achieve this? by adding them to .gitignore
! The problem is that by doing this EAS doesn't pick them up when uploading to it.
The solution we have rn is to override the .gitignore
with a .easignore
which has everything ignored by the .gitignore
except for the google services files.
This is not considered the best way to handle this situation as mentioned in the related issue; we should follow the solution in the related issue and handle everything with Environment variables in the EAS dashboard, this will benefit in both not having to keep a local copy of the services files and also not having to copy every change to the .gitignore
to the .easignore
.
When previously trying to use this solution it wasn't working as intended and the build services couldn't decode and copy the files from env.
$ base64 google-services.json
).easignore
"eas-build-pre-install": "echo $GOOGLE_SERVICES_ANDROID_BASE64 | base64 --decode > ./google-services.json && echo $GOOGLE_SERVICES_IOS_BASE64 | base64 --decode > ./GoogleService-Info.plist"
Everything should build without failing in the last steps; if it fails will probably be with a message "Can not find google-services.json / GoogleServices_Info.plist"
This will only impact the build phase and should not have any side effect
EAS related issue: expo/eas-cli#228
Add the configuration needed to use the Expo Application Service (EAS), its a simple eas.json
file with the build configurations
eas.json
like this:{
"cli": {
"version": ">= 0.49.0"
},
"build": {
"development": {
"distribution": "internal",
"android": {
"gradleCommand": ":app:assembleDebug"
},
"ios": {
"simulator": true,
"buildConfiguration": "Debug",
"cocoapods": "1.11.2"
}
},
"preview": {
"distribution": "internal"
},
"production": {
"ios": {
"cocoapods": "1.11.2"
}
}
},
"submit": {
"production": {}
}
}
None
The code for the config file is copied from this merge #6
Configure hover the air updates to allow for the publication of fixes and features without the need to submit a new version to the store
Simply follow the guide on expo docs
I think none
Expo Get Started: https://docs.expo.dev/eas-update/getting-started/
Implement a Skeleton loading component to display when loading primarily notifications but also anything else if needed.
The component will need to be a basic View, customized to be animated with a skeleton-like opacity fading animation.
Skeleton.tsx
fileInboxScreen.tsx
None
Maybe if this turns out to be too sketchy try finding a good and simple library for this.
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.