Compare commits
10 Commits
552f32ec97
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0d3694b4f9 | ||
|
|
b463b592aa | ||
|
|
567caabb05 | ||
|
|
916d384101 | ||
|
|
add098adf5 | ||
|
|
18ba120bb6 | ||
|
|
fde630577e | ||
|
|
c29a8a4014 | ||
|
|
3a0d7fcaed | ||
|
|
7a5d1d27f9 |
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
.DS_Store
|
||||||
@@ -1,11 +1,14 @@
|
|||||||
|
GitHub repo: https://github.com/chsanden/appdev/tree/main/FastNotes
|
||||||
|
|
||||||
# FastNotes
|
# FastNotes
|
||||||
|
|
||||||
This project is an Expo React Native note-taking app built for a CS assignment submission. It supports:
|
This project is an Expo React Native note-taking app built for a SWE assignment submission. It supports:
|
||||||
|
|
||||||
- Email/password authentication with Supabase Auth
|
- Email/password authentication with Supabase Auth
|
||||||
- Creating, viewing, editing, and deleting notes
|
- Creating, viewing, editing, and deleting notes
|
||||||
|
- Separate "My Notes" and "Work Notes" lists
|
||||||
- Optional image upload for notes using Supabase Storage
|
- Optional image upload for notes using Supabase Storage
|
||||||
- Push notification support through Expo and a Supabase Edge Function fallback path
|
- Remote push notifications through Expo, with a realtime-driven local notification fallback when push registration is unavailable
|
||||||
|
|
||||||
## Requirements
|
## Requirements
|
||||||
|
|
||||||
@@ -13,10 +16,11 @@ To build and run this project locally, you need:
|
|||||||
|
|
||||||
- Node.js (LTS recommended)
|
- Node.js (LTS recommended)
|
||||||
- npm
|
- npm
|
||||||
|
- Deno (only required if you want to run `npm run typecheck:functions`)
|
||||||
- Expo Go on a physical device, or an Android/iOS emulator
|
- Expo Go on a physical device, or an Android/iOS emulator
|
||||||
- A Supabase project that you configure yourself
|
- A Supabase project that you configure yourself
|
||||||
|
|
||||||
The repository does not include a committed `.env` file. That is intentional. The `.env` file is ignored by Git by design, so anyone running this project must create their own local `.env` file with their own Supabase and Expo values.
|
The repository does not include a committed `.env` file. That is intentional. The app reads runtime values from your local untracked `.env` through `app.config.js`, so anyone running this project must create their own `.env` file with their own Supabase and Expo values.
|
||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
@@ -42,8 +46,9 @@ Notes:
|
|||||||
|
|
||||||
- `EXPO_PUBLIC_SUPABASE_URL` is the URL of your Supabase project.
|
- `EXPO_PUBLIC_SUPABASE_URL` is the URL of your Supabase project.
|
||||||
- `EXPO_PUBLIC_SUPABASE_KEY` is the public anonymous key for your Supabase project.
|
- `EXPO_PUBLIC_SUPABASE_KEY` is the public anonymous key for your Supabase project.
|
||||||
- `EXPO_PUBLIC_EAS_PROJECT_ID` is optional and is only used for Expo push notification registration and related build/push flows.
|
- `EXPO_PUBLIC_EAS_PROJECT_ID` is used for Expo push notification registration and related build/push flows.
|
||||||
- The app requires `EXPO_PUBLIC_SUPABASE_URL` and `EXPO_PUBLIC_SUPABASE_KEY` at runtime. If those two values are missing, the app will not start correctly.
|
- The app requires `EXPO_PUBLIC_SUPABASE_URL` and `EXPO_PUBLIC_SUPABASE_KEY` at runtime. If those two values are missing, the app will not start correctly.
|
||||||
|
- These values are injected into Expo config by `app.config.js`.
|
||||||
|
|
||||||
## Build And Run Instructions
|
## Build And Run Instructions
|
||||||
|
|
||||||
@@ -149,6 +154,12 @@ note-images
|
|||||||
|
|
||||||
This bucket is used to upload note images. Stored image paths are then saved in the `Notes` table.
|
This bucket is used to upload note images. Stored image paths are then saved in the `Notes` table.
|
||||||
|
|
||||||
|
Images are validated and processed by the app with these constraints:
|
||||||
|
|
||||||
|
- Allowed formats: PNG, JPG/JPEG, WEBP
|
||||||
|
- Maximum size after processing: 15 MB
|
||||||
|
- Large images may be resized/compressed before upload
|
||||||
|
|
||||||
### 5. `user_push_tokens` table
|
### 5. `user_push_tokens` table
|
||||||
|
|
||||||
For push notifications, the app expects a table named `user_push_tokens` with fields used for registering device tokens. Based on the code, it uses:
|
For push notifications, the app expects a table named `user_push_tokens` with fields used for registering device tokens. Based on the code, it uses:
|
||||||
@@ -160,6 +171,34 @@ For push notifications, the app expects a table named `user_push_tokens` with fi
|
|||||||
- `is_active`
|
- `is_active`
|
||||||
- `updated_at`
|
- `updated_at`
|
||||||
|
|
||||||
|
## Notifications
|
||||||
|
|
||||||
|
The app has two notification paths:
|
||||||
|
|
||||||
|
### 1. Remote push notifications
|
||||||
|
|
||||||
|
On supported native builds, the app requests notification permission, obtains an Expo push token, and stores it in `user_push_tokens`.
|
||||||
|
|
||||||
|
This path depends on:
|
||||||
|
|
||||||
|
- A valid `EXPO_PUBLIC_EAS_PROJECT_ID`
|
||||||
|
- A physical device
|
||||||
|
- Notification permissions being granted
|
||||||
|
|
||||||
|
Important limitation:
|
||||||
|
|
||||||
|
- Android push notifications are currently not supported in Expo Go. To test Android push behavior, you need a development build or another native build type instead of Expo Go.
|
||||||
|
|
||||||
|
### 2. Realtime local-notification fallback
|
||||||
|
|
||||||
|
If push registration is unavailable, the app falls back to listening for new `Notes` inserts through Supabase Realtime and schedules a local notification on-device instead.
|
||||||
|
|
||||||
|
This fallback can happen when:
|
||||||
|
|
||||||
|
- The app is running on a simulator or emulator
|
||||||
|
- The Expo push project ID is missing
|
||||||
|
- Push token registration fails for another reason
|
||||||
|
|
||||||
## Supabase Edge Function
|
## Supabase Edge Function
|
||||||
|
|
||||||
This repository includes a Supabase Edge Function at:
|
This repository includes a Supabase Edge Function at:
|
||||||
@@ -168,7 +207,7 @@ This repository includes a Supabase Edge Function at:
|
|||||||
supabase/functions/push/index.ts
|
supabase/functions/push/index.ts
|
||||||
```
|
```
|
||||||
|
|
||||||
That function is responsible for sending push notifications when notes are created.
|
That function is responsible for sending remote push notifications when notes are created.
|
||||||
|
|
||||||
If you want to use that function, your Supabase function environment will need its own server-side values, including:
|
If you want to use that function, your Supabase function environment will need its own server-side values, including:
|
||||||
|
|
||||||
@@ -182,7 +221,8 @@ Notes:
|
|||||||
|
|
||||||
- `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` are required by the function code.
|
- `SUPABASE_URL` and `SUPABASE_SERVICE_ROLE_KEY` are required by the function code.
|
||||||
- `EXPO_ACCESS_TOKEN` may be needed depending on how you configure Expo push notification delivery.
|
- `EXPO_ACCESS_TOKEN` may be needed depending on how you configure Expo push notification delivery.
|
||||||
|
- The function must be connected to a database webhook that sends `POST` requests for `INSERT` events on the `Notes` table.
|
||||||
|
|
||||||
## Important Submission Note
|
## Important Submission Note
|
||||||
|
|
||||||
Because `.env` is intentionally ignored by Git, this submission does not include live secrets or a working personal backend configuration. To run the project successfully, the evaluator must create their own `.env` file and connect the app to their own Supabase project configured with the expected tables, columns, and storage bucket described above.
|
Because `.env` is intentionally ignored by Git, this submission does not include a committed working local backend configuration. To run the project successfully, the evaluator must create their own `.env` file and connect the app to their own Supabase project configured with the expected tables, columns, storage bucket, and notification setup described above.
|
||||||
|
|||||||
@@ -7,5 +7,9 @@ export default ({ config }) => ({
|
|||||||
supabaseUrl: process.env.EXPO_PUBLIC_SUPABASE_URL,
|
supabaseUrl: process.env.EXPO_PUBLIC_SUPABASE_URL,
|
||||||
supabaseKey: process.env.EXPO_PUBLIC_SUPABASE_KEY,
|
supabaseKey: process.env.EXPO_PUBLIC_SUPABASE_KEY,
|
||||||
easProjectId: process.env.EXPO_PUBLIC_EAS_PROJECT_ID,
|
easProjectId: process.env.EXPO_PUBLIC_EAS_PROJECT_ID,
|
||||||
|
eas: {
|
||||||
|
...config.extra?.eas,
|
||||||
|
projectId: process.env.EXPO_PUBLIC_EAS_PROJECT_ID,
|
||||||
|
},
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
"expo": {
|
"expo": {
|
||||||
"name": "FastNotes",
|
"name": "FastNotes",
|
||||||
"slug": "FastNotes",
|
"slug": "FastNotes",
|
||||||
"version": "1.0.0",
|
"version": "1.0.3",
|
||||||
"orientation": "portrait",
|
"orientation": "portrait",
|
||||||
"icon": "./assets/images/icon.png",
|
"icon": "./assets/images/icon.png",
|
||||||
"scheme": "fastnotes",
|
"scheme": "fastnotes",
|
||||||
@@ -63,12 +63,14 @@
|
|||||||
"reactCompiler": true
|
"reactCompiler": true
|
||||||
},
|
},
|
||||||
"extra": {
|
"extra": {
|
||||||
|
"router": {},
|
||||||
"supabaseUrl": "https://mogieparkvgcobaukpsr.supabase.co",
|
"supabaseUrl": "https://mogieparkvgcobaukpsr.supabase.co",
|
||||||
"supabaseKey": "sb_publishable_V_59BIi7RykQTnH7HNMWbg_dWN9hlbS",
|
"supabaseKey": "sb_publishable_V_59BIi7RykQTnH7HNMWbg_dWN9hlbS",
|
||||||
"router": {},
|
"easProjectId": "7eb7c779-f343-49c8-8412-286e56ee15f9",
|
||||||
"eas": {
|
"eas": {
|
||||||
"projectId": "7eb7c779-f343-49c8-8412-286e56ee15f9"
|
"projectId": "7eb7c779-f343-49c8-8412-286e56ee15f9"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"owner": "chsanden"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,10 @@
|
|||||||
"distribution": "internal"
|
"distribution": "internal"
|
||||||
},
|
},
|
||||||
"preview": {
|
"preview": {
|
||||||
"distribution": "internal"
|
"distribution": "internal",
|
||||||
|
"android": {
|
||||||
|
"buildType": "apk"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"production": {
|
"production": {
|
||||||
"autoIncrement": true
|
"autoIncrement": true
|
||||||
|
|||||||
BIN
FastNotes/fastnotes.apk
Normal file
BIN
FastNotes/fastnotes.apk
Normal file
Binary file not shown.
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "fastnotes",
|
"name": "fastnotes",
|
||||||
"main": "expo-router/entry",
|
"main": "expo-router/entry",
|
||||||
"version": "1.0.1",
|
"version": "1.0.3",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"start": "expo start",
|
"start": "expo start",
|
||||||
"reset-project": "node ./scripts/reset-project.js",
|
"reset-project": "node ./scripts/reset-project.js",
|
||||||
|
|||||||
Reference in New Issue
Block a user