Feature SDKs (Pro)
feedback_sdk Pro
- Tier
- Proversion 2.0.4
- Command
archipelago generate feedback_sdk- Generates
features/feedback/feedback_apifeatures/feedback/feedback_impl
- Generates first
- storage_sdk, package_info_providerwhen needed and missing, so there is nothing to install first
In-app feedback SDK with offline queue, metadata enrichment, and optional feature voting. Configurable endpoint, app version/device info attachment, and queue limit.
Variables
| Variable | Type | Default | Description |
|---|---|---|---|
| includeFeatureVoting | boolean | true | Enable feature-request listing and voting (GET/POST /feature-requests) — templated into FeedbackConfig.featureVotingEnabled |
| defaultEndpoint | string | "" | Default endpoint URL pre-filled in FeedbackConfig.endpoint (can be changed later) |
Install
Interactive
archipelago generate feedback_sdkNon-interactive (CI)
archipelago generate feedback_sdk --config my_config.jsonPrerequisites
- An existing Archipelago workspace (
archipelago.yamlat the project root, written byflutter_modular_monorepo);pre_genexits otherwise. storage_sdk— self-generated automatically (SubBrickGenerator) if not already installed.feedback_impl's offline queue isAppStorage-backed viastorage_sdk_api'sStorageProvider, requesting its own'feedback'namespace — this avoids the duplicate-SharedPreferences-registration crash that hit two other features before 1.2.0.package_info_provider— also self-generated automatically (SubBrickGenerator; since 1.4.2) if not already installed.feedback_implresolvesPackageInfofrom that brick's single global registration instead of registering its own (fixed in 1.3.0, for the same class of GetIt duplicate-registration crash).
Generated Structure
features/
└── feedback/
├── feedback_api/
│ └── lib/src/
│ └── models/
└── feedback_impl/
└── lib/src/
├── data/
└── di/Public API
final feedbackSDK = getIt<FeedbackSDK>();
final result = await feedbackSDK.submit(
FeedbackSubmission(text: 'The checkout button is hard to find', category: FeedbackCategory.bug),
);
// result: FeedbackSubmitResultSubmitted | FeedbackSubmitResultQueued (offline/5xx) | FeedbackSubmitResultFailed (4xx)
await feedbackSDK.getQueuedCount(); // items currently queued offline
await feedbackSDK.flushQueue(); // POST queued items now, returns count flushed
await feedbackSDK.clearQueue(); // drop the queue without sending
final requests = await feedbackSDK.getFeatureRequests(page: 1, pageSize: 20);
await feedbackSDK.voteOnFeatureRequest(requests.first.id); // locally deduplicated
await feedbackSDK.submitFeatureRequest(title: 'Dark mode', description: '...');
feedbackSDK.config; // active FeedbackConfigEndpoint Configuration
The generated FeedbackRegisterModule (feedback_impl/lib/src/di/register_module.dart) provides the default FeedbackConfig, templated from defaultEndpoint and includeFeatureVoting:
featureVotingEnabled: true, // or false, from includeFeatureVotingTo customise it, override FeedbackConfig with your own @module:
@module
abstract class AppFeedbackModule {
@lazySingleton
FeedbackConfig get feedbackConfig => const FeedbackConfig(
endpoint: 'https://api.yourapp.com/feedback',
attachAppVersion: true,
attachDeviceInfo: true,
featureVotingEnabled: true,
);
}Register this module before FeedbackImplPackageModule.
Offline Queue
Submissions and votes are held in AppStorage (via storage_sdk_api, under a 'feedback' namespace — not raw SharedPreferences directly) when the device is offline or the server returns a 5xx. Each queued item carries a kind discriminator (feedback or feature_request) so flushQueue() dispatches it to the right endpoint. Wire connectivity_sdk to flush the queue automatically:
connectivitySDK.stateStream.listen((state) {
feedbackSDK.recordConnectivity(online: state.isOnline);
});The queue drains automatically when connectivity is restored.
Shake-to-Feedback (Optional)
Install shake and call submit() from a ShakeDetector callback:
ShakeDetector.autoStart(
onPhoneShake: () async {
await feedbackSDK.submit(
FeedbackSubmission(
text: await _promptUserForText(),
category: FeedbackCategory.general,
),
);
},
);Feature Voting
When FeedbackConfig.featureVotingEnabled is true, users can browse, vote on, and submit feature requests:
final requests = await feedbackSDK.getFeatureRequests();
final result = await feedbackSDK.voteOnFeatureRequest(requests.first.id);
await feedbackSDK.submitFeatureRequest(title: 'Dark mode', description: '...');Votes are locally deduplicated — a second call for the same requestId returns FeatureRequestVoteResultAlreadyVoted without hitting the network. When voting is disabled, getFeatureRequests returns an empty list and voteOnFeatureRequest/submitFeatureRequest return a failure result with reason featureVotingDisabled.
DI & Wiring
FeedbackImplPackageModule is declared under the archipelago: di_modules: manifest key with depends_on: [storage_sdk_shared_preferences, package_info_provider] — monorepo_toolkit generate host-registry uses this to order the generated injector's module registrations correctly.
The module's own Dio is registered as @Named('feedback'), so it does not collide with the app-wide Dio from network_sdk_dio. To reuse it, resolve getIt<Dio>(instanceName: 'feedback').
Dependencies
feedback_impl: dio ^5.11.0, device_info_plus ^13.2.0, package_info_plus ^10.2.1 (the PackageInfo instance itself comes from package_info_provider's global registration, not a second one here), plus workspace storage_sdk_api.
Platform Setup
None beyond what device_info_plus/package_info_plus/storage_sdk already require.
Limitations
- The generated
FeedbackSDKimplementation is a lazy@LazySingleton(as: FeedbackSDK)(since 2.0.0); nothing runs at boot, and the app flushes the queue throughflushQueue()orrecordConnectivity(). - Shake-to-feedback requires manually adding the third-party
shakepackage; it is not a brick dependency.
Changelog
Run archipelago brick info feedback_sdk to see the latest published version. Enterprise customers can read the full CHANGELOG.md in the brick source repository.