wiredash 0.2.0

  • Readme
  • Changelog
  • Example
  • Installing
  • 94

Wiredash Logo

Wiredash SDK for Flutter #

Pub Build Website

Wiredash is probably the easiest and most convenient way to capture in-app user feedback, wishes, ratings and much more. The SDK is completely written in Dart and runs on Android, iOS, Desktop and the Web. For more info, head over to wiredash.io.

Getting Started #

In order to get started, you need to create an account at wiredash.io - you do this by simply signing in with a valid Google or GitHub account.

Setting up your Flutter project #

After successfully creating a new project in the Wiredash admin console it's time to add Wiredash to your app. Simply open your pubspec.yaml file and add the current version of Wiredash as a dependency, e.g. wiredash: 0.1.0. Make sure to get the newest version.

Now get all pub packages by clicking on Packages get in your IDE or executing flutter packages get inside your Flutter project.

Head over to the main entry point of your app which most likely resides inside main.dart. In here wrap your root widget inside a Wiredash widget and provide your API credentials and your app's navigator key as parameters. That was already the hard part πŸ™Œ

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
  final _navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    return Wiredash(
      projectId: "YOUR-PROJECT-ID",
      secret: "YOUR-SECRET",
      navigatorKey: _navigatorKey,
      child: MaterialApp(
        navigatorKey: _navigatorKey,
        title: 'Flutter Demo',
        home: ...
      ),
    );
  }  
}

Now you can call Wiredash.of(context).show() from anywhere inside your app to start the feedback process!

Setting user properties #

You can set user properties to be sent together with the feedback by calling:

Wiredash.of(context).setUserProperties(
  userEmail: 'mail@example.com',
  userId: 'custom-id',
);

Passing build information to Wiredash #

In runtime

You can receive information about build number and build version together with the user feedback. Set build properties before sending the feedback by calling:

Wiredash.of(context).setBuildProperties(
  buildNumber: '42',
  buildVersion: '1.42',
);

You can also define them during compile-time instead.

Setting build properties during compile time

Available only when using Flutter 1.17 or newer

If you want to receive information about build number, build version or specific commit related to the feedback you can pass additional parameters to your flutter build or flutter run command.

To receive the build information along with your feedback you mast pass --dart-define flags to your flutter build command as follows:

flutter build --dart-define=BUILD_NUMBER=$BUILD_NUMBER --dart-define=BUILD_VERSION=$BUILD_VERSION --dart-define=BUILD_COMMIT=$FCI_COMMIT

Supported keys are:

  • BUILD_NUMBER
  • BUILD_VERSION
  • BUILD_COMMIT

In the example above $BUILD_NUMBER is an environment variable defined in CI. Of course you can also use any other value or variable like --dart-define=BUILD_NUMBER="1.0.42".

Most of the CI platforms define some common environment variables containing current build number and SHA of commit used to build the app. For instance, on Codemagic these are BUILD_NUMBER and FCI_COMMIT respectively.

Be aware that this feature was added in Flutter 1.17 and won't work in previous versions.

Android / iOS / MacOS specific setup #

Wiredash is by design written in Dart and relies on very few dependencies by the official Flutter team. However, when running on Android it needs the internet permission (for sending user feedback back to you). If you already use Flutter in production, chances are quite high that you already added the internet permission to the manifest - if not, add the following line to the AndroidManifest.xml in your Android project folder:

<manifest ...>
 <uses-permission android:name="android.permission.INTERNET" />
 <application ...
</manifest>

That's it!

On MacOS, you also need the internet permission, so don't forget to open Runner.xcodeproj located in the macos folder in the root directory of your app, then go in the "Signing & Capabilities" tab of your XCode project. There, be sure to check the box "Outgoing Connections (Client)".

VoilΓ  !

Localization/internationalization support πŸ‡¬πŸ‡§πŸ‡΅πŸ‡±πŸ‡©πŸ‡ͺ #

Wiredash supports several languages out of the box (see the list of supported translation files here). By default Wiredash will be shown in the device language provided it's supported by the package.

If you want to override the default locale just pass locale parameter as follows. If the locale is not supported then English will be used by default.

return Wiredash(
  ...
  options: WiredashOptionsData(
    /// You can set your own locale to override device default (`window.locale` by default)
    locale: const Locale.fromSubtags(languageCode: 'pl'),
  ),
  ...
);

Providing custom terms #

You can also provide custom translations. You can choose if you want to provide all the possible terms or only selected (e.g. you want to get rid of the emojis in current locale).

For instance you can provide locale for unsupported language and use this locale by providing proper value to locale property.

return Wiredash(
  //...
  options: WiredashOptionsData(
    customTranslations: {
      const Locale.fromSubtags(languageCode: 'zh'):
          const DemoCustomTranslations()
    },
    locale: const Locale.fromSubtags(languageCode: 'zh'),
  ),
  //...
);

If you want to add new locale the custom translation class should extend WiredashTranslations:

// WiredashTranslations is abstract
class DemoCustomTranslations extends WiredashTranslations {
  const DemoCustomTranslations() : super();

  @override
  String get feedbackStateIntroTitle => 'Good morning!';
  /// override all the terms
}

Or if you want to override only selected Polish terms you should extend built-in WiredashLocalizedTranslations:

import 'package:wiredash/src/common/translation/l10n/messages_pl.dart' as pl;

class DemoPolishTranslations extends pl.WiredashLocalizedTranslations {
  const DemoPolishTranslations() : super();

  @override
  String get feedbackStateIntroTitle => 'DzieΕ„ dobry!';
}

Then provide the instance of this class to WiredashOptionsData as in the snippet below:

return Wiredash(
  //...
  options: WiredashOptionsData(
    customTranslations: {
      const Locale.fromSubtags(languageCode: 'pl'):
          const DemoPolishTranslations(),
    },
    locale: const Locale('pl'),
  ),
  //...
);

Contribute your translations πŸŽ‰ #

If you want to contribute your own translations you can join our public POEditor project here.

Translation contributors

Thank you so much to following people who helped translate Wiredash! πŸ™Œ

License #

The Wiredash SDK is released under the Attribution Assurance License. See LICENSE for details.

[0.2.0] - Internationalization Support πŸ‡¬πŸ‡§πŸ‡©πŸ‡ͺπŸ‡΅πŸ‡± #

We added initial internationalization support for several languages. Feel free to contribute your own translations (check out the docs for more info on that)!

  • Added WiredashLocalizations
  • Added ability to provide custom WiredashTranslations
  • Added buildNumber, buildVersion and buildCommit properties that can be passed through dart-define
  • Constrained the SDK to 2.8.0 or newer and Flutter to 1.17.0 or newer
  • Deprecated method setIdentifiers in favor of setUserProperties and setBuildProperties
  • Minor bug fixes

[0.1.0] - Floating Entry πŸ“², Confidential πŸ‘€ & Provider πŸ— #

Wiredash now uses the Provider package for internal state management and supports version 3.0.0 and higher. If you are also using Provider in your app, please make sure to at least use version 3.0.0.

  • Added a Floating Entry which is shown by default in debug to show Wiredash from any screen
  • Added WiredashOptions to further customize the Wiredash widget (e.g. the Floating Entry)
  • Added a Confidential widget to automatically hide sensitive widgets during screen capture
  • Added a Wiredash.of(context).visible ValueListener to check if Wiredash is in screen capture mode (e.g. for hiding certain widgets being screen captured)
  • Improved error handling when there is no valid root navigator key
  • Improved performance
  • Minor bug fixes

[0.0.1] - Public Release #

  • Wiredash gets released to the public πŸŽ‰

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:wiredash/wiredash.dart';
import 'package:wiredash/src/common/translation/l10n/messages_pl.dart' as pl;

part 'main_localizations.dart';

void main() => runApp(const ExampleApp());

class ExampleApp extends StatefulWidget {
  const ExampleApp({Key key}) : super(key: key);
  @override
  _ExampleAppState createState() => _ExampleAppState();
}

class _ExampleAppState extends State<ExampleApp> {
  /// Wiredash uses a navigation key to show and hide our overlay. This key must be passed to
  /// the `MaterialApp` and `Wiredash` widgets.
  /// Note you are not required to use `MaterialApp`, Wiredash will work perfectly fine with
  /// `CupertinoApp` and `WidgetsApp`.
  final _navigatorKey = GlobalKey<NavigatorState>();

  @override
  Widget build(BuildContext context) {
    /// Here we wrap our app at the top level using a `Wiredash` widget. This requires us to pass
    /// the `projectId` and `secret` obtained from the "configuration" section of your console.
    /// Notice we are also passing our `_navigatorKey` to both widgets.
    /// Wiredash also allows you to setup custom themes and translations using `WiredashThemeData` and
    /// `WiredashOptionsData`. Both of these are optional but should your heart desire an extra layer
    /// of customizability, you can make wiredash your own.
    /// Read more about translations support in the package's README.
    return Wiredash(
      projectId: "YOUR-PROJECT-ID",
      secret: "YOUR-SECRET",
      navigatorKey: _navigatorKey,
      options: WiredashOptionsData(
        showDebugFloatingEntryPoint: true,

        /// Uncomment below to see how custom translations work
        // customTranslations: {
        //   const Locale.fromSubtags(languageCode: 'en'):
        //       const DemoCustomTranslations(),
        //   const Locale.fromSubtags(languageCode: 'pl'):
        //       const DemoPolishTranslations(),
        // },

        /// Uncomment below to override default device locale
        // locale: const Locale('de'),
      ),
      theme: WiredashThemeData(brightness: Theme.of(context).brightness),
      child: MaterialApp(
        navigatorKey: _navigatorKey,
        title: 'Adventure 🌎',
        home: const DemoHomePage(),
      ),
    );
  }
}

class DemoHomePage extends StatelessWidget {
  const DemoHomePage({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF6F9FC),
      drawer: Drawer(
        child: Column(
          children: const <Widget>[
            DrawerHeader(
              child: Center(child: Text('Wiredash example')),
            ),
            UserInfoButton(),
            BuildInfoButton(),
          ],
        ),
      ),
      appBar: AppBar(
        title: const Text('Adventure 🌎'),
        backgroundColor: const Color(0xFF02579B),
        actions: <Widget>[
          IconButton(
            icon: const Icon(Icons.help_outline),

            /// In a single line of code, we can show the Wiredash menu. Because we wrapped our app
            /// with the `Wiredash` widget at the very top level, we can access this method from anywhere in our code.
            onPressed: () => Wiredash.of(context).show(),
          )
        ],
      ),
      body: SafeArea(
        child: ListView.builder(
          itemCount: CitiesModel.cities.length,
          itemBuilder: (context, index) {
            return CountryCard(item: CitiesModel.cities[index]);
          },
        ),
      ),
    );
  }
}

class CitiesModel {
  const CitiesModel({
    @required this.title,
    @required this.description,
    @required this.image,
  });

  final String title;
  final String description;
  final String image;
  static const cities = <CitiesModel>[
    CitiesModel(
      title: 'Germany',
      description:
          "Frankfurt, a central German city on the river Main, is a major financial hub that's home to the European Central Bank. It's the birthplace of famed writer Johann Wolfgang von Goethe, whose former home is now the Goethe House Museum.",
      image:
          "https://user-images.githubusercontent.com/25674767/82772933-badd0880-9e0e-11ea-9b25-0c1f084052a1.jpg",
    ),
    CitiesModel(
      title: 'Ne York',
      description:
          "At its core is Manhattan, a densely populated borough that’s among the world’s major commercial, financial and cultural centers. Its iconic sites include skyscrapers such as the Empire State Building and sprawling Central Park.",
      image:
          "https://user-images.githubusercontent.com/25674767/82772939-bdd7f900-9e0e-11ea-9de6-1adf978c91b4.jpg",
    ),
    CitiesModel(
      title: 'Trinidad and Tobago',
      description:
          "Trinidad and Tobago is a dual-island Caribbean nation near Venezuela,  with distinctive Creole traditions and cuisines. Trinidad’s capital,  Port of Spain, hosts a boisterous carnival featuring calypso and soca music.",
      image:
          "https://user-images.githubusercontent.com/25674767/82772941-bf092600-9e0e-11ea-9fd7-7eb40161274b.jpg",
    ),
  ];
}

class CountryCard extends StatelessWidget {
  const CountryCard({Key key, @required this.item}) : super(key: key);
  final CitiesModel item;
  @override
  Widget build(BuildContext context) {
    return Card(
      clipBehavior: Clip.antiAlias,
      shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
      margin: const EdgeInsets.all(12.0),
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.start,
        children: [
          Image.network(
            item.image,
            width: double.maxFinite,
          ),
          Padding(
            padding: const EdgeInsets.only(
              top: 18.0,
              left: 12.0,
              right: 12.0,
            ),
            child: Text(
              item.title,
              style: Theme.of(context).textTheme.headline6,
            ),
          ),
          Padding(
            padding: const EdgeInsets.only(
              top: 12.0,
              left: 12.0,
              right: 12.0,
              bottom: 8.0,
            ),
            child: Text(
              item.description,
              style: Theme.of(context).textTheme.caption.copyWith(
                    fontSize: 16.0,
                  ),
              textAlign: TextAlign.justify,
            ),
          ),
        ],
      ),
    );
  }
}

class BuildInfoButton extends StatelessWidget {
  const BuildInfoButton({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: () {
        Wiredash.of(context).setBuildProperties(
          buildNumber: '42',
          buildVersion: '1.42',
        );
      },
      child: const Text('Set random build parameters'),
    );
  }
}

class UserInfoButton extends StatelessWidget {
  const UserInfoButton({Key key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FlatButton(
      onPressed: () {
        Wiredash.of(context).setUserProperties(
          userEmail: 'mail@example.com',
          userId: 'custom-id',
        );
      },
      child: const Text('Set random user parameters'),
    );
  }
}

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:


dependencies:
  wiredash: ^0.2.0

2. Install it

You can install packages from the command line:

with Flutter:


$ flutter pub get

Alternatively, your editor might support flutter pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:


import 'package:wiredash/wiredash.dart';
  
Popularity:
Describes how popular the package is relative to other packages. [more]
87
Health:
Code health derived from static analysis. [more]
100
Maintenance:
Reflects how tidy and up-to-date the package is. [more]
100
Overall:
Weighted score of the above. [more]
94
Learn more about scoring.

We analyzed this package on Jul 8, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.8.4
  • pana: 0.13.13
  • Flutter: 1.17.5

Analysis suggestions

Package does not support Flutter platform android

Because of import path [package:wiredash/wiredash.dart, package:wiredash/src/wiredash_widget.dart, package:wiredash/src/feedback/feedback_model.dart, package:wiredash/src/common/utils/device_info.dart, package:wiredash/src/common/build_info/build_info_manager.dart, package:wiredash/src/common/utils/build_info.dart, package:shared_preferences/shared_preferences.dart, package:shared_preferences_linux/shared_preferences_linux.dart] that declares support for platforms: linux

Package does not support Flutter platform ios

Because of import path [package:wiredash/wiredash.dart, package:wiredash/src/wiredash_widget.dart, package:wiredash/src/feedback/feedback_model.dart, package:wiredash/src/common/utils/device_info.dart, package:wiredash/src/common/build_info/build_info_manager.dart, package:wiredash/src/common/utils/build_info.dart, package:shared_preferences/shared_preferences.dart, package:shared_preferences_linux/shared_preferences_linux.dart] that declares support for platforms: linux

Package does not support Flutter platform macos

Because of import path [package:wiredash/wiredash.dart, package:wiredash/src/wiredash_widget.dart, package:wiredash/src/feedback/feedback_model.dart, package:wiredash/src/common/utils/device_info.dart, package:wiredash/src/common/build_info/build_info_manager.dart, package:wiredash/src/common/utils/build_info.dart, package:shared_preferences/shared_preferences.dart, package:shared_preferences_linux/shared_preferences_linux.dart] that declares support for platforms: linux

Package does not support Flutter platform web

Because of import path [package:wiredash/wiredash.dart, package:wiredash/src/wiredash_widget.dart, package:wiredash/src/feedback/feedback_model.dart, package:wiredash/src/common/utils/device_info.dart, package:wiredash/src/common/build_info/build_info_manager.dart, package:wiredash/src/common/utils/build_info.dart, package:shared_preferences/shared_preferences.dart, package:shared_preferences_linux/shared_preferences_linux.dart] that declares support for platforms: linux

Package does not support Flutter platform windows

Because of import path [package:wiredash/wiredash.dart, package:wiredash/src/wiredash_widget.dart, package:wiredash/src/feedback/feedback_model.dart, package:wiredash/src/common/utils/device_info.dart, package:wiredash/src/common/build_info/build_info_manager.dart, package:wiredash/src/common/utils/build_info.dart, package:shared_preferences/shared_preferences.dart] that declares support for platforms: android, ios, linux, macos, web

Package not compatible with SDK dart

because of import path [wiredash] that is in a package requiring null.

Dependencies

Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.8.0 <3.0.0
flutter 0.0.0
http ^0.12.0 0.12.1
http_parser ^3.1.0 3.1.4
provider >=3.0.0 <5.0.0 4.2.0
shared_preferences ^0.5.6 0.5.8
Transitive dependencies
charcode 1.1.3
collection 1.14.12 1.14.13
file 5.2.1
flutter_web_plugins 0.0.0
intl 0.16.1
meta 1.1.8 1.2.1
nested 0.0.4
path 1.7.0
path_provider_linux 0.0.1+2
path_provider_platform_interface 1.0.2
pedantic 1.9.0 1.9.1
platform 2.2.1
plugin_platform_interface 1.0.2
process 3.0.13
shared_preferences_linux 0.0.2+1
shared_preferences_macos 0.0.1+10
shared_preferences_platform_interface 1.0.4
shared_preferences_web 0.1.2+7
sky_engine 0.0.99
source_span 1.7.0
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6 1.2.0
vector_math 2.0.8
xdg_directories 0.1.0
Dev dependencies
flutter_test
lint ^1.2.0
mockito any