diff --git a/assets/l10n/app_en.arb b/assets/l10n/app_en.arb index 70417e356e..5de40b17fe 100644 --- a/assets/l10n/app_en.arb +++ b/assets/l10n/app_en.arb @@ -870,5 +870,9 @@ "zulipAppTitle": "Zulip", "@zulipAppTitle": { "description": "The name of Zulip. This should be either 'Zulip' or a transliteration." + }, + "composeBoxAttachGlobalTimeTooltip": "Attach a global time", + "@composeBoxAttachGlobalTimeTooltip": { + "description": "Tooltip for the button to attach a global time to the compose box." } } diff --git a/lib/generated/l10n/zulip_localizations.dart b/lib/generated/l10n/zulip_localizations.dart index 3203569966..82bcf5a26d 100644 --- a/lib/generated/l10n/zulip_localizations.dart +++ b/lib/generated/l10n/zulip_localizations.dart @@ -1274,6 +1274,12 @@ abstract class ZulipLocalizations { /// In en, this message translates to: /// **'Zulip'** String get zulipAppTitle; + + /// Tooltip for the button to attach a global time to the compose box. + /// + /// In en, this message translates to: + /// **'Attach a global time'** + String get composeBoxAttachGlobalTimeTooltip; } class _ZulipLocalizationsDelegate extends LocalizationsDelegate { diff --git a/lib/generated/l10n/zulip_localizations_ar.dart b/lib/generated/l10n/zulip_localizations_ar.dart index 20ad3cbe24..5109256221 100644 --- a/lib/generated/l10n/zulip_localizations_ar.dart +++ b/lib/generated/l10n/zulip_localizations_ar.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsAr extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_en.dart b/lib/generated/l10n/zulip_localizations_en.dart index a88981fc26..88099c0264 100644 --- a/lib/generated/l10n/zulip_localizations_en.dart +++ b/lib/generated/l10n/zulip_localizations_en.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsEn extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_ja.dart b/lib/generated/l10n/zulip_localizations_ja.dart index be6eee8870..b3fb84d01b 100644 --- a/lib/generated/l10n/zulip_localizations_ja.dart +++ b/lib/generated/l10n/zulip_localizations_ja.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsJa extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_nb.dart b/lib/generated/l10n/zulip_localizations_nb.dart index 8e51c7a19b..85429c36f7 100644 --- a/lib/generated/l10n/zulip_localizations_nb.dart +++ b/lib/generated/l10n/zulip_localizations_nb.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsNb extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_pl.dart b/lib/generated/l10n/zulip_localizations_pl.dart index 0e4009a462..e758fccd43 100644 --- a/lib/generated/l10n/zulip_localizations_pl.dart +++ b/lib/generated/l10n/zulip_localizations_pl.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsPl extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_ru.dart b/lib/generated/l10n/zulip_localizations_ru.dart index f3ec9d623c..a1d7833a6e 100644 --- a/lib/generated/l10n/zulip_localizations_ru.dart +++ b/lib/generated/l10n/zulip_localizations_ru.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsRu extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/generated/l10n/zulip_localizations_sk.dart b/lib/generated/l10n/zulip_localizations_sk.dart index 6d22409eb5..ab092a8edf 100644 --- a/lib/generated/l10n/zulip_localizations_sk.dart +++ b/lib/generated/l10n/zulip_localizations_sk.dart @@ -678,4 +678,7 @@ class ZulipLocalizationsSk extends ZulipLocalizations { @override String get zulipAppTitle => 'Zulip'; + + @override + String get composeBoxAttachGlobalTimeTooltip => 'Attach a global time'; } diff --git a/lib/widgets/compose_box.dart b/lib/widgets/compose_box.dart index 1665227d51..faa2007c2b 100644 --- a/lib/widgets/compose_box.dart +++ b/lib/widgets/compose_box.dart @@ -4,7 +4,7 @@ import 'package:app_settings/app_settings.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:mime/mime.dart'; - +import 'package:intl/intl.dart'; import '../api/exception.dart'; import '../api/model/model.dart'; import '../api/route/messages.dart'; @@ -1034,6 +1034,68 @@ class _AttachFromCameraButton extends _AttachUploadsButton { } } +class _AttachGlobalTimeButton extends _AttachUploadsButton { + const _AttachGlobalTimeButton({required super.controller}); + + @override + IconData get icon => ZulipIcons.clock; + + @override + String tooltip(ZulipLocalizations zulipLocalizations) => + zulipLocalizations.composeBoxAttachGlobalTimeTooltip; + + @override + Future> getFiles(BuildContext context) async { + // Ensure the context is still valid + if (!context.mounted) return []; + + // Request a date and time from the user. + final DateTime? pickedDate = await showDatePicker( + context: context, + initialDate: DateTime.now(), + firstDate: DateTime(2000), + lastDate: DateTime(2100), + ); + + // Recheck context after async operation + if (!context.mounted) return []; + + if (pickedDate == null) { + return []; // User canceled, no action needed. + } + + final TimeOfDay? pickedTime = await showTimePicker( + context: context, + initialTime: TimeOfDay.now(), + ); + + // Recheck context after async operation + if (!context.mounted) return []; + + if (pickedTime == null) { + return []; + } + + // Combine the picked date and time. + final DateTime fullDateTime = DateTime( + pickedDate.year, + pickedDate.month, + pickedDate.day, + pickedTime.hour, + pickedTime.minute, + ); + + // Format the date-time for the new markup. + final String timeMarkup = + ""; + + // Safely update the content controller + controller.content.text += timeMarkup; + + return []; + } +} + class _SendButton extends StatefulWidget { const _SendButton({required this.controller, required this.getDestination}); @@ -1270,6 +1332,7 @@ abstract class _ComposeBoxBody extends StatelessWidget { _AttachFileButton(controller: controller), _AttachMediaButton(controller: controller), _AttachFromCameraButton(controller: controller), + _AttachGlobalTimeButton(controller: controller), ]; final topicInput = buildTopicInput();