mirror of
				https://github.com/zulip/zulip.git
				synced 2025-10-31 12:03:46 +00:00 
			
		
		
		
	With a comment added by tabbott on live-update considerations. See https://chat.zulip.org/#narrow/stream/9-issues/topic/FormatJS.20error.20in.20standalone.20pages/near/1168413 for context. Signed-off-by: Anders Kaseorg <anders@zulip.com>
		
			
				
	
	
		
			726 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
			
		
		
	
	
			726 lines
		
	
	
		
			31 KiB
		
	
	
	
		
			JavaScript
		
	
	
	
	
	
| import $ from "jquery";
 | |
| 
 | |
| import * as emoji from "../shared/js/emoji";
 | |
| 
 | |
| import * as activity from "./activity";
 | |
| import * as alert_words from "./alert_words";
 | |
| import * as alert_words_ui from "./alert_words_ui";
 | |
| import * as attachments_ui from "./attachments_ui";
 | |
| import * as blueslip from "./blueslip";
 | |
| import * as bot_data from "./bot_data";
 | |
| import * as compose from "./compose";
 | |
| import * as compose_fade from "./compose_fade";
 | |
| import * as composebox_typeahead from "./composebox_typeahead";
 | |
| import * as emoji_picker from "./emoji_picker";
 | |
| import * as hotspots from "./hotspots";
 | |
| import * as markdown from "./markdown";
 | |
| import * as message_edit from "./message_edit";
 | |
| import * as message_events from "./message_events";
 | |
| import * as message_flags from "./message_flags";
 | |
| import * as message_list from "./message_list";
 | |
| import * as message_lists from "./message_lists";
 | |
| import * as muting_ui from "./muting_ui";
 | |
| import * as narrow_state from "./narrow_state";
 | |
| import * as night_mode from "./night_mode";
 | |
| import * as notifications from "./notifications";
 | |
| import * as overlays from "./overlays";
 | |
| import {page_params} from "./page_params";
 | |
| import * as panels from "./panels";
 | |
| import * as peer_data from "./peer_data";
 | |
| import * as people from "./people";
 | |
| import * as reactions from "./reactions";
 | |
| import * as realm_icon from "./realm_icon";
 | |
| import * as realm_logo from "./realm_logo";
 | |
| import * as realm_playground from "./realm_playground";
 | |
| import * as reload from "./reload";
 | |
| import * as scroll_bar from "./scroll_bar";
 | |
| import * as settings_account from "./settings_account";
 | |
| import * as settings_bots from "./settings_bots";
 | |
| import * as settings_config from "./settings_config";
 | |
| import * as settings_display from "./settings_display";
 | |
| import * as settings_emoji from "./settings_emoji";
 | |
| import * as settings_exports from "./settings_exports";
 | |
| import * as settings_invites from "./settings_invites";
 | |
| import * as settings_linkifiers from "./settings_linkifiers";
 | |
| import * as settings_notifications from "./settings_notifications";
 | |
| import * as settings_org from "./settings_org";
 | |
| import * as settings_playgrounds from "./settings_playgrounds";
 | |
| import * as settings_profile_fields from "./settings_profile_fields";
 | |
| import * as settings_streams from "./settings_streams";
 | |
| import * as settings_user_groups from "./settings_user_groups";
 | |
| import * as settings_users from "./settings_users";
 | |
| import * as starred_messages from "./starred_messages";
 | |
| import * as stream_data from "./stream_data";
 | |
| import * as stream_events from "./stream_events";
 | |
| import * as stream_list from "./stream_list";
 | |
| import * as stream_topic_history from "./stream_topic_history";
 | |
| import * as sub_store from "./sub_store";
 | |
| import * as submessage from "./submessage";
 | |
| import * as subs from "./subs";
 | |
| import * as typing_events from "./typing_events";
 | |
| import * as unread_ops from "./unread_ops";
 | |
| import * as user_events from "./user_events";
 | |
| import * as user_groups from "./user_groups";
 | |
| import * as user_status from "./user_status";
 | |
| 
 | |
| export function dispatch_normal_event(event) {
 | |
|     const noop = function () {};
 | |
|     switch (event.type) {
 | |
|         case "alert_words":
 | |
|             alert_words.set_words(event.alert_words);
 | |
|             alert_words_ui.render_alert_words_ui();
 | |
|             break;
 | |
| 
 | |
|         case "attachment":
 | |
|             attachments_ui.update_attachments(event);
 | |
|             break;
 | |
| 
 | |
|         case "custom_profile_fields":
 | |
|             page_params.custom_profile_fields = event.fields;
 | |
|             settings_profile_fields.populate_profile_fields(page_params.custom_profile_fields);
 | |
|             settings_account.add_custom_profile_fields_to_settings();
 | |
|             break;
 | |
| 
 | |
|         case "default_streams":
 | |
|             stream_data.set_realm_default_streams(event.default_streams);
 | |
|             settings_streams.update_default_streams_table();
 | |
|             break;
 | |
| 
 | |
|         case "delete_message": {
 | |
|             const msg_ids = event.message_ids;
 | |
|             // message is passed to unread.get_unread_messages,
 | |
|             // which returns all the unread messages out of a given list.
 | |
|             // So double marking something as read would not occur
 | |
|             unread_ops.process_read_messages_event(msg_ids);
 | |
|             // This methods updates message_list too and since stream_topic_history relies on it
 | |
|             // this method should be called first.
 | |
|             message_events.remove_messages(msg_ids);
 | |
| 
 | |
|             if (event.message_type === "stream") {
 | |
|                 stream_topic_history.remove_messages({
 | |
|                     stream_id: event.stream_id,
 | |
|                     topic_name: event.topic,
 | |
|                     num_messages: msg_ids.length,
 | |
|                     max_removed_msg_id: Math.max(...msg_ids),
 | |
|                 });
 | |
|                 stream_list.update_streams_sidebar();
 | |
|             }
 | |
| 
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "has_zoom_token":
 | |
|             page_params.has_zoom_token = event.value;
 | |
|             if (event.value) {
 | |
|                 for (const callback of compose.zoom_token_callbacks.values()) {
 | |
|                     callback();
 | |
|                 }
 | |
|                 compose.zoom_token_callbacks.clear();
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "hotspots":
 | |
|             hotspots.load_new(event.hotspots);
 | |
|             page_params.hotspots = page_params.hotspots
 | |
|                 ? page_params.hotspots.concat(event.hotspots)
 | |
|                 : event.hotspots;
 | |
|             break;
 | |
| 
 | |
|         case "invites_changed":
 | |
|             if ($("#admin-invites-list").length) {
 | |
|                 settings_invites.set_up(false);
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "muted_topics":
 | |
|             muting_ui.handle_topic_updates(event.muted_topics);
 | |
|             break;
 | |
| 
 | |
|         case "muted_users":
 | |
|             muting_ui.handle_user_updates(event.muted_users);
 | |
|             break;
 | |
| 
 | |
|         case "presence":
 | |
|             activity.update_presence_info(event.user_id, event.presence, event.server_timestamp);
 | |
|             break;
 | |
| 
 | |
|         case "restart": {
 | |
|             const reload_options = {
 | |
|                 save_pointer: true,
 | |
|                 save_narrow: true,
 | |
|                 save_compose: true,
 | |
|                 message_html: "The application has been updated; reloading!",
 | |
|             };
 | |
|             if (event.immediate) {
 | |
|                 reload_options.immediate = true;
 | |
|             }
 | |
|             reload.initiate(reload_options);
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "reaction":
 | |
|             switch (event.op) {
 | |
|                 case "add":
 | |
|                     reactions.add_reaction(event);
 | |
|                     break;
 | |
|                 case "remove":
 | |
|                     reactions.remove_reaction(event);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type reaction/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "realm": {
 | |
|             const realm_settings = {
 | |
|                 add_emoji_by_admins_only: settings_emoji.update_custom_emoji_ui,
 | |
|                 allow_edit_history: noop,
 | |
|                 allow_message_deleting: noop,
 | |
|                 allow_message_editing: noop,
 | |
|                 allow_community_topic_editing: noop,
 | |
|                 user_group_edit_policy: noop,
 | |
|                 avatar_changes_disabled: settings_account.update_avatar_change_display,
 | |
|                 bot_creation_policy: settings_bots.update_bot_permissions_ui,
 | |
|                 create_stream_policy: noop,
 | |
|                 invite_to_stream_policy: noop,
 | |
|                 default_code_block_language: noop,
 | |
|                 default_language: noop,
 | |
|                 default_twenty_four_hour_time: noop,
 | |
|                 description: noop,
 | |
|                 digest_emails_enabled: noop,
 | |
|                 digest_weekday: noop,
 | |
|                 email_address_visibility: noop,
 | |
|                 email_changes_disabled: settings_account.update_email_change_display,
 | |
|                 disallow_disposable_email_addresses: noop,
 | |
|                 inline_image_preview: noop,
 | |
|                 inline_url_embed_preview: noop,
 | |
|                 invite_to_realm_policy: noop,
 | |
|                 invite_required: noop,
 | |
|                 mandatory_topics: noop,
 | |
|                 message_content_edit_limit_seconds: noop,
 | |
|                 message_content_delete_limit_seconds: noop,
 | |
|                 message_retention_days: noop,
 | |
|                 name: notifications.redraw_title,
 | |
|                 name_changes_disabled: settings_account.update_name_change_display,
 | |
|                 notifications_stream_id: noop,
 | |
|                 private_message_policy: noop,
 | |
|                 send_welcome_emails: noop,
 | |
|                 message_content_allowed_in_email_notifications: noop,
 | |
|                 signup_notifications_stream_id: noop,
 | |
|                 emails_restricted_to_domains: noop,
 | |
|                 video_chat_provider: compose.update_video_chat_button_display,
 | |
|                 waiting_period_threshold: noop,
 | |
|                 wildcard_mention_policy: noop,
 | |
|             };
 | |
|             switch (event.op) {
 | |
|                 case "update":
 | |
|                     if (Object.prototype.hasOwnProperty.call(realm_settings, event.property)) {
 | |
|                         page_params["realm_" + event.property] = event.value;
 | |
|                         realm_settings[event.property]();
 | |
|                         settings_org.sync_realm_settings(event.property);
 | |
|                         if (event.property === "create_stream_policy") {
 | |
|                             // TODO: Add waiting_period_threshold logic here.
 | |
|                             page_params.can_create_streams =
 | |
|                                 page_params.is_admin ||
 | |
|                                 page_params.realm_create_stream_policy === 1;
 | |
|                         } else if (event.property === "invite_to_stream_policy") {
 | |
|                             // TODO: Add waiting_period_threshold logic here.
 | |
|                             page_params.can_invite_to_stream =
 | |
|                                 page_params.is_admin ||
 | |
|                                 page_params.realm_invite_to_stream_policy === 1;
 | |
|                         } else if (event.property === "invite_to_realm_policy") {
 | |
|                             // TODO: Add waiting period threshold logic here.
 | |
|                             page_params.can_invite_others_to_realm =
 | |
|                                 page_params.is_admin ||
 | |
|                                 page_params.realm_invite_to_realm_policy === 1;
 | |
|                         }
 | |
| 
 | |
|                         if (event.property === "name" && window.electron_bridge !== undefined) {
 | |
|                             window.electron_bridge.send_event("realm_name", event.value);
 | |
|                         }
 | |
|                     }
 | |
|                     break;
 | |
|                 case "update_dict":
 | |
|                     switch (event.property) {
 | |
|                         case "default":
 | |
|                             for (const [key, value] of Object.entries(event.data)) {
 | |
|                                 page_params["realm_" + key] = value;
 | |
|                                 if (key === "allow_message_editing") {
 | |
|                                     message_edit.update_message_topic_editing_pencil();
 | |
|                                 }
 | |
|                                 if (Object.prototype.hasOwnProperty.call(realm_settings, key)) {
 | |
|                                     settings_org.sync_realm_settings(key);
 | |
|                                 }
 | |
|                             }
 | |
|                             if (event.data.authentication_methods !== undefined) {
 | |
|                                 settings_org.populate_auth_methods(
 | |
|                                     event.data.authentication_methods,
 | |
|                                 );
 | |
|                             }
 | |
|                             break;
 | |
|                         case "icon":
 | |
|                             page_params.realm_icon_url = event.data.icon_url;
 | |
|                             page_params.realm_icon_source = event.data.icon_source;
 | |
|                             realm_icon.rerender();
 | |
|                             {
 | |
|                                 const electron_bridge = window.electron_bridge;
 | |
|                                 if (electron_bridge !== undefined) {
 | |
|                                     electron_bridge.send_event(
 | |
|                                         "realm_icon_url",
 | |
|                                         event.data.icon_url,
 | |
|                                     );
 | |
|                                 }
 | |
|                             }
 | |
|                             break;
 | |
|                         case "logo":
 | |
|                             page_params.realm_logo_url = event.data.logo_url;
 | |
|                             page_params.realm_logo_source = event.data.logo_source;
 | |
|                             realm_logo.rerender();
 | |
|                             break;
 | |
|                         case "night_logo":
 | |
|                             page_params.realm_night_logo_url = event.data.night_logo_url;
 | |
|                             page_params.realm_night_logo_source = event.data.night_logo_source;
 | |
|                             realm_logo.rerender();
 | |
|                             break;
 | |
|                         default:
 | |
|                             blueslip.error(
 | |
|                                 "Unexpected event type realm/update_dict/" + event.property,
 | |
|                             );
 | |
|                             break;
 | |
|                     }
 | |
|                     break;
 | |
|                 case "deactivated":
 | |
|                     // This handler is likely unnecessary, in that if we
 | |
|                     // did nothing here, we'd reload and end up at the
 | |
|                     // same place when we attempt the next `GET /events`
 | |
|                     // and get an error.  Some clients will do that even
 | |
|                     // with this code, if they didn't have an active
 | |
|                     // longpoll waiting at the moment the realm was
 | |
|                     // deactivated.
 | |
|                     window.location.href = "/accounts/deactivated/";
 | |
|                     break;
 | |
|             }
 | |
|             if (page_params.is_admin) {
 | |
|                 // Update the UI notice about the user's profile being
 | |
|                 // incomplete, as we might have filled in the missing field(s).
 | |
|                 panels.show_profile_incomplete(panels.check_profile_incomplete());
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "realm_bot":
 | |
|             switch (event.op) {
 | |
|                 case "add":
 | |
|                     bot_data.add(event.bot);
 | |
|                     settings_bots.eventually_render_bots();
 | |
|                     settings_users.update_bot_data(event.bot.user_id);
 | |
|                     break;
 | |
|                 case "remove":
 | |
|                     bot_data.deactivate(event.bot.user_id);
 | |
|                     event.bot.is_active = false;
 | |
|                     settings_bots.eventually_render_bots();
 | |
|                     settings_users.update_bot_data(event.bot.user_id);
 | |
|                     break;
 | |
|                 case "delete":
 | |
|                     blueslip.info("ignoring bot deletion for live UI update");
 | |
|                     break;
 | |
|                 case "update":
 | |
|                     bot_data.update(event.bot.user_id, event.bot);
 | |
|                     settings_bots.eventually_render_bots();
 | |
|                     settings_users.update_bot_data(event.bot.user_id);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type realm_bot/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
|         case "realm_emoji":
 | |
|             // The authoritative data source is here.
 | |
|             emoji.update_emojis(event.realm_emoji);
 | |
| 
 | |
|             // And then let other widgets know.
 | |
|             settings_emoji.populate_emoji();
 | |
|             emoji_picker.rebuild_catalog();
 | |
|             composebox_typeahead.update_emoji_data();
 | |
|             break;
 | |
| 
 | |
|         case "realm_linkifiers":
 | |
|             page_params.realm_linkifiers = event.realm_linkifiers;
 | |
|             markdown.update_linkifier_rules(page_params.realm_linkifiers);
 | |
|             settings_linkifiers.populate_linkifiers(page_params.realm_linkifiers);
 | |
|             break;
 | |
| 
 | |
|         case "realm_playgrounds":
 | |
|             page_params.realm_playgrounds = event.realm_playgrounds;
 | |
|             realm_playground.update_playgrounds(page_params.realm_playgrounds);
 | |
|             settings_playgrounds.populate_playgrounds(page_params.realm_playgrounds);
 | |
|             break;
 | |
| 
 | |
|         case "realm_domains":
 | |
|             {
 | |
|                 let i;
 | |
|                 switch (event.op) {
 | |
|                     case "add":
 | |
|                         page_params.realm_domains.push(event.realm_domain);
 | |
|                         settings_org.populate_realm_domains(page_params.realm_domains);
 | |
|                         break;
 | |
|                     case "change":
 | |
|                         for (i = 0; i < page_params.realm_domains.length; i += 1) {
 | |
|                             if (page_params.realm_domains[i].domain === event.realm_domain.domain) {
 | |
|                                 page_params.realm_domains[i].allow_subdomains =
 | |
|                                     event.realm_domain.allow_subdomains;
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         settings_org.populate_realm_domains(page_params.realm_domains);
 | |
|                         break;
 | |
|                     case "remove":
 | |
|                         for (i = 0; i < page_params.realm_domains.length; i += 1) {
 | |
|                             if (page_params.realm_domains[i].domain === event.domain) {
 | |
|                                 page_params.realm_domains.splice(i, 1);
 | |
|                                 break;
 | |
|                             }
 | |
|                         }
 | |
|                         settings_org.populate_realm_domains(page_params.realm_domains);
 | |
|                         break;
 | |
|                     default:
 | |
|                         blueslip.error("Unexpected event type realm_domains/" + event.op);
 | |
|                         break;
 | |
|                 }
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "realm_user":
 | |
|             switch (event.op) {
 | |
|                 case "add":
 | |
|                     people.add_active_user(event.person);
 | |
|                     break;
 | |
|                 case "remove":
 | |
|                     people.deactivate(event.person);
 | |
|                     stream_events.remove_deactivated_user_from_all_streams(event.person.user_id);
 | |
|                     break;
 | |
|                 case "update":
 | |
|                     user_events.update_person(event.person);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type realm_user/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "stream":
 | |
|             switch (event.op) {
 | |
|                 case "update":
 | |
|                     // Legacy: Stream properties are still managed by subs.js on the client side.
 | |
|                     stream_events.update_property(event.stream_id, event.property, event.value, {
 | |
|                         rendered_description: event.rendered_description,
 | |
|                         history_public_to_subscribers: event.history_public_to_subscribers,
 | |
|                     });
 | |
|                     settings_streams.update_default_streams_table();
 | |
|                     break;
 | |
|                 case "create":
 | |
|                     stream_data.create_streams(event.streams);
 | |
| 
 | |
|                     for (const stream of event.streams) {
 | |
|                         const sub = sub_store.get(stream.stream_id);
 | |
|                         if (overlays.streams_open()) {
 | |
|                             subs.add_sub_to_table(sub);
 | |
|                         }
 | |
|                     }
 | |
|                     break;
 | |
|                 case "delete":
 | |
|                     for (const stream of event.streams) {
 | |
|                         const was_subscribed = sub_store.get(stream.stream_id).subscribed;
 | |
|                         const is_narrowed_to_stream = narrow_state.is_for_stream_id(
 | |
|                             stream.stream_id,
 | |
|                         );
 | |
|                         subs.remove_stream(stream.stream_id);
 | |
|                         stream_data.delete_sub(stream.stream_id);
 | |
|                         if (was_subscribed) {
 | |
|                             stream_list.remove_sidebar_row(stream.stream_id);
 | |
|                         }
 | |
|                         settings_streams.update_default_streams_table();
 | |
|                         stream_data.remove_default_stream(stream.stream_id);
 | |
|                         if (is_narrowed_to_stream) {
 | |
|                             message_lists.current.update_trailing_bookend();
 | |
|                         }
 | |
|                         if (page_params.realm_notifications_stream_id === stream.stream_id) {
 | |
|                             page_params.realm_notifications_stream_id = -1;
 | |
|                             settings_org.sync_realm_settings("notifications_stream_id");
 | |
|                         }
 | |
|                         if (page_params.realm_signup_notifications_stream_id === stream.stream_id) {
 | |
|                             page_params.realm_signup_notifications_stream_id = -1;
 | |
|                             settings_org.sync_realm_settings("signup_notifications_stream_id");
 | |
|                         }
 | |
|                     }
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type stream/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "submessage": {
 | |
|             // The fields in the event don't quite exactly
 | |
|             // match the layout of a submessage, since there's
 | |
|             // an event id.  We also want to be explicit here.
 | |
|             const submsg = {
 | |
|                 id: event.submessage_id,
 | |
|                 sender_id: event.sender_id,
 | |
|                 msg_type: event.msg_type,
 | |
|                 message_id: event.message_id,
 | |
|                 content: event.content,
 | |
|             };
 | |
|             submessage.handle_event(submsg);
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "subscription":
 | |
|             switch (event.op) {
 | |
|                 case "add":
 | |
|                     for (const rec of event.subscriptions) {
 | |
|                         const sub = sub_store.get(rec.stream_id);
 | |
|                         if (sub) {
 | |
|                             stream_data.update_stream_email_address(sub, rec.email_address);
 | |
|                             stream_events.mark_subscribed(sub, rec.subscribers, rec.color);
 | |
|                         } else {
 | |
|                             blueslip.error(
 | |
|                                 "Subscribing to unknown stream with ID " + rec.stream_id,
 | |
|                             );
 | |
|                         }
 | |
|                     }
 | |
|                     break;
 | |
|                 case "peer_add": {
 | |
|                     const stream_ids = sub_store.validate_stream_ids(event.stream_ids);
 | |
|                     const user_ids = people.validate_user_ids(event.user_ids);
 | |
| 
 | |
|                     peer_data.bulk_add_subscribers({stream_ids, user_ids});
 | |
| 
 | |
|                     for (const stream_id of stream_ids) {
 | |
|                         const sub = sub_store.get(stream_id);
 | |
|                         subs.update_subscribers_ui(sub);
 | |
|                     }
 | |
| 
 | |
|                     compose_fade.update_faded_users();
 | |
|                     break;
 | |
|                 }
 | |
|                 case "peer_remove": {
 | |
|                     const stream_ids = sub_store.validate_stream_ids(event.stream_ids);
 | |
|                     const user_ids = people.validate_user_ids(event.user_ids);
 | |
| 
 | |
|                     peer_data.bulk_remove_subscribers({stream_ids, user_ids});
 | |
| 
 | |
|                     for (const stream_id of stream_ids) {
 | |
|                         const sub = sub_store.get(stream_id);
 | |
|                         subs.update_subscribers_ui(sub);
 | |
|                     }
 | |
| 
 | |
|                     compose_fade.update_faded_users();
 | |
|                     break;
 | |
|                 }
 | |
|                 case "remove":
 | |
|                     for (const rec of event.subscriptions) {
 | |
|                         const sub = sub_store.get(rec.stream_id);
 | |
|                         stream_events.mark_unsubscribed(sub);
 | |
|                     }
 | |
|                     break;
 | |
|                 case "update":
 | |
|                     stream_events.update_property(event.stream_id, event.property, event.value);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type subscription/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
|         case "typing":
 | |
|             if (event.sender.user_id === page_params.user_id) {
 | |
|                 // typing notifications are sent to the user who is typing
 | |
|                 // as well as recipients; we ignore such self-generated events.
 | |
|                 return;
 | |
|             }
 | |
|             switch (event.op) {
 | |
|                 case "start":
 | |
|                     typing_events.display_notification(event);
 | |
|                     break;
 | |
|                 case "stop":
 | |
|                     typing_events.hide_notification(event);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type typing/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
| 
 | |
|         case "update_display_settings": {
 | |
|             const user_display_settings = [
 | |
|                 "color_scheme",
 | |
|                 "default_language",
 | |
|                 "default_view",
 | |
|                 "demote_inactive_streams",
 | |
|                 "dense_mode",
 | |
|                 "emojiset",
 | |
|                 "fluid_layout_width",
 | |
|                 "high_contrast_mode",
 | |
|                 "left_side_userlist",
 | |
|                 "timezone",
 | |
|                 "twenty_four_hour_time",
 | |
|                 "translate_emoticons",
 | |
|                 "starred_message_counts",
 | |
|             ];
 | |
|             if (user_display_settings.includes(event.setting_name)) {
 | |
|                 page_params[event.setting_name] = event.setting;
 | |
|             }
 | |
|             if (event.setting_name === "default_language") {
 | |
|                 // We additionally need to set the language name.
 | |
|                 //
 | |
|                 // Note that this does not change translations at all;
 | |
|                 // a reload is fundamentally required because we
 | |
|                 // cannot rerender with the new language the strings
 | |
|                 // present in the backend/Jinja2 templates.
 | |
|                 page_params.default_language_name = event.language_name;
 | |
|             }
 | |
|             if (event.setting_name === "twenty_four_hour_time") {
 | |
|                 // Rerender the whole message list UI
 | |
|                 message_lists.home.rerender();
 | |
|                 if (message_lists.current === message_list.narrowed) {
 | |
|                     message_list.narrowed.rerender();
 | |
|                 }
 | |
|             }
 | |
|             if (event.setting_name === "high_contrast_mode") {
 | |
|                 $("body").toggleClass("high-contrast");
 | |
|             }
 | |
|             if (event.setting_name === "demote_inactive_streams") {
 | |
|                 stream_list.update_streams_sidebar();
 | |
|                 stream_data.set_filter_out_inactives();
 | |
|             }
 | |
|             if (event.setting_name === "dense_mode") {
 | |
|                 $("body").toggleClass("less_dense_mode");
 | |
|                 $("body").toggleClass("more_dense_mode");
 | |
|             }
 | |
|             if (event.setting_name === "color_scheme") {
 | |
|                 $("body").fadeOut(300);
 | |
|                 setTimeout(() => {
 | |
|                     if (event.setting === settings_config.color_scheme_values.night.code) {
 | |
|                         night_mode.enable();
 | |
|                         realm_logo.rerender();
 | |
|                     } else if (event.setting === settings_config.color_scheme_values.day.code) {
 | |
|                         night_mode.disable();
 | |
|                         realm_logo.rerender();
 | |
|                     } else {
 | |
|                         night_mode.default_preference_checker();
 | |
|                         realm_logo.rerender();
 | |
|                     }
 | |
|                     $("body").fadeIn(300);
 | |
|                 }, 300);
 | |
|             }
 | |
|             if (event.setting_name === "starred_message_counts") {
 | |
|                 starred_messages.rerender_ui();
 | |
|             }
 | |
|             if (event.setting_name === "fluid_layout_width") {
 | |
|                 scroll_bar.set_layout_width();
 | |
|             }
 | |
|             if (event.setting_name === "left_side_userlist") {
 | |
|                 // TODO: Make this change the view immediately rather
 | |
|                 // than requiring a reload or page resize.
 | |
|             }
 | |
|             if (event.setting_name === "default_language") {
 | |
|                 // TODO: Make this change the view immediately rather than
 | |
|                 // requiring a reload.  This is likely fairly difficult,
 | |
|                 // because various i18n strings are rendered by the
 | |
|                 // server; we may want to instead just trigger a page
 | |
|                 // reload.
 | |
|             }
 | |
|             if (event.setting_name === "emojiset") {
 | |
|                 settings_display.report_emojiset_change();
 | |
| 
 | |
|                 // Rerender the whole message list UI
 | |
|                 message_lists.home.rerender();
 | |
|                 if (message_lists.current === message_list.narrowed) {
 | |
|                     message_list.narrowed.rerender();
 | |
|                 }
 | |
|             }
 | |
|             settings_display.update_page();
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "update_global_notifications":
 | |
|             notifications.handle_global_notification_updates(
 | |
|                 event.notification_name,
 | |
|                 event.setting,
 | |
|             );
 | |
|             settings_notifications.update_page();
 | |
|             // TODO: This should also do a refresh of the stream_edit UI
 | |
|             // if it's currently displayed, possibly reusing some code
 | |
|             // from stream_events.js
 | |
|             // (E.g. update_stream_push_notifications).
 | |
|             break;
 | |
| 
 | |
|         case "update_message_flags": {
 | |
|             const new_value = event.op === "add";
 | |
|             switch (event.flag) {
 | |
|                 case "starred":
 | |
|                     for (const message_id of event.messages) {
 | |
|                         message_flags.update_starred_flag(message_id, new_value);
 | |
|                     }
 | |
| 
 | |
|                     if (event.op === "add") {
 | |
|                         starred_messages.add(event.messages);
 | |
|                     } else {
 | |
|                         starred_messages.remove(event.messages);
 | |
|                     }
 | |
|                     break;
 | |
|                 case "read":
 | |
|                     unread_ops.process_read_messages_event(event.messages);
 | |
|                     break;
 | |
|             }
 | |
|             break;
 | |
|         }
 | |
| 
 | |
|         case "user_group":
 | |
|             switch (event.op) {
 | |
|                 case "add":
 | |
|                     user_groups.add(event.group);
 | |
|                     break;
 | |
|                 case "remove":
 | |
|                     user_groups.remove(user_groups.get_user_group_from_id(event.group_id));
 | |
|                     break;
 | |
|                 case "add_members":
 | |
|                     user_groups.add_members(event.group_id, event.user_ids);
 | |
|                     break;
 | |
|                 case "remove_members":
 | |
|                     user_groups.remove_members(event.group_id, event.user_ids);
 | |
|                     break;
 | |
|                 case "update":
 | |
|                     user_groups.update(event);
 | |
|                     break;
 | |
|                 default:
 | |
|                     blueslip.error("Unexpected event type user_group/" + event.op);
 | |
|                     break;
 | |
|             }
 | |
|             settings_user_groups.reload();
 | |
|             break;
 | |
| 
 | |
|         case "user_status":
 | |
|             if (event.away !== undefined) {
 | |
|                 if (event.away) {
 | |
|                     activity.on_set_away(event.user_id);
 | |
|                 } else {
 | |
|                     activity.on_revoke_away(event.user_id);
 | |
|                 }
 | |
|             }
 | |
| 
 | |
|             if (event.status_text !== undefined) {
 | |
|                 user_status.set_status_text({
 | |
|                     user_id: event.user_id,
 | |
|                     status_text: event.status_text,
 | |
|                 });
 | |
|                 activity.redraw_user(event.user_id);
 | |
|             }
 | |
|             break;
 | |
|         case "realm_export":
 | |
|             settings_exports.populate_exports_table(event.exports);
 | |
|             break;
 | |
|     }
 | |
| }
 |