Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions assets/l10n/app_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -1153,6 +1153,35 @@
"@updateStatusErrorTitle": {
"description": "Error title when updating user status failed."
},
"statusExpirationLabel": "Automatically clear status",
"@statusExpirationLabel": {
"description": "Label for the dropdown to select when status should be automatically cleared."
},
"statusExpirationNever": "Never",
"@statusExpirationNever": {
"description": "Option to never automatically clear the status."
},
"statusExpirationIn30Minutes": "In 30 minutes",
"@statusExpirationIn30Minutes": {
"description": "Option to clear status in 30 minutes."
},
"statusExpirationIn1Hour": "In 1 hour",
"@statusExpirationIn1Hour": {
"description": "Option to clear status in 1 hour."
},
"statusExpirationTodayAtTime": "Today at {time}",
"@statusExpirationTodayAtTime": {
"description": "Option to clear status today at a specific time.",
"placeholders": { "time": {"type": "String"} }
},
"statusExpirationTomorrow": "Tomorrow",
"@statusExpirationTomorrow": {
"description": "Option to clear status tomorrow."
},
"statusExpirationCustom": "Custom",
"@statusExpirationCustom": {
"description": "Option to set a custom time to clear the status."
},
"searchMessagesPageTitle": "Search",
"@searchMessagesPageTitle": {
"description": "Page title for the 'Search' message view."
Expand Down
41 changes: 37 additions & 4 deletions lib/api/model/model.dart
Original file line number Diff line number Diff line change
Expand Up @@ -270,19 +270,42 @@ class UserStatusChange {
final Option<String?> text;
final Option<StatusEmoji?> emoji;

const UserStatusChange({required this.text, required this.emoji});
/// The scheduled end time for the status (Unix timestamp in seconds).
///
/// If [OptionSome] with a non-null value, the status will be automatically
/// cleared at that time. If [OptionSome] with null, any existing scheduled
/// end time will be cleared. If [OptionNone], no change to the scheduled
/// end time.
final Option<int?> scheduledEndTime;

const UserStatusChange({
required this.text,
required this.emoji,
this.scheduledEndTime = const OptionNone(),
});

UserStatus apply(UserStatus old) {
return UserStatus(text: text.or(old.text), emoji: emoji.or(old.emoji));
}

UserStatusChange copyWith({Option<String?>? text, Option<StatusEmoji?>? emoji}) {
return UserStatusChange(text: text ?? this.text, emoji: emoji ?? this.emoji);
UserStatusChange copyWith({
Option<String?>? text,
Option<StatusEmoji?>? emoji,
Option<int?>? scheduledEndTime,
}) {
return UserStatusChange(
text: text ?? this.text,
emoji: emoji ?? this.emoji,
scheduledEndTime: scheduledEndTime ?? this.scheduledEndTime,
);
}

factory UserStatusChange.fromJson(Map<String, dynamic> json) {
return UserStatusChange(
text: _textFromJson(json), emoji: _emojiFromJson(json));
text: _textFromJson(json),
emoji: _emojiFromJson(json),
scheduledEndTime: _scheduledEndTimeFromJson(json),
);
}

static Option<String?> _textFromJson(Map<String, dynamic> json) {
Expand Down Expand Up @@ -313,6 +336,14 @@ class UserStatusChange {
}
}

static Option<int?> _scheduledEndTimeFromJson(Map<String, dynamic> json) {
if (!json.containsKey('scheduled_end_time')) {
return OptionNone();
}
final value = json['scheduled_end_time'] as int?;
return OptionSome(value);
}

Map<String, dynamic> toJson() {
return {
if (text case OptionSome<String?>(:var value))
Expand All @@ -325,6 +356,8 @@ class UserStatusChange {
'emoji_code': value.emojiCode,
'reaction_type': value.reactionType,
},
if (scheduledEndTime case OptionSome<int?>(:var value))
'scheduled_end_time': value,
};
}
}
Expand Down
5 changes: 4 additions & 1 deletion lib/api/route/users.dart
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,13 @@ Future<void> updateStatus(ApiConnection connection, {
'emoji_name': RawParameter(value?.emojiName ?? ''),
'emoji_code': RawParameter(value?.emojiCode ?? ''),
'reaction_type': RawParameter(value?.reactionType.toJson() ?? ''),
}
},
if (change.scheduledEndTime case OptionSome(:var value))
'scheduled_end_time': value,
});
}


/// https://zulip.com/api/update-presence
///
/// Passes true for `slim_presence` to avoid getting an ancient data format
Expand Down
42 changes: 42 additions & 0 deletions lib/generated/l10n/zulip_localizations.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1691,6 +1691,48 @@ abstract class ZulipLocalizations {
/// **'Error updating user status. Please try again.'**
String get updateStatusErrorTitle;

/// Label for the dropdown to select when status should be automatically cleared.
///
/// In en, this message translates to:
/// **'Automatically clear status'**
String get statusExpirationLabel;

/// Option to never automatically clear the status.
///
/// In en, this message translates to:
/// **'Never'**
String get statusExpirationNever;

/// Option to clear status in 30 minutes.
///
/// In en, this message translates to:
/// **'In 30 minutes'**
String get statusExpirationIn30Minutes;

/// Option to clear status in 1 hour.
///
/// In en, this message translates to:
/// **'In 1 hour'**
String get statusExpirationIn1Hour;

/// Option to clear status today at a specific time.
///
/// In en, this message translates to:
/// **'Today at {time}'**
String statusExpirationTodayAtTime(String time);

/// Option to clear status tomorrow.
///
/// In en, this message translates to:
/// **'Tomorrow'**
String get statusExpirationTomorrow;

/// Option to set a custom time to clear the status.
///
/// In en, this message translates to:
/// **'Custom'**
String get statusExpirationCustom;

/// Page title for the 'Search' message view.
///
/// In en, this message translates to:
Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_ar.dart
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,29 @@ class ZulipLocalizationsAr extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Error updating user status. Please try again.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Search';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_de.dart
Original file line number Diff line number Diff line change
Expand Up @@ -995,6 +995,29 @@ class ZulipLocalizationsDe extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Fehler beim Update des Benutzerstatus. Bitte versuche es nochmal.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Suche';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_el.dart
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,29 @@ class ZulipLocalizationsEl extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Error updating user status. Please try again.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Search';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_en.dart
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,29 @@ class ZulipLocalizationsEn extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Error updating user status. Please try again.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Search';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_es.dart
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,29 @@ class ZulipLocalizationsEs extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Error updating user status. Please try again.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Search';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_fr.dart
Original file line number Diff line number Diff line change
Expand Up @@ -986,6 +986,29 @@ class ZulipLocalizationsFr extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Erreur lors de la mise à jour du statut de l\'utilisateur. Merci de réessayer.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Recherche';

Expand Down
23 changes: 23 additions & 0 deletions lib/generated/l10n/zulip_localizations_he.dart
Original file line number Diff line number Diff line change
Expand Up @@ -970,6 +970,29 @@ class ZulipLocalizationsHe extends ZulipLocalizations {
String get updateStatusErrorTitle =>
'Error updating user status. Please try again.';

@override
String get statusExpirationLabel => 'Automatically clear status';

@override
String get statusExpirationNever => 'Never';

@override
String get statusExpirationIn30Minutes => 'In 30 minutes';

@override
String get statusExpirationIn1Hour => 'In 1 hour';

@override
String statusExpirationTodayAtTime(String time) {
return 'Today at $time';
}

@override
String get statusExpirationTomorrow => 'Tomorrow';

@override
String get statusExpirationCustom => 'Custom';

@override
String get searchMessagesPageTitle => 'Search';

Expand Down
Loading