Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
73 changes: 73 additions & 0 deletions .agent/rules/agent.md
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.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Fix typos/hyphenation in the guidelines text.
Minor wording issues in the doc.

✏️ Suggested edits
-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.
+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.
...
-- 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`.
+- The app is multi-lingual, so ensure all text is wrapped in `t()` from `react-i18next` for translations with the dictionary files stored in `src/translations`.

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
In @.agent/rules/agent.md at line 9, Update the guideline sentence in
.agent/rules/agent.md to fix typos and hyphenation: change "mobile application"
phrasing to "mobile-friendly" (hyphenated), remove the repeated "and", ensure
platform names are capitalized as "iOS and Android", and rephrase for clarity to
something like "This is a mobile application, so ensure all components are
mobile-friendly, responsive, and support both iOS and Android platforms;
optimize the app for both platforms." Locate the exact sentence shown in the
diff and replace it with the corrected, hyphenated version.


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 &&
120 changes: 87 additions & 33 deletions .github/workflows/react-native-cicd.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

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
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 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 -100

Repository: 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 -80

Repository: 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 5

Repository: 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 5

Repository: 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 2

Repository: 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 2

Repository: 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 8

Repository: 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 -10

Repository: 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 -20

Repository: Resgrid/Dispatch

Length of output: 184


🏁 Script executed:

# Check GitHub Actions documentation online for merge-multiple behavior
web_search

Repository: Resgrid/Dispatch

Length of output: 110


🌐 Web query:

GitHub Actions upload-artifact download-artifact merge-multiple directory structure preservation behavior

💡 Result:

  • What gets preserved on upload (actions/upload-artifact): the artifact stores files with their relative paths, with the artifact “root” determined by:

    • Multiple path: entries → GitHub uses the least common ancestor (LCA) of the matched paths as the root of the artifact.
    • Globs → path hierarchy is preserved after the first wildcard (so parts before the first */?/[] are not kept). [1]
  • What happens on download (actions/download-artifact) when multiple artifacts are selected (via pattern, no name, etc.):

    • Default (merge-multiple: false): each artifact is extracted into its own subdirectory named after the artifact under path. [2]
    • With merge-multiple: true: all selected artifacts are extracted into the same path directory, i.e., their internal directory trees are overlaid/merged. [2][3]
    • Collision behavior: if two artifacts contain the same relative file path, the later-extracted one can overwrite the earlier one (so avoid identical paths unless you want last-wins). [2]
  • Practical implication: merge-multiple does not “recreate a per-artifact folder”; it simply controls whether GitHub adds that extra top-level directory per artifact. The internal structure from upload is preserved either way—just either under path/<artifact-name>/... or directly under path/.... [1][2]


Fix artifact paths: electron builds won't be found by release action.

The build-electron job uploads artifacts from dist/electron/* paths. Due to how GitHub Actions handles glob patterns, the dist/electron/ prefix is preserved in the artifact storage. When download-artifact@v4 downloads with merge-multiple: true to ./artifacts, the files end up at artifacts/dist/electron/*.dmg (and similarly for .exe, .AppImage, .zip). However, the release action's glob patterns on line 561 expect files directly at artifacts/*.dmg—this mismatch causes the release step to fail and skip electron build artifacts.

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: warn

This uploads the directory contents directly without preserving the dist/electron/ prefix, so files will be at artifacts/*.dmg as expected by the release action.

🤖 Prompt for AI Agents
In @.github/workflows/react-native-cicd.yml around lines 483 - 487, The electron
artifacts are being uploaded with their dist/electron/ prefix so
download-artifact@v4 with merge-multiple writes them into
artifacts/dist/electron/*.dmg, but the release step expects artifacts/*.dmg;
update the upload step in the build-electron job (the actions/upload-artifact
invocation that uploads electron outputs) to flatten the archive by uploading
the directory contents rather than the parent folder — e.g. change the uploaded
path from the directory (dist/electron) to a glob that matches files inside
(dist/electron/*) or otherwise configure upload-artifact to preserve only
filenames so downloaded artifacts land at artifacts/*.dmg and the release
action's globs will match.


Comment on lines +477 to +488
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🌐 Web query:

actions/download-artifact@v4 permissions requirements

💡 Result:

For actions/download-artifact@v4, the permission requirement depends on what you’re downloading:

  • Downloading artifacts from the same repo + same workflow run (default behavior):
    You typically don’t need to add anything unless you’ve restricted the job/workflow GITHUB_TOKEN permissions. The action uses the token’s ability to read Actions artifacts, so ensure the token isn’t missing Actions read.

  • If you set explicit/restricted permissions: add:

    permissions:
      actions: read

    (Otherwise the action may fail to list/download artifacts.) [1][2]

  • Downloading artifacts from a different repo or a different workflow run:
    You must pass github-token: and that token must have Actions (read) permission on the target repository. The action’s README calls this out explicitly. [1]
    For GitHub REST access to artifacts, fine-grained tokens need Actions: read; for private repos, classic PATs generally need repo. [2]

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 actions: read for artifact download.

actions/download-artifact@v4 requires actions: read permission when the job has explicit restricted permissions. With only contents: write set, the download step will fail to list or fetch artifacts.

🔧 Proposed fix
     permissions:
       contents: write
+      actions: read
🤖 Prompt for AI Agents
In @.github/workflows/react-native-cicd.yml around lines 476 - 487, The job
permissions are missing actions: read which is required by the
actions/download-artifact@v4 step; update the job permissions block (the
permissions mapping used by the workflow) to include actions: read in addition
to contents: write so the Download all artifacts step can list and fetch
artifacts successfully when using actions/download-artifact@v4.

- 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
Expand Down Expand Up @@ -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
Expand Down
Binary file modified assets/adaptive-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/favicon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file added assets/icons-08.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/ios-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/notification-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified assets/splash-icon.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
45 changes: 45 additions & 0 deletions electron/main.js
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();
}
});
13 changes: 13 additions & 0 deletions electron/preload.js
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])
}
})
39 changes: 37 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"version": "0.0.1",
"versionCode": "1",
"private": true,
"main": "expo-router/entry",
"main": "electron/main.js",
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cd /repo && pwd && git ls-files | head -20

Repository: Resgrid/Dispatch

Length of output: 115


🏁 Script executed:

cat -n package.json

Repository: 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 -10

Repository: Resgrid/Dispatch

Length of output: 147


🌐 Web query:

Expo package.json main field entry point resolution

💡 Result:

In Expo, the app’s bundle entry module is taken from the project’s package.json main field (relative to the project root). If you change main, you’re changing what Metro starts bundling. [1]

What main should be

  • Expo Router projects: set
    { "main": "expo-router/entry" }
    (or point main to your own index.js that imports expo-router/entry last). [2]
  • Non–Expo Router projects: main can point to any file, but that file must call registerRootComponent(...) (otherwise your exported component won’t become the root). [1]

How resolution actually happens (why main can seem “ignored”)

Metro doesn’t always use main first. It resolves a package entry by checking package.json fields in order defined by resolverMainFields, whose default is ['browser', 'main']. So if something provides a browser field, Metro will prefer that over main. You can override this in metro.config.js. [3]

Sources: Expo docs on custom entry files [1], Expo Router installation / entrypoint [2], Metro resolver resolverMainFields behavior [3].


Update main field to avoid breaking Expo Router bundling.

Setting main to electron/main.js breaks Expo Router's entry point resolution. Since this project still supports mobile and web builds, the main field must point to expo-router/entry. Update the electron:dev script to explicitly reference the Electron main file:

Required changes
-  "main": "electron/main.js",
+  "main": "expo-router/entry",
   
   "scripts": {
-    "electron:dev": "concurrently \"cross-env BROWSER=none yarn web\" \"wait-on http://localhost:8081 && electron .\"",
+    "electron:dev": "concurrently \"cross-env BROWSER=none yarn web\" \"wait-on http://localhost:8081 && electron electron/main.js\"",
🤖 Prompt for AI Agents
In `@package.json` at line 6, Change the package.json "main" field from
"electron/main.js" to "expo-router/entry" to avoid breaking Expo Router's entry
resolution, and update the "electron:dev" npm script to explicitly point to the
Electron entry (the actual Electron bootstrap file, e.g., electron/main.js) so
Electron runs the correct main process file while mobile/web builds use
expo-router/entry.

"scripts": {
"start": "cross-env EXPO_NO_DOTENV=1 expo start",
"prebuild": "cross-env EXPO_NO_DOTENV=1 yarn expo prebuild",
Expand Down Expand Up @@ -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",
Expand Down Expand Up @@ -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",
Expand All @@ -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",
Expand Down
2 changes: 1 addition & 1 deletion src/features/livekit-call/store/useLiveKitCallStore.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import { ConnectionState, type LocalParticipant, type Participant, type RemoteParticipant, Room, type RoomConnectOptions, RoomEvent, type RoomOptions } from 'livekit-client'; // livekit-react-native re-exports these
import { Platform } from 'react-native';
import create from 'zustand';
import { create } from 'zustand';

import { logger } from '../../../lib/logging';

Expand Down
4 changes: 2 additions & 2 deletions src/services/bluetooth-audio/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@

export * from './base.service';
export * from './factory.service';
export * from './native.service';
export * from './web.service';
// export * from './native.service'; // Removed to prevent bundler errors on web
// export * from './web.service'; // Removed to prevent bundler errors on web

// Export a singleton instance for convenience
import { createBluetoothAudioService } from './factory.service';
Expand Down
Loading