delta_text_view 1.0.0 copy "delta_text_view: ^1.0.0" to clipboard
delta_text_view: ^1.0.0 copied to clipboard

Пакет для отображения Delta формата (используется в Quill редакторе) в виде текста во Flutter

example/lib/main.dart

import 'dart:convert';

import 'package:dart_quill_delta/dart_quill_delta.dart';
import 'package:delta_text_view/delta_text_view.dart';
import 'package:delta_text_view_example/edt.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';

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

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

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Delta Text View Example',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.blue),
        useMaterial3: true,
      ),
      home: const ExamplePage(),
    );
  }
}

/// Модель упоминания пользователя. Демонстрирует реализацию [MentionDelta].
class UserMention implements MentionDelta {
  final String id;
  final String name;

  UserMention({required this.id, required this.name});

  @override
  String get displayData => name;

  @override
  Map<String, dynamic> toJson() => {'id': id, 'name': name};

  static UserMention? fromJson(Map<String, dynamic> json) {
    final id = json['id'] as String?;
    final name = json['name'] as String?;
    if (id == null || name == null) return null;
    return UserMention(id: id, name: name);
  }
}

/// Модель упоминания канала/группы. Другой тип [MentionDelta] — иные поля и стиль.
class ChannelMention implements MentionDelta {
  final String channelId;
  final String channelName;

  ChannelMention({required this.channelId, required this.channelName});

  @override
  String get displayData => channelName;

  @override
  Map<String, dynamic> toJson() => {'channelId': channelId, 'channelName': channelName};

  static ChannelMention? fromJson(Map<String, dynamic> json) {
    final channelId = json['channelId'] as String?;
    final channelName = json['channelName'] as String?;
    if (channelId == null || channelName == null) return null;
    return ChannelMention(channelId: channelId, channelName: channelName);
  }
}

/// Пробует распарсить как [UserMention], затем как [ChannelMention].
MentionDelta? _combinedFromJson(Map<String, dynamic> json) =>
    UserMention.fromJson(json) ?? ChannelMention.fromJson(json);

Widget _buildMentionWidget(MentionDelta mention) {
  if (mention is ChannelMention) {
    return Text(
      '#${mention.channelName}',
      style: const TextStyle(color: Colors.teal, fontWeight: FontWeight.w500),
    );
  }
  return Text(
    '@${mention.displayData}',
    style: const TextStyle(color: Colors.blue, fontWeight: FontWeight.w500),
  );
}

/// [MentionConfig] только для отображения (без tap-callback).
final _displayMentionConfig = MentionConfig(
  fromJson: _combinedFromJson,
  widgetBuilder: _buildMentionWidget,
);

/// [MentionConfig] с tap — показывает SnackBar. Требует [BuildContext].
MentionConfig _tapMentionConfig(BuildContext context) => MentionConfig(
      fromJson: _combinedFromJson,
      widgetBuilder: _buildMentionWidget,
      onTap: ({required MentionDelta mention, required TapDownDetails details}) {
        final String message = switch (mention) {
          UserMention m => 'Пользователь: ${m.name} (ID: ${m.id}) globalPosition: ${details.globalPosition}',
          ChannelMention m => 'Канал: #${m.channelName} (ID: ${m.channelId}) globalPosition: ${details.globalPosition}',
          _ => mention.displayData,
        };
        ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text(message)));
      },
    );

/// Секция примера: выделение текста + виджет, отображающий выделенный Delta.
class SelectionDemoSection extends StatefulWidget {
  const SelectionDemoSection({
    super.key,
    required this.title,
    required this.richTextDelta,
    required this.formattedDelta,
  });

  final String title;
  final Delta richTextDelta;
  final Delta formattedDelta;

  @override
  State<SelectionDemoSection> createState() => _SelectionDemoSectionState();
}

class _SelectionDemoSectionState extends State<SelectionDemoSection> {
  Delta? _selectedDelta;

  @override
  Widget build(BuildContext context) {
    final theme = Theme.of(context);
    final defaultStyle = TextStyle(
      fontSize: 16,
      color: theme.colorScheme.onSurface,
    );

    final mentionConfig = _tapMentionConfig(context);

    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        DecoratedBox(
          decoration: BoxDecoration(
            color: Colors.red,
            border: Border.all(
              color: theme.colorScheme.outline.withValues(alpha: 0.2),
            ),
            borderRadius: BorderRadius.circular(8),
          ),
          child: ExpandableDeltaText(
            key: ValueKey('SelectionDemoSection_MessageText_${widget.richTextDelta.length}'),
            maxLinesCollapsed: 10,
            defaultStyle: defaultStyle,
            mentionConfig: mentionConfig,
            selectionColor: theme.colorScheme.primary.withAlpha(100),
            delta: _createBasicDelta(),
          ),
        ),
        Text(
          widget.title,
          style: theme.textTheme.titleLarge?.copyWith(
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 4),
        Text(
          'Проведите курсором мыши по тексту, чтобы выделить его. '
          'Выделенный фрагмент отображается ниже и выводится в консоль (print).',
          style: theme.textTheme.bodySmall?.copyWith(
            color: theme.colorScheme.onSurfaceVariant,
          ),
        ),
        const SizedBox(height: 8),
        Text(
          'DeltaTextView (selectable: true):',
          style: theme.textTheme.titleSmall,
        ),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: theme.colorScheme.surface,
            border: Border.all(
              color: theme.colorScheme.outline.withValues(alpha: 0.2),
            ),
            borderRadius: BorderRadius.circular(8),
          ),
          child: DeltaTextView(emojiConfig: const EmojiConfig(),
            mentionConfig: mentionConfig,
            delta: widget.richTextDelta,
            defaultStyle: defaultStyle,
            selectable: true,
            onSelectionChangedAsDelta: (selectionDelta) {
              if (kDebugMode) {
                print('DeltaTextView selection: ${jsonEncode(selectionDelta?.toJson())}');
              }
              setState(() => _selectedDelta = selectionDelta);
            },
          ),
        ),
        const SizedBox(height: 16),
        Text(
          'Выделенный фрагмент (из callback):',
          style: theme.textTheme.titleSmall,
        ),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: theme.colorScheme.surfaceContainerHighest.withValues(alpha: 0.5),
            border: Border.all(
              color: theme.colorScheme.outline.withValues(alpha: 0.3),
            ),
            borderRadius: BorderRadius.circular(8),
          ),
          child: _selectedDelta == null
              ? Text(
                  'Выделите текст выше — здесь отобразится тот же контент как Delta.',
                  style: theme.textTheme.bodyMedium?.copyWith(
                    color: theme.colorScheme.onSurfaceVariant,
                    fontStyle: FontStyle.italic,
                  ),
                )
              : Column(
                  crossAxisAlignment: CrossAxisAlignment.start,
                  mainAxisSize: MainAxisSize.min,
                  children: [
                    Text('DeltaTextView:', style: theme.textTheme.labelSmall),
                    const SizedBox(height: 4),
                    DeltaTextView(emojiConfig: const EmojiConfig(),
                      mentionConfig: _displayMentionConfig,
                      delta: _selectedDelta!,
                      defaultStyle: defaultStyle,
                    ),
                  ],
                ),
        ),
      ],
    );
  }
}

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Delta Text View Examples'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: SingleChildScrollView(
        padding: const EdgeInsets.all(16.0),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            _buildSection(
              context,
              '1. Базовое использование DeltaTextView',
              _createBasicDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            SelectionDemoSection(
              title: '2. Выделение текста курсором мыши',
              richTextDelta: _createSelectionDemoDelta(),
              formattedDelta: _createBlockDelta(),
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '3. Inline форматирование (жирный, курсив, подчеркивание)',
              _createInlineFormattingDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '4. Цвета текста и фона',
              _createColorDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '5. Ссылки',
              _createLinkDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '6. Упоминания (нажмите на @имя)',
              _createMentionDelta(),
              withTap: true,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '7. Блоковые элементы (DeltaTextView — текстовые префиксы)',
              _createBlockDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '8. Нумерованный список',
              _createNumberedListDelta(),
              withTap: false,
            ),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '9. Комплексный пример',
              _createComplexDelta(),
              withTap: true,
            ),
            const SizedBox(height: 24),
            _buildSectionSelectionColor(
              context,
              '10. Кастомный цвет выделения',
              _createBasicDelta(),
            ),
            const SizedBox(height: 24),
            _buildSectionSelectableDisabled(
              context,
              '11. Выделение отключено (selectable: false)',
              _createBasicDelta(),
            ),
            const SizedBox(height: 24),
            _buildSectionOverflow(context),
            const SizedBox(height: 24),
            _buildSectionScrollPhysics(context),
            const SizedBox(height: 24),
            _buildSection(
              context,
              '16. Нумерованный список с list-start',
              _createListStartDelta(),
              withTap: false,
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildSection(
    BuildContext context,
    String title,
    Delta delta, {
    required bool withTap,
  }) {
    final mentionConfig = withTap ? _tapMentionConfig(context) : _displayMentionConfig;
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 8),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surface,
            border: Border.all(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2)),
            borderRadius: BorderRadius.circular(8),
          ),
          child: DeltaTextView(emojiConfig: const EmojiConfig(),
            mentionConfig: mentionConfig,
            delta: delta,
            selectable: true,
            onSelectionChangedAsDelta: (selectionDelta) {
              print(selectionDelta);
            },
            defaultStyle: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurface),
          ),
        ),
      ],
    );
  }

  Widget _buildSectionSelectionColor(BuildContext context, String title, Delta delta) {
    final selectionColor = Colors.amber.withValues(alpha: 0.4);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 8),
        Text('DeltaTextView с selectionColor:', style: Theme.of(context).textTheme.titleSmall),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surface,
            border: Border.all(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2)),
            borderRadius: BorderRadius.circular(8),
          ),
          child: DeltaTextView(emojiConfig: const EmojiConfig(),
            mentionConfig: _displayMentionConfig,
            delta: delta,
            defaultStyle: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurface),
            selectionColor: selectionColor,
          ),
        ),
      ],
    );
  }

  Widget _buildSectionSelectableDisabled(BuildContext context, String title, Delta delta) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 4),
        Text(
          'Текст нельзя выделить — попробуйте провести по нему.',
          style: Theme.of(context).textTheme.bodySmall?.copyWith(
                color: Theme.of(context).colorScheme.onSurfaceVariant,
              ),
        ),
        const SizedBox(height: 8),
        Text('DeltaTextView (selectable: false):', style: Theme.of(context).textTheme.titleSmall),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surface,
            border: Border.all(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2)),
            borderRadius: BorderRadius.circular(8),
          ),
          child: DeltaTextView(emojiConfig: const EmojiConfig(),
            mentionConfig: _displayMentionConfig,
            delta: delta,
            defaultStyle: TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurface),
            selectable: false,
          ),
        ),
      ],
    );
  }

  Widget _buildSectionOverflow(BuildContext context) {
    final defaultStyle = TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurface);
    final longDelta = Delta.fromJson([
      {
        'insert': 'Длинный текст в одну строку с ellipsis: Lorem ipsum dolor sit amet, consectetur adipiscing elit,'
            'sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.\n'
      },
    ]);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '14. Overflow (одна строка с ellipsis)',
          style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 4),
        Text(
          'Достаточно передать maxLines и overflow — selectable: false указывать не нужно.',
          style: Theme.of(context).textTheme.bodySmall?.copyWith(
                color: Theme.of(context).colorScheme.onSurfaceVariant,
              ),
        ),
        const SizedBox(height: 8),
        Text('DeltaTextView (maxLines: 1, overflow: ellipsis):', style: Theme.of(context).textTheme.titleSmall),
        const SizedBox(height: 4),
        Container(
          padding: const EdgeInsets.all(12),
          decoration: BoxDecoration(
            color: Theme.of(context).colorScheme.surface,
            border: Border.all(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2)),
            borderRadius: BorderRadius.circular(8),
          ),
          child: DeltaTextView(emojiConfig: const EmojiConfig(),
            mentionConfig: _displayMentionConfig,
            delta: longDelta,
            defaultStyle: defaultStyle,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
          ),
        ),
      ],
    );
  }

  Widget _buildSectionScrollPhysics(BuildContext context) {
    const scrollHeight = 180.0;
    final defaultStyle = TextStyle(fontSize: 16, color: Theme.of(context).colorScheme.onSurface);
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          '15. Скролл (scrollPhysics)',
          style: Theme.of(context).textTheme.titleLarge?.copyWith(fontWeight: FontWeight.bold),
        ),
        const SizedBox(height: 4),
        Text(
          'Контент в области фиксированной высоты с разной физикой скролла.',
          style: Theme.of(context).textTheme.bodySmall?.copyWith(
                color: Theme.of(context).colorScheme.onSurfaceVariant,
              ),
        ),
        const SizedBox(height: 8),
        Text('DeltaTextView:', style: Theme.of(context).textTheme.titleSmall),
        const SizedBox(height: 4),
        SizedBox(
          height: scrollHeight,
          child: Container(
            padding: const EdgeInsets.all(12),
            decoration: BoxDecoration(
              color: Theme.of(context).colorScheme.surface,
              border: Border.all(color: Theme.of(context).colorScheme.outline.withValues(alpha: 0.2)),
              borderRadius: BorderRadius.circular(8),
            ),
            child: DeltaTextView(emojiConfig: const EmojiConfig(),
              mentionConfig: _displayMentionConfig,
              delta: _createLongScrollableDelta(),
              defaultStyle: defaultStyle,
            ),
          ),
        ),
      ],
    );
  }
}

// ─── Delta factories ───────────────────────────────────────────────────────────

Delta _createBasicDelta() {
  return Delta.fromJson([
    {'insert': 'Это простой текст без форматирования.\n'},
    {'insert': '🫣😋🙃🙂😉😍😍😜😑\n'},
    {
      'insert': {'emoji': '😉\n'}
    },
  ]);
}

Delta _createSelectionDemoDelta() {
  return Delta.fromJson([
    {'insert': 'Выделите этот текст мышью — от начала до конца. '},
    {
      'insert': 'Форматированный фрагмент',
      'attributes': {'bold': true, 'italic': true}
    },
    {'insert': ' тоже можно выделять. 🔥🔥🔥🔥🔥 Пользователи: '},
    {
      'insert': {'mention': UserMention(id: 'u1', name: 'Анна').toJson()}
    },
    {'insert': ', '},
    {
      'insert': {'mention': UserMention(id: 'u2', name: 'Борис').toJson()}
    },
    {'insert': '. Каналы: '},
    {
      'insert': {'mention': ChannelMention(channelId: 'ch1', channelName: 'general').toJson()}
    },
    {'insert': ', '},
    {
      'insert': {'mention': ChannelMention(channelId: 'ch2', channelName: 'разработка').toJson()}
    },
    {'insert': ' — все упоминания входят в выделение и Delta.\n'},
    {'insert': '\n'},
    {'insert': '\n'},
    {'insert': '\n'},
    {
      "insert": "asd",
      "attributes": {"link": "https://gitlab.satel.org/rtuc-forks/frontend/delta_widget/-/tree/1.3.2?ref_type=heads"}
    },
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "qwe"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "rty"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "uio"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    }
  ]);
}

Delta _createInlineFormattingDelta() {
  return Delta.fromJson([
    {'insert': 'Обычный текст, '},
    {
      'insert': 'жирный текст',
      'attributes': {'bold': true}
    },
    {'insert': ', '},
    {
      'insert': 'курсив',
      'attributes': {'italic': true}
    },
    {'insert': ', '},
    {
      'insert': 'подчеркнутый',
      'attributes': {'underline': true}
    },
    {'insert': ', '},
    {
      'insert': 'зачеркнутый',
      'attributes': {'strike': true}
    },
    {'insert': '.\n'},
  ]);
}

Delta _createColorDelta() {
  return Delta.fromJson([
    {'insert': 'Текст с '},
    {
      'insert': 'красным цветом',
      'attributes': {'color': '#FF0000'}
    },
    {'insert': ' и '},
    {
      'insert': 'зеленым фоном',
      'attributes': {'background': '#00FF00'}
    },
    {'insert': '.\n'},
  ]);
}

Delta _createLinkDelta() {
  return Delta.fromJson([
    {'insert': 'Ссылка на '},
    {
      'insert': 'Google',
      'attributes': {'link': 'https://www.google.com'}
    },
    {'insert': ' и '},
    {
      'insert': 'GitHub',
      'attributes': {'link': 'https://github.com'}
    },
    {'insert': '.\n'},
  ]);
}

Delta _createMentionDelta() {
  return Delta.fromJson([
    {'insert': 'Привет, '},
    {
      'insert': {'mention': UserMention(id: 'user123', name: 'Иван Иванов').toJson()}
    },
    {'insert': ' и '},
    {
      'insert': {'mention': UserMention(id: 'user456', name: 'Елена').toJson()}
    },
    {'insert': '! Обсуждение в '},
    {
      'insert': {'mention': ChannelMention(channelId: 'ch10', channelName: 'general').toJson()}
    },
    {'insert': ' и '},
    {
      'insert': {'mention': ChannelMention(channelId: 'ch11', channelName: 'random').toJson()}
    },
    {'insert': '.\n'},
  ]);
}

Delta _createLongScrollableDelta() {
  final lines = <Map<String, dynamic>>[];
  for (var i = 1; i <= 15; i++) {
    lines.add({'insert': 'Строка $i. Прокрутите контент вверх и вниз.\n'});
  }
  return Delta.fromJson(lines);
}

Delta _createBlockDelta() {
  return Delta.fromJson([
    {
      'insert': 'Заголовок 1',
      'attributes': {'header': 1}
    },
    {'insert': '\nОбычный параграф.\n'},
    {
      'insert': 'Заголовок 2',
      'attributes': {'header': 2}
    },
    {
      'insert': '\nЭлемент списка 1',
      'attributes': {'list': 'bullet'}
    },
    {
      'insert': '\nЭлемент списка 2',
      'attributes': {'list': 'bullet'}
    },
    {
      'insert': '\nЦитата',
      'attributes': {'blockquote': true}
    },
    {
      'insert': '\nБлок кода',
      'attributes': {'code-block': true}
    },
    {'insert': '\n'},
  ]);
}

Delta _createNumberedListDelta() {
  return Delta.fromJson([
    {
      "insert": "asd",
      "attributes": {"link": "https://gitlab.satel.org/rtuc-forks/frontend/delta_widget/-/tree/1.3.2?ref_type=heads"}
    },
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "qwe"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "rty"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    },
    {"insert": "uio"},
    {
      "insert": "\n",
      "attributes": {"list": "ordered"}
    }
  ]);
}

Delta _createComplexDelta() {
  return Delta.fromJson([
    {
      'insert': 'Комплексный пример',
      'attributes': {'header': 1}
    },
    {'insert': '\nЭтот текст содержит '},
    {
      'insert': 'жирный',
      'attributes': {'bold': true}
    },
    {'insert': ' и '},
    {
      'insert': 'курсивный',
      'attributes': {'italic': true}
    },
    {'insert': ' текст.\n'},
    {
      'insert': 'Список покупок:',
      'attributes': {'header': 2}
    },
    {
      'insert': '\nМолоко',
      'attributes': {'list': 'bullet'}
    },
    {
      'insert': '\nХлеб',
      'attributes': {'list': 'bullet'}
    },
    {
      'insert': '\nЯйца',
      'attributes': {'list': 'bullet'}
    },
    {
      'insert': '\nВажная цитата:',
      'attributes': {'header': 2}
    },
    {
      'insert': '\n"Код пишется один раз, а читается тысячи раз."',
      'attributes': {'blockquote': true}
    },
    {
      'insert': '\nПример кода:',
      'attributes': {'header': 2}
    },
    {
      'insert': '\nvoid main() {\n  print("Hello, World!");\n}',
      'attributes': {'code-block': true}
    },
    {'insert': '\nСвяжитесь с '},
    {
      'insert': {'mention': UserMention(id: 'user456', name: 'Петр Петров').toJson()}
    },
    {'insert': ' для вопросов.\n'},
    {
      'insert': 'Посетите наш сайт',
      'attributes': {'link': 'https://example.com', 'bold': true}
    },
    {'insert': '.\n'},
  ]);
}

Delta _createListStartDelta() {
  return Delta.fromJson([
    {
      "insert": "обычный текст\n",
      "attributes": {"list": "ordered", "list-real-index": 1}
    },
    {
      "insert": "жирный",
      "attributes": {"bold": true}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 2}
    },
    {
      "insert": "курсив",
      "attributes": {"italic": true}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 3}
    },
    {
      "insert": "подчеркнутый",
      "attributes": {"underline": true}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 4}
    },
    {
      "insert": "красный",
      "attributes": {"color": "#ff0000"}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 5}
    },
    {
      "insert": "зачеркнутый",
      "attributes": {"strike": true}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 6}
    },
    {
      "insert": "жирный ",
      "attributes": {"bold": true}
    },
    {
      "insert": "и красный",
      "attributes": {"bold": true, "color": "#ff0000"}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 7}
    },
    {
      "insert": "код",
      "attributes": {"code": true}
    },
    {
      "insert": " текст\n",
      "attributes": {"list": "ordered", "list-real-index": 8}
    }
  ]);
}
1
likes
130
points
38
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

Пакет для отображения Delta формата (используется в Quill редакторе) в виде текста во Flutter

Repository (GitHub)
View/report issues

License

MIT (license)

Dependencies

dart_quill_delta, flutter, url_launcher

More

Packages that depend on delta_text_view