augnito_flutter_sdk 0.0.4 copy "augnito_flutter_sdk: ^0.0.4" to clipboard
augnito_flutter_sdk: ^0.0.4 copied to clipboard

Use the Augnito Flutter SDK to enable Text To Speech and voice commands into a Flutter application.

example/lib/main.dart

import 'package:augnito_flutter_sdk/config/augnito_api_server.dart';
import 'package:augnito_flutter_sdk/config/augnito_config.dart';
import 'package:augnito_flutter_sdk/dictation/dictation_manager.dart';
import 'package:augnito_flutter_sdk/dictation/models/action_recipe.dart';
import 'package:augnito_flutter_sdk/dictation/support/dictation_error.dart';
import 'package:augnito_flutter_sdk/text/utils/text_field_processor.dart';
import 'package:augnito_flutter_sdk_example/app_helpers.dart';
import 'package:flutter/material.dart';
import 'package:flutter_dotenv/flutter_dotenv.dart';
import 'dart:async';
import 'package:collection/collection.dart';

import 'command_list.dart';
import 'models/commands.dart';

Future main() async {
  await dotenv.load(fileName: ".env");
  runApp(MaterialApp(
    theme: ThemeData(
      scaffoldBackgroundColor: Colors.white,
      colorScheme: ColorScheme.fromSwatch(
        primarySwatch:
            AppHelpers.createMaterialColor(const Color.fromRGBO(0, 77, 99, 1)),
      ),
    ),
    home: const HomeScreen(),
  ));
}

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

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

/// Dictionary of available editors.
abstract class AvailableEditors {
  static const String patientId = "patientId";
  static const String diagnosis = "diagnosis";
  static const String medication = "medication";
  static const String history = "history";
}

/// Utility class to simplify the interactions with the fields on screen.
class SelectableEditor {
  final String name;
  final focusNode = FocusNode();
  final textEditingController = TextEditingController();
  SelectableEditor(this.name);
}

class _HomeScreenState extends State<HomeScreen> {
  var _connected = false;
  var _busy = false;
  final _menuActionTextStart = "Tap here to start";
  final _menuActionTextStop = "Listening...";
  var _currentMenuActionText = "";
  late DictationManager _dictationManager;
  final AugnitoConfig _config = AugnitoConfig(
      AugnitoAPIServer.india,
      dotenv.env['ACCOUNT_CODE'] ?? "",
      dotenv.env['ACCESS_KEY'] ?? "",
      dotenv.env['LMID'] ?? "",
      dotenv.env['USER_TAG'] ?? "",
      sourceApp: dotenv.env['SOURCE_APP'] ?? "fluttersdkexample");

  final selectableEditors = List<SelectableEditor>.from([
    SelectableEditor(AvailableEditors.patientId),
    SelectableEditor(AvailableEditors.diagnosis),
    SelectableEditor(AvailableEditors.medication),
    SelectableEditor(AvailableEditors.history)
  ]);

  SelectableEditor? focusedEditor;

  @override
  void initState() {
    super.initState();
    _currentMenuActionText = _menuActionTextStart;
    initPlatformState();
  }

  // Platform messages are asynchronous, so we initialize in an async method.
  Future<void> initPlatformState() async {
    // Platform messages may fail, so we use a try/catch PlatformException.
    // We also handle the message potentially returning null.

    // If the widget was removed from the tree while the asynchronous platform
    // message was in flight, we want to discard the reply rather than calling
    // setState to update our non-existent appearance.
    if (!mounted) return;
    _dictationManager = DictationManager(_config,
        onConnected: _onConnected,
        onDisconnected: _onDisconnected,
        onError: _onError,
        onPartialResult: _onPartialResult,
        onFinalResult: _onFinalResult,
        onCommandResult: _onCommand,
        enableLogs: true);
  }

  SelectableEditor _getEditorByName(String name) {
    return selectableEditors.firstWhere((element) => element.name == name);
  }

  void _onPartialResult(String hypothesis) {
    setState(() {
      _currentMenuActionText = hypothesis.length > 15
          ? hypothesis.replaceRange(12, hypothesis.length, '...')
          : hypothesis;
    });
    print("partial result: $hypothesis");
  }

  void _onFinalResult(String transcription) {
    if (focusedEditor != null) {
      TextFieldProcessor.addContent(
          transcription, focusedEditor!.textEditingController);
    }
    setState(() {
      _currentMenuActionText = _menuActionTextStop;
    });
    print("final result: $transcription");
  }

  void _onCommand(ActionRecipe actionRecipe) {
    setState(() {
      _currentMenuActionText = _menuActionTextStop;
    });

    if (focusedEditor == null) {
      return;
    }
    switch (actionRecipe.name) {
      case Commands.StopMic:
        _onToggleDictation();
        break;
      case Commands.DeleteIt:
      case Commands.DeleteThat:
      case Commands.DeletePreviousWord:
      case Commands.DeletePreviousLine:
        _processStaticDelete(actionRecipe);
        break;
      case Commands.SelectWord:
        _processSelectWord(actionRecipe);
        break;
      case Commands.SelectLine:
        _processSelectLine(actionRecipe);
        break;
      case Commands.Goto:
        _processGoToTextField(actionRecipe);
        break;
      default:
    }
    print("command: ${actionRecipe.name}");
    print(actionRecipe.toString());
  }

  void _processGoToTextField(ActionRecipe actionRecipe) {
    final control = actionRecipe.searchText.replaceAll(RegExp(r"\s+"), "");
    final target = selectableEditors
        .firstWhereOrNull((element) => element.name.toLowerCase() == control);
    if (target != null) {
      target.focusNode.requestFocus();
    }
  }

  void _processSelectLine(ActionRecipe actionRecipe) {
    TextFieldProcessor.selectLastLines(focusedEditor!.textEditingController,
        offset: actionRecipe.chooseNumber);

    if (actionRecipe.selectFor == Commands.Delete) {
      TextFieldProcessor.deleteSelection(focusedEditor!.textEditingController);
    }
  }

  void _processSelectWord(ActionRecipe actionRecipe) {
    TextFieldProcessor.selectLastWords(focusedEditor!.textEditingController,
        offset: actionRecipe.chooseNumber);
    if (actionRecipe.selectFor == Commands.Delete) {
      TextFieldProcessor.deleteSelection(focusedEditor!.textEditingController);
    }
  }

  void _processStaticDelete(ActionRecipe actionRecipe) {
    TextFieldProcessor.selectLastWords(focusedEditor!.textEditingController);
    TextFieldProcessor.deleteSelection(focusedEditor!.textEditingController);
  }

  void _onConnected() {
    setState(() {
      _connected = true;
      _busy = false;
      _currentMenuActionText = _menuActionTextStop;
    });
  }

  void _onDisconnected() {
    setState(() {
      _connected = false;
      _busy = false;
      _currentMenuActionText = _menuActionTextStart;
    });
  }

  void _onError(DictationError error) {
    print("error ${error.errorMessage}");
  }

  void _onChangeFocus(SelectableEditor editor) {
    setState(() {
      focusedEditor = editor;
    });
  }

  void _onToggleDictation() {
    if (_busy) {
      return;
    }
    setState(() {
      _busy = true;
    });
    _dictationManager.toggleDictation();
  }

  @override
  void dispose() {
    for (var editor in selectableEditors) {
      editor.textEditingController.dispose();
      editor.focusNode.dispose();
    }
    _dictationManager.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        leading: PopupMenuButton(
            // add icon, by default "3 dot" icon
            icon: const Icon(Icons.more_vert),
            itemBuilder: (context) {
              return [
                const PopupMenuItem<int>(
                  value: 0,
                  child: Text("COMMAND HELP"),
                ),
              ];
            },
            onSelected: (value) {
              if (value == 0) {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                      builder: (context) => const CommandListPage()),
                );
              }
            }),
        actions: [
          Opacity(
            opacity: _busy ? 0.3 : 1,
            child: TextButton(
              onPressed: _onToggleDictation,
              style: ButtonStyle(
                foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
              ),
              child: Row(children: [
                Padding(
                  padding: const EdgeInsets.only(right: 8),
                  child: Text(_currentMenuActionText),
                ),
                _connected
                    ? Image.asset("assets/stop_mic.png")
                    : Image.asset("assets/start_mic.png")
              ]),
            ),
          )
        ],
      ),
      body: SingleChildScrollView(
        child: Padding(
          padding: const EdgeInsets.all(16),
          child: Column(
            children: <Widget>[
              Focus(
                onFocusChange: (value) => {
                  if (value)
                    {
                      _onChangeFocus(
                          _getEditorByName(AvailableEditors.patientId))
                    }
                },
                child: TextField(
                  focusNode:
                      _getEditorByName(AvailableEditors.patientId).focusNode,
                  autofocus: true,
                  keyboardType: TextInputType.none,
                  controller: _getEditorByName(AvailableEditors.patientId)
                      .textEditingController,
                  decoration: const InputDecoration(
                    alignLabelWithHint: true,
                    label: Text('Patient Id'),
                    border: OutlineInputBorder(),
                  ),
                ),
              ),
              const SizedBox(height: 16),
              Focus(
                onFocusChange: (value) => {
                  if (value)
                    {
                      _onChangeFocus(
                          _getEditorByName(AvailableEditors.diagnosis))
                    }
                },
                child: TextField(
                  focusNode:
                      _getEditorByName(AvailableEditors.diagnosis).focusNode,
                  keyboardType: TextInputType.none,
                  controller: _getEditorByName(AvailableEditors.diagnosis)
                      .textEditingController,
                  decoration: const InputDecoration(
                    alignLabelWithHint: true,
                    label: Text('Diagnosis'),
                    border: OutlineInputBorder(),
                  ),
                ),
              ),
              const SizedBox(height: 16),
              Focus(
                onFocusChange: (value) => {
                  if (value)
                    {
                      _onChangeFocus(
                          _getEditorByName(AvailableEditors.medication))
                    }
                },
                child: TextField(
                  focusNode:
                      _getEditorByName(AvailableEditors.medication).focusNode,
                  keyboardType: TextInputType.none,
                  controller: _getEditorByName(AvailableEditors.medication)
                      .textEditingController,
                  decoration: const InputDecoration(
                    alignLabelWithHint: true,
                    label: Text('Medication'),
                    border: OutlineInputBorder(),
                  ),
                ),
              ),
              const SizedBox(height: 16),
              Focus(
                onFocusChange: (value) => {
                  if (value)
                    {_onChangeFocus(_getEditorByName(AvailableEditors.history))}
                },
                child: TextField(
                  focusNode:
                      _getEditorByName(AvailableEditors.history).focusNode,
                  keyboardType: TextInputType.none,
                  maxLines: 5,
                  controller: _getEditorByName(AvailableEditors.history)
                      .textEditingController,
                  decoration: const InputDecoration(
                    label: Text('History'),
                    alignLabelWithHint: true,
                    border: OutlineInputBorder(),
                  ),
                ),
              ),
            ],
          ),
        ),
      ),
    );
  }
}
0
likes
120
pub points
21%
popularity

Publisher

unverified uploader

Use the Augnito Flutter SDK to enable Text To Speech and voice commands into a Flutter application.

Homepage

Documentation

API reference

License

BSD-3-Clause (LICENSE)

Dependencies

flutter, http

More

Packages that depend on augnito_flutter_sdk