settings: Add personal setting to show or hide AI features.

Fixes #33231.
This commit is contained in:
Sahil Batra
2025-02-11 18:49:41 +05:30
committed by Tim Abbott
parent 4ca28bb850
commit 7eeb8a2c26
16 changed files with 102 additions and 23 deletions

View File

@@ -28,6 +28,9 @@ format used by the Zulip server that they are interacting with.
`PATCH /realm`: Added `can_summarize_topics_group` realm setting which is
a [group-setting value](/api/group-setting-values) describing the set of
users with permission to use AI summarization.
* [`PATCH /realm/user_settings_defaults`](/api/update-realm-user-settings-defaults),
[`POST /register`](/api/register-queue), [`PATCH /settings`](/api/update-settings):
Added new `hide_ai_features` option for hiding all AI features in the UI.
**Feature level 349**

View File

@@ -34,7 +34,7 @@ DESKTOP_WARNING_VERSION = "5.9.3"
# new level means in api_docs/changelog.md, as well as "**Changes**"
# entries in the endpoint's documentation in `zulip.yaml`.
API_FEATURE_LEVEL = 349 # Last bumped for taking into account stream metadata access permissions.
API_FEATURE_LEVEL = 350 # Last bumped for AI settings.
# Bump the minor PROVISION_VERSION to indicate that folks should provision
# only when going from an old version of the code to a newer version. Bump

View File

@@ -217,7 +217,6 @@ export function build_page(): void {
color_scheme_values: settings_config.color_scheme_values,
web_home_view_values: settings_config.web_home_view_values,
settings_object: realm_user_settings_defaults,
information_section_checkbox_group: settings_config.information_section_checkbox_group,
information_density_settings: settings_config.get_information_density_preferences(),
settings_render_only: settings_config.get_settings_render_only(),
settings_label: settings_config.realm_user_settings_defaults_labels,

View File

@@ -67,6 +67,7 @@ type TopicPopoverContext = {
visibility_policy: number | false;
all_visibility_policies: AllVisibilityPolicies;
can_summarize_topics: boolean;
show_ai_features: boolean;
};
type VisibilityChangePopoverContext = {
@@ -276,6 +277,7 @@ export function get_topic_popover_content_context({
all_visibility_policies,
can_summarize_topics:
realm.server_can_summarize_topics && settings_data.user_can_summarize_topics(),
show_ai_features: !user_settings.hide_ai_features,
};
}

View File

@@ -38,6 +38,7 @@ export const realm_default_settings_schema = z.object({
enable_stream_push_notifications: z.boolean(),
enter_sends: z.boolean(),
fluid_layout_width: z.boolean(),
hide_ai_features: z.boolean(),
high_contrast_mode: z.boolean(),
left_side_userlist: z.boolean(),
message_content_in_email_notifications: z.boolean(),

View File

@@ -817,6 +817,7 @@ export function dispatch_normal_event(event) {
"web_navigate_to_sent_message",
"enter_sends",
"web_suggest_update_timezone",
"hide_ai_features",
];
const original_home_view = user_settings.web_home_view;

View File

@@ -121,7 +121,6 @@ export function build_page(): void {
desktop_icon_count_display_values: settings_config.desktop_icon_count_display_values,
disabled_notification_settings:
settings_config.all_notifications(user_settings).disabled_notification_settings,
information_section_checkbox_group: settings_config.information_section_checkbox_group,
information_density_settings: settings_config.get_information_density_preferences(),
settings_render_only: settings_config.get_settings_render_only(),
user_can_change_name: settings_data.user_can_change_name(),

View File

@@ -187,17 +187,6 @@ export type DisplaySettings = {
render_group?: boolean;
};
/* istanbul ignore next */
export const information_section_checkbox_group: DisplaySettings = {
settings: {
user_preferences: [
"starred_message_counts",
"receives_typing_notifications",
"fluid_layout_width",
],
},
};
/* istanbul ignore next */
export const get_information_density_preferences = (): DisplaySettings => ({
render_group: page_params.development_environment,
@@ -208,6 +197,7 @@ export const get_information_density_preferences = (): DisplaySettings => ({
type SettingsRenderOnly = {
dense_mode: boolean;
hide_ai_features: boolean;
high_contrast_mode: boolean;
web_font_size_px: boolean;
web_line_height_percent: boolean;
@@ -216,6 +206,9 @@ type SettingsRenderOnly = {
/* istanbul ignore next */
export const get_settings_render_only = (): SettingsRenderOnly => ({
dense_mode: page_params.development_environment,
// Offer the UI for hiding AI features exactly when the server
// supports doing so.
hide_ai_features: realm.server_can_summarize_topics,
high_contrast_mode: page_params.development_environment,
web_font_size_px: page_params.development_environment,
web_line_height_percent: page_params.development_environment,
@@ -576,6 +569,7 @@ export const preferences_settings_labels = {
}),
),
fluid_layout_width: $t({defaultMessage: "Use full width on wide screens"}),
hide_ai_features: $t({defaultMessage: "Hide AI features"}),
high_contrast_mode: $t({defaultMessage: "High contrast mode"}),
enter_sends: new Handlebars.SafeString(
$t_html({defaultMessage: "<kbd>Enter</kbd> sends when composing a message"}),

View File

@@ -56,6 +56,7 @@ export const user_settings_schema = stream_notification_settings_schema
enable_online_push_notifications: z.boolean(),
enter_sends: z.boolean(),
fluid_layout_width: z.boolean(),
hide_ai_features: z.boolean(),
high_contrast_mode: z.boolean(),
left_side_userlist: z.boolean(),
message_content_in_email_notifications: z.boolean(),

View File

@@ -38,7 +38,7 @@
{{else}}
{{!-- Group 2 --}}
<li role="separator" class="popover-menu-separator"></li>
{{#if can_summarize_topics}}
{{#if (and show_ai_features can_summarize_topics)}}
<li role="none" class="link-item popover-menu-list-item">
<a role="menuitem" class="sidebar-popover-summarize-topic popover-menu-link" tabindex="0">
<i class="popover-menu-icon fa fa-magic" aria-hidden="true"></i>

View File

@@ -63,14 +63,33 @@
</select>
</div>
{{#each information_section_checkbox_group.settings.user_preferences}}
{{> settings_checkbox
setting_name=this
is_checked=(lookup ../settings_object this)
label=(lookup ../settings_label this)
render_only=(lookup ../settings_render_only.render_only this)
prefix=../prefix}}
{{/each}}
{{> settings_checkbox
setting_name="starred_message_counts"
is_checked=settings_object.starred_message_counts
label=settings_label.starred_message_counts
render_only=settings_render_only.starred_message_counts
prefix=prefix}}
{{> settings_checkbox
setting_name="receives_typing_notifications"
is_checked=settings_object.receives_typing_notifications
label=settings_label.receives_typing_notifications
render_only=settings_render_only.receives_typing_notifications
prefix=prefix}}
{{> settings_checkbox
setting_name="hide_ai_features"
is_checked=settings_object.hide_ai_features
label=settings_label.hide_ai_features
render_only=settings_render_only.hide_ai_features
prefix=prefix}}
{{> settings_checkbox
setting_name="fluid_layout_width"
is_checked=settings_object.fluid_layout_width
label=settings_label.fluid_layout_width
render_only=settings_render_only.fluid_layout_width
prefix=prefix}}
<div class="input-group">
<label for="{{prefix}}demote_inactive_streams" class="settings-field-label">{{t "Demote inactive channels" }}

View File

@@ -0,0 +1,22 @@
# Generated by Django 5.0.10 on 2025-02-11 10:11
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("zerver", "0666_alter_realm_can_summarize_topics_group"),
]
operations = [
migrations.AddField(
model_name="realmuserdefault",
name="hide_ai_features",
field=models.BooleanField(default=False),
),
migrations.AddField(
model_name="userprofile",
name="hide_ai_features",
field=models.BooleanField(default=False),
),
]

View File

@@ -296,6 +296,9 @@ class UserBaseSettings(models.Model):
EMAIL_ADDRESS_VISIBILITY_TYPES = list(EMAIL_ADDRESS_VISIBILITY_ID_TO_NAME_MAP.keys())
# Whether user wants to see AI features in the UI.
hide_ai_features = models.BooleanField(default=False)
display_settings_legacy = dict(
# Don't add anything new to this legacy dict.
# Instead, see `modern_settings` below.
@@ -359,6 +362,7 @@ class UserBaseSettings(models.Model):
web_line_height_percent=int,
web_navigate_to_sent_message=bool,
web_suggest_update_timezone=bool,
hide_ai_features=bool,
)
modern_notification_settings = dict(

View File

@@ -12288,6 +12288,13 @@ paths:
- 2
- 3
example: 2
hide_ai_features:
type: boolean
description: |
Controls whether user wants AI features like topic summarization to
be hidden in all Zulip clients.
**Changes**: New in Zulip 10.0 (feature level 350).
enable_stream_desktop_notifications:
description: |
Enable visual desktop notifications for channel messages.
@@ -12599,6 +12606,8 @@ paths:
contentType: application/json
web_stream_unreads_count_display_policy:
contentType: application/json
hide_ai_features:
contentType: application/json
enable_stream_desktop_notifications:
contentType: application/json
enable_stream_email_notifications:
@@ -15639,6 +15648,13 @@ paths:
- 3 - No channels
**Changes**: New in Zulip 8.0 (feature level 210).
hide_ai_features:
type: boolean
description: |
Controls whether user wants AI features like topic summarization to
be hidden in all Zulip clients.
**Changes**: New in Zulip 10.0 (feature level 350).
timezone:
type: string
description: |
@@ -18272,6 +18288,13 @@ paths:
- 3 - No channels
**Changes**: New in Zulip 8.0 (feature level 210).
hide_ai_features:
type: boolean
description: |
Controls whether user wants AI features like topic summarization to
be hidden in all Zulip clients.
**Changes**: New in Zulip 10.0 (feature level 350).
enable_stream_desktop_notifications:
type: boolean
description: |
@@ -19513,6 +19536,13 @@ paths:
- 2
- 3
example: 2
hide_ai_features:
type: boolean
description: |
Controls whether user wants AI features like topic summarization to
be hidden in all Zulip clients.
**Changes**: New in Zulip 10.0 (feature level 350).
timezone:
description: |
The IANA identifier of the user's [configured time zone](/help/change-your-timezone).
@@ -19910,6 +19940,8 @@ paths:
contentType: application/json
web_stream_unreads_count_display_policy:
contentType: application/json
hide_ai_features:
contentType: application/json
enable_stream_desktop_notifications:
contentType: application/json
enable_stream_email_notifications:

View File

@@ -674,6 +674,7 @@ def update_realm_user_settings_defaults(
| None = None,
web_navigate_to_sent_message: Json[bool] | None = None,
web_suggest_update_timezone: Json[bool] | None = None,
hide_ai_features: Json[bool] | None = None,
) -> HttpResponse:
if notification_sound is not None or email_notifications_batching_period_seconds is not None:
check_settings_values(notification_sound, email_notifications_batching_period_seconds)

View File

@@ -329,6 +329,7 @@ def json_change_settings(
| None = None,
web_navigate_to_sent_message: Json[bool] | None = None,
web_suggest_update_timezone: Json[bool] | None = None,
hide_ai_features: Json[bool] | None = None,
) -> HttpResponse:
# UserProfile object is being refetched here to make sure that we
# do not use stale object from cache which can happen when a