Implement mobile-first navigation with tabs, server-side auto-connect, improve mobile UX (#1008)
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: thomasnordquist <7721625+thomasnordquist@users.noreply.github.com> Co-authored-by: Thomas Nordquist <thomasnordquist@users.noreply.github.com>
This commit is contained in:
42
.github/copilot-instructions.md
vendored
42
.github/copilot-instructions.md
vendored
@@ -91,3 +91,45 @@ When modifying or creating UI components, follow the styling patterns documented
|
||||
- Access theme colors via `theme.palette.*`, spacing via `theme.spacing()`, typography via `theme.typography.*`
|
||||
- Support both light and dark modes with theme-conditional styling
|
||||
- Import Material-UI colors: `import { blueGrey, amber, green, red } from '@mui/material/colors'`
|
||||
|
||||
## Mobile Testing Workflow
|
||||
|
||||
**Prerequisites for mobile testing:**
|
||||
```bash
|
||||
# Install Playwright browsers
|
||||
npx playwright install --with-deps chromium
|
||||
|
||||
# Configure mosquitto to allow anonymous connections (for local testing)
|
||||
echo "listener 1883
|
||||
allow_anonymous true" | sudo tee /etc/mosquitto/conf.d/allow-anonymous.conf
|
||||
sudo systemctl restart mosquitto
|
||||
```
|
||||
|
||||
**Interactive testing with mobile viewport:**
|
||||
```bash
|
||||
# Set up environment
|
||||
export MQTT_EXPLORER_SKIP_AUTH=true
|
||||
export MQTT_AUTO_CONNECT_HOST=127.0.0.1
|
||||
|
||||
# Build and start server
|
||||
yarn build:server
|
||||
node dist/src/server.js
|
||||
|
||||
# In another terminal, run Playwright test with mobile viewport
|
||||
# Create test script with viewport: { width: 412, height: 914 }
|
||||
# Always INSPECT the rendered output, don't rely on assumptions
|
||||
```
|
||||
|
||||
**Key lesson**: Mobile tree visibility issues often stem from:
|
||||
1. CSS flex/absolute positioning conflicts
|
||||
2. Missing Redux state updates (connection not propagated to frontend)
|
||||
3. MQTT broker authentication (mosquitto requires `allow_anonymous true` for testing)
|
||||
4. Timing issues (frontend subscribing to events after backend emits them)
|
||||
|
||||
**Server-side auto-connect** (for testing):
|
||||
```bash
|
||||
export MQTT_AUTO_CONNECT_HOST=127.0.0.1
|
||||
export MQTT_AUTO_CONNECT_PORT=1883 # optional
|
||||
export MQTT_AUTO_CONNECT_PROTOCOL=mqtt # optional
|
||||
```
|
||||
|
||||
|
||||
43
.github/workflows/tests.yml
vendored
43
.github/workflows/tests.yml
vendored
@@ -176,8 +176,12 @@ jobs:
|
||||
- name: Build Browser Mode
|
||||
run: yarn build:server
|
||||
- name: Generate Mobile Demo Video
|
||||
id: generate_video
|
||||
continue-on-error: true
|
||||
run: ./scripts/uiTestsMobile.sh
|
||||
- name: Post-processing
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
run: ./scripts/prepareVideoMobile.sh
|
||||
- name: Generate unique base path
|
||||
id: basepath
|
||||
@@ -199,24 +203,32 @@ jobs:
|
||||
aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
|
||||
aws-region: 'eu-central-1'
|
||||
- name: Upload full mobile video to S3
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
env:
|
||||
AWS_BUCKET: ${{ vars.AWS_BUCKET }}
|
||||
BASEPATH: ${{ steps.basepath.outputs.basepath }}
|
||||
run: |
|
||||
# Upload GIF
|
||||
aws s3api put-object \
|
||||
--bucket ${AWS_BUCKET} \
|
||||
--key artifacts/${BASEPATH}/ui-test-mobile.gif \
|
||||
--body ./ui-test-mobile.gif \
|
||||
--content-type image/gif
|
||||
# Upload GIF if it exists
|
||||
if [ -f ./ui-test-mobile.gif ]; then
|
||||
aws s3api put-object \
|
||||
--bucket ${AWS_BUCKET} \
|
||||
--key artifacts/${BASEPATH}/ui-test-mobile.gif \
|
||||
--body ./ui-test-mobile.gif \
|
||||
--content-type image/gif
|
||||
fi
|
||||
|
||||
# Upload MP4
|
||||
aws s3api put-object \
|
||||
--bucket ${AWS_BUCKET} \
|
||||
--key artifacts/${BASEPATH}/ui-test-mobile.mp4 \
|
||||
--body ./ui-test-mobile.mp4 \
|
||||
--content-type video/mp4
|
||||
# Upload MP4 if it exists
|
||||
if [ -f ./ui-test-mobile.mp4 ]; then
|
||||
aws s3api put-object \
|
||||
--bucket ${AWS_BUCKET} \
|
||||
--key artifacts/${BASEPATH}/ui-test-mobile.mp4 \
|
||||
--body ./ui-test-mobile.mp4 \
|
||||
--content-type video/mp4
|
||||
fi
|
||||
- name: Upload mobile video segments to S3
|
||||
if: always()
|
||||
continue-on-error: true
|
||||
env:
|
||||
AWS_BUCKET: ${{ vars.AWS_BUCKET }}
|
||||
BASEPATH: ${{ steps.basepath.outputs.basepath }}
|
||||
@@ -234,6 +246,7 @@ jobs:
|
||||
done
|
||||
shopt -u nullglob # Restore default behavior
|
||||
- name: Generate file URLs
|
||||
if: always()
|
||||
id: fileurl
|
||||
env:
|
||||
AWS_BUCKET: ${{ vars.AWS_BUCKET }}
|
||||
@@ -243,20 +256,24 @@ jobs:
|
||||
echo "base-url=${BASE_URL}" >> $GITHUB_OUTPUT
|
||||
echo "Uploaded to: ${BASE_URL}"
|
||||
- name: Generate markdown summary
|
||||
if: always()
|
||||
id: markdown
|
||||
env:
|
||||
BASE_URL: ${{ steps.fileurl.outputs.base-url }}
|
||||
TEST_STATUS: ${{ steps.generate_video.outcome }}
|
||||
run: |
|
||||
MARKDOWN=$(node ./scripts/generateMarkdownSummaryMobile.js "${BASE_URL}")
|
||||
MARKDOWN=$(node ./scripts/generateMarkdownSummaryMobile.js "${BASE_URL}" "${TEST_STATUS}")
|
||||
echo "markdown<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$MARKDOWN" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
- name: Add to workflow summary
|
||||
if: always()
|
||||
env:
|
||||
MARKDOWN: ${{ steps.markdown.outputs.markdown }}
|
||||
run: |
|
||||
echo "$MARKDOWN" >> $GITHUB_STEP_SUMMARY
|
||||
- name: Post mobile video to PR
|
||||
if: always()
|
||||
uses: actions/github-script@v7
|
||||
env:
|
||||
MARKDOWN: ${{ steps.markdown.outputs.markdown }}
|
||||
|
||||
Reference in New Issue
Block a user