diff --git a/web/src/clipboard_handler.ts b/web/src/clipboard_handler.ts index ce947719b2..bd155de12f 100644 --- a/web/src/clipboard_handler.ts +++ b/web/src/clipboard_handler.ts @@ -1,8 +1,8 @@ -import * as hash_util from "./hash_util"; -import * as stream_data from "./stream_data"; +import * as hash_util from "./hash_util.ts"; +import * as stream_data from "./stream_data.ts"; -export function generate_formatted_link(link_text: string): string { - const stream_topic = hash_util.decode_stream_topic_from_url(link_text); +export function generate_formatted_link(link_data: string): string { + const stream_topic = hash_util.decode_stream_topic_from_url(link_data); if (!stream_topic) { return "Invalid stream"; @@ -17,22 +17,30 @@ export function generate_formatted_link(link_text: string): string { const topic_name = stream_topic.topic_name?.replace(//g, ">"); const stream_name = stream?.name?.replace(//g, ">"); - if (topic_name !== undefined) { - return `#${stream_name}>${topic_name}`; - } + const message_id = stream_topic?.message_id; + let formatted_url; - return `#${stream_name}`; + if (message_id === undefined) { + if (topic_name !== undefined) { + formatted_url = `#${stream_name}>${topic_name}`; + } else { + formatted_url = `#${stream_name}`; + } + } else { + formatted_url = `#${stream_name}>${topic_name}@${message_id}`; + } + return formatted_url; } -export function copy_to_clipboard(link_text: string, after_copy_cb: () => void): void { - const formatted_url = generate_formatted_link(link_text); +export function copy_to_clipboard(link_data: string, after_copy_cb: () => void): void { + const formatted_url = generate_formatted_link(link_data); if (formatted_url === "Invalid stream") { return; } const clipboardItem = new ClipboardItem({ - "text/plain": new Blob([link_text], { + "text/plain": new Blob([link_data], { type: "text/plain", }), "text/html": new Blob([formatted_url], {type: "text/html"}), diff --git a/web/src/message_actions_popover.js b/web/src/message_actions_popover.js index 957da457b4..2c17c94880 100644 --- a/web/src/message_actions_popover.js +++ b/web/src/message_actions_popover.js @@ -1,10 +1,10 @@ -import ClipboardJS from "clipboard"; import $ from "jquery"; import assert from "minimalistic-assert"; import render_message_actions_popover from "../templates/popovers/message_actions_popover.hbs"; import * as blueslip from "./blueslip.ts"; +import * as clipboard_handler from "./clipboard_handler.ts"; import * as compose_reply from "./compose_reply.ts"; import * as condense from "./condense.ts"; import {show_copied_confirmation} from "./copied_tooltip.ts"; @@ -217,14 +217,11 @@ export function initialize() { popover_menus.hide_current_popover_if_visible(instance); }); - new ClipboardJS($popper.find(".copy_link")[0]).on("success", () => { + $popper.on("click", ".copy_link", () => { + clipboard_handler.copy_to_clipboard($(".copy_link").data("clipboard-text"), () => + popover_menus.hide_current_popover_if_visible(instance), + ); show_copied_confirmation($(instance.reference).closest(".message_controls")[0]); - setTimeout(() => { - // The Clipboard library works by focusing to a hidden textarea. - // We unfocus this so keyboard shortcuts, etc., will work again. - $(":focus").trigger("blur"); - }, 0); - popover_menus.hide_current_popover_if_visible(instance); }); }, onHidden(instance) { diff --git a/web/src/stream_popover.js b/web/src/stream_popover.js index 102e8004f1..9dcc0de7a1 100644 --- a/web/src/stream_popover.js +++ b/web/src/stream_popover.js @@ -7,7 +7,7 @@ import render_left_sidebar_stream_actions_popover from "../templates/popovers/le import * as blueslip from "./blueslip.ts"; import * as browser_history from "./browser_history.ts"; -import * as clipboard_handler from "./clipboard_handler"; +import * as clipboard_handler from "./clipboard_handler.ts"; import * as composebox_typeahead from "./composebox_typeahead.ts"; import * as dialog_widget from "./dialog_widget.ts"; import * as dropdown_widget from "./dropdown_widget.ts"; diff --git a/web/src/topic_popover.js b/web/src/topic_popover.js index d4bd9f7d82..f4c4eb7ab8 100644 --- a/web/src/topic_popover.js +++ b/web/src/topic_popover.js @@ -3,7 +3,7 @@ import $ from "jquery"; import render_delete_topic_modal from "../templates/confirm_dialog/confirm_delete_topic.hbs"; import render_left_sidebar_topic_actions_popover from "../templates/popovers/left_sidebar/left_sidebar_topic_actions_popover.hbs"; -import * as clipboard_handler from "./clipboard_handler"; +import * as clipboard_handler from "./clipboard_handler.ts"; import * as confirm_dialog from "./confirm_dialog.ts"; import {$t_html} from "./i18n.ts"; import * as message_edit from "./message_edit.ts"; diff --git a/web/tests/clipboard_handler.test.js b/web/tests/clipboard_handler.test.cjs similarity index 84% rename from web/tests/clipboard_handler.test.js rename to web/tests/clipboard_handler.test.cjs index 0b8779c8e6..b1249be1a0 100644 --- a/web/tests/clipboard_handler.test.js +++ b/web/tests/clipboard_handler.test.cjs @@ -2,9 +2,9 @@ const assert = require("node:assert/strict"); -const {zrequire} = require("./lib/namespace"); -const {make_stub} = require("./lib/stub"); -const {run_test} = require("./lib/test"); +const {zrequire} = require("./lib/namespace.cjs"); +const {make_stub} = require("./lib/stub.cjs"); +const {run_test} = require("./lib/test.cjs"); const clipboard_handler = zrequire("clipboard_handler"); const stream_data = zrequire("stream_data"); @@ -29,18 +29,19 @@ stream_data.add_sub(stream); stream_data.add_sub(markdown_stream); const normal_stream_with_topic = - "http://zulip.zulipdev.com/#narrow/stream/1-Stream/topic/normal.20topic"; + "http://zulip.zulipdev.com/#narrow/channel/1-Stream/topic/normal.20topic"; const markdown_stream_with_normal_topic = "http://zulip.zulipdev.com/#narrow/channel/2-.3CStream*.24.60.26.3E/topic/normal.20topic"; const normal_stream_with_markdown_topic = - "http://zulip.zulipdev.com/#narrow/stream/1-Stream/topic/.3C.24topic.60*.26.3E"; + "http://zulip.zulipdev.com/#narrow/channel/1-Stream/topic/.3C.24topic.60*.26.3E"; const markdown_stream_with_markdown_topic = "http://zulip.zulipdev.com/#narrow/channel/2-.3CStream*.24.60.26.3E/topic/.3C.24topic.60*.26.3E"; const invalid_stream = "http://zulip.zulipdev.com/#narrow/stream/99-Stream"; -const normal_stream_no_topic = "http://zulip.zulipdev.com/#narrow/stream/1-Stream"; +const normal_stream_no_topic = "http://zulip.zulipdev.com/#narrow/channel/1-Stream"; const markdown_stream_no_topic = "http://zulip.zulipdev.com/#narrow/channel/2-.3CStream*.24.60.26.3E"; - +const link_to_message = + "http://zulip.zulipdev.com/#narrow/channel/1-Stream/topic/normal.20topic/near/86"; run_test("generate_formatted_url", () => { assert.equal( clipboard_handler.generate_formatted_link(normal_stream_with_topic), @@ -73,6 +74,10 @@ run_test("generate_formatted_url", () => { clipboard_handler.generate_formatted_link(markdown_stream_no_topic), `#<Stream*$\`&>`, ); + assert.equal( + clipboard_handler.generate_formatted_link(link_to_message), + `#Stream>normal topic@86`, + ); }); global.ClipboardItem = class {