diff --git a/web/src/filter.ts b/web/src/filter.ts index 7b00503995..8fee434d7d 100644 --- a/web/src/filter.ts +++ b/web/src/filter.ts @@ -726,6 +726,45 @@ export class Filter { return true; } + static adjusted_terms_if_moved(raw_terms: NarrowTerm[], message: Message): NarrowTerm[] | null { + if (message.type !== "stream") { + return null; + } + + assert(typeof message.display_recipient === "string"); + assert(typeof message.topic === "string"); + + const adjusted_terms = []; + let terms_changed = false; + + for (const term of raw_terms) { + const adjusted_term = {...term}; + if ( + Filter.canonicalize_operator(term.operator) === "channel" && + !util.lower_same(term.operand, message.display_recipient) + ) { + adjusted_term.operand = message.display_recipient; + terms_changed = true; + } + + if ( + Filter.canonicalize_operator(term.operator) === "topic" && + !util.lower_same(term.operand, message.topic) + ) { + adjusted_term.operand = message.topic; + terms_changed = true; + } + + adjusted_terms.push(adjusted_term); + } + + if (!terms_changed) { + return null; + } + + return adjusted_terms; + } + equals(filter: Filter, excluded_operators?: string[]): boolean { return _.isEqual( filter.sorted_terms(excluded_operators), diff --git a/web/src/message_view.js b/web/src/message_view.js index e5d3fad2b5..f4eac4cd2b 100644 --- a/web/src/message_view.js +++ b/web/src/message_view.js @@ -402,38 +402,6 @@ export function show(raw_terms, opts) { if (id_info.target_id && filter.has_operator("channel") && filter.has_operator("topic")) { const target_message = message_store.get(id_info.target_id); - function adjusted_terms_if_moved(raw_terms, message) { - const adjusted_terms = []; - let terms_changed = false; - - for (const term of raw_terms) { - const adjusted_term = {...term}; - if ( - Filter.canonicalize_operator(term.operator) === "channel" && - !util.lower_same(term.operand, message.display_recipient) - ) { - adjusted_term.operand = message.display_recipient; - terms_changed = true; - } - - if ( - Filter.canonicalize_operator(term.operator) === "topic" && - !util.lower_same(term.operand, message.topic) - ) { - adjusted_term.operand = message.topic; - terms_changed = true; - } - - adjusted_terms.push(adjusted_term); - } - - if (!terms_changed) { - return null; - } - - return adjusted_terms; - } - if (target_message) { // If we have the target message ID for the narrow in our // local cache, and the target message has been moved from @@ -447,7 +415,10 @@ export function show(raw_terms, opts) { // The stream name is invalid or incorrect in the URL. // We reconstruct the narrow with the data from the // target message ID that we have. - const adjusted_terms = adjusted_terms_if_moved(raw_terms, target_message); + const adjusted_terms = Filter.adjusted_terms_if_moved( + raw_terms, + target_message, + ); if (adjusted_terms === null) { blueslip.error("adjusted_terms impossibly null"); @@ -485,7 +456,10 @@ export function show(raw_terms, opts) { !narrow_matches_target_message && (narrow_exists_in_edit_history || !realm.realm_allow_edit_history) ) { - const adjusted_terms = adjusted_terms_if_moved(raw_terms, target_message); + const adjusted_terms = Filter.adjusted_terms_if_moved( + raw_terms, + target_message, + ); if (adjusted_terms !== null) { show(adjusted_terms, { ...opts, diff --git a/web/tests/filter.test.js b/web/tests/filter.test.js index 8abc942d0c..daff0cbda5 100644 --- a/web/tests/filter.test.js +++ b/web/tests/filter.test.js @@ -2204,3 +2204,59 @@ run_test("equals", () => { ), ); }); + +run_test("adjusted_terms_if_moved", () => { + // should return null for non-stream messages + let raw_terms = [{operator: "channel", operand: "Foo"}]; + let message = {type: "private"}; + let result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.strictEqual(result, null); + + // should return null if no terms are changed + raw_terms = [{operator: "channel", operand: "general"}]; + message = {type: "stream", display_recipient: "general", topic: "discussion"}; + result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.strictEqual(result, null); + + // should adjust channel term to match message's display_recipient + raw_terms = [{operator: "channel", operand: "random"}]; + message = {type: "stream", display_recipient: "general", topic: "discussion"}; + let expected = [{operator: "channel", operand: "general"}]; + result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.deepStrictEqual(result, expected); + + // should adjust topic term to match message's topic + raw_terms = [{operator: "topic", operand: "random"}]; + message = {type: "stream", display_recipient: "general", topic: "discussion"}; + expected = [{operator: "topic", operand: "discussion"}]; + result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.deepStrictEqual(result, expected); + + // should adjust both channel and topic terms when both are different + raw_terms = [ + {operator: "channel", operand: "random"}, + {operator: "topic", operand: "random"}, + ]; + message = {type: "stream", display_recipient: "general", topic: "discussion"}; + expected = [ + {operator: "channel", operand: "general"}, + {operator: "topic", operand: "discussion"}, + ]; + result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.deepStrictEqual(result, expected); + + // should not adjust terms that are not channel or topic + raw_terms = [ + {operator: "channel", operand: "random"}, + {operator: "topic", operand: "random"}, + {operator: "sender", operand: "alice"}, + ]; + message = {type: "stream", display_recipient: "general", topic: "discussion"}; + expected = [ + {operator: "channel", operand: "general"}, + {operator: "topic", operand: "discussion"}, + {operator: "sender", operand: "alice"}, + ]; + result = Filter.adjusted_terms_if_moved(raw_terms, message); + assert.deepStrictEqual(result, expected); +});