mirror of https://github.com/zulip/zulip.git
tsconfig: Enable noUncheckedIndexedAccess.
Signed-off-by: Anders Kaseorg <anders@zulip.com>
This commit is contained in:
parent
4e91572c96
commit
804c3706ff
|
@ -26,6 +26,7 @@
|
||||||
"forceConsistentCasingInFileNames": true,
|
"forceConsistentCasingInFileNames": true,
|
||||||
"isolatedModules": true,
|
"isolatedModules": true,
|
||||||
"noImplicitOverride": true,
|
"noImplicitOverride": true,
|
||||||
|
"noUncheckedIndexedAccess": true,
|
||||||
|
|
||||||
/* Additional checks */
|
/* Additional checks */
|
||||||
"noUnusedLocals": true,
|
"noUnusedLocals": true,
|
||||||
|
|
|
@ -215,9 +215,9 @@ export function process_fenced_code(content: string): string {
|
||||||
consume_line = function consume_line(output_lines: string[], line: string) {
|
consume_line = function consume_line(output_lines: string[], line: string) {
|
||||||
const match = fence_re.exec(line);
|
const match = fence_re.exec(line);
|
||||||
if (match) {
|
if (match) {
|
||||||
const fence = match[1];
|
const fence = match[1]!;
|
||||||
const lang = match[3];
|
const lang = match[3]!;
|
||||||
const header = match[5];
|
const header = match[5]!;
|
||||||
const handler = handler_for_fence(output_lines, fence, lang, header);
|
const handler = handler_for_fence(output_lines, fence, lang, header);
|
||||||
handler_stack.push(handler);
|
handler_stack.push(handler);
|
||||||
} else {
|
} else {
|
||||||
|
@ -255,7 +255,7 @@ export function get_unused_fence(content: string): string {
|
||||||
let match;
|
let match;
|
||||||
fence_length_re.lastIndex = 0;
|
fence_length_re.lastIndex = 0;
|
||||||
while ((match = fence_length_re.exec(content)) !== null) {
|
while ((match = fence_length_re.exec(content)) !== null) {
|
||||||
length = Math.max(length, match[1].length + 1);
|
length = Math.max(length, match[1]!.length + 1);
|
||||||
}
|
}
|
||||||
return "`".repeat(length);
|
return "`".repeat(length);
|
||||||
}
|
}
|
||||||
|
|
|
@ -68,12 +68,12 @@ export function last_prefix_match(prefix: string, words: string[]): number | nul
|
||||||
let found = false;
|
let found = false;
|
||||||
while (left < right) {
|
while (left < right) {
|
||||||
const mid = Math.floor((left + right) / 2);
|
const mid = Math.floor((left + right) / 2);
|
||||||
if (words[mid].startsWith(prefix)) {
|
if (words[mid]!.startsWith(prefix)) {
|
||||||
// Note that left can never be 0 if `found` is true,
|
// Note that left can never be 0 if `found` is true,
|
||||||
// since it is incremented at least once here.
|
// since it is incremented at least once here.
|
||||||
left = mid + 1;
|
left = mid + 1;
|
||||||
found = true;
|
found = true;
|
||||||
} else if (words[mid] < prefix) {
|
} else if (words[mid]! < prefix) {
|
||||||
left = mid + 1;
|
left = mid + 1;
|
||||||
} else {
|
} else {
|
||||||
right = mid;
|
right = mid;
|
||||||
|
|
|
@ -19,12 +19,12 @@ export function launch(): void {
|
||||||
|
|
||||||
const zulip_version_clipboard = new ClipboardJS("#about-zulip .fa-copy.zulip-version");
|
const zulip_version_clipboard = new ClipboardJS("#about-zulip .fa-copy.zulip-version");
|
||||||
zulip_version_clipboard.on("success", () => {
|
zulip_version_clipboard.on("success", () => {
|
||||||
show_copied_confirmation($("#about-zulip .fa-copy.zulip-version")[0]);
|
show_copied_confirmation($("#about-zulip .fa-copy.zulip-version")[0]!);
|
||||||
});
|
});
|
||||||
|
|
||||||
const zulip_merge_base_clipboard = new ClipboardJS("#about-zulip .fa-copy.zulip-merge-base");
|
const zulip_merge_base_clipboard = new ClipboardJS("#about-zulip .fa-copy.zulip-merge-base");
|
||||||
zulip_merge_base_clipboard.on("success", () => {
|
zulip_merge_base_clipboard.on("success", () => {
|
||||||
show_copied_confirmation($("#about-zulip .fa-copy.zulip-merge-base")[0]);
|
show_copied_confirmation($("#about-zulip .fa-copy.zulip-merge-base")[0]!);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,6 @@ export function update_notification_sound_source(
|
||||||
if (notification_sound !== "none") {
|
if (notification_sound !== "none") {
|
||||||
// Load it so that it is ready to be played; without this the old sound
|
// Load it so that it is ready to be played; without this the old sound
|
||||||
// is played.
|
// is played.
|
||||||
$container_elem[0].load();
|
$container_elem[0]!.load();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -158,7 +158,7 @@ export function update_discount_details(
|
||||||
}
|
}
|
||||||
|
|
||||||
export function is_valid_input($elem: JQuery<HTMLFormElement>): boolean {
|
export function is_valid_input($elem: JQuery<HTMLFormElement>): boolean {
|
||||||
return $elem[0].checkValidity();
|
return $elem[0]!.checkValidity();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function redirect_to_billing_with_successful_upgrade(billing_base_url: string): void {
|
export function redirect_to_billing_with_successful_upgrade(billing_base_url: string): void {
|
||||||
|
|
|
@ -279,7 +279,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
select(e?: JQuery.ClickEvent | JQuery.KeyUpEvent | JQuery.KeyDownEvent): this {
|
select(e?: JQuery.ClickEvent | JQuery.KeyUpEvent | JQuery.KeyDownEvent): this {
|
||||||
const val = this.values.get(this.$menu.find(".active")[0]);
|
const val = this.values.get(this.$menu.find(".active")[0]!);
|
||||||
assert(val !== undefined);
|
assert(val !== undefined);
|
||||||
if (this.input_element.type === "contenteditable") {
|
if (this.input_element.type === "contenteditable") {
|
||||||
this.input_element.$element
|
this.input_element.$element
|
||||||
|
@ -295,8 +295,8 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
const [from, to_before, to_after] = get_string_diff(element_val, after_text);
|
const [from, to_before, to_after] = get_string_diff(element_val, after_text);
|
||||||
const replacement = after_text.slice(from, to_after);
|
const replacement = after_text.slice(from, to_after);
|
||||||
// select / highlight the minimal text to be replaced
|
// select / highlight the minimal text to be replaced
|
||||||
this.input_element.$element[0].setSelectionRange(from, to_before);
|
this.input_element.$element[0]!.setSelectionRange(from, to_before);
|
||||||
insertTextIntoField(this.input_element.$element[0], replacement);
|
insertTextIntoField(this.input_element.$element[0]!, replacement);
|
||||||
this.input_element.$element.trigger("change");
|
this.input_element.$element.trigger("change");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
}
|
}
|
||||||
|
|
||||||
set_value(): void {
|
set_value(): void {
|
||||||
const val = this.values.get(this.$menu.find(".active")[0]);
|
const val = this.values.get(this.$menu.find(".active")[0]!);
|
||||||
assert(typeof val === "string");
|
assert(typeof val === "string");
|
||||||
if (this.input_element.type === "contenteditable") {
|
if (this.input_element.type === "contenteditable") {
|
||||||
this.input_element.$element.text(val);
|
this.input_element.$element.text(val);
|
||||||
|
@ -340,7 +340,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
// We don't need tippy to position typeaheads which already know where they should be.
|
// We don't need tippy to position typeaheads which already know where they should be.
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
this.instance = tippy.default(this.input_element.$element[0], {
|
this.instance = tippy.default(this.input_element.$element[0]!, {
|
||||||
// Lets typeahead take the width needed to fit the content
|
// Lets typeahead take the width needed to fit the content
|
||||||
// and wraps it if it overflows the visible container.
|
// and wraps it if it overflows the visible container.
|
||||||
maxWidth: "none",
|
maxWidth: "none",
|
||||||
|
@ -371,7 +371,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
interactive: true,
|
interactive: true,
|
||||||
appendTo: () => document.body,
|
appendTo: () => document.body,
|
||||||
showOnCreate: true,
|
showOnCreate: true,
|
||||||
content: this.$container[0],
|
content: this.$container[0]!,
|
||||||
// We expect the typeahead creator to handle when to hide / show the typeahead.
|
// We expect the typeahead creator to handle when to hide / show the typeahead.
|
||||||
trigger: "manual",
|
trigger: "manual",
|
||||||
arrow: false,
|
arrow: false,
|
||||||
|
@ -449,7 +449,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
render(final_items: ItemType[], matching_items: ItemType[]): this {
|
render(final_items: ItemType[], matching_items: ItemType[]): this {
|
||||||
const $items: JQuery[] = final_items.map((item) => {
|
const $items: JQuery[] = final_items.map((item) => {
|
||||||
const $i = $(ITEM_HTML);
|
const $i = $(ITEM_HTML);
|
||||||
this.values.set($i[0], item);
|
this.values.set($i[0]!, item);
|
||||||
const item_html = this.highlighter_html(item, this.query) ?? "";
|
const item_html = this.highlighter_html(item, this.query) ?? "";
|
||||||
const $item_html = $i.find("a").html(item_html);
|
const $item_html = $i.find("a").html(item_html);
|
||||||
|
|
||||||
|
@ -461,7 +461,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
return $i;
|
return $i;
|
||||||
});
|
});
|
||||||
|
|
||||||
$items[0].addClass("active");
|
$items[0]!.addClass("active");
|
||||||
this.$menu.empty().append($items);
|
this.$menu.empty().append($items);
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
@ -621,12 +621,12 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
|
|
||||||
this.select(e);
|
this.select(e);
|
||||||
|
|
||||||
if (this.input_element.$element[0].id === "stream_message_recipient_topic") {
|
if (this.input_element.$element[0]!.id === "stream_message_recipient_topic") {
|
||||||
assert(this.input_element.type === "input");
|
assert(this.input_element.type === "input");
|
||||||
// Move the cursor to the end of the topic
|
// Move the cursor to the end of the topic
|
||||||
const topic_length = this.input_element.$element.val()!.length;
|
const topic_length = this.input_element.$element.val()!.length;
|
||||||
this.input_element.$element[0].selectionStart = topic_length;
|
this.input_element.$element[0]!.selectionStart = topic_length;
|
||||||
this.input_element.$element[0].selectionEnd = topic_length;
|
this.input_element.$element[0]!.selectionEnd = topic_length;
|
||||||
}
|
}
|
||||||
|
|
||||||
break;
|
break;
|
||||||
|
@ -653,7 +653,7 @@ export class Typeahead<ItemType extends string | object> {
|
||||||
// when shift (keycode 16) + tabbing to the topic field
|
// when shift (keycode 16) + tabbing to the topic field
|
||||||
if (
|
if (
|
||||||
pseudo_keycode === 16 &&
|
pseudo_keycode === 16 &&
|
||||||
this.input_element.$element[0].id === "stream_message_recipient_topic"
|
this.input_element.$element[0]!.id === "stream_message_recipient_topic"
|
||||||
) {
|
) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -170,7 +170,7 @@ export class BuddyList extends BuddyListConf {
|
||||||
// This will default to "bottom" placement for this tooltip.
|
// This will default to "bottom" placement for this tooltip.
|
||||||
placement = "auto";
|
placement = "auto";
|
||||||
}
|
}
|
||||||
tippy.default($elem[0], {
|
tippy.default($elem[0]!, {
|
||||||
// Because the buddy list subheadings are potential click targets
|
// Because the buddy list subheadings are potential click targets
|
||||||
// for purposes having nothing to do with the subscriber count
|
// for purposes having nothing to do with the subscriber count
|
||||||
// (collapsing/expanding), we delay showing the tooltip until the
|
// (collapsing/expanding), we delay showing the tooltip until the
|
||||||
|
@ -765,7 +765,7 @@ export class BuddyList extends BuddyListConf {
|
||||||
|
|
||||||
const elem = scroll_util
|
const elem = scroll_util
|
||||||
.get_scroll_element($(this.scroll_container_selector))
|
.get_scroll_element($(this.scroll_container_selector))
|
||||||
.expectOne()[0];
|
.expectOne()[0]!;
|
||||||
|
|
||||||
// Add a fudge factor.
|
// Add a fudge factor.
|
||||||
height += 10;
|
height += 10;
|
||||||
|
|
|
@ -62,7 +62,7 @@ export function claim_colors(subs: {color: string}[]): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function pick_color(): string {
|
export function pick_color(): string {
|
||||||
const color = unused_colors[0];
|
const color = unused_colors[0]!;
|
||||||
|
|
||||||
claim_color(color);
|
claim_color(color);
|
||||||
|
|
||||||
|
|
|
@ -108,7 +108,7 @@ function set_password_toggle_label(
|
||||||
): void {
|
): void {
|
||||||
$(password_selector).attr("aria-label", label);
|
$(password_selector).attr("aria-label", label);
|
||||||
if (tippy_tooltips) {
|
if (tippy_tooltips) {
|
||||||
const element: tippy.ReferenceElement = $(password_selector)[0];
|
const element: tippy.ReferenceElement = $(password_selector)[0]!;
|
||||||
const tippy_instance = element._tippy ?? tippy.default(element);
|
const tippy_instance = element._tippy ?? tippy.default(element);
|
||||||
tippy_instance.setContent(label);
|
tippy_instance.setContent(label);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -82,7 +82,7 @@ export function toggle(opts: {
|
||||||
|
|
||||||
meta.idx = idx;
|
meta.idx = idx;
|
||||||
if (opts.callback) {
|
if (opts.callback) {
|
||||||
opts.callback(opts.values[idx].label, opts.values[idx].key);
|
opts.callback(opts.values[idx]!.label, opts.values[idx]!.key);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!opts.child_wants_focus) {
|
if (!opts.child_wants_focus) {
|
||||||
|
@ -162,7 +162,7 @@ export function toggle(opts: {
|
||||||
|
|
||||||
value() {
|
value() {
|
||||||
if (meta.idx >= 0) {
|
if (meta.idx >= 0) {
|
||||||
return opts.values[meta.idx].label;
|
return opts.values[meta.idx]!.label;
|
||||||
}
|
}
|
||||||
/* istanbul ignore next */
|
/* istanbul ignore next */
|
||||||
return undefined;
|
return undefined;
|
||||||
|
|
|
@ -213,7 +213,7 @@ export function update_rendered_message_groups(
|
||||||
// the other code takes advantage of blocks beneath recipient bars.
|
// the other code takes advantage of blocks beneath recipient bars.
|
||||||
for (const message_group of message_groups) {
|
for (const message_group of message_groups) {
|
||||||
const $elt = get_element(message_group);
|
const $elt = get_element(message_group);
|
||||||
const first_message = message_group.message_containers[0].msg;
|
const first_message = message_group.message_containers[0]!.msg;
|
||||||
const should_fade = compose_fade_helper.should_fade_message(first_message);
|
const should_fade = compose_fade_helper.should_fade_message(first_message);
|
||||||
change_fade_state($elt, should_fade);
|
change_fade_state($elt, should_fade);
|
||||||
}
|
}
|
||||||
|
|
|
@ -314,7 +314,7 @@ function on_hidden_callback(): void {
|
||||||
// Always move focus to the topic input even if it's not empty,
|
// Always move focus to the topic input even if it's not empty,
|
||||||
// since it's likely the user will want to update the topic
|
// since it's likely the user will want to update the topic
|
||||||
// after updating the stream.
|
// after updating the stream.
|
||||||
ui_util.place_caret_at_end($("input#stream_message_recipient_topic")[0]);
|
ui_util.place_caret_at_end($("input#stream_message_recipient_topic")[0]!);
|
||||||
} else {
|
} else {
|
||||||
if (compose_state.private_message_recipient().length === 0) {
|
if (compose_state.private_message_recipient().length === 0) {
|
||||||
$("#private_message_recipient").trigger("focus").trigger("select");
|
$("#private_message_recipient").trigger("focus").trigger("select");
|
||||||
|
|
|
@ -98,9 +98,9 @@ export function insert_and_scroll_into_view(
|
||||||
replace_all = false,
|
replace_all = false,
|
||||||
): void {
|
): void {
|
||||||
if (replace_all) {
|
if (replace_all) {
|
||||||
setFieldText($textarea[0], content);
|
setFieldText($textarea[0]!, content);
|
||||||
} else {
|
} else {
|
||||||
insertTextIntoField($textarea[0], content);
|
insertTextIntoField($textarea[0]!, content);
|
||||||
}
|
}
|
||||||
// Blurring and refocusing ensures the cursor / selection is in view
|
// Blurring and refocusing ensures the cursor / selection is in view
|
||||||
// in chromium browsers.
|
// in chromium browsers.
|
||||||
|
@ -275,7 +275,7 @@ export function replace_syntax(
|
||||||
// for details.
|
// for details.
|
||||||
|
|
||||||
const old_text = $textarea.val();
|
const old_text = $textarea.val();
|
||||||
replaceFieldText($textarea[0], old_syntax, () => new_syntax, "after-replacement");
|
replaceFieldText($textarea[0]!, old_syntax, () => new_syntax, "after-replacement");
|
||||||
const new_text = $textarea.val();
|
const new_text = $textarea.val();
|
||||||
|
|
||||||
// When replacing content in a textarea, we need to move the cursor
|
// When replacing content in a textarea, we need to move the cursor
|
||||||
|
|
|
@ -250,7 +250,7 @@ function handle_bulleting_or_numbering(
|
||||||
if (bulleted_numbered_list_util.strip_bullet(previous_line) === "") {
|
if (bulleted_numbered_list_util.strip_bullet(previous_line) === "") {
|
||||||
// below we select and replace the last 2 characters in the textarea before
|
// below we select and replace the last 2 characters in the textarea before
|
||||||
// the cursor - the bullet syntax - with an empty string
|
// the cursor - the bullet syntax - with an empty string
|
||||||
$textarea[0].setSelectionRange($textarea.caret() - 2, $textarea.caret());
|
$textarea[0]!.setSelectionRange($textarea.caret() - 2, $textarea.caret());
|
||||||
compose_ui.insert_and_scroll_into_view("", $textarea);
|
compose_ui.insert_and_scroll_into_view("", $textarea);
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return;
|
return;
|
||||||
|
@ -264,7 +264,7 @@ function handle_bulleting_or_numbering(
|
||||||
if (bulleted_numbered_list_util.strip_numbering(previous_line) === "") {
|
if (bulleted_numbered_list_util.strip_numbering(previous_line) === "") {
|
||||||
// below we select then replaces the last few characters in the textarea before
|
// below we select then replaces the last few characters in the textarea before
|
||||||
// the cursor - the numbering syntax - with an empty string
|
// the cursor - the numbering syntax - with an empty string
|
||||||
$textarea[0].setSelectionRange(
|
$textarea[0]!.setSelectionRange(
|
||||||
$textarea.caret() - previous_number_string.length - 2,
|
$textarea.caret() - previous_number_string.length - 2,
|
||||||
$textarea.caret(),
|
$textarea.caret(),
|
||||||
);
|
);
|
||||||
|
@ -297,7 +297,7 @@ export function handle_enter($textarea: JQuery<HTMLTextAreaElement>, e: JQuery.K
|
||||||
|
|
||||||
// If the selectionStart and selectionEnd are not the same, that
|
// If the selectionStart and selectionEnd are not the same, that
|
||||||
// means that some text was selected.
|
// means that some text was selected.
|
||||||
if ($textarea[0].selectionStart !== $textarea[0].selectionEnd) {
|
if ($textarea[0]!.selectionStart !== $textarea[0]!.selectionEnd) {
|
||||||
// Replace it with the newline, remembering to resize the
|
// Replace it with the newline, remembering to resize the
|
||||||
// textarea if needed.
|
// textarea if needed.
|
||||||
compose_ui.insert_and_scroll_into_view("\n", $textarea);
|
compose_ui.insert_and_scroll_into_view("\n", $textarea);
|
||||||
|
@ -431,7 +431,7 @@ export function tokenize_compose_str(s: string): string {
|
||||||
case "_":
|
case "_":
|
||||||
if (i === 0) {
|
if (i === 0) {
|
||||||
return s;
|
return s;
|
||||||
} else if (/[\s"'(/<[{]/.test(s[i - 1])) {
|
} else if (/[\s"'(/<[{]/.test(s[i - 1]!)) {
|
||||||
return s.slice(i);
|
return s.slice(i);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -775,7 +775,7 @@ export function get_candidates(
|
||||||
|
|
||||||
// We will likely want to extend this list to be more i18n-friendly.
|
// We will likely want to extend this list to be more i18n-friendly.
|
||||||
const terminal_symbols = ",.;?!()[]> \"'\n\t";
|
const terminal_symbols = ",.;?!()[]> \"'\n\t";
|
||||||
if (rest !== "" && !terminal_symbols.includes(rest[0])) {
|
if (rest !== "" && !terminal_symbols.includes(rest[0]!)) {
|
||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1158,7 +1158,7 @@ export function content_typeahead_selected(
|
||||||
$textbox.caret(beginning.length);
|
$textbox.caret(beginning.length);
|
||||||
compose_ui.autosize_textarea($textbox);
|
compose_ui.autosize_textarea($textbox);
|
||||||
};
|
};
|
||||||
flatpickr.show_flatpickr(input_element.$element[0], on_timestamp_selection, timestamp);
|
flatpickr.show_flatpickr(input_element.$element[0]!, on_timestamp_selection, timestamp);
|
||||||
return beginning + rest;
|
return beginning + rest;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ function get_message_height(elem: HTMLElement): number {
|
||||||
// This needs to be very fast. This function runs hundreds of times
|
// This needs to be very fast. This function runs hundreds of times
|
||||||
// when displaying a message feed view that has hundreds of message
|
// when displaying a message feed view that has hundreds of message
|
||||||
// history, which ideally should render in <100ms.
|
// history, which ideally should render in <100ms.
|
||||||
return $(elem).find(".message_content")[0].scrollHeight;
|
return $(elem).find(".message_content")[0]!.scrollHeight;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function hide_message_expander($row: JQuery): void {
|
export function hide_message_expander($row: JQuery): void {
|
||||||
|
|
|
@ -132,7 +132,7 @@ function select_div($div: JQuery, selection: Selection): void {
|
||||||
background: "#FFF",
|
background: "#FFF",
|
||||||
}).attr("id", "copytempdiv");
|
}).attr("id", "copytempdiv");
|
||||||
$("body").append($div);
|
$("body").append($div);
|
||||||
selection.selectAllChildren($div[0]);
|
selection.selectAllChildren($div[0]!);
|
||||||
}
|
}
|
||||||
|
|
||||||
function remove_div(_div: JQuery, ranges: Range[]): void {
|
function remove_div(_div: JQuery, ranges: Range[]): void {
|
||||||
|
@ -591,7 +591,7 @@ function is_safe_url_paste_target($textarea: JQuery<HTMLTextAreaElement>): boole
|
||||||
// Look at the two characters before the start of the original
|
// Look at the two characters before the start of the original
|
||||||
// range in search of the tell-tale `](` from existing Markdown
|
// range in search of the tell-tale `](` from existing Markdown
|
||||||
// link syntax
|
// link syntax
|
||||||
const possible_markdown_link_markers = $textarea[0].value.slice(range.start - 2, range.start);
|
const possible_markdown_link_markers = $textarea[0]!.value.slice(range.start - 2, range.start);
|
||||||
|
|
||||||
if (possible_markdown_link_markers === "](") {
|
if (possible_markdown_link_markers === "](") {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -367,7 +367,7 @@ function draft_notify(): void {
|
||||||
content: $t({defaultMessage: "Saved as draft"}),
|
content: $t({defaultMessage: "Saved as draft"}),
|
||||||
arrow: true,
|
arrow: true,
|
||||||
placement: "right",
|
placement: "right",
|
||||||
})[0];
|
})[0]!;
|
||||||
instance.show();
|
instance.show();
|
||||||
function remove_instance(): void {
|
function remove_instance(): void {
|
||||||
instance.destroy();
|
instance.destroy();
|
||||||
|
|
|
@ -86,7 +86,7 @@ function zephyr_topic_name_match(message: Message & {type: "stream"}, operand: s
|
||||||
const m = /^(.*?)(?:\.d)*$/i.exec(operand);
|
const m = /^(.*?)(?:\.d)*$/i.exec(operand);
|
||||||
// m should never be null because any string matches that regex.
|
// m should never be null because any string matches that regex.
|
||||||
assert(m !== null);
|
assert(m !== null);
|
||||||
const base_topic = m[1];
|
const base_topic = m[1]!;
|
||||||
let related_regexp;
|
let related_regexp;
|
||||||
|
|
||||||
// Additionally, Zephyr users expect the empty instance and
|
// Additionally, Zephyr users expect the empty instance and
|
||||||
|
@ -257,7 +257,7 @@ export class Filter {
|
||||||
constructor(terms: NarrowTerm[]) {
|
constructor(terms: NarrowTerm[]) {
|
||||||
this._terms = this.fix_terms(terms);
|
this._terms = this.fix_terms(terms);
|
||||||
if (this.has_operator("channel")) {
|
if (this.has_operator("channel")) {
|
||||||
this._sub = stream_data.get_sub_by_name(this.operands("channel")[0]);
|
this._sub = stream_data.get_sub_by_name(this.operands("channel")[0]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -724,7 +724,7 @@ export class Filter {
|
||||||
}
|
}
|
||||||
|
|
||||||
is_non_huddle_pm(): boolean {
|
is_non_huddle_pm(): boolean {
|
||||||
return this.has_operator("dm") && this.operands("dm")[0].split(",").length === 1;
|
return this.has_operator("dm") && this.operands("dm")[0]!.split(",").length === 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
supports_collapsing_recipients(): boolean {
|
supports_collapsing_recipients(): boolean {
|
||||||
|
@ -872,7 +872,7 @@ export class Filter {
|
||||||
"/#narrow/" +
|
"/#narrow/" +
|
||||||
CHANNEL_SYNONYM +
|
CHANNEL_SYNONYM +
|
||||||
"/" +
|
"/" +
|
||||||
stream_data.name_to_slug(this.operands("channel")[0]) +
|
stream_data.name_to_slug(this.operands("channel")[0]!) +
|
||||||
"/topic/" +
|
"/topic/" +
|
||||||
this.operands("topic")[0]
|
this.operands("topic")[0]
|
||||||
);
|
);
|
||||||
|
@ -894,7 +894,7 @@ export class Filter {
|
||||||
"/#narrow/" +
|
"/#narrow/" +
|
||||||
CHANNEL_SYNONYM +
|
CHANNEL_SYNONYM +
|
||||||
"/" +
|
"/" +
|
||||||
stream_data.name_to_slug(this.operands("channel")[0])
|
stream_data.name_to_slug(this.operands("channel")[0]!)
|
||||||
);
|
);
|
||||||
case "is-dm":
|
case "is-dm":
|
||||||
return "/#narrow/is/dm";
|
return "/#narrow/is/dm";
|
||||||
|
@ -911,7 +911,7 @@ export class Filter {
|
||||||
// TODO: It is ambiguous how we want to handle the 'sender' case,
|
// TODO: It is ambiguous how we want to handle the 'sender' case,
|
||||||
// we may remove it in the future based on design decisions
|
// we may remove it in the future based on design decisions
|
||||||
case "sender":
|
case "sender":
|
||||||
return "/#narrow/sender/" + people.emails_to_slug(this.operands("sender")[0]);
|
return "/#narrow/sender/" + people.emails_to_slug(this.operands("sender")[0]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -991,7 +991,7 @@ export class Filter {
|
||||||
(term_types.length === 2 && _.isEqual(term_types, ["dm", "near"])) ||
|
(term_types.length === 2 && _.isEqual(term_types, ["dm", "near"])) ||
|
||||||
(term_types.length === 1 && _.isEqual(term_types, ["dm"]))
|
(term_types.length === 1 && _.isEqual(term_types, ["dm"]))
|
||||||
) {
|
) {
|
||||||
const emails = this.operands("dm")[0].split(",");
|
const emails = this.operands("dm")[0]!.split(",");
|
||||||
const names = emails.map((email) => {
|
const names = emails.map((email) => {
|
||||||
const person = people.get_by_email(email);
|
const person = people.get_by_email(email);
|
||||||
if (!person) {
|
if (!person) {
|
||||||
|
@ -1006,7 +1006,7 @@ export class Filter {
|
||||||
return util.format_array_as_list(names, "long", "conjunction");
|
return util.format_array_as_list(names, "long", "conjunction");
|
||||||
}
|
}
|
||||||
if (term_types.length === 1 && _.isEqual(term_types, ["sender"])) {
|
if (term_types.length === 1 && _.isEqual(term_types, ["sender"])) {
|
||||||
const email = this.operands("sender")[0];
|
const email = this.operands("sender")[0]!;
|
||||||
const user = people.get_by_email(email);
|
const user = people.get_by_email(email);
|
||||||
let sender = email;
|
let sender = email;
|
||||||
if (user) {
|
if (user) {
|
||||||
|
|
|
@ -25,7 +25,7 @@ export function show_flatpickr(
|
||||||
): flatpickr.Instance {
|
): flatpickr.Instance {
|
||||||
const $flatpickr_input = $<HTMLInputElement>("<input>").attr("id", "#timestamp_flatpickr");
|
const $flatpickr_input = $<HTMLInputElement>("<input>").attr("id", "#timestamp_flatpickr");
|
||||||
|
|
||||||
flatpickr_instance = flatpickr($flatpickr_input[0], {
|
flatpickr_instance = flatpickr($flatpickr_input[0]!, {
|
||||||
mode: "single",
|
mode: "single",
|
||||||
enableTime: true,
|
enableTime: true,
|
||||||
clickOpens: false,
|
clickOpens: false,
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export function get_hash_category(hash?: string): string {
|
export function get_hash_category(hash?: string): string {
|
||||||
// given "#channels/subscribed", returns "channels"
|
// given "#channels/subscribed", returns "channels"
|
||||||
return hash ? hash.replace(/^#/, "").split(/\//)[0] : "";
|
return hash ? hash.replace(/^#/, "").split(/\//)[0]! : "";
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_hash_section(hash?: string): string {
|
export function get_hash_section(hash?: string): string {
|
||||||
|
@ -88,7 +88,7 @@ export function is_editing_stream(desired_stream_id: number): boolean {
|
||||||
|
|
||||||
// if the string casted to a number is valid, and another component
|
// if the string casted to a number is valid, and another component
|
||||||
// after exists then it's a stream name/id pair.
|
// after exists then it's a stream name/id pair.
|
||||||
const stream_id = Number.parseFloat(hash_components[1]);
|
const stream_id = Number.parseFloat(hash_components[1]!);
|
||||||
|
|
||||||
return stream_id === desired_stream_id;
|
return stream_id === desired_stream_id;
|
||||||
}
|
}
|
||||||
|
|
|
@ -164,7 +164,7 @@ export function parse_narrow(hash: string[]): NarrowTerm[] | undefined {
|
||||||
for (i = 1; i < hash.length; i += 2) {
|
for (i = 1; i < hash.length; i += 2) {
|
||||||
// We don't construct URLs with an odd number of components,
|
// We don't construct URLs with an odd number of components,
|
||||||
// but the user might write one.
|
// but the user might write one.
|
||||||
let operator = internal_url.decodeHashComponent(hash[i]);
|
let operator = internal_url.decodeHashComponent(hash[i]!);
|
||||||
// Do not parse further if empty operator encountered.
|
// Do not parse further if empty operator encountered.
|
||||||
if (operator === "") {
|
if (operator === "") {
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -324,7 +324,7 @@ function insert_dms(keys_to_insert: string[]): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keys_to_insert.includes(key)) {
|
if (keys_to_insert.includes(key)) {
|
||||||
const $previous_row = get_row_from_conversation_key(sorted_keys[i - 1]);
|
const $previous_row = get_row_from_conversation_key(sorted_keys[i - 1]!);
|
||||||
$previous_row.after($(render_inbox_row(dms_dict.get(key))));
|
$previous_row.after($(render_inbox_row(dms_dict.get(key))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -462,7 +462,7 @@ function insert_stream(
|
||||||
if (stream_index === 0) {
|
if (stream_index === 0) {
|
||||||
$("#inbox-streams-container").prepend($(rendered_stream));
|
$("#inbox-streams-container").prepend($(rendered_stream));
|
||||||
} else {
|
} else {
|
||||||
const previous_stream_key = sorted_stream_keys[stream_index - 1];
|
const previous_stream_key = sorted_stream_keys[stream_index - 1]!;
|
||||||
$(rendered_stream).insertAfter(get_stream_container(previous_stream_key));
|
$(rendered_stream).insertAfter(get_stream_container(previous_stream_key));
|
||||||
}
|
}
|
||||||
return !streams_dict.get(stream_key)!.is_hidden;
|
return !streams_dict.get(stream_key)!.is_hidden;
|
||||||
|
@ -486,7 +486,7 @@ function insert_topics(keys: string[], stream_key: string): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (keys.includes(key)) {
|
if (keys.includes(key)) {
|
||||||
const $previous_row = get_row_from_conversation_key(sorted_keys[i - 1]);
|
const $previous_row = get_row_from_conversation_key(sorted_keys[i - 1]!);
|
||||||
$previous_row.after($(render_inbox_row(stream_topics_data.get(key))));
|
$previous_row.after($(render_inbox_row(stream_topics_data.get(key))));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1393,7 +1393,7 @@ function move_focus_to_visible_area(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const INBOX_ROW_HEIGHT = 30;
|
const INBOX_ROW_HEIGHT = 30;
|
||||||
const position = $("#inbox-filters")[0].getBoundingClientRect();
|
const position = $("#inbox-filters")[0]!.getBoundingClientRect();
|
||||||
const inbox_center_x = (position.left + position.right) / 2;
|
const inbox_center_x = (position.left + position.right) / 2;
|
||||||
// We are aiming to get the first row if it is completely visible or the second row.
|
// We are aiming to get the first row if it is completely visible or the second row.
|
||||||
const inbox_row_below_filters = position.bottom + INBOX_ROW_HEIGHT;
|
const inbox_row_below_filters = position.bottom + INBOX_ROW_HEIGHT;
|
||||||
|
|
|
@ -225,10 +225,10 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
const idx = store.pills.findIndex((pill) => pill.$element[0] === element);
|
const idx = store.pills.findIndex((pill) => pill.$element[0] === element);
|
||||||
|
|
||||||
if (idx !== -1) {
|
if (idx !== -1) {
|
||||||
store.pills[idx].$element.remove();
|
store.pills[idx]!.$element.remove();
|
||||||
const pill = store.pills.splice(idx, 1);
|
const pill = store.pills.splice(idx, 1);
|
||||||
if (store.onPillRemove !== undefined) {
|
if (store.onPillRemove !== undefined) {
|
||||||
store.onPillRemove(pill[0]);
|
store.onPillRemove(pill[0]!);
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is needed to run the "change" event handler registered in
|
// This is needed to run the "change" event handler registered in
|
||||||
|
@ -264,7 +264,7 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
this.removeLastPill(quiet);
|
this.removeLastPill(quiet);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.clear(store.$input[0]);
|
this.clear(store.$input[0]!);
|
||||||
},
|
},
|
||||||
|
|
||||||
insertManyPills(pills: string | string[]) {
|
insertManyPills(pills: string | string[]) {
|
||||||
|
@ -285,7 +285,7 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
// when using the `text` insertion feature with jQuery the caret is
|
// when using the `text` insertion feature with jQuery the caret is
|
||||||
// placed at the beginning of the input field, so this moves it to
|
// placed at the beginning of the input field, so this moves it to
|
||||||
// the end.
|
// the end.
|
||||||
ui_util.place_caret_at_end(store.$input[0]);
|
ui_util.place_caret_at_end(store.$input[0]!);
|
||||||
|
|
||||||
// this sends a flag if the operation wasn't completely successful,
|
// this sends a flag if the operation wasn't completely successful,
|
||||||
// which in this case is defined as some of the pills not autofilling
|
// which in this case is defined as some of the pills not autofilling
|
||||||
|
@ -370,7 +370,7 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
// if the pill is successful, it will create the pill and clear
|
// if the pill is successful, it will create the pill and clear
|
||||||
// the input.
|
// the input.
|
||||||
if (funcs.appendPill(store.$input.text().trim())) {
|
if (funcs.appendPill(store.$input.text().trim())) {
|
||||||
funcs.clear(store.$input[0]);
|
funcs.clear(store.$input[0]!);
|
||||||
}
|
}
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
|
|
||||||
|
@ -399,7 +399,7 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
break;
|
break;
|
||||||
case "Backspace": {
|
case "Backspace": {
|
||||||
const $next = $pill.next();
|
const $next = $pill.next();
|
||||||
funcs.removePill($pill[0]);
|
funcs.removePill($pill[0]!);
|
||||||
$next.trigger("focus");
|
$next.trigger("focus");
|
||||||
// the "Backspace" key in Firefox will go back a page if you do
|
// the "Backspace" key in Firefox will go back a page if you do
|
||||||
// not prevent it.
|
// not prevent it.
|
||||||
|
@ -439,7 +439,7 @@ export function create<T>(opts: InputPillCreateOptions<T>): InputPillContainer<T
|
||||||
const $pill = $(this).closest(".pill");
|
const $pill = $(this).closest(".pill");
|
||||||
const $next = $pill.next();
|
const $next = $pill.next();
|
||||||
|
|
||||||
funcs.removePill($pill[0]);
|
funcs.removePill($pill[0]!);
|
||||||
$next.trigger("focus");
|
$next.trigger("focus");
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -52,7 +52,9 @@ export function show_generate_integration_url_modal(api_key: string): void {
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
clipboard.on("success", () => {
|
clipboard.on("success", () => {
|
||||||
show_copied_confirmation($("#generate-integration-url-modal .dialog_submit_button")[0]);
|
show_copied_confirmation(
|
||||||
|
$("#generate-integration-url-modal .dialog_submit_button")[0]!,
|
||||||
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
$override_topic.on("change", function () {
|
$override_topic.on("change", function () {
|
||||||
|
|
|
@ -206,7 +206,7 @@ function submit_invitation_form(): void {
|
||||||
$("#invite-user-modal .dialog_submit_button").text($t({defaultMessage: "Invite"}));
|
$("#invite-user-modal .dialog_submit_button").text($t({defaultMessage: "Invite"}));
|
||||||
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
|
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
|
||||||
$("#invite-user-modal .dialog_exit_button").prop("disabled", false);
|
$("#invite-user-modal .dialog_exit_button").prop("disabled", false);
|
||||||
$invite_status[0].scrollIntoView();
|
$invite_status[0]!.scrollIntoView();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -226,7 +226,7 @@ function generate_multiuse_invite(): void {
|
||||||
clipboard.on("success", () => {
|
clipboard.on("success", () => {
|
||||||
const tippy_timeout_in_ms = 800;
|
const tippy_timeout_in_ms = 800;
|
||||||
show_copied_confirmation(
|
show_copied_confirmation(
|
||||||
$("#copy_generated_invite_link")[0],
|
$("#copy_generated_invite_link")[0]!,
|
||||||
() => {
|
() => {
|
||||||
// Do nothing on hide
|
// Do nothing on hide
|
||||||
},
|
},
|
||||||
|
@ -243,7 +243,7 @@ function generate_multiuse_invite(): void {
|
||||||
);
|
);
|
||||||
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
|
$("#invite-user-modal .dialog_submit_button").prop("disabled", false);
|
||||||
$("#invite-user-modal .dialog_exit_button").prop("disabled", false);
|
$("#invite-user-modal .dialog_exit_button").prop("disabled", false);
|
||||||
$invite_status[0].scrollIntoView();
|
$invite_status[0]!.scrollIntoView();
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ function set_streams_to_join_list_visibility(): void {
|
||||||
const realm_has_default_streams = stream_data.get_default_stream_ids().length !== 0;
|
const realm_has_default_streams = stream_data.get_default_stream_ids().length !== 0;
|
||||||
const hide_streams_list =
|
const hide_streams_list =
|
||||||
realm_has_default_streams &&
|
realm_has_default_streams &&
|
||||||
$<HTMLInputElement>("input#invite_select_default_streams")[0].checked;
|
$<HTMLInputElement>("input#invite_select_default_streams")[0]!.checked;
|
||||||
if (hide_streams_list) {
|
if (hide_streams_list) {
|
||||||
$("#streams_to_add .invite-stream-controls").hide();
|
$("#streams_to_add .invite-stream-controls").hide();
|
||||||
$("#invite-stream-checkboxes").hide();
|
$("#invite-stream-checkboxes").hide();
|
||||||
|
|
|
@ -114,12 +114,12 @@ export class PanZoomControl {
|
||||||
// See https://github.com/anvaka/panzoom/issues/112 for upstream discussion.
|
// See https://github.com/anvaka/panzoom/issues/112 for upstream discussion.
|
||||||
|
|
||||||
const {scale, x, y} = e.getTransform();
|
const {scale, x, y} = e.getTransform();
|
||||||
const image_width = $(".zoom-element > img")[0].clientWidth * scale;
|
const image_width = $(".zoom-element > img")[0]!.clientWidth * scale;
|
||||||
const image_height = $(".zoom-element > img")[0].clientHeight * scale;
|
const image_height = $(".zoom-element > img")[0]!.clientHeight * scale;
|
||||||
const zoom_element_width = $(".zoom-element")[0].clientWidth * scale;
|
const zoom_element_width = $(".zoom-element")[0]!.clientWidth * scale;
|
||||||
const zoom_element_height = $(".zoom-element")[0].clientHeight * scale;
|
const zoom_element_height = $(".zoom-element")[0]!.clientHeight * scale;
|
||||||
const max_translate_x = $(".image-preview")[0].clientWidth;
|
const max_translate_x = $(".image-preview")[0]!.clientWidth;
|
||||||
const max_translate_y = $(".image-preview")[0].clientHeight;
|
const max_translate_y = $(".image-preview")[0]!.clientHeight;
|
||||||
|
|
||||||
// When the image is dragged out of the image-preview container
|
// When the image is dragged out of the image-preview container
|
||||||
// (max_translate) it will be "snapped" back so that the number
|
// (max_translate) it will be "snapped" back so that the number
|
||||||
|
@ -377,7 +377,7 @@ export function build_open_media_function(
|
||||||
payload = asset_map.get($preview_src);
|
payload = asset_map.get($preview_src);
|
||||||
}
|
}
|
||||||
if (payload === undefined) {
|
if (payload === undefined) {
|
||||||
payload = parse_media_data($media[0]);
|
payload = parse_media_data($media[0]!);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -562,7 +562,7 @@ export function initialize(): void {
|
||||||
|
|
||||||
// Bind the pan/zoom control the newly created element.
|
// Bind the pan/zoom control the newly created element.
|
||||||
const pan_zoom_control = new PanZoomControl(
|
const pan_zoom_control = new PanZoomControl(
|
||||||
$("#lightbox_overlay .image-preview > .zoom-element")[0],
|
$("#lightbox_overlay .image-preview > .zoom-element")[0]!,
|
||||||
);
|
);
|
||||||
|
|
||||||
const reset_lightbox_state = function (): void {
|
const reset_lightbox_state = function (): void {
|
||||||
|
|
|
@ -29,7 +29,7 @@ function python_to_js_linkifier(
|
||||||
let current_group = 1;
|
let current_group = 1;
|
||||||
const group_number_to_name: Record<number, string> = {};
|
const group_number_to_name: Record<number, string> = {};
|
||||||
while (match) {
|
while (match) {
|
||||||
const name = match[1];
|
const name = match[1]!;
|
||||||
// Replace named group with regular matching group
|
// Replace named group with regular matching group
|
||||||
pattern = pattern.replace("(?P<" + name + ">", "(");
|
pattern = pattern.replace("(?P<" + name + ">", "(");
|
||||||
// Map numbered reference to named reference for template expansion
|
// Map numbered reference to named reference for template expansion
|
||||||
|
@ -49,7 +49,7 @@ function python_to_js_linkifier(
|
||||||
// JS regexes only support i (case insensitivity) and m (multiline)
|
// JS regexes only support i (case insensitivity) and m (multiline)
|
||||||
// flags, so keep those and ignore the rest
|
// flags, so keep those and ignore the rest
|
||||||
if (match) {
|
if (match) {
|
||||||
const py_flags = match[1];
|
const py_flags = match[1]!;
|
||||||
|
|
||||||
for (const flag of py_flags) {
|
for (const flag of py_flags) {
|
||||||
if ("im".includes(flag)) {
|
if ("im".includes(flag)) {
|
||||||
|
|
|
@ -518,10 +518,10 @@ export function create<Key, Item = Key>(
|
||||||
}
|
}
|
||||||
const rendered_row = opts.modifier_html(item, meta.filter_value);
|
const rendered_row = opts.modifier_html(item, meta.filter_value);
|
||||||
if (insert_index === meta.filtered_list.length - 1) {
|
if (insert_index === meta.filtered_list.length - 1) {
|
||||||
const $target_row = opts.html_selector!(meta.filtered_list[insert_index - 1]);
|
const $target_row = opts.html_selector!(meta.filtered_list[insert_index - 1]!);
|
||||||
$target_row.after($(rendered_row));
|
$target_row.after($(rendered_row));
|
||||||
} else {
|
} else {
|
||||||
const $target_row = opts.html_selector!(meta.filtered_list[insert_index + 1]);
|
const $target_row = opts.html_selector!(meta.filtered_list[insert_index + 1]!);
|
||||||
$target_row.before($(rendered_row));
|
$target_row.before($(rendered_row));
|
||||||
}
|
}
|
||||||
widget.increase_rendered_offset();
|
widget.increase_rendered_offset();
|
||||||
|
|
|
@ -250,7 +250,7 @@ function parse_with_options(
|
||||||
misfeature).
|
misfeature).
|
||||||
*/
|
*/
|
||||||
full_name = match[1];
|
full_name = match[1];
|
||||||
user_id = Number.parseInt(match[2], 10);
|
user_id = Number.parseInt(match[2]!, 10);
|
||||||
|
|
||||||
if (full_name === undefined) {
|
if (full_name === undefined) {
|
||||||
// For @**|id** syntax
|
// For @**|id** syntax
|
||||||
|
@ -420,7 +420,7 @@ export function get_topic_links(topic: string): TopicLink[] {
|
||||||
const template_context = Object.fromEntries(
|
const template_context = Object.fromEntries(
|
||||||
match
|
match
|
||||||
.slice(1)
|
.slice(1)
|
||||||
.map((matched_group, i) => [group_number_to_name[i + 1], matched_group]),
|
.map((matched_group, i) => [group_number_to_name[i + 1]!, matched_group]),
|
||||||
);
|
);
|
||||||
const link_url = url_template.expand(template_context);
|
const link_url = url_template.expand(template_context);
|
||||||
// We store the starting index as well, to sort the order of occurrence of the links
|
// We store the starting index as well, to sort the order of occurrence of the links
|
||||||
|
@ -563,7 +563,7 @@ function handleLinkifier({
|
||||||
assert(item !== undefined);
|
assert(item !== undefined);
|
||||||
const {url_template, group_number_to_name} = item;
|
const {url_template, group_number_to_name} = item;
|
||||||
const template_context = Object.fromEntries(
|
const template_context = Object.fromEntries(
|
||||||
matches.map((match, i) => [group_number_to_name[i + 1], match]),
|
matches.map((match, i) => [group_number_to_name[i + 1]!, match]),
|
||||||
);
|
);
|
||||||
return url_template.expand(template_context);
|
return url_template.expand(template_context);
|
||||||
}
|
}
|
||||||
|
|
|
@ -240,7 +240,7 @@ export function fetch_and_render_message_history(message: Message): void {
|
||||||
.each(function () {
|
.each(function () {
|
||||||
rendered_markdown.update_elements($(this));
|
rendered_markdown.update_elements($(this));
|
||||||
});
|
});
|
||||||
const first_element_id = content_edit_history[0].timestamp;
|
const first_element_id = content_edit_history[0]!.timestamp;
|
||||||
messages_overlay_ui.set_initial_element(
|
messages_overlay_ui.set_initial_element(
|
||||||
String(first_element_id),
|
String(first_element_id),
|
||||||
keyboard_handling_context,
|
keyboard_handling_context,
|
||||||
|
|
|
@ -233,7 +233,7 @@ export class MessageListData {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
const recipient_id = Number.parseInt(recipients[0], 10);
|
const recipient_id = Number.parseInt(recipients[0]!, 10);
|
||||||
return (
|
return (
|
||||||
!muted_users.is_user_muted(recipient_id) &&
|
!muted_users.is_user_muted(recipient_id) &&
|
||||||
!muted_users.is_user_muted(message.sender_id)
|
!muted_users.is_user_muted(message.sender_id)
|
||||||
|
@ -487,7 +487,7 @@ export class MessageListData {
|
||||||
|
|
||||||
let idx = this.selected_idx() + 1;
|
let idx = this.selected_idx() + 1;
|
||||||
while (idx < this._items.length) {
|
while (idx < this._items.length) {
|
||||||
const msg_id = this._items[idx].id;
|
const msg_id = this._items[idx]!.id;
|
||||||
if (!id_set.has(msg_id)) {
|
if (!id_set.has(msg_id)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
|
@ -78,7 +78,7 @@ export function message_viewport_info(): MessageViewportInfo {
|
||||||
export function at_rendered_bottom(): boolean {
|
export function at_rendered_bottom(): boolean {
|
||||||
const bottom = scrollTop() + height();
|
const bottom = scrollTop() + height();
|
||||||
// This also includes bottom whitespace.
|
// This also includes bottom whitespace.
|
||||||
const full_height = $scroll_container[0].scrollHeight;
|
const full_height = $scroll_container[0]!.scrollHeight;
|
||||||
|
|
||||||
// We only know within a pixel or two if we're
|
// We only know within a pixel or two if we're
|
||||||
// exactly at the bottom, due to browser quirkiness,
|
// exactly at the bottom, due to browser quirkiness,
|
||||||
|
@ -94,7 +94,7 @@ export function bottom_rendered_message_visible(): boolean {
|
||||||
const $last_row = rows.last_visible();
|
const $last_row = rows.last_visible();
|
||||||
if ($last_row[0] !== undefined) {
|
if ($last_row[0] !== undefined) {
|
||||||
const message_bottom = $last_row[0].getBoundingClientRect().bottom;
|
const message_bottom = $last_row[0].getBoundingClientRect().bottom;
|
||||||
const bottom_of_feed = $("#compose")[0].getBoundingClientRect().top;
|
const bottom_of_feed = $("#compose")[0]!.getBoundingClientRect().top;
|
||||||
return bottom_of_feed > message_bottom;
|
return bottom_of_feed > message_bottom;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -214,7 +214,7 @@ const top_of_feed = new util.CachedValue({
|
||||||
|
|
||||||
const bottom_of_feed = new util.CachedValue({
|
const bottom_of_feed = new util.CachedValue({
|
||||||
compute_value() {
|
compute_value() {
|
||||||
return $("#compose")[0].getBoundingClientRect().top;
|
return $("#compose")[0]!.getBoundingClientRect().top;
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
|
@ -74,10 +74,10 @@ export function modals_handle_events(event_key: string, context: Context): void
|
||||||
export function set_initial_element(element_id: string, context: Context): void {
|
export function set_initial_element(element_id: string, context: Context): void {
|
||||||
if (element_id) {
|
if (element_id) {
|
||||||
const $current_element = get_element_by_id(element_id, context);
|
const $current_element = get_element_by_id(element_id, context);
|
||||||
const focus_element = $current_element[0].children[0];
|
const focus_element = $current_element[0]!.children[0];
|
||||||
assert(focus_element instanceof HTMLElement);
|
assert(focus_element instanceof HTMLElement);
|
||||||
activate_element(focus_element, context);
|
activate_element(focus_element, context);
|
||||||
$(`.${CSS.escape(context.items_list_selector)}`)[0].scrollTop = 0;
|
$(`.${CSS.escape(context.items_list_selector)}`)[0]!.scrollTop = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,7 +132,7 @@ function initialize_focus(event_name: string, context: Context): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const $element = get_element_by_id(id, context);
|
const $element = get_element_by_id(id, context);
|
||||||
const focus_element = $element[0].children[0];
|
const focus_element = $element[0]!.children[0];
|
||||||
assert(focus_element instanceof HTMLElement);
|
assert(focus_element instanceof HTMLElement);
|
||||||
activate_element(focus_element, context);
|
activate_element(focus_element, context);
|
||||||
}
|
}
|
||||||
|
@ -152,28 +152,28 @@ function scroll_to_element($element: JQuery, context: Context): void {
|
||||||
const $box_item = $(`.${CSS.escape(context.box_item_selector)}`);
|
const $box_item = $(`.${CSS.escape(context.box_item_selector)}`);
|
||||||
|
|
||||||
// If focused element is first, scroll to the top.
|
// If focused element is first, scroll to the top.
|
||||||
if ($box_item.first()[0].parentElement === $element[0]) {
|
if ($box_item.first()[0]!.parentElement === $element[0]) {
|
||||||
$items_list[0].scrollTop = 0;
|
$items_list[0]!.scrollTop = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If focused element is last, scroll to the bottom.
|
// If focused element is last, scroll to the bottom.
|
||||||
if ($box_item.last()[0].parentElement === $element[0]) {
|
if ($box_item.last()[0]!.parentElement === $element[0]) {
|
||||||
$items_list[0].scrollTop = $items_list[0].scrollHeight - ($items_list.height() ?? 0);
|
$items_list[0]!.scrollTop = $items_list[0]!.scrollHeight - ($items_list.height() ?? 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// If focused element is cut off from the top, scroll up halfway in modal.
|
// If focused element is cut off from the top, scroll up halfway in modal.
|
||||||
if ($element.position().top < 55) {
|
if ($element.position().top < 55) {
|
||||||
// 55 is the minimum distance from the top that will require extra scrolling.
|
// 55 is the minimum distance from the top that will require extra scrolling.
|
||||||
$items_list[0].scrollTop -= $items_list[0].clientHeight / 2;
|
$items_list[0]!.scrollTop -= $items_list[0]!.clientHeight / 2;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If focused element is cut off from the bottom, scroll down halfway in modal.
|
// If focused element is cut off from the bottom, scroll down halfway in modal.
|
||||||
const dist_from_top = $element.position().top;
|
const dist_from_top = $element.position().top;
|
||||||
const total_dist = dist_from_top + $element[0].clientHeight;
|
const total_dist = dist_from_top + $element[0].clientHeight;
|
||||||
const dist_from_bottom = $items_container[0].clientHeight - total_dist;
|
const dist_from_bottom = $items_container[0]!.clientHeight - total_dist;
|
||||||
if (dist_from_bottom < -4) {
|
if (dist_from_bottom < -4) {
|
||||||
// -4 is the min dist from the bottom that will require extra scrolling.
|
// -4 is the min dist from the bottom that will require extra scrolling.
|
||||||
$items_list[0].scrollTop += $items_list[0].clientHeight / 2;
|
$items_list[0]!.scrollTop += $items_list[0]!.clientHeight / 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ function retrieve_search_query_data(): SearchData {
|
||||||
const current_filter = narrow_state.filter();
|
const current_filter = narrow_state.filter();
|
||||||
assert(current_filter !== undefined);
|
assert(current_filter !== undefined);
|
||||||
const search_query = current_filter.operands("search")[0];
|
const search_query = current_filter.operands("search")[0];
|
||||||
const query_words = search_query.split(" ");
|
const query_words = search_query!.split(" ");
|
||||||
|
|
||||||
const search_string_result: SearchData = {
|
const search_string_result: SearchData = {
|
||||||
query_words: [],
|
query_words: [],
|
||||||
|
@ -96,7 +96,7 @@ function pick_empty_narrow_banner(): NarrowBannerData {
|
||||||
return default_banner;
|
return default_banner;
|
||||||
}
|
}
|
||||||
|
|
||||||
const first_term = current_filter.terms()[0];
|
const first_term = current_filter.terms()[0]!;
|
||||||
const first_operator = first_term.operator;
|
const first_operator = first_term.operator;
|
||||||
const first_operand = first_term.operand;
|
const first_operand = first_term.operand;
|
||||||
const num_terms = current_filter.terms().length;
|
const num_terms = current_filter.terms().length;
|
||||||
|
|
|
@ -47,7 +47,7 @@ export function compute_narrow_title(filter?: Filter): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.has_operator("dm")) {
|
if (filter.has_operator("dm")) {
|
||||||
const emails = filter.operands("dm")[0];
|
const emails = filter.operands("dm")[0]!;
|
||||||
const user_ids = people.emails_strings_to_user_ids_string(emails);
|
const user_ids = people.emails_strings_to_user_ids_string(emails);
|
||||||
|
|
||||||
if (user_ids !== undefined) {
|
if (user_ids !== undefined) {
|
||||||
|
@ -60,7 +60,7 @@ export function compute_narrow_title(filter?: Filter): string {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filter.has_operator("sender")) {
|
if (filter.has_operator("sender")) {
|
||||||
const user = people.get_by_email(filter.operands("sender")[0]);
|
const user = people.get_by_email(filter.operands("sender")[0]!);
|
||||||
if (user) {
|
if (user) {
|
||||||
if (people.is_my_user_id(user.user_id)) {
|
if (people.is_my_user_id(user.user_id)) {
|
||||||
return $t({defaultMessage: "Messages sent by you"});
|
return $t({defaultMessage: "Messages sent by you"});
|
||||||
|
|
|
@ -737,7 +737,7 @@ export function slug_to_emails(slug: string): string | undefined {
|
||||||
*/
|
*/
|
||||||
const m = /^([\d,]+)(-.*)?/.exec(slug);
|
const m = /^([\d,]+)(-.*)?/.exec(slug);
|
||||||
if (m) {
|
if (m) {
|
||||||
let user_ids_string = m[1];
|
let user_ids_string = m[1]!;
|
||||||
user_ids_string = exclude_me_from_string(user_ids_string);
|
user_ids_string = exclude_me_from_string(user_ids_string);
|
||||||
return user_ids_string_to_emails_string(user_ids_string);
|
return user_ids_string_to_emails_string(user_ids_string);
|
||||||
}
|
}
|
||||||
|
|
|
@ -126,7 +126,7 @@ function register_click_handlers(): void {
|
||||||
}
|
}
|
||||||
const popover_target = $view_in_playground_button.find(
|
const popover_target = $view_in_playground_button.find(
|
||||||
".playground-links-popover-container",
|
".playground-links-popover-container",
|
||||||
)[0];
|
)[0]!;
|
||||||
toggle_playground_links_popover(popover_target, playground_store);
|
toggle_playground_links_popover(popover_target, playground_store);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -46,7 +46,7 @@ export function poll_options_setup(): void {
|
||||||
|
|
||||||
// setTimeout is needed to here to give time for simplebar to initialise
|
// setTimeout is needed to here to give time for simplebar to initialise
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
SortableJS.create($("#add-poll-form .poll-options-list .simplebar-content")[0], {
|
SortableJS.create($("#add-poll-form .poll-options-list .simplebar-content")[0]!, {
|
||||||
onUpdate() {
|
onUpdate() {
|
||||||
// Do nothing on drag; the order is only processed on submission.
|
// Do nothing on drag; the order is only processed on submission.
|
||||||
},
|
},
|
||||||
|
|
|
@ -192,7 +192,7 @@ export const default_popover_props: Partial<tippy.Props> = {
|
||||||
// $tippy_box[0].hasAttribute("data-reference-hidden"); is the real check
|
// $tippy_box[0].hasAttribute("data-reference-hidden"); is the real check
|
||||||
// but linter wants us to write it like this.
|
// but linter wants us to write it like this.
|
||||||
const is_reference_outside_window = Object.hasOwn(
|
const is_reference_outside_window = Object.hasOwn(
|
||||||
$tippy_box[0].dataset,
|
$tippy_box[0]!.dataset,
|
||||||
"referenceHidden",
|
"referenceHidden",
|
||||||
);
|
);
|
||||||
if (is_reference_outside_window) {
|
if (is_reference_outside_window) {
|
||||||
|
@ -215,7 +215,7 @@ export const default_popover_props: Partial<tippy.Props> = {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reference_rect = $reference[0].getBoundingClientRect();
|
const reference_rect = $reference[0]!.getBoundingClientRect();
|
||||||
// This is the logic we want but since it is too expensive to run
|
// This is the logic we want but since it is too expensive to run
|
||||||
// on every scroll, we run a cheaper version of this to just check if
|
// on every scroll, we run a cheaper version of this to just check if
|
||||||
// compose, sticky header or navbar are not obscuring the reference
|
// compose, sticky header or navbar are not obscuring the reference
|
||||||
|
|
|
@ -8,7 +8,7 @@ function get_new_rand(old_random_int: number, max: number): number {
|
||||||
|
|
||||||
function get_random_item_from_array<T>(array: T[]): T {
|
function get_random_item_from_array<T>(array: T[]): T {
|
||||||
assert(array.length >= 1);
|
assert(array.length >= 1);
|
||||||
return array[Math.floor(Math.random() * array.length)];
|
return array[Math.floor(Math.random() * array.length)]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
const current_client_logo_class_names = new Set([
|
const current_client_logo_class_names = new Set([
|
||||||
|
@ -40,7 +40,7 @@ function update_client_logo(): void {
|
||||||
current_client_logo_class_names_index,
|
current_client_logo_class_names_index,
|
||||||
client_logos.length,
|
client_logos.length,
|
||||||
);
|
);
|
||||||
const client_logo_elt = client_logos[current_client_logo_class_names_index];
|
const client_logo_elt = client_logos[current_client_logo_class_names_index]!;
|
||||||
|
|
||||||
const current_logo_class = client_logo_elt.className;
|
const current_logo_class = client_logo_elt.className;
|
||||||
current_client_logo_class_names.delete(current_logo_class);
|
current_client_logo_class_names.delete(current_logo_class);
|
||||||
|
|
|
@ -58,7 +58,7 @@ export function activate_correct_tab($tabbed_section: JQuery): void {
|
||||||
const $active_list_items = $li.filter(".active");
|
const $active_list_items = $li.filter(".active");
|
||||||
if (!$active_list_items.length) {
|
if (!$active_list_items.length) {
|
||||||
$li.first().addClass("active");
|
$li.first().addClass("active");
|
||||||
const tab_key = $li.first()[0].dataset.tabKey;
|
const tab_key = $li.first()[0]!.dataset.tabKey;
|
||||||
if (tab_key) {
|
if (tab_key) {
|
||||||
$blocks.filter("[data-tab-key=" + tab_key + "]").addClass("active");
|
$blocks.filter("[data-tab-key=" + tab_key + "]").addClass("active");
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -89,7 +89,7 @@ export function show_user_list(message_id: number): void {
|
||||||
$("#read_receipts_modal .read_receipts_list").html(
|
$("#read_receipts_modal .read_receipts_list").html(
|
||||||
render_read_receipts(context),
|
render_read_receipts(context),
|
||||||
);
|
);
|
||||||
new SimpleBar($("#read_receipts_modal .modal__content")[0]);
|
new SimpleBar($("#read_receipts_modal .modal__content")[0]!);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
error(xhr) {
|
error(xhr) {
|
||||||
|
|
|
@ -340,7 +340,7 @@ function set_table_focus(row: number, col: number, using_keyboard = false): bool
|
||||||
if (using_keyboard) {
|
if (using_keyboard) {
|
||||||
const scroll_element = $(
|
const scroll_element = $(
|
||||||
"#recent_view_table .table_fix_head .simplebar-content-wrapper",
|
"#recent_view_table .table_fix_head .simplebar-content-wrapper",
|
||||||
)[0];
|
)[0]!;
|
||||||
const half_height_of_visible_area = scroll_element.offsetHeight / 2;
|
const half_height_of_visible_area = scroll_element.offsetHeight / 2;
|
||||||
const topic_offset = topic_offset_to_visible_area($topic_row);
|
const topic_offset = topic_offset_to_visible_area($topic_row);
|
||||||
|
|
||||||
|
@ -1093,14 +1093,14 @@ function topic_offset_to_visible_area($topic_row: JQuery): string | undefined {
|
||||||
}
|
}
|
||||||
const $scroll_container = $("#recent_view_table .table_fix_head");
|
const $scroll_container = $("#recent_view_table .table_fix_head");
|
||||||
const thead_height = $scroll_container.find("thead").outerHeight(true)!;
|
const thead_height = $scroll_container.find("thead").outerHeight(true)!;
|
||||||
const scroll_container_props = $scroll_container[0].getBoundingClientRect();
|
const scroll_container_props = $scroll_container[0]!.getBoundingClientRect();
|
||||||
|
|
||||||
// Since user cannot see row under thead, exclude it as part of the scroll container.
|
// Since user cannot see row under thead, exclude it as part of the scroll container.
|
||||||
const scroll_container_top = scroll_container_props.top + thead_height;
|
const scroll_container_top = scroll_container_props.top + thead_height;
|
||||||
const compose_height = $("#compose").outerHeight(true)!;
|
const compose_height = $("#compose").outerHeight(true)!;
|
||||||
const scroll_container_bottom = scroll_container_props.bottom - compose_height;
|
const scroll_container_bottom = scroll_container_props.bottom - compose_height;
|
||||||
|
|
||||||
const topic_props = $topic_row[0].getBoundingClientRect();
|
const topic_props = $topic_row[0]!.getBoundingClientRect();
|
||||||
|
|
||||||
// Topic is above the visible scroll region.
|
// Topic is above the visible scroll region.
|
||||||
if (topic_props.top < scroll_container_top) {
|
if (topic_props.top < scroll_container_top) {
|
||||||
|
@ -1119,7 +1119,7 @@ function recenter_focus_if_off_screen(): void {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const table_wrapper_element = $("#recent_view_table .table_fix_head")[0];
|
const table_wrapper_element = $("#recent_view_table .table_fix_head")[0]!;
|
||||||
const $topic_rows = $("#recent_view_table table tbody tr");
|
const $topic_rows = $("#recent_view_table table tbody tr");
|
||||||
|
|
||||||
if (row_focus >= $topic_rows.length) {
|
if (row_focus >= $topic_rows.length) {
|
||||||
|
|
|
@ -312,7 +312,7 @@ export const update_elements = ($content: JQuery): void => {
|
||||||
$view_in_playground_button.attr("aria-label", title);
|
$view_in_playground_button.attr("aria-label", title);
|
||||||
}
|
}
|
||||||
const $copy_button = $buttonContainer.find(".copy_codeblock");
|
const $copy_button = $buttonContainer.find(".copy_codeblock");
|
||||||
const clipboard = new ClipboardJS($copy_button[0], {
|
const clipboard = new ClipboardJS($copy_button[0]!, {
|
||||||
text(copy_element) {
|
text(copy_element) {
|
||||||
const $code = $(copy_element).parent().siblings("code");
|
const $code = $(copy_element).parent().siblings("code");
|
||||||
return $code.text();
|
return $code.text();
|
||||||
|
@ -320,7 +320,7 @@ export const update_elements = ($content: JQuery): void => {
|
||||||
});
|
});
|
||||||
|
|
||||||
clipboard.on("success", () => {
|
clipboard.on("success", () => {
|
||||||
show_copied_confirmation($copy_button[0]);
|
show_copied_confirmation($copy_button[0]!);
|
||||||
});
|
});
|
||||||
$codehilite.addClass("zulip-code-block");
|
$codehilite.addClass("zulip-code-block");
|
||||||
});
|
});
|
||||||
|
|
|
@ -5,7 +5,7 @@ import SimpleBar from "simplebar";
|
||||||
type JQueryOrZJQuery = {__zjquery?: true} & JQuery;
|
type JQueryOrZJQuery = {__zjquery?: true} & JQuery;
|
||||||
|
|
||||||
export function get_content_element($element: JQuery): JQuery {
|
export function get_content_element($element: JQuery): JQuery {
|
||||||
const element = $element.expectOne()[0];
|
const element = $element.expectOne()[0]!;
|
||||||
const sb = SimpleBar.instances.get(element);
|
const sb = SimpleBar.instances.get(element);
|
||||||
if (sb) {
|
if (sb) {
|
||||||
return $(sb.getContentElement()!);
|
return $(sb.getContentElement()!);
|
||||||
|
@ -19,7 +19,7 @@ export function get_scroll_element($element: JQueryOrZJQuery): JQuery {
|
||||||
return $element;
|
return $element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const element = $element.expectOne()[0];
|
const element = $element.expectOne()[0]!;
|
||||||
const sb = SimpleBar.instances.get(element);
|
const sb = SimpleBar.instances.get(element);
|
||||||
if (sb) {
|
if (sb) {
|
||||||
return $(sb.getScrollElement()!);
|
return $(sb.getScrollElement()!);
|
||||||
|
@ -32,7 +32,7 @@ export function get_scroll_element($element: JQueryOrZJQuery): JQuery {
|
||||||
}
|
}
|
||||||
|
|
||||||
export function reset_scrollbar($element: JQuery): void {
|
export function reset_scrollbar($element: JQuery): void {
|
||||||
const element = $element.expectOne()[0];
|
const element = $element.expectOne()[0]!;
|
||||||
const sb = SimpleBar.instances.get(element);
|
const sb = SimpleBar.instances.get(element);
|
||||||
if (sb) {
|
if (sb) {
|
||||||
sb.getScrollElement()!.scrollTop = 0;
|
sb.getScrollElement()!.scrollTop = 0;
|
||||||
|
|
|
@ -187,7 +187,7 @@ export function extract_property_name($elem: JQuery, for_realm_default_settings?
|
||||||
// "realm_{settings_name}}" because both user and realm default
|
// "realm_{settings_name}}" because both user and realm default
|
||||||
// settings use the same template and each element should have
|
// settings use the same template and each element should have
|
||||||
// unique id.
|
// unique id.
|
||||||
return /^realm_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1];
|
return /^realm_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem_id.startsWith("id_authmethod")) {
|
if (elem_id.startsWith("id_authmethod")) {
|
||||||
|
@ -197,14 +197,14 @@ export function extract_property_name($elem: JQuery, for_realm_default_settings?
|
||||||
// The [\da-z]+ part of the regexp covers the auth method name itself.
|
// The [\da-z]+ part of the regexp covers the auth method name itself.
|
||||||
// We assume it's not an empty string and can contain only digits and lowercase ASCII letters,
|
// We assume it's not an empty string and can contain only digits and lowercase ASCII letters,
|
||||||
// this is ensured by a respective allowlist-based filter in populate_auth_methods().
|
// this is ensured by a respective allowlist-based filter in populate_auth_methods().
|
||||||
return /^id_authmethod[\da-z]+_(.*)$/.exec(elem_id)![1];
|
return /^id_authmethod[\da-z]+_(.*)$/.exec(elem_id)![1]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (elem_id.startsWith("id-custom-profile-field")) {
|
if (elem_id.startsWith("id-custom-profile-field")) {
|
||||||
return /^id_custom_profile_field_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1];
|
return /^id_custom_profile_field_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
return /^id_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1];
|
return /^id_(.*)$/.exec(elem_id.replaceAll("-", "_"))![1]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function get_subsection_property_elements($subsection: JQuery): HTMLElement[] {
|
export function get_subsection_property_elements($subsection: JQuery): HTMLElement[] {
|
||||||
|
@ -397,7 +397,7 @@ function read_select_field_data_from_form(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
$profile_field_form.find("div.choice-row").each(function (this: HTMLElement) {
|
$profile_field_form.find("div.choice-row").each(function (this: HTMLElement) {
|
||||||
const text = $(this).find("input")[0].value;
|
const text = $(this).find("input")[0]!.value;
|
||||||
if (text) {
|
if (text) {
|
||||||
let value = old_option_value_map.get(text);
|
let value = old_option_value_map.get(text);
|
||||||
if (value !== undefined) {
|
if (value !== undefined) {
|
||||||
|
@ -753,7 +753,7 @@ export function get_auth_method_list_data(): Record<string, boolean> {
|
||||||
for (const method_row of $auth_method_rows) {
|
for (const method_row of $auth_method_rows) {
|
||||||
const method = $(method_row).attr("data-method");
|
const method = $(method_row).attr("data-method");
|
||||||
assert(method !== undefined);
|
assert(method !== undefined);
|
||||||
new_auth_methods[method] = $(method_row).find<HTMLInputElement>("input")[0].checked;
|
new_auth_methods[method] = $(method_row).find<HTMLInputElement>("input")[0]!.checked;
|
||||||
}
|
}
|
||||||
|
|
||||||
return new_auth_methods;
|
return new_auth_methods;
|
||||||
|
@ -957,11 +957,11 @@ export function populate_data_for_request(
|
||||||
$input_elem.attr("id")!,
|
$input_elem.attr("id")!,
|
||||||
);
|
);
|
||||||
assert(match_array !== null);
|
assert(match_array !== null);
|
||||||
property_name = match_array[1];
|
property_name = match_array[1]!;
|
||||||
} else {
|
} else {
|
||||||
const match_array = /^id_realm_(.*)$/.exec($input_elem.attr("id")!);
|
const match_array = /^id_realm_(.*)$/.exec($input_elem.attr("id")!);
|
||||||
assert(match_array !== null);
|
assert(match_array !== null);
|
||||||
property_name = match_array[1];
|
property_name = match_array[1]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (property_name === "stream_privacy") {
|
if (property_name === "stream_privacy") {
|
||||||
|
@ -1146,7 +1146,7 @@ function enable_or_disable_save_button($subsection_elem: JQuery): void {
|
||||||
const $button_wrapper = $subsection_elem.find<tippy.PopperElement>(
|
const $button_wrapper = $subsection_elem.find<tippy.PopperElement>(
|
||||||
".subsection-changes-save",
|
".subsection-changes-save",
|
||||||
);
|
);
|
||||||
const tippy_instance = $button_wrapper[0]._tippy;
|
const tippy_instance = $button_wrapper[0]!._tippy;
|
||||||
if (disable_save_btn) {
|
if (disable_save_btn) {
|
||||||
// avoid duplication of tippy
|
// avoid duplication of tippy
|
||||||
if (!tippy_instance) {
|
if (!tippy_instance) {
|
||||||
|
@ -1184,5 +1184,5 @@ export function initialize_disable_btn_hint_popover(
|
||||||
if (hint_text !== undefined) {
|
if (hint_text !== undefined) {
|
||||||
tippy_opts.content = hint_text;
|
tippy_opts.content = hint_text;
|
||||||
}
|
}
|
||||||
tippy.default($btn_wrapper[0], tippy_opts);
|
tippy.default($btn_wrapper[0]!, tippy_opts);
|
||||||
}
|
}
|
||||||
|
|
|
@ -265,7 +265,7 @@ function show_modal(): void {
|
||||||
}
|
}
|
||||||
|
|
||||||
const formData = new FormData();
|
const formData = new FormData();
|
||||||
const files = $<HTMLInputElement>("input#emoji_file_input")[0].files;
|
const files = $<HTMLInputElement>("input#emoji_file_input")[0]!.files;
|
||||||
assert(files !== null);
|
assert(files !== null);
|
||||||
for (const [i, file] of [...files].entries()) {
|
for (const [i, file] of [...files].entries()) {
|
||||||
formData.append("file-" + i, file);
|
formData.append("file-" + i, file);
|
||||||
|
|
|
@ -194,7 +194,7 @@ export function populate_linkifiers(linkifiers_data: RealmLinkifiers): void {
|
||||||
});
|
});
|
||||||
|
|
||||||
if (current_user.is_admin) {
|
if (current_user.is_admin) {
|
||||||
new SortableJS($linkifiers_table[0], {
|
new SortableJS($linkifiers_table[0]!, {
|
||||||
onUpdate: update_linkifiers_order,
|
onUpdate: update_linkifiers_order,
|
||||||
handle: ".move-handle",
|
handle: ".move-handle",
|
||||||
filter: "input",
|
filter: "input",
|
||||||
|
|
|
@ -421,7 +421,7 @@ function set_up_select_field_edit_form(
|
||||||
|
|
||||||
// Add blank choice at last
|
// Add blank choice at last
|
||||||
create_choice_row($choice_list);
|
create_choice_row($choice_list);
|
||||||
SortableJS.create($choice_list[0], {
|
SortableJS.create($choice_list[0]!, {
|
||||||
onUpdate() {
|
onUpdate() {
|
||||||
// Do nothing on drag. We process the order on submission
|
// Do nothing on drag. We process the order on submission
|
||||||
},
|
},
|
||||||
|
@ -706,7 +706,7 @@ export function do_populate_profile_fields(profile_fields_data: CustomProfileFie
|
||||||
display_in_profile_summary_fields_limit_reached = display_in_profile_summary_fields_count >= 2;
|
display_in_profile_summary_fields_limit_reached = display_in_profile_summary_fields_count >= 2;
|
||||||
|
|
||||||
if (current_user.is_admin) {
|
if (current_user.is_admin) {
|
||||||
const field_list = $("#admin_profile_fields_table")[0];
|
const field_list = $("#admin_profile_fields_table")[0]!;
|
||||||
SortableJS.create(field_list, {
|
SortableJS.create(field_list, {
|
||||||
onUpdate: update_field_order,
|
onUpdate: update_field_order,
|
||||||
filter: "input",
|
filter: "input",
|
||||||
|
@ -724,7 +724,7 @@ function set_up_select_field(): void {
|
||||||
create_choice_row($("#profile_field_choices"));
|
create_choice_row($("#profile_field_choices"));
|
||||||
|
|
||||||
if (current_user.is_admin) {
|
if (current_user.is_admin) {
|
||||||
const choice_list = $("#profile_field_choices")[0];
|
const choice_list = $("#profile_field_choices")[0]!;
|
||||||
SortableJS.create(choice_list, {
|
SortableJS.create(choice_list, {
|
||||||
onUpdate() {
|
onUpdate() {
|
||||||
// Do nothing on drag. We process the order on submission
|
// Do nothing on drag. We process the order on submission
|
||||||
|
|
|
@ -114,7 +114,7 @@ export function setup_realm_domains_modal_handlers(): void {
|
||||||
const domain = $widget.find(".new-realm-domain").val();
|
const domain = $widget.find(".new-realm-domain").val();
|
||||||
const allow_subdomains = $widget.find<HTMLInputElement>(
|
const allow_subdomains = $widget.find<HTMLInputElement>(
|
||||||
"input.new-realm-domain-allow-subdomains",
|
"input.new-realm-domain-allow-subdomains",
|
||||||
)[0].checked;
|
)[0]!.checked;
|
||||||
const data = {
|
const data = {
|
||||||
domain,
|
domain,
|
||||||
allow_subdomains: JSON.stringify(allow_subdomains),
|
allow_subdomains: JSON.stringify(allow_subdomains),
|
||||||
|
|
|
@ -25,7 +25,7 @@ $(() => {
|
||||||
}
|
}
|
||||||
|
|
||||||
$.fn.get_offset_to_window = function () {
|
$.fn.get_offset_to_window = function () {
|
||||||
return this[0].getBoundingClientRect();
|
return this[0]!.getBoundingClientRect();
|
||||||
};
|
};
|
||||||
|
|
||||||
$.fn.expectOne = function () {
|
$.fn.expectOne = function () {
|
||||||
|
|
|
@ -21,7 +21,7 @@ function expand_spoiler($spoiler: JQuery): void {
|
||||||
// of the content). CSS animations do not work with properties set to
|
// of the content). CSS animations do not work with properties set to
|
||||||
// `auto`, so we get the actual height of the content here and temporarily
|
// `auto`, so we get the actual height of the content here and temporarily
|
||||||
// put it explicitly on the element styling to allow the transition to work.
|
// put it explicitly on the element styling to allow the transition to work.
|
||||||
const spoiler_height = $spoiler[0].scrollHeight;
|
const spoiler_height = $spoiler[0]!.scrollHeight;
|
||||||
$spoiler.height(`${spoiler_height}px`);
|
$spoiler.height(`${spoiler_height}px`);
|
||||||
// The `spoiler-content-open` class has CSS animations defined on it which
|
// The `spoiler-content-open` class has CSS animations defined on it which
|
||||||
// will trigger on the frame after this class change.
|
// will trigger on the frame after this class change.
|
||||||
|
|
|
@ -419,7 +419,7 @@ function populate_messages_sent_over_time(raw_data: unknown): void {
|
||||||
.on("plotly_hover", (data) => {
|
.on("plotly_hover", (data) => {
|
||||||
$("#hoverinfo").show();
|
$("#hoverinfo").show();
|
||||||
document.querySelector("#hover_date")!.textContent =
|
document.querySelector("#hover_date")!.textContent =
|
||||||
data.points[0].data.text[data.points[0].pointNumber];
|
data.points[0]!.data.text[data.points[0]!.pointNumber]!;
|
||||||
const values: Plotly.Datum[] = [null, null, null];
|
const values: Plotly.Datum[] = [null, null, null];
|
||||||
for (const trace of data.points) {
|
for (const trace of data.points) {
|
||||||
values[trace.curveNumber] = trace.y;
|
values[trace.curveNumber] = trace.y;
|
||||||
|
@ -432,16 +432,16 @@ function populate_messages_sent_over_time(raw_data: unknown): void {
|
||||||
];
|
];
|
||||||
for (const [i, value] of values.entries()) {
|
for (const [i, value] of values.entries()) {
|
||||||
if (value !== null) {
|
if (value !== null) {
|
||||||
document.querySelector<HTMLElement>(hover_text_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_text_ids[i]!)!.style.display =
|
||||||
"inline";
|
"inline";
|
||||||
document.querySelector<HTMLElement>(hover_value_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_value_ids[i]!)!.style.display =
|
||||||
"inline";
|
"inline";
|
||||||
document.querySelector<HTMLElement>(hover_value_ids[i])!.textContent =
|
document.querySelector<HTMLElement>(hover_value_ids[i]!)!.textContent =
|
||||||
value.toString();
|
value.toString();
|
||||||
} else {
|
} else {
|
||||||
document.querySelector<HTMLElement>(hover_text_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_text_ids[i]!)!.style.display =
|
||||||
"none";
|
"none";
|
||||||
document.querySelector<HTMLElement>(hover_value_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_value_ids[i]!)!.style.display =
|
||||||
"none";
|
"none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -461,13 +461,13 @@ function populate_messages_sent_over_time(raw_data: unknown): void {
|
||||||
let start;
|
let start;
|
||||||
let is_boundary;
|
let is_boundary;
|
||||||
if (aggregation === "day") {
|
if (aggregation === "day") {
|
||||||
start = floor_to_local_day(start_dates[0]);
|
start = floor_to_local_day(start_dates[0]!);
|
||||||
is_boundary = function (date: Date) {
|
is_boundary = function (date: Date) {
|
||||||
return date.getHours() === 0;
|
return date.getHours() === 0;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
assert(aggregation === "week");
|
assert(aggregation === "week");
|
||||||
start = floor_to_local_week(start_dates[0]);
|
start = floor_to_local_week(start_dates[0]!);
|
||||||
is_boundary = function (date: Date) {
|
is_boundary = function (date: Date) {
|
||||||
return date.getHours() === 0 && date.getDay() === 0;
|
return date.getHours() === 0 && date.getDay() === 0;
|
||||||
};
|
};
|
||||||
|
@ -476,25 +476,25 @@ function populate_messages_sent_over_time(raw_data: unknown): void {
|
||||||
const values: DataByUserType<number[]> = {human: [], bot: [], me: []};
|
const values: DataByUserType<number[]> = {human: [], bot: [], me: []};
|
||||||
let current: DataByUserType<number> = {human: 0, bot: 0, me: 0};
|
let current: DataByUserType<number> = {human: 0, bot: 0, me: 0};
|
||||||
let i_init = 0;
|
let i_init = 0;
|
||||||
if (is_boundary(start_dates[0])) {
|
if (is_boundary(start_dates[0]!)) {
|
||||||
current = {
|
current = {
|
||||||
human: data.everyone.human[0],
|
human: data.everyone.human[0]!,
|
||||||
bot: data.everyone.bot[0],
|
bot: data.everyone.bot[0]!,
|
||||||
me: data.user.human[0],
|
me: data.user.human[0]!,
|
||||||
};
|
};
|
||||||
i_init = 1;
|
i_init = 1;
|
||||||
}
|
}
|
||||||
for (let i = i_init; i < start_dates.length; i += 1) {
|
for (let i = i_init; i < start_dates.length; i += 1) {
|
||||||
if (is_boundary(start_dates[i])) {
|
if (is_boundary(start_dates[i]!)) {
|
||||||
dates.push(start_dates[i]);
|
dates.push(start_dates[i]!);
|
||||||
values.human.push(current.human);
|
values.human.push(current.human);
|
||||||
values.bot.push(current.bot);
|
values.bot.push(current.bot);
|
||||||
values.me.push(current.me);
|
values.me.push(current.me);
|
||||||
current = {human: 0, bot: 0, me: 0};
|
current = {human: 0, bot: 0, me: 0};
|
||||||
}
|
}
|
||||||
current.human += data.everyone.human[i];
|
current.human += data.everyone.human[i]!;
|
||||||
current.bot += data.everyone.bot[i];
|
current.bot += data.everyone.bot[i]!;
|
||||||
current.me += data.user.human[i];
|
current.me += data.user.human[i]!;
|
||||||
}
|
}
|
||||||
values.human.push(current.human);
|
values.human.push(current.human);
|
||||||
values.bot.push(current.bot);
|
values.bot.push(current.bot);
|
||||||
|
@ -563,9 +563,9 @@ function populate_messages_sent_over_time(raw_data: unknown): void {
|
||||||
const plotDiv = document.querySelector<Plotly.PlotlyHTMLElement>(
|
const plotDiv = document.querySelector<Plotly.PlotlyHTMLElement>(
|
||||||
"#id_messages_sent_over_time",
|
"#id_messages_sent_over_time",
|
||||||
)!;
|
)!;
|
||||||
assert("visible" in plotDiv.data[0]);
|
assert("visible" in plotDiv.data[0]!);
|
||||||
assert("visible" in plotDiv.data[1]);
|
assert("visible" in plotDiv.data[1]!);
|
||||||
assert("visible" in plotDiv.data[2]);
|
assert("visible" in plotDiv.data[2]!);
|
||||||
traces.me.visible = plotDiv.data[0].visible;
|
traces.me.visible = plotDiv.data[0].visible;
|
||||||
traces.human.visible = plotDiv.data[1].visible;
|
traces.human.visible = plotDiv.data[1].visible;
|
||||||
traces.bot.visible = plotDiv.data[2].visible;
|
traces.bot.visible = plotDiv.data[2].visible;
|
||||||
|
@ -730,8 +730,8 @@ function populate_messages_sent_by_client(raw_data: unknown): void {
|
||||||
const label_values: {label: string; value: number}[] = [];
|
const label_values: {label: string; value: number}[] = [];
|
||||||
for (let i = 0; i < everyone_month.values.length; i += 1) {
|
for (let i = 0; i < everyone_month.values.length; i += 1) {
|
||||||
label_values.push({
|
label_values.push({
|
||||||
label: everyone_month.labels[i],
|
label: everyone_month.labels[i]!,
|
||||||
value: everyone_month.labels[i] === "Other" ? -1 : everyone_month.values[i],
|
value: everyone_month.labels[i] === "Other" ? -1 : everyone_month.values[i]!,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
label_values.sort((a, b) => b.value - a.value);
|
label_values.sort((a, b) => b.value - a.value);
|
||||||
|
@ -754,9 +754,9 @@ function populate_messages_sent_by_client(raw_data: unknown): void {
|
||||||
text: [],
|
text: [],
|
||||||
};
|
};
|
||||||
for (let i = 0; i < plot_data.values.length; i += 1) {
|
for (let i = 0; i < plot_data.values.length; i += 1) {
|
||||||
if (plot_data.values[i] > 0) {
|
if (plot_data.values[i]! > 0) {
|
||||||
annotations.values.push(plot_data.values[i]);
|
annotations.values.push(plot_data.values[i]!);
|
||||||
annotations.labels.push(plot_data.labels[i]);
|
annotations.labels.push(plot_data.labels[i]!);
|
||||||
annotations.text.push(
|
annotations.text.push(
|
||||||
" " + plot_data.labels[i] + " (" + plot_data.percentages[i] + ")",
|
" " + plot_data.labels[i] + " (" + plot_data.percentages[i] + ")",
|
||||||
);
|
);
|
||||||
|
@ -1044,7 +1044,7 @@ function populate_number_of_users(raw_data: unknown): void {
|
||||||
.on("plotly_hover", (data) => {
|
.on("plotly_hover", (data) => {
|
||||||
$("#users_hover_info").show();
|
$("#users_hover_info").show();
|
||||||
document.querySelector("#users_hover_date")!.textContent =
|
document.querySelector("#users_hover_date")!.textContent =
|
||||||
data.points[0].data.text[data.points[0].pointNumber];
|
data.points[0]!.data.text[data.points[0]!.pointNumber]!;
|
||||||
const values: Plotly.Datum[] = [null, null, null];
|
const values: Plotly.Datum[] = [null, null, null];
|
||||||
for (const trace of data.points) {
|
for (const trace of data.points) {
|
||||||
values[trace.curveNumber] = trace.y;
|
values[trace.curveNumber] = trace.y;
|
||||||
|
@ -1056,11 +1056,11 @@ function populate_number_of_users(raw_data: unknown): void {
|
||||||
];
|
];
|
||||||
for (const [i, value] of values.entries()) {
|
for (const [i, value] of values.entries()) {
|
||||||
if (value !== null) {
|
if (value !== null) {
|
||||||
document.querySelector<HTMLElement>(hover_value_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_value_ids[i]!)!.style.display =
|
||||||
"inline";
|
"inline";
|
||||||
document.querySelector(hover_value_ids[i])!.textContent = value.toString();
|
document.querySelector(hover_value_ids[i]!)!.textContent = value.toString();
|
||||||
} else {
|
} else {
|
||||||
document.querySelector<HTMLElement>(hover_value_ids[i])!.style.display =
|
document.querySelector<HTMLElement>(hover_value_ids[i]!)!.style.display =
|
||||||
"none";
|
"none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1185,7 +1185,7 @@ function populate_messages_read_over_time(raw_data: unknown): void {
|
||||||
.on("plotly_hover", (data) => {
|
.on("plotly_hover", (data) => {
|
||||||
$("#read_hover_info").show();
|
$("#read_hover_info").show();
|
||||||
document.querySelector("#read_hover_date")!.textContent =
|
document.querySelector("#read_hover_date")!.textContent =
|
||||||
data.points[0].data.text[data.points[0].pointNumber];
|
data.points[0]!.data.text[data.points[0]!.pointNumber]!;
|
||||||
const values: Plotly.Datum[] = [null, null];
|
const values: Plotly.Datum[] = [null, null];
|
||||||
for (const trace of data.points) {
|
for (const trace of data.points) {
|
||||||
values[trace.curveNumber] = trace.y;
|
values[trace.curveNumber] = trace.y;
|
||||||
|
@ -1194,18 +1194,20 @@ function populate_messages_read_over_time(raw_data: unknown): void {
|
||||||
const read_hover_value_ids = ["#read_hover_me_value", "#read_hover_everyone_value"];
|
const read_hover_value_ids = ["#read_hover_me_value", "#read_hover_everyone_value"];
|
||||||
for (const [i, value] of values.entries()) {
|
for (const [i, value] of values.entries()) {
|
||||||
if (value !== null) {
|
if (value !== null) {
|
||||||
document.querySelector<HTMLElement>(read_hover_text_ids[i])!.style.display =
|
|
||||||
"inline";
|
|
||||||
document.querySelector<HTMLElement>(
|
document.querySelector<HTMLElement>(
|
||||||
read_hover_value_ids[i],
|
read_hover_text_ids[i]!,
|
||||||
)!.style.display = "inline";
|
)!.style.display = "inline";
|
||||||
document.querySelector<HTMLElement>(read_hover_value_ids[i])!.textContent =
|
document.querySelector<HTMLElement>(
|
||||||
|
read_hover_value_ids[i]!,
|
||||||
|
)!.style.display = "inline";
|
||||||
|
document.querySelector<HTMLElement>(read_hover_value_ids[i]!)!.textContent =
|
||||||
value.toString();
|
value.toString();
|
||||||
} else {
|
} else {
|
||||||
document.querySelector<HTMLElement>(read_hover_text_ids[i])!.style.display =
|
|
||||||
"none";
|
|
||||||
document.querySelector<HTMLElement>(
|
document.querySelector<HTMLElement>(
|
||||||
read_hover_value_ids[i],
|
read_hover_text_ids[i]!,
|
||||||
|
)!.style.display = "none";
|
||||||
|
document.querySelector<HTMLElement>(
|
||||||
|
read_hover_value_ids[i]!,
|
||||||
)!.style.display = "none";
|
)!.style.display = "none";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1225,13 +1227,13 @@ function populate_messages_read_over_time(raw_data: unknown): void {
|
||||||
let start;
|
let start;
|
||||||
let is_boundary;
|
let is_boundary;
|
||||||
if (aggregation === "day") {
|
if (aggregation === "day") {
|
||||||
start = floor_to_local_day(start_dates[0]);
|
start = floor_to_local_day(start_dates[0]!);
|
||||||
is_boundary = function (date: Date) {
|
is_boundary = function (date: Date) {
|
||||||
return date.getHours() === 0;
|
return date.getHours() === 0;
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
assert(aggregation === "week");
|
assert(aggregation === "week");
|
||||||
start = floor_to_local_week(start_dates[0]);
|
start = floor_to_local_week(start_dates[0]!);
|
||||||
is_boundary = function (date: Date) {
|
is_boundary = function (date: Date) {
|
||||||
return date.getHours() === 0 && date.getDay() === 0;
|
return date.getHours() === 0 && date.getDay() === 0;
|
||||||
};
|
};
|
||||||
|
@ -1240,19 +1242,19 @@ function populate_messages_read_over_time(raw_data: unknown): void {
|
||||||
const values: DataByEveryoneMe<number[]> = {everyone: [], me: []};
|
const values: DataByEveryoneMe<number[]> = {everyone: [], me: []};
|
||||||
let current: DataByEveryoneMe<number> = {everyone: 0, me: 0};
|
let current: DataByEveryoneMe<number> = {everyone: 0, me: 0};
|
||||||
let i_init = 0;
|
let i_init = 0;
|
||||||
if (is_boundary(start_dates[0])) {
|
if (is_boundary(start_dates[0]!)) {
|
||||||
current = {everyone: data.everyone.read[0], me: data.user.read[0]};
|
current = {everyone: data.everyone.read[0]!, me: data.user.read[0]!};
|
||||||
i_init = 1;
|
i_init = 1;
|
||||||
}
|
}
|
||||||
for (let i = i_init; i < start_dates.length; i += 1) {
|
for (let i = i_init; i < start_dates.length; i += 1) {
|
||||||
if (is_boundary(start_dates[i])) {
|
if (is_boundary(start_dates[i]!)) {
|
||||||
dates.push(start_dates[i]);
|
dates.push(start_dates[i]!);
|
||||||
values.everyone.push(current.everyone);
|
values.everyone.push(current.everyone);
|
||||||
values.me.push(current.me);
|
values.me.push(current.me);
|
||||||
current = {everyone: 0, me: 0};
|
current = {everyone: 0, me: 0};
|
||||||
}
|
}
|
||||||
current.everyone += data.everyone.read[i];
|
current.everyone += data.everyone.read[i]!;
|
||||||
current.me += data.user.read[i];
|
current.me += data.user.read[i]!;
|
||||||
}
|
}
|
||||||
values.everyone.push(current.everyone);
|
values.everyone.push(current.everyone);
|
||||||
values.me.push(current.me);
|
values.me.push(current.me);
|
||||||
|
@ -1315,8 +1317,8 @@ function populate_messages_read_over_time(raw_data: unknown): void {
|
||||||
const plotDiv = document.querySelector<Plotly.PlotlyHTMLElement>(
|
const plotDiv = document.querySelector<Plotly.PlotlyHTMLElement>(
|
||||||
"#id_messages_read_over_time",
|
"#id_messages_read_over_time",
|
||||||
)!;
|
)!;
|
||||||
assert("visible" in plotDiv.data[0]);
|
assert("visible" in plotDiv.data[0]!);
|
||||||
assert("visible" in plotDiv.data[1]);
|
assert("visible" in plotDiv.data[1]!);
|
||||||
traces.me.visible = plotDiv.data[0].visible;
|
traces.me.visible = plotDiv.data[0].visible;
|
||||||
traces.everyone.visible = plotDiv.data[1].visible;
|
traces.everyone.visible = plotDiv.data[1].visible;
|
||||||
}
|
}
|
||||||
|
|
|
@ -270,7 +270,7 @@ export function slug_to_name(slug: string): string {
|
||||||
*/
|
*/
|
||||||
const m = /^(\d+)(-.*)?$/.exec(slug);
|
const m = /^(\d+)(-.*)?$/.exec(slug);
|
||||||
if (m) {
|
if (m) {
|
||||||
const stream_id = Number.parseInt(m[1], 10);
|
const stream_id = Number.parseInt(m[1]!, 10);
|
||||||
const sub = sub_store.get(stream_id);
|
const sub = sub_store.get(stream_id);
|
||||||
if (sub) {
|
if (sub) {
|
||||||
return sub.name;
|
return sub.name;
|
||||||
|
|
|
@ -285,7 +285,7 @@ export function initialize(): void {
|
||||||
const second_line = $t({defaultMessage: "File name: {filename}"}, {filename});
|
const second_line = $t({defaultMessage: "File name: {filename}"}, {filename});
|
||||||
$markup.append($("<br>"), $("<span>").text(second_line));
|
$markup.append($("<br>"), $("<span>").text(second_line));
|
||||||
}
|
}
|
||||||
instance.setContent($markup[0]);
|
instance.setContent($markup[0]!);
|
||||||
return undefined;
|
return undefined;
|
||||||
},
|
},
|
||||||
onHidden(instance) {
|
onHidden(instance) {
|
||||||
|
|
|
@ -19,19 +19,19 @@ export function next_topic(
|
||||||
const curr_stream_index = streams.indexOf(curr_stream); // -1 if not found
|
const curr_stream_index = streams.indexOf(curr_stream); // -1 if not found
|
||||||
|
|
||||||
if (curr_stream_index >= 0) {
|
if (curr_stream_index >= 0) {
|
||||||
const stream = streams[curr_stream_index];
|
const stream = streams[curr_stream_index]!;
|
||||||
const topics = get_topics(stream);
|
const topics = get_topics(stream);
|
||||||
const curr_topic_index = topics.indexOf(curr_topic); // -1 if not found
|
const curr_topic_index = topics.indexOf(curr_topic); // -1 if not found
|
||||||
|
|
||||||
for (let i = curr_topic_index + 1; i < topics.length; i += 1) {
|
for (let i = curr_topic_index + 1; i < topics.length; i += 1) {
|
||||||
const topic = topics[i];
|
const topic = topics[i]!;
|
||||||
if (has_unread_messages(stream, topic)) {
|
if (has_unread_messages(stream, topic)) {
|
||||||
return {stream, topic};
|
return {stream, topic};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < curr_topic_index; i += 1) {
|
for (let i = 0; i < curr_topic_index; i += 1) {
|
||||||
const topic = topics[i];
|
const topic = topics[i]!;
|
||||||
if (has_unread_messages(stream, topic)) {
|
if (has_unread_messages(stream, topic)) {
|
||||||
return {stream, topic};
|
return {stream, topic};
|
||||||
}
|
}
|
||||||
|
@ -39,7 +39,7 @@ export function next_topic(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = curr_stream_index + 1; i < streams.length; i += 1) {
|
for (let i = curr_stream_index + 1; i < streams.length; i += 1) {
|
||||||
const stream = streams[i];
|
const stream = streams[i]!;
|
||||||
for (const topic of get_topics(stream)) {
|
for (const topic of get_topics(stream)) {
|
||||||
if (has_unread_messages(stream, topic)) {
|
if (has_unread_messages(stream, topic)) {
|
||||||
return {stream, topic};
|
return {stream, topic};
|
||||||
|
@ -48,7 +48,7 @@ export function next_topic(
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < curr_stream_index; i += 1) {
|
for (let i = 0; i < curr_stream_index; i += 1) {
|
||||||
const stream = streams[i];
|
const stream = streams[i]!;
|
||||||
for (const topic of get_topics(stream)) {
|
for (const topic of get_topics(stream)) {
|
||||||
if (has_unread_messages(stream, topic)) {
|
if (has_unread_messages(stream, topic)) {
|
||||||
return {stream, topic};
|
return {stream, topic};
|
||||||
|
@ -150,13 +150,13 @@ export function get_next_unread_pm_string(curr_pm: string): string | undefined {
|
||||||
const curr_pm_index = my_pm_strings.indexOf(curr_pm); // -1 if not found
|
const curr_pm_index = my_pm_strings.indexOf(curr_pm); // -1 if not found
|
||||||
|
|
||||||
for (let i = curr_pm_index + 1; i < my_pm_strings.length; i += 1) {
|
for (let i = curr_pm_index + 1; i < my_pm_strings.length; i += 1) {
|
||||||
if (unread.num_unread_for_user_ids_string(my_pm_strings[i]) > 0) {
|
if (unread.num_unread_for_user_ids_string(my_pm_strings[i]!) > 0) {
|
||||||
return my_pm_strings[i];
|
return my_pm_strings[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (let i = 0; i < curr_pm_index; i += 1) {
|
for (let i = 0; i < curr_pm_index; i += 1) {
|
||||||
if (unread.num_unread_for_user_ids_string(my_pm_strings[i]) > 0) {
|
if (unread.num_unread_for_user_ids_string(my_pm_strings[i]!) > 0) {
|
||||||
return my_pm_strings[i];
|
return my_pm_strings[i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ export function highlight_with_escaping_and_regex(regex: RegExp, item: string):
|
||||||
let result = "";
|
let result = "";
|
||||||
|
|
||||||
for (const [i, piece] of pieces.entries()) {
|
for (const [i, piece] of pieces.entries()) {
|
||||||
if (regex.test(piece) && (i === 0 || pieces[i - 1].endsWith(" "))) {
|
if (regex.test(piece) && (i === 0 || pieces[i - 1]!.endsWith(" "))) {
|
||||||
// only highlight if the matching part is a word prefix, ie
|
// only highlight if the matching part is a word prefix, ie
|
||||||
// if it is the 1st piece or if there was a space before it
|
// if it is the 1st piece or if there was a space before it
|
||||||
result += "<strong>" + Handlebars.Utils.escapeExpression(piece) + "</strong>";
|
result += "<strong>" + Handlebars.Utils.escapeExpression(piece) + "</strong>";
|
||||||
|
|
|
@ -72,7 +72,7 @@ export function build_widget(
|
||||||
if (files === null || files === undefined || files.length === 0) {
|
if (files === null || files === undefined || files.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
get_file_input()[0].files = files;
|
get_file_input()[0]!.files = files;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
@ -160,7 +160,7 @@ export function build_direct_upload_widget(
|
||||||
if (files === null || files === undefined || files.length === 0) {
|
if (files === null || files === undefined || files.length === 0) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
get_file_input()[0].files = files;
|
get_file_input()[0]!.files = files;
|
||||||
e.preventDefault();
|
e.preventDefault();
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
|
@ -35,7 +35,7 @@ export function lower_bound<T1, T2>(
|
||||||
while (len > 0) {
|
while (len > 0) {
|
||||||
step = Math.floor(len / 2);
|
step = Math.floor(len / 2);
|
||||||
middle = first + step;
|
middle = first + step;
|
||||||
if (less(array[middle], value, middle)) {
|
if (less(array[middle]!, value, middle)) {
|
||||||
first = middle;
|
first = middle;
|
||||||
first += 1;
|
first += 1;
|
||||||
len = len - step - 1;
|
len = len - step - 1;
|
||||||
|
@ -204,7 +204,7 @@ export function find_stream_wildcard_mentions(message_content: string): string |
|
||||||
if (mention === null) {
|
if (mention === null) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return mention[2];
|
return mention[2]!;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const move_array_elements_to_front = function util_move_array_elements_to_front<T>(
|
export const move_array_elements_to_front = function util_move_array_elements_to_front<T>(
|
||||||
|
|
|
@ -38,7 +38,7 @@ export function eq_array<T>(
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return a.every((item, i) => eq(item, b[i]));
|
return a.every((item, i) => eq(item, b[i]!));
|
||||||
}
|
}
|
||||||
|
|
||||||
export function ul<T>(opts: Options<T>): Tag<T> {
|
export function ul<T>(opts: Options<T>): Tag<T> {
|
||||||
|
@ -198,7 +198,7 @@ export function update<T>(
|
||||||
const $child_elems = find().children();
|
const $child_elems = find().children();
|
||||||
|
|
||||||
for (const [i, new_node] of new_opts.keyed_nodes.entries()) {
|
for (const [i, new_node] of new_opts.keyed_nodes.entries()) {
|
||||||
const old_node = old_opts.keyed_nodes[i];
|
const old_node = old_opts.keyed_nodes[i]!;
|
||||||
if (new_node.eq(old_node)) {
|
if (new_node.eq(old_node)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue