<commit_before>import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../widgets/circle_timer.dart';
import '../../app/models.dart';
import '../models.dart';
import 'account_dialog.dart';
import 'account_mixin.dart';

class AccountView extends ConsumerWidget with AccountMixin {
  final YubiKeyData deviceData;
  @override
  final OathCredential credential;
  final FocusNode? focusNode;
  AccountView(this.deviceData, this.credential, {Key? key, this.focusNode})
      : super(key: key);

  Color _iconColor(int shade) {
    final colors = [
      Colors.red[shade],
      Colors.pink[shade],
      Colors.purple[shade],
      Colors.deepPurple[shade],
      Colors.indigo[shade],
      Colors.blue[shade],
      Colors.lightBlue[shade],
      Colors.cyan[shade],
      Colors.teal[shade],
      Colors.green[shade],
      Colors.lightGreen[shade],
      Colors.lime[shade],
      Colors.yellow[shade],
      Colors.amber[shade],
      Colors.orange[shade],
      Colors.deepOrange[shade],
      Colors.brown[shade],
      Colors.grey[shade],
      Colors.blueGrey[shade],
    ];
    return colors[label.hashCode % colors.length]!;
  }

  List<PopupMenuItem> _buildPopupMenu(BuildContext context, WidgetRef ref) {
    return buildActions(ref).map((e) {
      final action = e.action;
      return PopupMenuItem(
        child: ListTile(
          leading: e.icon,
          title: Text(e.text),
        ),
        enabled: action != null,
        onTap: () {
          Timer(Duration.zero, () {
            action?.call(context);
          });
        },
      );
    }).toList();
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final code = getCode(ref);
    final expired = isExpired(ref);
    final calculateReady = code == null ||
        credential.oathType == OathType.hotp ||
        (credential.touchRequired && expired);

    final darkMode = Theme.of(context).brightness == Brightness.dark;

    return GestureDetector(
      onSecondaryTapDown: (details) {
        showMenu(
          context: context,
          position: RelativeRect.fromLTRB(
              details.globalPosition.dx, details.globalPosition.dy, 0, 0),
          items: _buildPopupMenu(context, ref),
        );
      },
      child: ListTile(
        focusNode: focusNode,
        onTap: () {
          showDialog(
            context: context,
            builder: (context) {
              return AccountDialog(credential);
            },
          );
        },
        onLongPress: () async {
          if (calculateReady) {
            await calculateCode(
              context,
              ref,
            );
          }
          copyToClipboard(context, ref);
        },
        leading: CircleAvatar(
          foregroundColor: darkMode ? Colors.black : Colors.white,
          backgroundColor: _iconColor(darkMode ? 300 : 400),
          child: Text(
            (credential.issuer ?? credential.name)
                .characters
                .first
                .toUpperCase(),<commit_msg>Visual tweaks to OATH popup.<commit_after>import 'dart:async';

import 'package:flutter/material.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';

import '../../widgets/circle_timer.dart';
import '../../app/models.dart';
import '../models.dart';
import 'account_dialog.dart';
import 'account_mixin.dart';

class AccountView extends ConsumerWidget with AccountMixin {
  final YubiKeyData deviceData;
  @override
  final OathCredential credential;
  final FocusNode? focusNode;
  AccountView(this.deviceData, this.credential, {Key? key, this.focusNode})
      : super(key: key);

  Color _iconColor(int shade) {
    final colors = [
      Colors.red[shade],
      Colors.pink[shade],
      Colors.purple[shade],
      Colors.deepPurple[shade],
      Colors.indigo[shade],
      Colors.blue[shade],
      Colors.lightBlue[shade],
      Colors.cyan[shade],
      Colors.teal[shade],
      Colors.green[shade],
      Colors.lightGreen[shade],
      Colors.lime[shade],
      Colors.yellow[shade],
      Colors.amber[shade],
      Colors.orange[shade],
      Colors.deepOrange[shade],
      Colors.brown[shade],
      Colors.grey[shade],
      Colors.blueGrey[shade],
    ];
    return colors[label.hashCode % colors.length]!;
  }

  List<PopupMenuItem> _buildPopupMenu(BuildContext context, WidgetRef ref) {
    return buildActions(ref).map((e) {
      final action = e.action;
      return PopupMenuItem(
        child: ListTile(
          leading: e.icon,
          title: Text(e.text),
          dense: true,
          contentPadding: EdgeInsets.zero,
        ),
        enabled: action != null,
        onTap: () {
          // As soon as onTap returns, the Navigator is popped,
          // closing the topmost item. Since we sometimes open new dialogs in
          // the action, make sure that happens *after* the pop.
          Timer(Duration.zero, () {
            action?.call(context);
          });
        },
      );
    }).toList();
  }

  @override
  Widget build(BuildContext context, WidgetRef ref) {
    final code = getCode(ref);
    final expired = isExpired(ref);
    final calculateReady = code == null ||
        credential.oathType == OathType.hotp ||
        (credential.touchRequired && expired);

    final darkMode = Theme.of(context).brightness == Brightness.dark;

    return GestureDetector(
      onSecondaryTapDown: (details) {
        showMenu(
          context: context,
          position: RelativeRect.fromLTRB(
            details.globalPosition.dx,
            details.globalPosition.dy,
            details.globalPosition.dx,
            0,
          ),
          items: _buildPopupMenu(context, ref),
        );
      },
      child: ListTile(
        focusNode: focusNode,
        onTap: () {
          showDialog(
            context: context,
            builder: (context) {
              return AccountDialog(credential);
            },
          );
        },
        onLongPress: () async {
          if (calculateReady) {
            await calculateCode(
              context,
              ref,
            );
          }
          copyToClipboard(context, ref);
        },
        leading: CircleAvatar(
          foregroundColor: darkMode ? Colors.black : Colors.white,
          backgroundColor: _iconColor(darkMode ? 300 : 400),
          child: Text(
            (credential.issuer ?? credential.name)
                .characters
                .first
                .toUpperCase(),
{'fraction_non_alphanumeric': 0.11640696608615948, 'fraction_numerical': 0.00229147571035747, 'mean_word_length': 2.105787476280835, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 5, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '500089', 'n_tokens_mistral': 1993, 'n_tokens_neox': 1949, 'n_words': 376}