feedbackjar 1.2.1 copy "feedbackjar: ^1.2.1" to clipboard
feedbackjar: ^1.2.1 copied to clipboard

Flutter SDK for FeedbackJar — collect user feedback with automatic device metadata. You build the UI; the SDK handles submission and listing.

FeedbackJar Flutter SDK #

A lightweight Flutter SDK for collecting user feedback. You build your own form — the SDK handles submission (enriched with device metadata) and fetching the public feedback list.

  • Min SDK: Dart 3.0 / Flutter 3.10
  • Platforms: Android, iOS
  • Package: pub.dev
  • License: MIT

Installation #

Add to your pubspec.yaml:

dependencies:
  feedbackjar: ^1.0.0

Then run:

flutter pub get

Setup #

Initialize once before use — call configure in main() before runApp, or in your root widget's constructor. You need your widget ID from the FeedbackJar dashboard.

import 'package:feedbackjar/feedbackjar.dart';

void main() {
  WidgetsFlutterBinding.ensureInitialized();
  FeedbackJar.configure('your-widget-id');
  runApp(const MyApp());
}

Submitting feedback #

Submissions can be anonymous, or include a submitter name/email if you collect them in your own form. Each submission automatically carries device metadata (OS version, device model, screen size, app version, locale).

final result = await FeedbackJar.shared.submit(userText);

switch (result) {
  case FeedbackSuccess(:final value):
    print('Submitted: ${value.postId} (${value.type})');
    // show a success state in your UI
  case FeedbackFailure(:final error):
    print('Failed: $error');
    // show an error state
}

Callback (no async context needed) #

FeedbackJar.shared.submitCallback(userText, (result) {
  switch (result) {
    case FeedbackSuccess(:final value):
      // show success state
    case FeedbackFailure(:final error):
      // show error state
  }
});

Note: the server applies rate limiting (5 submissions per 15 minutes per IP). Handle the failure case in your UI.

Custom properties #

Attach your own key/value context to a submission — merged into the auto-collected app metadata (alongside packageName, versionName, versionCode). Values should be String, num, or bool; nested maps/lists aren't supported.

final result = await FeedbackJar.shared.submit(
  userText,
  properties: {'flavor': 'foss', 'plan': 'pro'},
);

Checking whether to ask for name/email #

The organization's dashboard settings ("Ask for Name" / "Ask for Email") control whether submitters should be prompted. The SDK doesn't render any UI itself, so read this before building your own form:

final result = await FeedbackJar.shared.getConfig();
if (result case FeedbackSuccess(:final value)) {
  showNameField = value.collectName;
  showEmailField = value.collectEmail;
}

Remembering submitter identity #

Name/email passed to submit are automatically remembered and reused on later calls, so you only need to ask once. Manage this directly with setIdentity / getIdentity / clearIdentity:

await FeedbackJar.shared.setIdentity(name: 'Ada Lovelace', email: 'ada@example.com');

final identity = await FeedbackJar.shared.getIdentity();
print(identity.name);

// e.g. on logout
await FeedbackJar.shared.clearIdentity();

Listing feedback #

Fetch the public feedback feed for your organization. Supports pagination via a cursor.

async/await #

final result = await FeedbackJar.shared.listFeedback(limit: 20);

if (result case FeedbackSuccess(:final value)) {
  for (final post in value.posts) {
    print('${post.title} — ${post.upvotes} upvotes, ${post.status}');
  }
  // value.nextCursor is non-null when more pages exist
}

Pagination #

String? cursor;

Future<void> loadNextPage() async {
  final result = await FeedbackJar.shared.listFeedback(
    limit: 20,
    cursor: cursor,
  );
  if (result case FeedbackSuccess(:final value)) {
    renderPosts(value.posts);
    cursor = value.nextCursor; // pass this back in for the next page
  }
}

Callback #

FeedbackJar.shared.listFeedbackCallback(
  limit: 20,
  callback: (result) {
    if (result case FeedbackSuccess(:final value)) {
      // render value.posts
    }
  },
);

API reference #

FeedbackJar #

Method Description
configure(widgetId) Configure the SDK. Call once before anything else.
shared.submit(content, {email?, name?, properties?}) Submit feedback, optionally with custom properties merged into app metadata. Returns Future<FeedbackResult<FeedbackResponse>>.
shared.submitCallback(content, callback, {email?, name?, properties?}) Callback variant.
shared.listFeedback({boardId?, limit = 20, cursor?}) List public feedback. limit is clamped to 1–50.
shared.listFeedbackCallback({boardId?, limit, cursor?, callback}) Callback variant.
shared.getConfig() Fetch whether the org asks for name/email. Returns Future<FeedbackResult<WidgetConfig>>.
shared.getConfigCallback(callback) Callback variant.
shared.setIdentity({name?, email?}) Remember a submitter's name/email for future submit calls.
shared.getIdentity() The currently remembered identity, if any. Returns Future<FeedbackIdentity>.
shared.clearIdentity() Forget the remembered identity.

FeedbackResult<T> #

A sealed class with two subtypes. Use Dart 3 pattern matching:

switch (result) {
  case FeedbackSuccess(:final value):
    // T value
  case FeedbackFailure(:final error):
    // Object error
}

FeedbackResponse #

class FeedbackResponse {
  final String postId;
  final String title;    // AI-generated title for the submission
  final String type;     // e.g. FEEDBACK, BUG, FEATURE_REQUEST
  final String boardId;
}

FeedbackPost #

class FeedbackPost {
  final String id;
  final String title;
  final String content;
  final String type;
  final String status;       // OPEN, IN_PROGRESS, COMPLETED, ...
  final String slug;
  final String boardId;
  final int voteCount;
  final int commentCount;
  final int upvotes;
  final String? authorName;
  final String createdAt;    // ISO-8601
  final String updatedAt;    // ISO-8601
}

FeedbackListResult #

class FeedbackListResult {
  final List<FeedbackPost> posts;
  final String? nextCursor;  // null when there are no more pages
}

WidgetConfig #

class WidgetConfig {
  final bool collectName;   // org asks for the submitter's name
  final bool collectEmail;  // org asks for the submitter's email
}

FeedbackIdentity #

class FeedbackIdentity {
  final String? name;
  final String? email;
}

Notes #

  • Feedback can be submitted anonymously, or with a name/email — the SDK never requires either.
  • Name/email are persisted on-device via shared_preferences so they survive app restarts.
  • Private boards and non-public posts are never returned by listFeedback.
  • All methods return a FeedbackResult; nothing throws on network or HTTP errors.
  • Requires WidgetsFlutterBinding.ensureInitialized() before configure if called before runApp.
1
likes
0
points
283
downloads

Publisher

verified publisherfeedbackjar.com

Weekly Downloads

Flutter SDK for FeedbackJar — collect user feedback with automatic device metadata. You build the UI; the SDK handles submission and listing.

Homepage

License

unknown (license)

Dependencies

device_info_plus, flutter, http, package_info_plus, shared_preferences

More

Packages that depend on feedbackjar