Skip to content

Commit cc9f6cb

Browse files
committed
model: Add toggle_topic_resolve_status function to (un)resolve topics.
Fixes zulip#1075 The function calls get_latest_message_in_topic to fetch recent message in topic to be (un)resolved. It verifies user and editing conditions using can_user_edit_topic function and finally add or remove RESOLVED_TOPIC_PREFIX from topic name.
1 parent 39ecf52 commit cc9f6cb

File tree

2 files changed

+114
-0
lines changed

2 files changed

+114
-0
lines changed

tests/model/test_model.py

+81
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from pytest import param as case
88
from zulip import Client, ZulipError
99

10+
from zulipterminal.api_types import RESOLVED_TOPIC_PREFIX
1011
from zulipterminal.config.symbols import STREAM_TOPIC_SEPARATOR
1112
from zulipterminal.helper import initial_index, powerset
1213
from zulipterminal.model import (
@@ -1255,6 +1256,86 @@ def test_can_user_edit_topic(
12551256
else:
12561257
report_error.assert_called_once_with(expected_response[user_type][0])
12571258

1259+
@pytest.mark.parametrize(
1260+
"topic_name, msg_response, server_feature_level, topic_editing_limit_seconds, expected_new_topic_name, expected_footer_error",
1261+
[
1262+
case(
1263+
"hi!",
1264+
{
1265+
"subject": "hi!",
1266+
"timestamp": 11662271397,
1267+
"id": 1,
1268+
},
1269+
12,
1270+
259200,
1271+
RESOLVED_TOPIC_PREFIX + "hi!",
1272+
None,
1273+
id="topic_resolved:Zulip2.1+:ZFL12",
1274+
),
1275+
case(
1276+
"hi!",
1277+
{
1278+
"subject": "hi!",
1279+
"timestamp": 0,
1280+
"id": 1,
1281+
},
1282+
None,
1283+
None,
1284+
RESOLVED_TOPIC_PREFIX + "hi!",
1285+
None,
1286+
id="no_time_limit:Zulip2.1+:None",
1287+
),
1288+
case(
1289+
RESOLVED_TOPIC_PREFIX + "hi!",
1290+
{
1291+
"subject": RESOLVED_TOPIC_PREFIX + "hi!",
1292+
"timestamp": 11662271397,
1293+
"id": 1,
1294+
},
1295+
10,
1296+
86400,
1297+
"hi!",
1298+
None,
1299+
id="topic_unresolved:Zulip2.1+:ZFL10",
1300+
),
1301+
],
1302+
)
1303+
def test_toggle_topic_resolve_status(
1304+
self,
1305+
mocker,
1306+
model,
1307+
initial_data,
1308+
topic_name,
1309+
msg_response,
1310+
server_feature_level,
1311+
topic_editing_limit_seconds,
1312+
expected_new_topic_name,
1313+
expected_footer_error,
1314+
stream_id=1,
1315+
):
1316+
model.initial_data = initial_data
1317+
model.server_feature_level = server_feature_level
1318+
initial_data[
1319+
"realm_community_topic_editing_limit_seconds"
1320+
] = topic_editing_limit_seconds
1321+
# If user can't edit topic, topic (un)resolve is disabled. Therefore,
1322+
# default return_value=True
1323+
model.can_user_edit_topic = mocker.Mock(return_value=True)
1324+
model.get_latest_message_in_topic = mocker.Mock(return_value=msg_response)
1325+
model.update_stream_message = mocker.Mock(return_value={"result": "success"})
1326+
report_error = model.controller.report_error
1327+
1328+
model.toggle_topic_resolve_status(stream_id, topic_name)
1329+
1330+
if not expected_footer_error:
1331+
model.update_stream_message.assert_called_once_with(
1332+
message_id=msg_response["id"],
1333+
topic=expected_new_topic_name,
1334+
propagate_mode="change_all",
1335+
)
1336+
else:
1337+
report_error.assert_called_once_with(expected_footer_error)
1338+
12581339
# NOTE: This tests only getting next-unread, not a fixed anchor
12591340
def test_success_get_messages(
12601341
self,

zulipterminal/model.py

+33
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030

3131
from zulipterminal import unicode_emojis
3232
from zulipterminal.api_types import (
33+
RESOLVED_TOPIC_PREFIX,
3334
Composition,
3435
EditPropagateMode,
3536
Event,
@@ -704,6 +705,38 @@ def can_user_edit_topic(self) -> bool:
704705
self.controller.report_error("User not found")
705706
return False
706707

708+
def toggle_topic_resolve_status(self, stream_id: int, topic_name: str) -> None:
709+
if self.can_user_edit_topic():
710+
latest_msg = self.get_latest_message_in_topic(stream_id, topic_name)
711+
if latest_msg:
712+
time_since_msg_sent = time.time() - latest_msg["timestamp"]
713+
# ZFL < 11, community_topic_editing_limit_seconds
714+
# was hardcoded as int value in secs eg. 86400s (1 day) or None
715+
if self.server_feature_level is None or self.server_feature_level >= 11:
716+
edit_time_limit = self.initial_data.get(
717+
"realm_community_topic_editing_limit_seconds", None
718+
)
719+
else:
720+
edit_time_limit = 86400
721+
# Don't allow editing topic if time-limit exceeded.
722+
if (
723+
edit_time_limit is not None
724+
and time_since_msg_sent >= edit_time_limit
725+
):
726+
self.controller.report_error(
727+
" Time limit for editing topic has been exceeded."
728+
)
729+
else:
730+
if topic_name.startswith(RESOLVED_TOPIC_PREFIX):
731+
topic_name = topic_name[2:]
732+
else:
733+
topic_name = RESOLVED_TOPIC_PREFIX + topic_name
734+
self.update_stream_message(
735+
message_id=latest_msg["id"],
736+
topic=topic_name,
737+
propagate_mode="change_all",
738+
)
739+
707740
def generate_all_emoji_data(
708741
self, custom_emoji: Dict[str, RealmEmojiData]
709742
) -> Tuple[NamedEmojiData, List[str]]:

0 commit comments

Comments
 (0)