From acc5cffae4186d760ec2b69818b0f03559d86ac7 Mon Sep 17 00:00:00 2001 From: Pratik Chanda Date: Fri, 29 Aug 2025 02:01:11 +0530 Subject: [PATCH] filter: Use encoding for channel/topic narrow for url redirect. Earlier, when generating redirect url for search exit, we did not encode the url in case of topic narrows. We expect some characters to be replaced when generating hash. This commit encodes the url for channels and topic narrows and prevents redirecting to broken hashes. --- web/src/filter.ts | 19 ++++++++++++------- web/tests/filter.test.cjs | 22 ++++++++++++++++++++++ 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/web/src/filter.ts b/web/src/filter.ts index f434b4e3e8..c6d903ab69 100644 --- a/web/src/filter.ts +++ b/web/src/filter.ts @@ -1,6 +1,7 @@ import _ from "lodash"; import assert from "minimalistic-assert"; +import * as internal_url from "../shared/src/internal_url.ts"; import * as resolved_topic from "../shared/src/resolved_topic.ts"; import render_search_description from "../templates/search_description.hbs"; @@ -18,6 +19,7 @@ import type {UserPillItem} from "./search_suggestion.ts"; import {current_user, realm} from "./state_data.ts"; import type {NarrowTerm} from "./state_data.ts"; import * as stream_data from "./stream_data.ts"; +import * as sub_store from "./sub_store.ts"; import * as user_topics from "./user_topics.ts"; import * as util from "./util.ts"; @@ -1311,12 +1313,12 @@ export class Filter { if (!sub) { return "#"; } - return ( - "/#narrow/channel/" + - stream_data.id_to_slug(sub.stream_id) + - "/topic/" + - this.operands("topic")[0] - ); + + return `/${internal_url.by_stream_topic_url( + sub.stream_id, + this.operands("topic")[0]!, + sub_store.maybe_get_stream_name, + )}`; } // eliminate "complex filters" @@ -1332,7 +1334,10 @@ export class Filter { if (!sub) { return "#"; } - return "/#narrow/channel/" + stream_data.id_to_slug(sub.stream_id); + return `/${internal_url.by_stream_url( + sub.stream_id, + sub_store.maybe_get_stream_name, + )}`; } case "is-dm": return "/#narrow/is/dm"; diff --git a/web/tests/filter.test.cjs b/web/tests/filter.test.cjs index 73293548db..7cbee58be3 100644 --- a/web/tests/filter.test.cjs +++ b/web/tests/filter.test.cjs @@ -2400,6 +2400,14 @@ test("navbar_helpers", ({override}) => { {operator: "channel", operand: invalid_channel_id.toString()}, {operator: "topic", operand: "bar"}, ]; + // channel/topic name using special character for url encoding. + const special_sub_id = new_stream_id(); + make_sub("Foo2.0", special_sub_id); + const char_channel_term = [{operator: "channel", operand: special_sub_id.toString()}]; + const char_channel_topic_term = [ + {operator: "channel", operand: special_sub_id.toString()}, + {operator: "topic", operand: "bar2.0"}, + ]; const public_sub_id = new_stream_id(); make_private_sub("psub", public_sub_id); const private_channel_term = [{operator: "channel", operand: public_sub_id.toString()}]; @@ -2526,6 +2534,20 @@ test("navbar_helpers", ({override}) => { title: "Foo", redirect_url_with_search: `/#narrow/channel/${foo_stream_id}-Foo/topic/bar`, }, + { + terms: char_channel_term, + is_common_narrow: true, + zulip_icon: "hashtag", + title: "Foo2.0", + redirect_url_with_search: `/#narrow/channel/${special_sub_id}-Foo2.2E0`, + }, + { + terms: char_channel_topic_term, + is_common_narrow: true, + zulip_icon: "hashtag", + title: "Foo2.0", + redirect_url_with_search: `/#narrow/channel/${special_sub_id}-Foo2.2E0/topic/bar2.2E0`, + }, { terms: invalid_channel_with_topic, is_common_narrow: true,