vivanta_connect_flutter 0.7.6 copy "vivanta_connect_flutter: ^0.7.6" to clipboard
vivanta_connect_flutter: ^0.7.6 copied to clipboard

Vivanta Connect for Flutter

example/lib/main.dart

import 'dart:io';

import 'package:vivanta_connect_example/helpers.dart';
import 'package:vivanta_connect_example/vivanta.dart';
import 'package:flutter/material.dart';
import 'package:vivanta_connect_example/write_to_health.dart';
import 'package:vivanta_connect_flutter/helpers/vivanta_sync.dart';
import 'package:vivanta_connect_flutter/services/preferences.dart';
import 'package:vivanta_connect_flutter/styles/colors.dart';
import 'package:vivanta_connect_flutter/styles/fonts.dart';
import 'package:vivanta_connect_flutter/views/embedded_graph.dart';

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

class Example extends StatelessWidget {
  const Example({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      title: 'Vivanta Connect Example',
      home: Home(),
    );
  }
}

class Home extends StatefulWidget {
  Home({Key? key}) : super(key: key);

  @override
  State<Home> createState() => _HomeState();
}

class _HomeState extends State<Home> {
  String companyId = 'Vivanta';
  final Preferences preferences = Preferences();
  late TextEditingController _usernameController;
  late TextEditingController _brandController;
  late FocusNode _usernameFocusNode;
  late FocusNode _brandFocusNode;

  @override
  void initState() {
    _usernameController = TextEditingController();
    _usernameFocusNode = FocusNode();
    _brandController = TextEditingController();
    _brandFocusNode = FocusNode();

    _usernameFocusNode.addListener(() {
      if (!_usernameFocusNode.hasFocus) {
        preferences.setExternalUserId(_usernameController.text);
      }
    });

    _brandFocusNode.addListener(() {
      if (!_brandFocusNode.hasFocus) {
        preferences.setBrandId(_brandController.text);
      }
    });
    initAsync();
    super.initState();
  }

  @override
  void dispose() {
    _usernameController.dispose();
    _usernameFocusNode.dispose();
    _brandController.dispose();
    _brandFocusNode.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Vivanta Connect Example'),
      ),
      body: Container(
        width: MediaQuery.of(context).size.width,
        child: ListView(
          children: [
            _box(),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      'External User ID:',
                      textAlign: TextAlign.start,
                    ),
                  ),
                  TextField(
                    keyboardType: TextInputType.text,
                    controller: _usernameController,
                    focusNode: _usernameFocusNode,
                    onEditingComplete: () {
                      FocusScope.of(context).unfocus();
                    },
                  ),
                ],
              ),
            ),
            _box(),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Column(
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Align(
                    alignment: Alignment.centerLeft,
                    child: Text(
                      'Brand ID:',
                      textAlign: TextAlign.start,
                    ),
                  ),
                  TextField(
                    keyboardType: TextInputType.text,
                    controller: _brandController,
                    focusNode: _brandFocusNode,
                    onEditingComplete: () {
                      FocusScope.of(context).unfocus();
                    },
                  ),
                ],
              ),
            ),
            _box(),
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 16),
              child: Column(
                children: [
                  TextButton(
                    onPressed: _usernameController.text.isEmpty
                        ? null
                        : _launchVivantaConnect,
                    style: _buttonStyle(),
                    child: Text(
                      'Connect your device with Vivanta',
                      textAlign: TextAlign.center,
                      style: VivantaFonts.button,
                    ),
                  ),
                  if (Platform.isIOS) ...[
                    _box(),
                    TextButton(
                      onPressed: _usernameController.text.isEmpty
                          ? null
                          : _launchVivantaSync,
                      style: _buttonStyle(),
                      child: Text(
                        'Sync Apple Health Data',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                    _box(),
                    TextButton(
                      onPressed: () => writeAppleHealthParameter(context),
                      style: _buttonStyle(),
                      child: Text(
                        'Write Apple Health parameter',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                    _box(),
                    TextButton(
                      onPressed: () => writeAppleHealthActivity(context),
                      style: _buttonStyle(),
                      child: Text(
                        'Write Apple Health activity',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                  ],
                  if (Platform.isAndroid) ...[
                    _box(),
                    TextButton(
                      onPressed: _usernameController.text.isEmpty
                          ? null
                          : _launchVivantaSync,
                      style: _buttonStyle(),
                      child: Text(
                        'Sync Google Health Connect Data',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                    _box(),
                    TextButton(
                      onPressed: () => writeGoogleHealthParameter(context),
                      style: _buttonStyle(),
                      child: Text(
                        'Write Google Health Connect parameter',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                    _box(),
                    TextButton(
                      onPressed: () => writeGoogleHealthActivity(context),
                      style: _buttonStyle(),
                      child: Text(
                        'Write Google Health Connect activity',
                        textAlign: TextAlign.center,
                        style: VivantaFonts.button,
                      ),
                    ),
                  ],
                  _box(),
                  _getButtonToGraph(
                    'Open activity graph',
                    GraphType.activity,
                  ),
                  _box(),
                  _getButtonToGraph(
                    'Open active time graph',
                    GraphType.activeTime,
                  ),
                  _box(),
                  _getButtonToGraph(
                    'Open sleep graph',
                    GraphType.sleep,
                  ),
                ],
              ),
            ),
          ],
        ),
      ),
    );
  }

  Future<void> initAsync() async {
    final externalUserId = await preferences.getExternalUserId();
    final brandId = await preferences.getBrandId();
    if (externalUserId.isNotEmpty) {
      _usernameController.text = externalUserId;
      setState(() {});
    }
    if (brandId.isNotEmpty) {
      _brandController.text = brandId;
      setState(() {});
    }
  }

  ButtonStyle _buttonStyle({
    Color backgroundColor = VivantaColors.primary,
  }) =>
      ButtonStyle(
        backgroundColor: MaterialStateProperty.all<Color>(backgroundColor),
        fixedSize: MaterialStateProperty.all<Size>(
          Size(MediaQuery.of(context).size.width - 32, 32),
        ),
      );

  Widget _box() => SizedBox(height: 24);

  void _launchVivantaConnect() {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return Container(
          height: 100,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                const Text('What type of start do you want to use?'),
                SizedBox(
                  height: 8,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                      child: const Text('With API key'),
                      onPressed: () async {
                        await launchVivantaConnectWithKeys(
                          context,
                          _usernameController.text,
                          companyId,
                        );
                        Navigator.pop(context);
                      },
                    ),
                    ElevatedButton(
                      child: const Text('With token'),
                      onPressed: () async {
                        final token =
                            await getToken(_usernameController.text, companyId);
                        await launchVivantaConnectWithToken(context, token);
                        Navigator.pop(context);
                      },
                    ),
                  ],
                ),
                SizedBox(
                  height: 8,
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  void _launchVivantaSync() {
    showModalBottomSheet(
      context: context,
      builder: (context) {
        return Container(
          height: 100,
          child: Center(
            child: Column(
              mainAxisAlignment: MainAxisAlignment.center,
              mainAxisSize: MainAxisSize.min,
              children: <Widget>[
                const Text('What type of sync process do you want to use?'),
                SizedBox(
                  height: 8,
                ),
                Row(
                  mainAxisAlignment: MainAxisAlignment.spaceAround,
                  children: [
                    ElevatedButton(
                      child: const Text('With API key'),
                      onPressed: () async {
                        await _sync(showSuccess: true);
                        Navigator.pop(context);
                      },
                    ),
                    ElevatedButton(
                      child: const Text('With token'),
                      onPressed: () async {
                        final token =
                            await getToken(_usernameController.text, companyId);
                        await _syncWithToken(token: token, showSuccess: true);
                        Navigator.pop(context);
                      },
                    ),
                  ],
                ),
                SizedBox(
                  height: 8,
                ),
              ],
            ),
          ),
        );
      },
    );
  }

  Widget _getButtonToGraph(String text, GraphType graphType) {
    final brandId = int.tryParse(_brandController.text);
    return TextButton(
      onPressed: _usernameController.text.isEmpty
          ? null
          : () {
              Navigator.of(context).push(
                MaterialPageRoute(
                  builder: (context) => EmbeddedGraph(
                    apiKey: Vivanta.apiKey,
                    customerId: Vivanta.customerId,
                    externalUserId: _usernameController.text,
                    graphType: graphType,
                    brandId: brandId,
                  ),
                ),
              );
            },
      style: _buttonStyle(
        backgroundColor: VivantaColors.accent,
      ),
      child: Text(
        text,
        textAlign: TextAlign.center,
        style: VivantaFonts.button,
      ),
    );
  }

  Future<void> _sync({
    bool showSuccess = true,
  }) async {
    final sync = VivantaSync(
      apiKey: Vivanta.apiKey,
      customerId: Vivanta.customerId,
      externalUserId: _usernameController.text,
    );
    sync.executeAll().then((value) {
      if (showSuccess) {
        showSyncSuccess(context);
      }
    }).catchError(
      (onError) {},
    );
  }

  Future<void> _syncWithToken({
    bool showSuccess = true,
    String token = '',
  }) async {
    final sync = VivantaSync(
      token: token,
    );
    sync.executeAll().then((value) {
      if (showSuccess) {
        showSyncSuccess(context);
      }
    }).catchError(
      (onError) {},
    );
  }
}