Skip to content

Commit 1e67475

Browse files
authored
feat!: 2.0.0-beta1 Modularization, Melos Support & Localization Refactor (#167)
* Refactor JSON serialization and deserialization across models - Updated `TextAnswerFormat` to handle nullable `maxLines` and set default `answerType`. - Enhanced `TextChoice` with equality operator and hash code implementation. - Simplified JSON serialization for `TextChoice`, `AudioContent`, `ImageContent`, `LottieContent`, `MarkdownContent`, `SectionContent`, `TextContent`, `VideoContent`, and `TimeAnswerFormat`. - Improved `StepResult` to include explicit JSON serialization and updated equality checks. - Adjusted `SurveyResult` to include list equality checks. - Updated `CustomDateTimeConverter` to preserve timezone during serialization. - Changed `pubspec.yaml` to update Dart SDK and dependencies. - Modified test cases to use UTC for `startTime` and `endTime` for consistency. * feat: add monorepo * refactor: modularize audio and video features into separate packages and update dependencies. * feat: Introduce `survey_kit_lottie` package to add Lottie animation support and update content model. * feat: Migrate to Flutter's `gen_l10n` for internationalization, replacing custom JSON-based localization. * feat: Add CI workflow, localization generation updates, and video/audio plugin improvements * feat: Add GitHub Actions workflow for publishing to pub.dev and extend CI triggers to include the develop branch. * refactor: simplify Melos script definitions by replacing `run` and `exec.concurrency` with direct `exec` commands. * chore: Resolve root dependencies in CI and remove explicit Melos SDK path configuration. * ci: Add debug environment step to CI workflow and remove extraneous blank lines from melos.yaml. * feat: Update CI analyze and test commands, ignore `invalid_dependency` linter rule, and specify `intl` dependency version. * feat: Decouple answer formats and content models from their views by removing `createView`/`createWidget` methods and introducing a new registry pattern with `SurveyKitPlugin` for external integrations. * docs: remove example code blocks from SurveyController documentation. * feat: Refactor task and navigation logic with `SurveyFlow` and `SurveyDefinition`, deprecate `NavigableTask`, and introduce Lottie, video, and audio packages. * refactor: Make `MultipleChoiceAnswerFormat` and `SingleChoiceAnswerFormat` generic with `TextChoice` and update their usage. * feat: Introduce a `center` property for `ContentWidget` vertical alignment, update package dependencies, remove `path_provider_foundation` from the macOS example, and clarify `initalStep` migration notes. * feat: introduce `NavigationTarget` for conditional navigation rules, remove `FlowTask`, and fix `QuestionAnswer` validation initialization. * feat: Allow steps without answer formats to be valid by default and make the example's next button reactive. * refactor!: Rename answer format properties, update SurveyController callbacks with a `proceed` parameter, and simplify `StepView` button logic. * feat: update survey welcome and completion texts and apply extensive custom theming to the app and SurveyKit UI. * feat: Update example app theme to a vibrant cyan color scheme, enhance `SelectionListTile` styling, and increase `SurveyAppBar` height. * refactor: Add AnswerMixin import to MultipleChoiceAutoCompleteAnswerView. * chore: Update package dependencies and apply consistent code formatting across various files.
1 parent 6b1a807 commit 1e67475

303 files changed

Lines changed: 7985 additions & 4193 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.fvmrc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"flutter": "3.41.4"
3+
}

.github/workflows/.github-actions.yml

Lines changed: 0 additions & 21 deletions
This file was deleted.

.github/workflows/publish.yml

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
name: Publish to pub.dev
2+
3+
on:
4+
release:
5+
types: [published]
6+
7+
concurrency:
8+
group: publish-${{ github.event.release.tag_name }}
9+
cancel-in-progress: false
10+
11+
jobs:
12+
publish:
13+
if: ${{ !github.event.release.draft }}
14+
permissions:
15+
contents: read
16+
id-token: write
17+
runs-on: ubuntu-latest
18+
steps:
19+
- uses: actions/checkout@v4
20+
21+
- uses: subosito/flutter-action@v2
22+
with:
23+
channel: 'stable'
24+
25+
- name: Install Melos
26+
run: dart pub global activate melos
27+
28+
- name: Resolve Root Dependencies
29+
run: flutter pub get
30+
31+
- name: Bootstrap Workspace
32+
run: melos bootstrap
33+
34+
- name: Analyze
35+
run: melos run analyze
36+
37+
- name: Test
38+
run: melos run test
39+
40+
- name: Verify release tag matches package versions
41+
env:
42+
RELEASE_TAG: ${{ github.event.release.tag_name }}
43+
run: |
44+
TAG_VERSION="${RELEASE_TAG#v}"
45+
for package in \
46+
packages/survey_kit \
47+
packages/survey_kit_audio \
48+
packages/survey_kit_lottie \
49+
packages/survey_kit_video
50+
do
51+
PACKAGE_VERSION="$(sed -n 's/^version: //p' "$package/pubspec.yaml")"
52+
if [ "$PACKAGE_VERSION" != "$TAG_VERSION" ]; then
53+
echo "Tag version ($TAG_VERSION) does not match $package version ($PACKAGE_VERSION)."
54+
exit 1
55+
fi
56+
done
57+
58+
- name: Publish packages
59+
env:
60+
RELEASE_TAG: ${{ github.event.release.tag_name }}
61+
run: |
62+
TAG_VERSION="${RELEASE_TAG#v}"
63+
64+
is_already_published() {
65+
package_name="$1"
66+
curl -fsSL "https://pub.dev/api/packages/$package_name" | grep -Eq "\"version\"[[:space:]]*:[[:space:]]*\"$TAG_VERSION\""
67+
}
68+
69+
publish_package() {
70+
package_path="$1"
71+
package_name="$2"
72+
73+
if is_already_published "$package_name"; then
74+
echo "$package_name $TAG_VERSION is already on pub.dev, skipping."
75+
return 0
76+
fi
77+
78+
for attempt in 1 2 3; do
79+
echo "Publishing $package_name (attempt $attempt)..."
80+
if (cd "$package_path" && flutter pub publish --force); then
81+
echo "$package_name published."
82+
return 0
83+
fi
84+
85+
if [ "$attempt" -lt 3 ]; then
86+
echo "Retrying $package_name in 60s..."
87+
sleep 60
88+
fi
89+
done
90+
91+
echo "Failed to publish $package_name after 3 attempts."
92+
return 1
93+
}
94+
95+
publish_package packages/survey_kit survey_kit
96+
publish_package packages/survey_kit_audio survey_kit_audio
97+
publish_package packages/survey_kit_lottie survey_kit_lottie
98+
publish_package packages/survey_kit_video survey_kit_video
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
name: CI
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main, develop ]
8+
9+
jobs:
10+
build:
11+
runs-on: ubuntu-latest
12+
13+
steps:
14+
- uses: actions/checkout@v4
15+
16+
- uses: subosito/flutter-action@v2
17+
with:
18+
channel: 'stable'
19+
20+
- name: Install Melos
21+
run: dart pub global activate melos
22+
23+
- name: Resolve Root Dependencies
24+
run: flutter pub get
25+
26+
- name: Bootstrap Workspace
27+
run: melos bootstrap
28+
29+
- name: Analyze
30+
run: melos exec -- flutter analyze .
31+
32+
- name: Run Tests
33+
run: melos exec --dir-exists="test" -- flutter test

.gitignore

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,16 +24,24 @@
2424
# Flutter/Dart/Pub related
2525
**/doc/api/
2626
**/ios/Flutter/.last_build_id
27+
**/ios/Flutter/ephemeral/
28+
**/macos/Flutter/ephemeral/
29+
**/linux/flutter/ephemeral/
30+
**/windows/flutter/ephemeral/
2731
.dart_tool/
2832
.flutter-plugins
2933
.flutter-plugins-dependencies
3034
.packages
3135
.pub-cache/
3236
.pub/
3337
/build/
38+
**/build/
39+
**/.gradle/
40+
**/local.properties
3441

3542
# Web related
3643
lib/generated_plugin_registrant.dart
44+
**/GeneratedPluginRegistrant.java
3745

3846
# Symbolication related
3947
app.*.symbols
@@ -45,4 +53,4 @@ app.*.map.json
4553
/android/app/debug
4654
/android/app/profile
4755
/android/app/release
48-
/example/linux/flutter/emphemeral/.plugin_symlinks
56+
**/linux/flutter/ephemeral/.plugin_symlinks

CHANGELOG.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,82 @@
1+
# 2.0.0-beta1
2+
3+
## Required Adjustments (1.x -> 2.0.0-beta1)
4+
5+
1. Update dependencies to `survey_kit: 2.0.0-beta1`, and add media plugins only
6+
if needed: `survey_kit_audio`, `survey_kit_video`, `survey_kit_lottie`.
7+
2. **BREAKING**: Rename `Task.initalStep` to `Task.initialStep`.
8+
3. Update imports for any media plugin package you use.
9+
4. Register media plugins through `SurveyKit(registries: [...])`.
10+
5. Migrate custom `AnswerFormat`/`Content` rendering from model methods to
11+
`answerViewBuilders` and `contentWidgetBuilders` (or custom `SurveyKitPlugin`).
12+
6. If you deserialize from JSON, register converters for custom and plugin
13+
types with `AnswerFormat.registerFromJson` and `Content.registerFromJson`.
14+
7. Ensure localization delegates include `SurveyKitLocalizations.delegate` and
15+
Flutter localization delegates.
16+
8. Prefer `SurveyDefinition.fromJson` over `Task.fromJson`
17+
(`Task` remains as a deprecated alias).
18+
19+
Full migration guide: [MIGRATION.md](MIGRATION.md)
20+
21+
## Highlights
22+
23+
- **BREAKING**: `ConditionalNavigationRule.resultToStepIdentifierMapper` now
24+
returns `NavigationTarget` instead of `String?`. Replace `'step_id'` with
25+
`NavigateToStep('step_id')`, `null` with `NavigateToNextInList()`, and use
26+
the new `FinishSurvey()` to end the survey early from a rule.
27+
- **BREAKING**: Removed model-level `createView`/`createWidget` coupling and
28+
moved rendering to registry builders.
29+
- **BREAKING**: Renamed `Task.initalStep` to `Task.initialStep`.
30+
- **BREAKING**: Split media integrations into dedicated packages:
31+
`survey_kit_audio`, `survey_kit_video`, `survey_kit_lottie`.
32+
- **FEATURE**: Added `SurveyFlow` as the unified task model for linear and
33+
branching surveys.
34+
- **FEATURE**: Added `SurveyDefinition` as the canonical survey definition base
35+
type.
36+
- **DEPRECATION**: `OrderedTask` and `NavigableTask` are now legacy wrappers
37+
around `SurveyFlow`.
38+
- **REMOVED**: `FlowTask` — introduced and immediately deprecated in this
39+
version, removed before release. Use `SurveyFlow` directly.
40+
- **DEPRECATION**: `Task` is now a legacy alias for `SurveyDefinition`.
41+
- **FEATURE**: Added `SurveyKitRegistry`/`SurveyKitPlugin` and `registries`,
42+
`answerViewBuilders`, `contentWidgetBuilders`.
43+
- **FEATURE**: Migrated localization generation to Flutter `gen_l10n` with
44+
`.arb` resources.
45+
- **FIX**: Improved JSON serialization/deserialization consistency, including
46+
`TimeResult` generation and UTC DateTime handling.
47+
- **TEST**: Improved test stability with deterministic setup.
48+
- **CHORE**: Migrated to Melos monorepo workflow and added CI/publish
49+
automation.
50+
- **DOCS**: Updated API docs for the registry architecture.
51+
52+
## Navigation/Controller Hardening
53+
54+
1. **FIX**: Hardened survey navigation transitions to avoid loading-route traps
55+
on empty/completed flows.
56+
2. **FIX**: Stabilized navigation rule serialization/deserialization for JSON
57+
surveys (`type` handling + legacy compatibility).
58+
3. **FIX**: Survey result emission is now deterministic and ordered by task step
59+
sequence.
60+
4. **FIX**: Tightened state update propagation and cleaned dead/duplicate view
61+
artifacts in provider/view wiring.
62+
5. **BREAKING**: Renamed `Task.initalStep` to `Task.initialStep`.
63+
6. **FEATURE**: `SurveyController` now supports context-free imperative
64+
navigation when attached to `SurveyKit` (`next`, `stepBack`, `closeSurvey`).
65+
7. **BREAKING**: `SurveyController.closeSurvey` no longer accepts a
66+
`BuildContext` parameter. The context is resolved internally via the
67+
navigator key. If you supply an `onCloseSurvey` callback, remove the
68+
`BuildContext` argument from its signature:
69+
`Function(StepResult?) onCloseSurvey`.
70+
8. **FIX**: `QuestionAnswer.isValid` now initialises to `false` for mandatory
71+
steps instead of always `true`. Previously, the Next button on a mandatory
72+
step was enabled before the user had selected any answer.
73+
9. **FIX**: `AnswerMixin.initValidation` added — call it in `initState` to sync
74+
a pre-filled or default answer into the validation state on first render.
75+
`SingleChoiceAnswerView` already calls this.
76+
10. **FIX**: `ContentWidget` now correctly respects `center: false`
77+
`mainAxisAlignment` was hardcoded to `center` regardless of the parameter.
78+
79+
180
# 1.0.3
281

382
- CHORE: Removed depracted lint `package_api_docs`

0 commit comments

Comments
 (0)