Skip to content
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
Show all changes
40 commits
Select commit Hold shift + click to select a range
4f67ef5
rebase
camsim99 Apr 20, 2026
7a58f80
one camera working on emulator?
camsim99 Feb 27, 2026
eb00f8a
it works??? without switching cameras
camsim99 Mar 2, 2026
929a070
saved previewview fixes switching cameras, aspect ratio causing jump …
camsim99 Mar 2, 2026
d7c47d6
fix example code bug
camsim99 Mar 2, 2026
b181e26
working state, need to try to remove workarounds and see if this was …
camsim99 Mar 17, 2026
7cd5f5e
inital state
camsim99 Apr 20, 2026
fe75707
initial plan
camsim99 Apr 20, 2026
a6f4a41
second revision of implemntation plan
camsim99 Apr 20, 2026
61911c2
restore android
camsim99 Apr 20, 2026
b33f6ae
more cleanup of source + example
camsim99 Apr 20, 2026
9aeefb3
implementation plan iteration 3
camsim99 Apr 24, 2026
b2ef1cb
first implementation attempt + walkthrough
camsim99 Apr 29, 2026
c56494b
Merge branch 'main' into camx-i160956-torchstate
reidbaker May 5, 2026
a817695
Revert agent authored changes
reidbaker May 5, 2026
f27b8c2
Update plan with feedback
reidbaker May 5, 2026
4359931
add all kevmoo skills
reidbaker May 5, 2026
a8fc895
Add hooks for formatting and analyzing
reidbaker May 5, 2026
8b66419
Make analyze only run on stop
reidbaker May 5, 2026
bbea45d
Use grill-with-docs to update the plan
reidbaker May 5, 2026
698302e
Add grill-with-docs skill
reidbaker May 5, 2026
d77a690
Add tdd skill then add it to the generate rules
reidbaker May 5, 2026
e9eafdd
Add zoom out skill
reidbaker May 5, 2026
d307332
Add high level architecture
reidbaker May 5, 2026
81c6e0b
symlink dart-doc-validation
reidbaker May 5, 2026
9f77fbe
add licence to hooks
reidbaker May 5, 2026
44d492b
Modify license checker to ignore a skill that does not have licence i…
reidbaker May 5, 2026
2c2f3b6
Reorg the plan and make sure that tests can pass before starting work
reidbaker May 5, 2026
014aecc
Make sure that we do more than run the commands we ensure they do not…
reidbaker May 5, 2026
3df8bf9
Add code review skill
reidbaker May 5, 2026
8e6197e
fix typo
reidbaker May 5, 2026
10f93d3
Add use of code review skill
reidbaker May 5, 2026
e9998d8
Fix torch state retention on camera switch in camera_android_camerax
reidbaker May 5, 2026
343c739
Bump version to 0.7.3 and update CHANGELOG
reidbaker May 5, 2026
a912eeb
Author the hooks in dart, change analyze to have its own log location
reidbaker May 6, 2026
0bb1433
Convert hooks to dart but the stop command does not seem to trigger w…
reidbaker May 6, 2026
fe1b38f
Use the relative path, add local logging
reidbaker May 6, 2026
1545fc6
Make sure ls files is run from the root
reidbaker May 6, 2026
a8b09f4
Add tests for the hooks infrastructure
reidbaker May 6, 2026
b9d6b2e
remove ignored log files
reidbaker May 6, 2026
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
54 changes: 54 additions & 0 deletions packages/.agents/skills/dart-best-practices/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
name: dart-best-practices
description: |-
General best practices for Dart development.
Covers code style, effective Dart, and language features.
license: Apache-2.0
---

# Dart Best Practices

## 1. When to use this skill
Use this skill when:
- Writing or reviewing Dart code.
- Looking for guidance on idiomatic Dart usage.

## 2. Best Practices

### Multi-line Strings
Prefer using multi-line strings (`'''`) over concatenating strings with `+` and
`\n`, especially for large blocks of text like SQL queries, HTML, or
PEM-encoded keys. This improves readability and avoids
`lines_longer_than_80_chars` lint errors by allowing natural line breaks.

**Avoid:**
```dart
final pem = '-----BEGIN RSA PRIVATE KEY-----\n' +
base64Encode(fullBytes) +
'\n-----END RSA PRIVATE KEY-----';
```

**Prefer:**
```dart
final pem = '''
-----BEGIN RSA PRIVATE KEY-----
${base64Encode(fullBytes)}
-----END RSA PRIVATE KEY-----''';
```

### Line Length
Avoid lines longer than 80 characters, even in Markdown files and comments.
This ensures code is readable in split-screen views and on smaller screens
without horizontal scrolling.

**Prefer:**
Target 80 characters for wrapping text. Exceptions are allowed for long URLs
or identifiers that cannot be broken.

## Related Skills

- **[dart-modern-features]**: For idiomatic
usage of modern Dart features like Pattern Matching (useful for deep JSON
extraction), Records, and Switch Expressions.

[dart-modern-features]: https://github.com/kevmoo/dash_skills/blob/main/.agent/skills/dart-modern-features/SKILL.md
83 changes: 83 additions & 0 deletions packages/.agents/skills/dart-package-maintenance/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
name: dart-package-maintenance
description: |-
Guidelines for maintaining external Dart packages, covering versioning,
publishing workflows, and pull request management. Use when updating Dart
packages, preparing for a release, or managing collaborative changes in a
repository.
---

# Dart Package Maintenance

Guidelines for maintaining Dart packages in alignment with Dart team best
practices.

## Versioning

### Semantic Versioning
- **Major**: Breaking changes.
- **Minor**: New features (non-breaking API changes).
- **Patch**: Bug fixes, documentation, or non-impacting changes.
- **Unstable packages**: Use `0.major.minor+patch`.
- **Recommendation**: Aim for `1.0.0` as soon as the package is stable.

### Pre-Edit Verification
- **Check Published Versions**: Before modifying `CHANGELOG.md` or
`pubspec.yaml`, ALWAYS check the currently released version (e.g., via
`git tag` or `pub.dev`).
- **Do Not Amend Released Versions**: Never add new entries to a version header
that corresponds to a released tag.
- **Increment for New Changes**: If the current version in `pubspec.yaml`
matches a released tag, increment the version (e.g., usually to `-wip`) and
create a new section in `CHANGELOG.md`.

- **Consistency**: The `CHANGELOG.md` header must match the new
`pubspec.yaml` version.

- **SemVer Guidelines**:
- **Breaking Changes**: Bump Major, reset Minor/Patch
(e.g., `2.0.0-wip`, `0.5.0-wip`).
- **New Features**: Bump Minor, reset Patch
(e.g., `1.1.0-wip`, `0.4.5-wip`).
- **Bug Fixes**: Bump Patch (e.g., `1.0.1-wip`).

### Changelog Content
- **Focus on User Impact**: Entries in `CHANGELOG.md` should focus on changes
visible to or impacting the end-user (e.g., new features, bug fixes,
breaking changes).
- **Omit Internal Changes**: Do not include internal refactorings, test
changes, or other modifications that do not affect the package's behavior
or API for the user.

### Work-in-Progress (WIP) Versions
- Immediately after a publish, or on the first change after a publish, update
`pubspec.yaml` and `CHANGELOG.md` with a `-wip` suffix (e.g., `1.1.0-wip`).
- This indicates the current state is not yet published.

### Breaking Changes
- Evaluate the impact on dependent packages and internal projects.
- Consider running changes through internal presubmits if possible.
- Prefer incremental rollouts (e.g., new behavior as opt-in) to minimize
downstream breakage.

## Publishing Process

1. **Preparation**: Remove the `-wip` suffix from `pubspec.yaml` and
`CHANGELOG.md` in a dedicated pull request.
2. **Execution**: Run `dart pub publish` (or `flutter pub publish`) and resolve
all warnings and errors.
3. **Tagging**: Create and push a git tag for the published version:
- For single-package repos: `v1.2.3`
- For monorepos: `package_name-v1.2.3`
- Example: `git tag v1.2.3 && git push --tags`

## Pull Request Management

- **Commits**: Each PR should generally correspond to a single squashed commit
upon merging.
- **Shared History**: Once a PR is open, avoid force pushing to the branch.
- **Conflict Resolution**: Prefer merging `main` into the PR branch rather than
rebasing to resolve conflicts. This preserves the review history and comments.
- **Reviewing**: Add comments from the "Files changed" view to batch them.
- **Local Inspection**: Use `gh pr checkout <number>` to inspect changes
locally in your IDE.
127 changes: 127 additions & 0 deletions packages/.agents/skills/dart-test-fundamentals/SKILL.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,127 @@
---
name: dart-test-fundamentals
description: |-
Core concepts and best practices for `package:test`.
Covers `test`, `group`, lifecycle methods (`setUp`, `tearDown`), and configuration (`dart_test.yaml`).
license: Apache-2.0
---

# Dart Test Fundamentals

## When to use this skill
Use this skill when:
- Writing new test files.
- structuring test suites with `group`.
- Configuring test execution via `dart_test.yaml`.
- Understanding test lifecycle methods.

## Core Concepts

### 1. Test Structure (`test` and `group`)

- **`test`**: The fundamental unit of testing.
```dart
test('description', () {
// assertions
});
```
- **`group`**: Used to organize tests into logical blocks.
- Groups can be nested.
- Descriptions are concatenated (e.g., "Group Description Test Description").
- Helps scope `setUp` and `tearDown` calls.
- **Naming**: Use `PascalCase` for groups that correspond to a class name
(e.g., `group('MyClient', ...)`).
- **Avoid Single Groups**: Do not wrap all tests in a file with a single
`group` call if it's the only one.

- **Naming Tests**:
- Avoid redundant "test" prefixes.
- Include the expected behavior or outcome in the description (e.g.,
`'throws StateError'` or `'adds API key to URL'`).
- Descriptions should read well when concatenated with their group name.

- **Named Parameters Placement**:
- For `test` and `group` calls, place named parameters (e.g., `testOn`,
`timeout`, `skip`) immediately after the description string, before the
callback closure. This improves readability by keeping the test logic last.
```dart
test('description', testOn: 'vm', () {
// assertions
});
```

### 2. Lifecycle Methods (`setUp`, `tearDown`)

- **`setUp`**: Runs *before* every `test` in the current `group` (and nested
groups).
- **`tearDown`**: Runs *after* every `test` in the current `group`.
- **`setUpAll`**: Runs *once* before any test in the group.
- **`tearDownAll`**: Runs *once* after all tests in the group.

**Best Practice:**
- Use `setUp` for resetting state to ensure test isolation.
- Avoid sharing mutable state between tests without resetting it.

### 3. Configuration (`dart_test.yaml`)

The `dart_test.yaml` file configures the test runner. Common configurations
include:

#### Platforms
Define where tests run (vm, chrome, node).

```yaml
platforms:
- vm
- chrome
```

#### Tags
Categorize tests to run specific subsets.

```yaml
tags:
integration:
timeout: 2x
```

Usage in code:
```dart
@Tags(['integration'])
import 'package:test/test.dart';
```

Running tags:
`dart test --tags integration`

#### Timeouts
Set default timeouts for tests.

```yaml
timeouts:
2x # Double the default timeout
```

### 4. File Naming
- Test files **must** end in `_test.dart` to be picked up by the test runner.
- Place tests in the `test/` directory.

## Common commands

- `dart test`: Run all tests.
- `dart test test/path/to/file_test.dart`: Run a specific file.
- `dart test --name "substring"`: Run tests matching a description.

## Related Skills

`dart-test-fundamentals` is the core skill for structuring and configuring
tests. For writing assertions within those tests, refer to:

- **[dart-matcher-best-practices]**:
Use this if the project sticks with the traditional
`package:matcher` (`expect` calls).
- **[dart-checks-migration]**: Use this
if the project is migrating to the modern `package:checks` (`check` calls).

[dart-matcher-best-practices]: https://github.com/kevmoo/dash_skills/blob/main/.agent/skills/dart-matcher-best-practices/SKILL.md
[dart-checks-migration]: https://github.com/kevmoo/dash_skills/blob/main/.agent/skills/dart-checks-migration/SKILL.md
93 changes: 93 additions & 0 deletions packages/camera/camera_android_camerax/implementation_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
# Fix Torch State Retention on Camera Switch in camera_android_camerax

## Goal Description

The `camera_android_camerax` package fails to retain the torch state when switching between cameras. Specifically, if the torch is turned on while using the rear camera, and the user switches to the front camera (which typically does not support torch) and then back to the rear camera, the torch does not turn back on automatically. Furthermore, attempting to turn it on again after switching back fails because the internal state (`torchEnabled`) still thinks it is on, causing an early return.

This plan proposes to fix this by tracking torch state per camera and restoring it when a camera becomes active, after verifying that the camera supports flash.

## User Review Required

> [!IMPORTANT]
> **Multi-Camera Support**: To prevent out-of-sync issues in complex camera switching cases (e.g., devices with more than 2 cameras), I propose changing `torchEnabled` from a single boolean to a map `_torchEnabledPerCamera = <String, bool>{}` keyed by the camera name (from `CameraDescription.name`). This ensures torch state is isolated per camera.
>
> **New Variable**: I am adding `_currentCameraDescription` to track the active camera. This is required because some methods (like `initializeCamera`) only receive a `cameraId` (which is the texture ID) and need to know which camera description it corresponds to in order to use its name as a key in `_torchEnabledPerCamera`.

> [!NOTE]
> **CameraX Expectations**: CameraX expects developers to check `CameraInfo.hasFlashUnit()` before calling `CameraControl.enableTorch()`.
> I will incorporate this by:
> 1. Exposing `hasFlashUnit()` via Pigeon in `CameraInfo`.
> 2. Checking it in Dart before attempting to restore torch state, and giving a helpful error if the user tries to turn on torch on a camera without flash.

## Prerequisites

Before making any code changes, run the following command to ensure dependencies are up to date:
```bash
dart run ../../../script/tool/bin/flutter_plugin_tools.dart fetch-deps --packages=camera_android_camerax
```

## Proposed Changes

### camera_android_camerax

Summary of changes to retain and restore torch state across camera switches.

---

#### [MODIFY] [pigeons/camerax_library.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/pigeons/camerax_library.dart)

- Add `bool hasFlashUnit();` to `abstract class CameraInfo`.
- Run the Pigeon generator to update generated files.
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I don't think we have to modify the plan here but I am wondering if the agents know how to use this library. I do think we should probably make sure that one of the automated verification steps will ensure that the generated files have been updated correctly and not by the agent.


#### [MODIFY] [android/src/main/java/io/flutter/plugins/camerax/CameraInfoProxyApi.java](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/android/src/main/java/io/flutter/plugins/camerax/CameraInfoProxyApi.java)
Comment thread
reidbaker marked this conversation as resolved.
Outdated

- Implement `hasFlashUnit(CameraInfo pigeonInstance)` to return `pigeonInstance.hasFlashUnit()`.

#### [MODIFY] [lib/src/android_camera_camerax.dart](file:///Users/camillesimon/packages/packages/camera/camera_android_camerax/lib/src/android_camera_camerax.dart)

- Add `_currentCameraDescription` instance variable to track the active camera.
- Update `_currentCameraDescription` in `createCameraWithSettings` and `setDescriptionWhileRecording`.
- Replace `torchEnabled` boolean with `Map<String, bool> _torchEnabledPerCamera = {};`.
- Update `setFlashMode` to use `_torchEnabledPerCamera` keyed by `_currentCameraDescription.name`. If mode is `FlashMode.torch`, check `await cameraInfo!.hasFlashUnit()` first and throw a specific `CameraException` if false.
- Modify `_enableTorchMode` to accept an optional `addErrorToStream` boolean parameter (defaulting to `true`). When restoring state, we will pass `false` to avoid spamming the stream if it fails unexpectedly.
- In `_updateCameraInfoAndLiveCameraState`, add logic to restore torch state: if `_torchEnabledPerCamera[_currentCameraDescription.name]` is true, check `await cameraInfo!.hasFlashUnit()`. If true, call `_enableTorchMode(true, addErrorToStream: false)`.

## Verification Plan

To make commands easier to read, you can use an alias:
```bash
alias tool="dart run ../../../script/tool/bin/flutter_plugin_tools.dart"
```

### Automated Tests

I will add unit tests in `android_camera_camerax_test.dart` to verify:
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

There should be a test for restoring a torch mode to off in addition to restoring to on.

1. `setFlashMode` with `FlashMode.torch` sets torch state for that camera.
2. `_updateCameraInfoAndLiveCameraState` attempts to restore torch state to ON if enabled for that camera and flash is available.
3. `_updateCameraInfoAndLiveCameraState` ensures torch state is OFF if not enabled for that camera.
4. `_enableTorchMode` handles failures by not adding to stream when `addErrorToStream` is false.

Run tests using:
```bash
tool dart-test --package=camera_android_camerax
```

### Codebase Health Guidelines

- Run `tool format --package=camera_android_camerax` and `tool analyze --package=camera_android_camerax` after every code edit.
- Run `tool fix --packages=camera_android_camerax` if errors are found in analyze before attempting any other mitigations.
- Run tests after each test case added and after finishing a unit of code work.
- Run `tool gradle-check --packages=camera_android_camerax` after touching `build.gradle` files.
- Run `tool license-check --packages=camera_android_camerax` after getting new files to their final state.
- When completely done, run `tool readme-check`, `tool version-check`, `tool pubspec-check`.
- Finally, run `tool publish-check`.

### Manual Verification
Comment thread
reidbaker marked this conversation as resolved.

1. **Example App**: Build and run the example app to check behavior visually.
2. **Integration Tests**: Run `flutter test` in `example/integration_test` to ensure nothing broke.
3. **Emulator Testing**:
- Start emulator: `../../Library/Android/sdk/emulator/emulator -avd Pixel_9_API_36` (or available AVD).
- Run example app: `flutter run example`
- Check torch state via adb: `adb shell dumpsys media.camera | grep -i "torch"`
- Ensure emulator has camera flash enabled in settings if testing actual toggle.
20 changes: 20 additions & 0 deletions packages/skills-lock.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"version": 1,
"skills": {
"dart-best-practices": {
"source": "kevmoo/dash_skills",
"sourceType": "github",
"computedHash": "1eb4a38aa94060d3d420f1b03b661ad784a1cd732ffb7ff4d8369d085024d4f5"
},
"dart-package-maintenance": {
"source": "kevmoo/dash_skills",
"sourceType": "github",
"computedHash": "38a88563712853149984bd823c41fa3b7c56400e5936c3166cdd2075d00f90ff"
},
"dart-test-fundamentals": {
"source": "kevmoo/dash_skills",
"sourceType": "github",
"computedHash": "eb99d0125ce554ac55fd85cfe865fbd703f5f311cab5bd551ce45c1f55af2adf"
}
}
}
Loading