feedback_plus 0.1.4 copy "feedback_plus: ^0.1.4" to clipboard
feedback_plus: ^0.1.4 copied to clipboard

discontinued

A Flutter package for getting better feedback. It allows the user to give interactive feedback directly in the app.

example/lib/main.dart

import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';

import 'package:example/feedback_functions.dart';
import 'package:feedback_plus/feedback_plus.dart';
import 'package:flutter/foundation.dart' show kIsWeb;
import 'package:flutter/material.dart';
import 'package:flutter_email_sender/flutter_email_sender.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_markdown/flutter_markdown.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart';
import 'package:share_plus/share_plus.dart';
import 'package:url_launcher/url_launcher.dart';

import 'custom_feedback.dart';

final appTheme = ThemeData(
  useMaterial3: true,
  colorScheme: ColorScheme.fromSeed(
    seedColor: _useCustomFeedback ? Colors.green : Colors.blue,
  ),
);

void main() {
  runApp(const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({super.key});

  @override
  State<MyApp> createState() => _MyAppState();
}

bool _useCustomFeedback = false;

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Feedback Demo',
      theme: appTheme,
      home: MyHomePage(_toggleCustomizedFeedback),
      builder: (context, child) {
        return BetterFeedback(
          feedbackBuilder: _useCustomFeedback
              ? (context, onSubmit, scrollController) => CustomFeedbackForm(
                    onSubmit: onSubmit,
                    scrollController: scrollController,
                  )
              : null,
          theme: FeedbackThemeData(
            background: Colors.grey,
            feedbackSheetColor: Colors.grey[50]!,
            drawColors: [
              Colors.red,
              Colors.green,
              Colors.blue,
              Colors.yellow,
            ],
          ),
          darkTheme: FeedbackThemeData.dark(),
          localizationsDelegates: [
            GlobalFeedbackLocalizationsDelegate(),
            GlobalMaterialLocalizations.delegate,
            GlobalCupertinoLocalizations.delegate,
            GlobalWidgetsLocalizations.delegate,
          ],
          localeOverride: const Locale('en'),
          mode: FeedbackMode.draw,
          pixelRatio: 1,
          child: child!,
        );
      },
    );
  }

  void _toggleCustomizedFeedback() =>
      setState(() => _useCustomFeedback = !_useCustomFeedback);
}

class MyHomePage extends StatelessWidget {
  const MyHomePage(this.toggleCustomizedFeedback, {super.key});

  final VoidCallback toggleCustomizedFeedback;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(_useCustomFeedback
            ? '(Custom) Feedback Example'
            : 'Feedback Example'),
      ),
      drawer: Drawer(
        child: Container(color: Colors.blue),
      ),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: SingleChildScrollView(
          child: Column(
            children: <Widget>[
              const SizedBox(height: 10),
              const MarkdownBody(
                data: '# How does it work?\n'
                    '1. Just press the `Provide feedback` button.\n'
                    '2. The feedback view opens. '
                    'You can choose between draw and navigation mode. '
                    'When in navigate mode, you can freely navigate in the '
                    'app. Try it by opening the navigation drawer or by '
                    'tapping the `Open scaffold` button. To switch to the '
                    'drawing mode just press the `Draw` button on the right '
                    'side. Now you can draw on the screen.\n'
                    '3. To finish your feedback just write a message '
                    'below and send it by pressing the `Submit` button.',
              ),
              const SizedBox(height: 10),
              ElevatedButton(
                child: const Text('Open scaffold'),
                onPressed: () {
                  Navigator.push<void>(
                    context,
                    MaterialPageRoute(
                      builder: (context) {
                        return _SecondaryScaffold();
                      },
                    ),
                  );
                },
              ),
              const Divider(),
              ElevatedButton(
                child: const Text('Provide feedback'),
                onPressed: () {
                  BetterFeedback.of(context).show(
                    (feedback) async {
                      // upload to server, share whatever
                      // for example purposes just show it to the user
                      alertFeedbackFunction(
                        context,
                        feedback,
                      );
                    },
                  );
                },
              ),
              const SizedBox(height: 10),
              if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) ...[
                TextButton(
                  child: const Text('Provide E-Mail feedback'),
                  onPressed: () {
                    BetterFeedback.of(context).show((feedback) async {
                      // draft an email and send to developer
                      final screenshotFilePath =
                          await writeImageToStorage(feedback.screenshot);

                      final Email email = Email(
                        body: feedback.text,
                        subject: 'App Feedback',
                        recipients: ['john.doe@flutter.dev'],
                        attachmentPaths: [screenshotFilePath],
                        isHTML: false,
                      );
                      await FlutterEmailSender.send(email);
                    });
                  },
                ),
                const SizedBox(height: 10),
              ],
              ElevatedButton(
                child: const Text('Provide feedback via platform sharing'),
                onPressed: () {
                  BetterFeedback.of(context).show(
                    (feedback) async {
                      final screenshotFilePath =
                          await writeImageToStorage(feedback.screenshot);

                      // ignore: deprecated_member_use
                      await Share.shareFiles(
                        [screenshotFilePath],
                        text: feedback.text,
                      );
                    },
                  );
                },
              ),
              const Divider(),
              const Text('This is the example app for the "feedback" library.'),
              const SizedBox(height: 10),
              ElevatedButton(
                child: const Text('Visit library page on pub.dev'),
                onPressed: () {
                  launchUrl(Uri.parse('https://pub.dev/packages/feedback'));
                },
              ),
              const TextField(),
            ],
          ),
        ),
      ),
      floatingActionButton: MaterialButton(
        color: Theme.of(context).primaryColor,
        shape: const RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(20))),
        child: const Text('toggle feedback mode',
            style: TextStyle(color: Colors.white)),
        onPressed: () {
          // don't toggle the feedback mode if it's currently visible
          if (!BetterFeedback.of(context).isVisible) {
            toggleCustomizedFeedback();
          }
        },
      ),
    );
  }
}

class _SecondaryScaffold extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Scaffold 2'),
      ),
      body: const Center(
        child: Text('Hello World'),
      ),
    );
  }
}

Future<String> writeImageToStorage(Uint8List feedbackScreenshot) async {
  final Directory output = await getTemporaryDirectory();
  final String screenshotFilePath =
      '${output.path}/feedback${feedbackScreenshot.hashCode}.png';
  final File screenshotFile = File(screenshotFilePath);
  await screenshotFile.writeAsBytes(feedbackScreenshot);
  return screenshotFilePath;
}

Future<void> createGitlabIssueFromFeedback(BuildContext context) async {
  BetterFeedback.of(context).show((feedback) async {
    const projectId = 'your-gitlab-project-id';
    const apiToken = 'your-gitlab-api-token';

    final screenshotFilePath = await writeImageToStorage(feedback.screenshot);

    // Upload screenshot
    final uploadRequest = http.MultipartRequest(
      'POST',
      Uri.https(
        'gitlab.com',
        '/api/v4/projects/$projectId/uploads',
      ),
    )
      ..files.add(await http.MultipartFile.fromPath(
        'file',
        screenshotFilePath,
      ))
      ..headers.putIfAbsent('PRIVATE-TOKEN', () => apiToken);
    final uploadResponse = await uploadRequest.send();

    final dynamic uploadResponseMap = jsonDecode(
      await uploadResponse.stream.bytesToString(),
    );

    // Create issue
    await http.post(
      Uri.https(
        'gitlab.com',
        '/api/v4/projects/$projectId/issues',
        <String, String>{
          'title': feedback.text.padRight(80),
          'description': '${feedback.text}\n'
              "${uploadResponseMap["markdown"] ?? "Missing image!"}",
        },
      ),
      headers: {
        'PRIVATE-TOKEN': apiToken,
      },
    );
  });
}
3
likes
160
pub points
0%
popularity

Publisher

verified publishershodev.live

A Flutter package for getting better feedback. It allows the user to give interactive feedback directly in the app.

Repository (GitHub)
View/report issues
Contributing

Documentation

API reference

License

MIT (license)

Dependencies

flutter, flutter_localizations

More

Packages that depend on feedback_plus