-
Notifications
You must be signed in to change notification settings - Fork 5
Develop #83
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Develop #83
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,73 @@ | ||
| You are an expert in TypeScript, React Native, Expo, and Mobile App Development. | ||
|
|
||
| Code Style and Structure: | ||
|
|
||
| - Write concise, type-safe TypeScript code. | ||
| - Use functional components and hooks over class components. | ||
| - Ensure components are modular, reusable, and maintainable. | ||
| - Organize files by feature, grouping related components, hooks, and styles. | ||
| - This is a mobile application, so ensure all components are mobile friendly and responsive and support both iOS and Android platforms and ensure that the app is optimized for both platforms. | ||
|
|
||
| Naming Conventions: | ||
|
|
||
| - Use camelCase for variable and function names (e.g., `isFetchingData`, `handleUserInput`). | ||
| - Use PascalCase for component names (e.g., `UserProfile`, `ChatScreen`). | ||
| - Directory and File names should be lowercase and hyphenated (e.g., `user-profile`, `chat-screen`). | ||
|
|
||
| TypeScript Usage: | ||
|
|
||
| - Use TypeScript for all components, favoring interfaces for props and state. | ||
| - Enable strict typing in `tsconfig.json`. | ||
| - Avoid using `any`; strive for precise types. | ||
| - Utilize `React.FC` for defining functional components with props. | ||
|
|
||
| Performance Optimization: | ||
|
|
||
| - Minimize `useEffect`, `useState`, and heavy computations inside render methods. | ||
| - Use `React.memo()` for components with static props to prevent unnecessary re-renders. | ||
| - Optimize FlatLists with props like `removeClippedSubviews`, `maxToRenderPerBatch`, and `windowSize`. | ||
| - Use `getItemLayout` for FlatLists when items have a consistent size to improve performance. | ||
| - Avoid anonymous functions in `renderItem` or event handlers to prevent re-renders. | ||
|
|
||
| UI and Styling: | ||
|
|
||
| - Use consistent styling leveraging `gluestack-ui`. If there isn't a Gluestack component in the `components/ui` directory for the component you are trying to use consistently style it either through `StyleSheet.create()` or Styled Components. | ||
| - Ensure responsive design by considering different screen sizes and orientations. | ||
| - Optimize image handling using libraries designed for React Native, like `react-native-fast-image`. | ||
|
|
||
| Web Platform Compatibility (React Native Web): | ||
|
|
||
| - When combining styles (e.g., `[styles.base, { color: dynamicColor }]`), always use `StyleSheet.flatten()` to merge them into a single object. Passing style arrays directly causes "Failed to set an indexed property on CSSStyleDeclaration" errors on web. | ||
| - For components that need dynamic styles, use: `style={StyleSheet.flatten([styles.myStyle, { color: dynamicValue }])}` | ||
| - Do not pass `style` props directly to lucide-react-native icons. Wrap icons in a `View` and apply styles to the wrapper instead. | ||
| - Avoid using the `gap` property in StyleSheet styles as it has inconsistent support on web. Use `marginLeft`, `marginRight`, `marginTop`, or `marginBottom` on child elements instead. | ||
| - When creating custom components that will render on web, prefer using React Native's core `Text` and `View` components (imported from 'react-native') over gluestack-ui wrappers for better style handling compatibility. | ||
|
|
||
| Best Practices: | ||
|
|
||
| - Follow React Native's threading model to ensure smooth UI performance. | ||
| - Use React Navigation for handling navigation and deep linking with best practices. | ||
| - Create and use Jest to test to validate all generated components | ||
| - Generate tests for all components, services and logic generated. Ensure tests run without errors and fix any issues. | ||
| - The app is multi-lingual, so ensure all text is wrapped in `t()` from `react-i18next` for translations with the dictonary files stored in `src/translations`. | ||
| - Ensure support for dark mode and light mode. | ||
| - Ensure the app is accessible, following WCAG guidelines for mobile applications. | ||
| - Make sure the app is optimized for performance, especially for low-end devices. | ||
| - Handle errors gracefully and provide user feedback. | ||
| - Implement proper offline support. | ||
| - Ensure the user interface is intuitive and user-friendly and works seamlessly across different devices and screen sizes. | ||
|
|
||
| Additional Rules: | ||
|
|
||
| - Use `yarn` as the package manager. | ||
| - Use Expo's secure store for sensitive data | ||
| - Implement proper offline support | ||
| - Use `zustand` for state management | ||
| - Use `react-hook-form` for form handling | ||
| - Use `react-query` for data fetching | ||
| - Use `react-i18next` for internationalization | ||
| - Use `react-native-mmkv` for local storage | ||
| - Use `axios` for API requests | ||
| - Use `@rnmapbox/maps` for maps, mapping or vehicle navigation | ||
| - Use `lucide-react-native` for icons and use those components directly in the markup and don't use the gluestack-ui icon component | ||
| - Use ? : for conditional rendering and not && | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -428,11 +428,93 @@ jobs: | |
| core.setOutput('pr_url', ''); | ||
| } | ||
|
|
||
|
|
||
| build-electron: | ||
| needs: test | ||
| if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')) || github.event_name == 'workflow_dispatch' | ||
| strategy: | ||
| matrix: | ||
| os: [macos-latest, ubuntu-latest, windows-latest] | ||
| runs-on: ${{ matrix.os }} | ||
| permissions: | ||
| contents: write | ||
| packages: write | ||
| actions: write | ||
| steps: | ||
| - name: 🏗 Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: 🏗 Setup Node.js | ||
| uses: actions/setup-node@v4 | ||
| with: | ||
| node-version: '24' | ||
| cache: 'yarn' | ||
|
|
||
| - name: 📦 Install dependencies | ||
| run: yarn install --frozen-lockfile | ||
|
|
||
| - name: 🖥️ Build Electron App | ||
| env: | ||
| GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} | ||
| run: | | ||
| yarn electron:pack | ||
|
|
||
| - name: 📦 Upload build artifacts | ||
| uses: actions/upload-artifact@v4 | ||
| with: | ||
| name: electron-build-${{ matrix.os }} | ||
| path: | | ||
| dist/electron/*.dmg | ||
| dist/electron/*.exe | ||
| dist/electron/*.AppImage | ||
| dist/electron/*.zip | ||
| if-no-files-found: warn | ||
coderabbitai[bot] marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
|
||
| publish-release: | ||
| needs: [build-and-deploy, build-electron] | ||
| if: (github.event_name == 'push' && (github.ref == 'refs/heads/main' || github.ref == 'refs/heads/master')) || (github.event_name == 'workflow_dispatch' && (github.event.inputs.buildType == 'all' || github.event.inputs.buildType == 'prod-apk')) | ||
| runs-on: ubuntu-latest | ||
| permissions: | ||
| contents: write | ||
| steps: | ||
| - name: 🏗 Checkout repository | ||
| uses: actions/checkout@v4 | ||
|
|
||
| - name: 📦 Download all artifacts | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| path: ./artifacts | ||
| merge-multiple: true | ||
|
Comment on lines
+483
to
+487
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: # First, let's check the workflow file structure and locate the build-electron job
cat -n .github/workflows/react-native-cicd.yml | head -100Repository: Resgrid/Dispatch Length of output: 4170 🏁 Script executed: # Find the build-electron job and its artifact upload configuration
rg -n "build-electron" .github/workflows/react-native-cicd.yml -A 50 | head -80Repository: Resgrid/Dispatch Length of output: 3063 🏁 Script executed: # Check the upload-artifact configuration in the build-electron job
rg -n "upload-artifact" .github/workflows/react-native-cicd.yml -B 2 -A 5Repository: Resgrid/Dispatch Length of output: 613 🏁 Script executed: # Check the release job to see what artifact paths it expects
rg -n "artifacts glob" .github/workflows/react-native-cicd.yml -B 5 -A 5Repository: Resgrid/Dispatch Length of output: 42 🏁 Script executed: # Look for any artifact glob patterns in the release step
rg -n "artifacts/" .github/workflows/react-native-cicd.yml -B 2 -A 2Repository: Resgrid/Dispatch Length of output: 398 🏁 Script executed: # Search for any GitHub Actions documentation or comments about merge-multiple behavior
rg -i "merge-multiple\|path.*structure\|directory.*preserve" .github/workflows/react-native-cicd.yml -B 2 -A 2Repository: Resgrid/Dispatch Length of output: 42 🏁 Script executed: # Check if there are any other download-artifact steps or artifact handling logic
rg -n "download-artifact\|upload-artifact" .github/workflows/react-native-cicd.yml -B 1 -A 8Repository: Resgrid/Dispatch Length of output: 42 🏁 Script executed: # Check if there's a .nojekyll, script, or documentation about how this workflow handles artifacts
find . -name "*.md" -o -name "*.txt" | xargs grep -l "electron\|artifact" 2>/dev/null | head -10Repository: Resgrid/Dispatch Length of output: 42 🏁 Script executed: # Look for any recent changes or comments about artifact paths
git log --oneline --all -- .github/workflows/react-native-cicd.yml | head -20Repository: Resgrid/Dispatch Length of output: 184 🏁 Script executed: # Check GitHub Actions documentation online for merge-multiple behavior
web_searchRepository: Resgrid/Dispatch Length of output: 110 🌐 Web query:
💡 Result:
Fix artifact paths: electron builds won't be found by release action. The Fix by updating the upload step to avoid nested directory storage: 🔧 Solution: Flatten upload paths - name: 📦 Upload build artifacts
uses: actions/upload-artifact@v4
with:
name: electron-build-${{ matrix.os }}
path: dist/electron/
if-no-files-found: warnThis uploads the directory contents directly without preserving the 🤖 Prompt for AI Agents |
||
|
|
||
|
Comment on lines
+477
to
+488
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🌐 Web query:
💡 Result: For
Example (cross-repo / cross-run): permissions:
actions: read
steps:
- uses: actions/download-artifact@v4
with:
github-token: ${{ secrets.GH_PAT }} # must have actions:read on target repo
repository: org/other-repo
run-id: 123456789
name: my-artifact[1][2] Add
🔧 Proposed fix permissions:
contents: write
+ actions: read🤖 Prompt for AI Agents |
||
| - name: 📋 Get PR information | ||
| id: pr_info | ||
| uses: actions/github-script@v7 | ||
| with: | ||
| script: | | ||
| const commit = context.sha; | ||
| const { data: prs } = await github.rest.repos.listPullRequestsAssociatedWithCommit({ | ||
| owner: context.repo.owner, | ||
| repo: context.repo.repo, | ||
| commit_sha: commit | ||
| }); | ||
|
|
||
| if (prs.length > 0) { | ||
| const pr = prs[0]; | ||
| core.setOutput('pr_number', pr.number); | ||
| core.setOutput('pr_title', pr.title); | ||
| core.setOutput('pr_body', pr.body || ''); | ||
| core.setOutput('pr_url', pr.html_url); | ||
| } else { | ||
| core.setOutput('pr_number', ''); | ||
| core.setOutput('pr_title', ''); | ||
| core.setOutput('pr_body', ''); | ||
| core.setOutput('pr_url', ''); | ||
| } | ||
|
|
||
| - name: 📋 Prepare Release Notes file | ||
| if: ${{ matrix.platform == 'android' }} | ||
| env: | ||
| RELEASE_NOTES_INPUT: ${{ github.event.inputs.release_notes }} | ||
| PR_BODY: ${{ github.event_name == 'pull_request' && github.event.pull_request.body || steps.pr_info.outputs.pr_body }} | ||
| PR_BODY: ${{ steps.pr_info.outputs.pr_body }} | ||
| run: | | ||
| set -eo pipefail | ||
| # Determine source of release notes: workflow input, PR body, or recent commits | ||
|
|
@@ -467,48 +549,20 @@ jobs: | |
| echo | ||
| printf '%s\n' "$NOTES" | ||
| } > RELEASE_NOTES.md | ||
|
|
||
| # Store release notes for later use | ||
| echo "RELEASE_NOTES<<EOF" >> $GITHUB_ENV | ||
| cat RELEASE_NOTES.md >> $GITHUB_ENV | ||
| echo "EOF" >> $GITHUB_ENV | ||
|
|
||
| - name: 📦 Download Web Artifacts | ||
| if: ${{ matrix.platform == 'android' && (github.event.inputs.buildType == 'all' || github.event_name == 'push' || github.event.inputs.buildType == 'prod-apk') }} | ||
| uses: actions/download-artifact@v4 | ||
| with: | ||
| name: app-builds-web | ||
| path: ./web-artifacts | ||
| continue-on-error: true | ||
|
|
||
| - name: � Check Web Artifacts | ||
| if: ${{ matrix.platform == 'android' && (github.event.inputs.buildType == 'all' || github.event_name == 'push' || github.event.inputs.buildType == 'prod-apk') }} | ||
| id: check-web-artifacts | ||
| run: | | ||
| if [ -f "./web-artifacts/ResgridDispatch-web.zip" ]; then | ||
| echo "WEB_ARTIFACT_EXISTS=true" >> $GITHUB_ENV | ||
| echo "RELEASE_ARTIFACTS=./ResgridDispatch-prod.apk,./web-artifacts/ResgridDispatch-web.zip" >> $GITHUB_ENV | ||
| echo "Web artifact found" | ||
| else | ||
| echo "WEB_ARTIFACT_EXISTS=false" >> $GITHUB_ENV | ||
| echo "RELEASE_ARTIFACTS=./ResgridDispatch-prod.apk" >> $GITHUB_ENV | ||
| echo "Web artifact not found, will only include APK" | ||
| fi | ||
|
|
||
| - name: 📦 Create Release | ||
| if: ${{ matrix.platform == 'android' && (github.event.inputs.buildType == 'all' || github.event_name == 'push' || github.event.inputs.buildType == 'prod-apk') }} | ||
| - name: 🚀 Publish to Release | ||
| uses: ncipollo/release-action@v1 | ||
| with: | ||
| tag: '1.${{ github.run_number }}' | ||
| commit: ${{ github.sha }} | ||
| makeLatest: true | ||
| allowUpdates: true | ||
| name: '1.${{ github.run_number }}' | ||
| artifacts: ${{ env.RELEASE_ARTIFACTS }} | ||
| artifacts: "artifacts/ResgridDispatch-prod.apk,artifacts/ResgridDispatch-web.zip,artifacts/*.dmg,artifacts/*.exe,artifacts/*.AppImage,artifacts/*.zip" | ||
| bodyFile: 'RELEASE_NOTES.md' | ||
| token: ${{ secrets.GITHUB_TOKEN }} | ||
|
|
||
| - name: 📡 Send Release Notes to Changerawr | ||
| if: ${{ matrix.platform == 'android' && (github.event.inputs.buildType == 'all' || github.event_name == 'push' || github.event.inputs.buildType == 'prod-apk') }} | ||
| continue-on-error: true | ||
| run: | | ||
| set -eo pipefail | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,45 @@ | ||
| const { app, BrowserWindow } = require('electron'); | ||
| const path = require('path'); | ||
| const isDev = require('electron-is-dev'); | ||
|
|
||
| function createWindow() { | ||
| const mainWindow = new BrowserWindow({ | ||
| width: 1200, | ||
| height: 800, | ||
| webPreferences: { | ||
| preload: path.join(__dirname, 'preload.js'), | ||
| nodeIntegration: isDev, | ||
| contextIsolation: !isDev, | ||
| webSecurity: !isDev | ||
| }, | ||
| }); | ||
|
|
||
| // In development, load the local Expo web server | ||
| // In production, load the built index.html | ||
| const startUrl = isDev | ||
| ? 'http://localhost:8081' | ||
| : `file://${path.join(__dirname, '../dist/index.html')}`; | ||
|
|
||
| console.log('Loading URL:', startUrl); | ||
| mainWindow.loadURL(startUrl); | ||
|
|
||
| if (isDev) { | ||
| mainWindow.webContents.openDevTools(); | ||
| } | ||
| } | ||
|
|
||
| app.whenReady().then(() => { | ||
| createWindow(); | ||
|
|
||
| app.on('activate', () => { | ||
| if (BrowserWindow.getAllWindows().length === 0) { | ||
| createWindow(); | ||
| } | ||
| }); | ||
| }); | ||
|
|
||
| app.on('window-all-closed', () => { | ||
| if (process.platform !== 'darwin') { | ||
| app.quit(); | ||
| } | ||
| }); |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| // preload.js | ||
| // All of the Node.js APIs are available in the preload process. | ||
| // It has the same sandbox as a Chrome extension. | ||
| window.addEventListener('DOMContentLoaded', () => { | ||
| const replaceText = (selector, text) => { | ||
| const element = document.getElementById(selector) | ||
| if (element) element.innerText = text | ||
| } | ||
|
|
||
| for (const dependency of ['chrome', 'node', 'electron']) { | ||
| replaceText(`${dependency}-version`, process.versions[dependency]) | ||
| } | ||
| }) |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,7 +3,7 @@ | |
| "version": "0.0.1", | ||
| "versionCode": "1", | ||
| "private": true, | ||
| "main": "expo-router/entry", | ||
| "main": "electron/main.js", | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🧩 Analysis chain🏁 Script executed: cd /repo && pwd && git ls-files | head -20Repository: Resgrid/Dispatch Length of output: 115 🏁 Script executed: cat -n package.jsonRepository: Resgrid/Dispatch Length of output: 13523 🏁 Script executed: fd -type f -name "app.json" -o -name "eas.json" -o -name "expo.config.*"Repository: Resgrid/Dispatch Length of output: 230 🏁 Script executed: rg -l "entry|main" --type json | head -10Repository: Resgrid/Dispatch Length of output: 147 🌐 Web query:
💡 Result: In Expo, the app’s bundle entry module is taken from the project’s What
|
||
| "scripts": { | ||
| "start": "cross-env EXPO_NO_DOTENV=1 expo start", | ||
| "prebuild": "cross-env EXPO_NO_DOTENV=1 yarn expo prebuild", | ||
|
|
@@ -45,12 +45,42 @@ | |
| "install-maestro": "curl -Ls 'https://get.maestro.mobile.dev' | bash", | ||
| "e2e-test": "maestro test .maestro/ -e APP_ID=com.obytes.development", | ||
| "web:build": "cross-env APP_ENV=production expo export --platform web", | ||
| "electron:dev": "concurrently \"cross-env BROWSER=none yarn web\" \"wait-on http://localhost:8081 && electron .\"", | ||
| "electron:pack": "yarn web:build && electron-builder -c.extraMetadata.main=electron/main.js", | ||
| "docker:build": "docker build -t resgrid-dispatch-web .", | ||
| "docker:run": "docker run -p 3000:80 --env-file .env.docker resgrid-dispatch-web", | ||
| "docker:up": "docker-compose up -d", | ||
| "docker:down": "docker-compose down", | ||
| "docker:logs": "docker-compose logs -f" | ||
| }, | ||
| "build": { | ||
| "appId": "com.resgrid.dispatch", | ||
| "productName": "Dispatch", | ||
| "directories": { | ||
| "output": "dist/electron" | ||
| }, | ||
| "files": [ | ||
| "dist/**/*", | ||
| "electron/**/*", | ||
| "package.json" | ||
| ], | ||
| "mac": { | ||
| "category": "public.app-category.productivity", | ||
| "target": [ | ||
| "dmg" | ||
| ] | ||
| }, | ||
| "win": { | ||
| "target": [ | ||
| "nsis" | ||
| ] | ||
| }, | ||
| "linux": { | ||
| "target": [ | ||
| "AppImage" | ||
| ] | ||
| } | ||
| }, | ||
| "dependencies": { | ||
| "@config-plugins/react-native-callkeep": "^11.0.0", | ||
| "@config-plugins/react-native-webrtc": "~12.0.0", | ||
|
|
@@ -195,8 +225,12 @@ | |
| "@typescript-eslint/eslint-plugin": "~5.62.0", | ||
| "@typescript-eslint/parser": "~5.62.0", | ||
| "babel-jest": "~30.0.0", | ||
| "concurrently": "^9.2.1", | ||
| "cross-env": "~7.0.3", | ||
| "dotenv": "~16.4.5", | ||
| "electron": "^40.1.0", | ||
| "electron-builder": "^26.7.0", | ||
| "electron-is-dev": "^3.0.1", | ||
| "eslint": "~8.57.0", | ||
| "eslint-config-expo": "~7.1.2", | ||
| "eslint-config-prettier": "~9.1.0", | ||
|
|
@@ -223,7 +257,8 @@ | |
| "tailwindcss": "3.4.4", | ||
| "ts-jest": "~29.1.2", | ||
| "ts-node": "~10.9.2", | ||
| "typescript": "~5.8.3" | ||
| "typescript": "~5.8.3", | ||
| "wait-on": "^9.0.3" | ||
| }, | ||
| "repository": { | ||
| "type": "git", | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typos/hyphenation in the guidelines text.
Minor wording issues in the doc.
✏️ Suggested edits
Also applies to: 52-52
🧰 Tools
🪛 LanguageTool
[grammar] ~9-~9: Use a hyphen to join words.
Context: ...ion, so ensure all components are mobile friendly and responsive and support both...
(QB_NEW_EN_HYPHEN)
🤖 Prompt for AI Agents