123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187 |
- import 'package:appflowy/date/date_service.dart';
- import 'package:appflowy/generated/locale_keys.g.dart';
- import 'package:appflowy/plugins/document/presentation/editor_plugins/base/string_extension.dart';
- import 'package:appflowy/plugins/document/presentation/editor_plugins/mention/mention_block.dart';
- import 'package:appflowy/plugins/inline_actions/inline_actions_result.dart';
- import 'package:appflowy_editor/appflowy_editor.dart';
- import 'package:easy_localization/easy_localization.dart';
- import 'package:flutter/material.dart';
- final _keywords = [
- LocaleKeys.inlineActions_date.tr().toLowerCase(),
- ];
- class DateReferenceService {
- DateReferenceService(this.context) {
- // Initialize locale
- _locale = context.locale.toLanguageTag();
- // Initializes options
- _setOptions();
- }
- final BuildContext context;
- late String _locale;
- late List<InlineActionsMenuItem> _allOptions;
- List<InlineActionsMenuItem> options = [];
- Future<InlineActionsResult> dateReferenceDelegate([
- String? search,
- ]) async {
- // Checks if Locale has changed since last
- _setLocale();
- // Filters static options
- _filterOptions(search);
- // Searches for date by pattern
- _searchDate(search);
- // Searches for date by natural language prompt
- await _searchDateNLP(search);
- return InlineActionsResult(
- title: LocaleKeys.inlineActions_date.tr(),
- results: options,
- );
- }
- void _filterOptions(String? search) {
- if (search == null || search.isEmpty) {
- options = _allOptions;
- return;
- }
- options = _allOptions
- .where(
- (option) =>
- option.keywords != null &&
- option.keywords!.isNotEmpty &&
- option.keywords!.any(
- (keyword) => keyword.contains(search.toLowerCase()),
- ),
- )
- .toList();
- if (options.isEmpty && _keywords.any((k) => search.startsWith(k))) {
- options = _allOptions;
- }
- }
- void _searchDate(String? search) {
- if (search == null || search.isEmpty) {
- return;
- }
- try {
- final date = DateFormat.yMd(_locale).parse(search);
- options.insert(0, _itemFromDate(date));
- } catch (_) {
- return;
- }
- }
- Future<void> _searchDateNLP(String? search) async {
- if (search == null || search.isEmpty) {
- return;
- }
- final result = await DateService.queryDate(search);
- result.fold(
- (l) {},
- (date) => options.insert(0, _itemFromDate(date)),
- );
- }
- Future<void> _insertDateReference(
- EditorState editorState,
- DateTime date,
- int start,
- int end,
- ) async {
- final selection = editorState.selection;
- if (selection == null || !selection.isCollapsed) {
- return;
- }
- final node = editorState.getNodeAtPath(selection.end.path);
- final delta = node?.delta;
- if (node == null || delta == null) {
- return;
- }
- final transaction = editorState.transaction
- ..replaceText(
- node,
- start,
- end,
- '\$',
- attributes: {
- MentionBlockKeys.mention: {
- MentionBlockKeys.type: MentionType.date.name,
- MentionBlockKeys.date: date.toIso8601String(),
- }
- },
- );
- await editorState.apply(transaction);
- }
- void _setOptions() {
- final today = DateTime.now();
- final tomorrow = today.add(const Duration(days: 1));
- final yesterday = today.subtract(const Duration(days: 1));
- _allOptions = [
- _itemFromDate(
- today,
- LocaleKeys.relativeDates_today.tr(),
- [DateFormat.yMd(_locale).format(today)],
- ),
- _itemFromDate(
- tomorrow,
- LocaleKeys.relativeDates_tomorrow.tr(),
- [DateFormat.yMd(_locale).format(tomorrow)],
- ),
- _itemFromDate(
- yesterday,
- LocaleKeys.relativeDates_yesterday.tr(),
- [DateFormat.yMd(_locale).format(yesterday)],
- ),
- ];
- }
- /// Sets Locale on each search to make sure
- /// keywords are localized
- void _setLocale() {
- final locale = context.locale.toLanguageTag();
- if (locale != _locale) {
- _locale = locale;
- _setOptions();
- }
- }
- InlineActionsMenuItem _itemFromDate(
- DateTime date, [
- String? label,
- List<String>? keywords,
- ]) {
- final labelStr = label ?? DateFormat.yMd(_locale).format(date);
- return InlineActionsMenuItem(
- label: labelStr.capitalize(),
- keywords: [labelStr.toLowerCase(), ...?keywords],
- onSelected: (context, editorState, menuService, replace) =>
- _insertDateReference(
- editorState,
- date,
- replace.$1,
- replace.$2,
- ),
- );
- }
- }
|