mirror of
https://github.com/zulip/zulip.git
synced 2025-10-23 04:52:12 +00:00
events: Add support for processing modern presence event in web client.
This commit is contained in:
@@ -68,8 +68,9 @@ def get_event_checker(event: dict[str, Any]) -> Callable[[str, dict[str, Any]],
|
||||
# Change to CamelCase
|
||||
name = name.replace("_", " ").title().replace(" ", "")
|
||||
|
||||
# Use EventModernPresence type to check "presence" events
|
||||
if name == "Presence":
|
||||
name = "Legacy" + name
|
||||
name = "Modern" + name
|
||||
|
||||
# And add the prefix.
|
||||
name = "Event" + name
|
||||
|
@@ -227,11 +227,12 @@ export function initialize(opts: {narrow_by_email: (email: string) => void}): vo
|
||||
activity.send_presence_to_server();
|
||||
}
|
||||
|
||||
export function update_presence_info(
|
||||
user_id: number,
|
||||
info: PresenceInfoFromEvent,
|
||||
server_time: number,
|
||||
): void {
|
||||
export function update_presence_info(info: PresenceInfoFromEvent): void {
|
||||
const presence_entry = Object.entries(info)[0];
|
||||
assert(presence_entry !== undefined);
|
||||
const [user_id_string, presence_info] = presence_entry;
|
||||
const user_id = Number.parseInt(user_id_string, 10);
|
||||
|
||||
// There can be some case where the presence event
|
||||
// was set for an inaccessible user if
|
||||
// CAN_ACCESS_ALL_USERS_GROUP_LIMITS_PRESENCE is
|
||||
@@ -241,7 +242,7 @@ export function update_presence_info(
|
||||
return;
|
||||
}
|
||||
|
||||
presence.update_info_from_event(user_id, info, server_time);
|
||||
presence.update_info_from_event(user_id, presence_info);
|
||||
redraw_user(user_id);
|
||||
pm_list.update_private_messages();
|
||||
}
|
||||
|
@@ -15,14 +15,13 @@ export type PresenceStatus = {
|
||||
last_active?: number | undefined;
|
||||
};
|
||||
|
||||
export const presence_info_from_event_schema = z.object({
|
||||
website: z.object({
|
||||
client: z.literal("website"),
|
||||
status: z.enum(["idle", "active"]),
|
||||
timestamp: z.number(),
|
||||
pushable: z.boolean(),
|
||||
export const presence_info_from_event_schema = z.record(
|
||||
z.string(),
|
||||
z.object({
|
||||
active_timestamp: z.number(),
|
||||
idle_timestamp: z.number(),
|
||||
}),
|
||||
});
|
||||
);
|
||||
export type PresenceInfoFromEvent = z.output<typeof presence_info_from_event_schema>;
|
||||
|
||||
export const user_last_seen_response_schema = z.object({
|
||||
@@ -163,18 +162,16 @@ export function status_from_raw(raw: RawPresence, user: User | undefined): Prese
|
||||
|
||||
export function update_info_from_event(
|
||||
user_id: number,
|
||||
info: PresenceInfoFromEvent | null,
|
||||
server_timestamp: number,
|
||||
info: z.infer<typeof presence_schema> | null,
|
||||
server_timestamp: number | undefined = undefined,
|
||||
): void {
|
||||
/*
|
||||
Example of `info`:
|
||||
|
||||
{
|
||||
website: {
|
||||
client: 'website',
|
||||
pushable: false,
|
||||
status: 'active',
|
||||
timestamp: 1585745225
|
||||
"10": {
|
||||
active_timestamp: 1585745133,
|
||||
idle_timestamp: 1585745091
|
||||
}
|
||||
}
|
||||
|
||||
@@ -190,16 +187,16 @@ export function update_info_from_event(
|
||||
server_timestamp: 0,
|
||||
};
|
||||
|
||||
raw.server_timestamp = server_timestamp;
|
||||
if (server_timestamp !== undefined) {
|
||||
// The event itself doesn't contain a server_timestamp. But
|
||||
// since the event should be newer than our last polling
|
||||
// response from the server, it should be safe to use that.
|
||||
raw.server_timestamp = server_timestamp;
|
||||
}
|
||||
|
||||
for (const rec of Object.values(info ?? {})) {
|
||||
if (rec.status === "active" && rec.timestamp > (raw.active_timestamp ?? 0)) {
|
||||
raw.active_timestamp = rec.timestamp;
|
||||
}
|
||||
|
||||
if (rec.status === "idle" && rec.timestamp > (raw.idle_timestamp ?? 0)) {
|
||||
raw.idle_timestamp = rec.timestamp;
|
||||
}
|
||||
if (info !== null) {
|
||||
raw.active_timestamp = info.active_timestamp;
|
||||
raw.idle_timestamp = info.idle_timestamp;
|
||||
}
|
||||
|
||||
raw_info.set(user_id, raw);
|
||||
|
@@ -230,7 +230,7 @@ export function dispatch_normal_event(event) {
|
||||
break;
|
||||
|
||||
case "presence":
|
||||
activity_ui.update_presence_info(event.user_id, event.presence, event.server_timestamp);
|
||||
activity_ui.update_presence_info(event.presences);
|
||||
break;
|
||||
|
||||
case "restart":
|
||||
|
@@ -694,11 +694,10 @@ test("update_presence_info", ({override, override_rewire}) => {
|
||||
override(realm, "server_presence_ping_interval_seconds", 60);
|
||||
override(realm, "server_presence_offline_threshold_seconds", 200);
|
||||
|
||||
const server_time = 500;
|
||||
const info = {
|
||||
website: {
|
||||
status: "active",
|
||||
timestamp: server_time,
|
||||
let info = {
|
||||
[me.user_id]: {
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
},
|
||||
};
|
||||
|
||||
@@ -711,12 +710,19 @@ test("update_presence_info", ({override, override_rewire}) => {
|
||||
});
|
||||
|
||||
presence.presence_info.delete(me.user_id);
|
||||
activity_ui.update_presence_info(me.user_id, info, server_time);
|
||||
activity_ui.update_presence_info(info);
|
||||
assert.ok(inserted);
|
||||
assert.deepEqual(presence.presence_info.get(me.user_id).status, "active");
|
||||
|
||||
info = {
|
||||
[alice.user_id]: {
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
},
|
||||
};
|
||||
|
||||
presence.presence_info.delete(alice.user_id);
|
||||
activity_ui.update_presence_info(alice.user_id, info, server_time);
|
||||
activity_ui.update_presence_info(info);
|
||||
assert.ok(inserted);
|
||||
|
||||
const expected = {status: "active", last_active: 500};
|
||||
@@ -724,7 +730,13 @@ test("update_presence_info", ({override, override_rewire}) => {
|
||||
|
||||
// Test invalid and inaccessible user IDs.
|
||||
const invalid_user_id = 99;
|
||||
activity_ui.update_presence_info(invalid_user_id, info, server_time);
|
||||
info = {
|
||||
[invalid_user_id]: {
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
},
|
||||
};
|
||||
activity_ui.update_presence_info(info);
|
||||
assert.equal(presence.presence_info.get(invalid_user_id), undefined);
|
||||
|
||||
const inaccessible_user_id = 10;
|
||||
@@ -735,7 +747,13 @@ test("update_presence_info", ({override, override_rewire}) => {
|
||||
"Unknown user",
|
||||
);
|
||||
people._add_user(inaccessible_user);
|
||||
activity_ui.update_presence_info(inaccessible_user_id, info, server_time);
|
||||
info = {
|
||||
[inaccessible_user_id]: {
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
},
|
||||
};
|
||||
activity_ui.update_presence_info(info);
|
||||
assert.equal(presence.presence_info.get(inaccessible_user_id), undefined);
|
||||
});
|
||||
|
||||
|
@@ -461,10 +461,8 @@ test("level", ({override}) => {
|
||||
|
||||
const server_time = 9999;
|
||||
const info = {
|
||||
website: {
|
||||
status: "active",
|
||||
timestamp: server_time,
|
||||
},
|
||||
active_timestamp: 9999,
|
||||
idle_timestamp: 9999,
|
||||
};
|
||||
presence.update_info_from_event(me.user_id, info, server_time);
|
||||
presence.update_info_from_event(selma.user_id, info, server_time);
|
||||
|
@@ -461,10 +461,8 @@ run_test("presence", ({override}) => {
|
||||
override(activity_ui, "update_presence_info", stub.f);
|
||||
dispatch(event);
|
||||
assert.equal(stub.num_calls, 1);
|
||||
const args = stub.get_args("user_id", "presence", "server_time");
|
||||
assert_same(args.user_id, event.user_id);
|
||||
assert_same(args.presence, event.presence);
|
||||
assert_same(args.server_time, event.server_timestamp);
|
||||
const args = stub.get_args("presences");
|
||||
assert_same(args.presences, event.presences);
|
||||
});
|
||||
|
||||
run_test("reaction", ({override}) => {
|
||||
|
@@ -328,17 +328,12 @@ exports.fixtures = {
|
||||
|
||||
presence: {
|
||||
type: "presence",
|
||||
email: "alice@example.com",
|
||||
user_id: 42,
|
||||
presence: {
|
||||
electron: {
|
||||
status: "active",
|
||||
timestamp: fake_now,
|
||||
client: "electron",
|
||||
pushable: false,
|
||||
presences: {
|
||||
42: {
|
||||
active_timestamp: fake_now,
|
||||
idle_timestamp: fake_now,
|
||||
},
|
||||
},
|
||||
server_timestamp: fake_now,
|
||||
},
|
||||
|
||||
reaction__add: {
|
||||
|
@@ -315,10 +315,8 @@ test("update_info_from_event", () => {
|
||||
let info;
|
||||
|
||||
info = {
|
||||
website: {
|
||||
status: "active",
|
||||
timestamp: 500,
|
||||
},
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
};
|
||||
|
||||
presence.presence_info.delete(alice.user_id);
|
||||
@@ -330,10 +328,8 @@ test("update_info_from_event", () => {
|
||||
});
|
||||
|
||||
info = {
|
||||
mobile: {
|
||||
status: "idle",
|
||||
timestamp: 510,
|
||||
},
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 500,
|
||||
};
|
||||
presence.update_info_from_event(alice.user_id, info, 510);
|
||||
|
||||
@@ -343,10 +339,8 @@ test("update_info_from_event", () => {
|
||||
});
|
||||
|
||||
info = {
|
||||
mobile: {
|
||||
status: "idle",
|
||||
timestamp: 1000,
|
||||
},
|
||||
active_timestamp: 500,
|
||||
idle_timestamp: 1000,
|
||||
};
|
||||
presence.update_info_from_event(alice.user_id, info, 1000);
|
||||
|
||||
|
@@ -105,6 +105,7 @@ def build_page_params_for_home_page_load(
|
||||
include_deactivated_groups=True,
|
||||
archived_channels=True,
|
||||
empty_topic_name=True,
|
||||
simplified_presence_events=True,
|
||||
)
|
||||
|
||||
if user_profile is not None:
|
||||
|
Reference in New Issue
Block a user