mirror of
https://github.com/zulip/zulip.git
synced 2025-10-26 09:34:02 +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
|
# Change to CamelCase
|
||||||
name = name.replace("_", " ").title().replace(" ", "")
|
name = name.replace("_", " ").title().replace(" ", "")
|
||||||
|
|
||||||
|
# Use EventModernPresence type to check "presence" events
|
||||||
if name == "Presence":
|
if name == "Presence":
|
||||||
name = "Legacy" + name
|
name = "Modern" + name
|
||||||
|
|
||||||
# And add the prefix.
|
# And add the prefix.
|
||||||
name = "Event" + name
|
name = "Event" + name
|
||||||
|
|||||||
@@ -227,11 +227,12 @@ export function initialize(opts: {narrow_by_email: (email: string) => void}): vo
|
|||||||
activity.send_presence_to_server();
|
activity.send_presence_to_server();
|
||||||
}
|
}
|
||||||
|
|
||||||
export function update_presence_info(
|
export function update_presence_info(info: PresenceInfoFromEvent): void {
|
||||||
user_id: number,
|
const presence_entry = Object.entries(info)[0];
|
||||||
info: PresenceInfoFromEvent,
|
assert(presence_entry !== undefined);
|
||||||
server_time: number,
|
const [user_id_string, presence_info] = presence_entry;
|
||||||
): void {
|
const user_id = Number.parseInt(user_id_string, 10);
|
||||||
|
|
||||||
// There can be some case where the presence event
|
// There can be some case where the presence event
|
||||||
// was set for an inaccessible user if
|
// was set for an inaccessible user if
|
||||||
// CAN_ACCESS_ALL_USERS_GROUP_LIMITS_PRESENCE is
|
// CAN_ACCESS_ALL_USERS_GROUP_LIMITS_PRESENCE is
|
||||||
@@ -241,7 +242,7 @@ export function update_presence_info(
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
presence.update_info_from_event(user_id, info, server_time);
|
presence.update_info_from_event(user_id, presence_info);
|
||||||
redraw_user(user_id);
|
redraw_user(user_id);
|
||||||
pm_list.update_private_messages();
|
pm_list.update_private_messages();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -15,14 +15,13 @@ export type PresenceStatus = {
|
|||||||
last_active?: number | undefined;
|
last_active?: number | undefined;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const presence_info_from_event_schema = z.object({
|
export const presence_info_from_event_schema = z.record(
|
||||||
website: z.object({
|
z.string(),
|
||||||
client: z.literal("website"),
|
z.object({
|
||||||
status: z.enum(["idle", "active"]),
|
active_timestamp: z.number(),
|
||||||
timestamp: z.number(),
|
idle_timestamp: z.number(),
|
||||||
pushable: z.boolean(),
|
|
||||||
}),
|
}),
|
||||||
});
|
);
|
||||||
export type PresenceInfoFromEvent = z.output<typeof presence_info_from_event_schema>;
|
export type PresenceInfoFromEvent = z.output<typeof presence_info_from_event_schema>;
|
||||||
|
|
||||||
export const user_last_seen_response_schema = z.object({
|
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(
|
export function update_info_from_event(
|
||||||
user_id: number,
|
user_id: number,
|
||||||
info: PresenceInfoFromEvent | null,
|
info: z.infer<typeof presence_schema> | null,
|
||||||
server_timestamp: number,
|
server_timestamp: number | undefined = undefined,
|
||||||
): void {
|
): void {
|
||||||
/*
|
/*
|
||||||
Example of `info`:
|
Example of `info`:
|
||||||
|
|
||||||
{
|
{
|
||||||
website: {
|
"10": {
|
||||||
client: 'website',
|
active_timestamp: 1585745133,
|
||||||
pushable: false,
|
idle_timestamp: 1585745091
|
||||||
status: 'active',
|
|
||||||
timestamp: 1585745225
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -190,16 +187,16 @@ export function update_info_from_event(
|
|||||||
server_timestamp: 0,
|
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 (info !== null) {
|
||||||
if (rec.status === "active" && rec.timestamp > (raw.active_timestamp ?? 0)) {
|
raw.active_timestamp = info.active_timestamp;
|
||||||
raw.active_timestamp = rec.timestamp;
|
raw.idle_timestamp = info.idle_timestamp;
|
||||||
}
|
|
||||||
|
|
||||||
if (rec.status === "idle" && rec.timestamp > (raw.idle_timestamp ?? 0)) {
|
|
||||||
raw.idle_timestamp = rec.timestamp;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
raw_info.set(user_id, raw);
|
raw_info.set(user_id, raw);
|
||||||
|
|||||||
@@ -230,7 +230,7 @@ export function dispatch_normal_event(event) {
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case "presence":
|
case "presence":
|
||||||
activity_ui.update_presence_info(event.user_id, event.presence, event.server_timestamp);
|
activity_ui.update_presence_info(event.presences);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case "restart":
|
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_ping_interval_seconds", 60);
|
||||||
override(realm, "server_presence_offline_threshold_seconds", 200);
|
override(realm, "server_presence_offline_threshold_seconds", 200);
|
||||||
|
|
||||||
const server_time = 500;
|
let info = {
|
||||||
const info = {
|
[me.user_id]: {
|
||||||
website: {
|
active_timestamp: 500,
|
||||||
status: "active",
|
idle_timestamp: 500,
|
||||||
timestamp: server_time,
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -711,12 +710,19 @@ test("update_presence_info", ({override, override_rewire}) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
presence.presence_info.delete(me.user_id);
|
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.ok(inserted);
|
||||||
assert.deepEqual(presence.presence_info.get(me.user_id).status, "active");
|
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);
|
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);
|
assert.ok(inserted);
|
||||||
|
|
||||||
const expected = {status: "active", last_active: 500};
|
const expected = {status: "active", last_active: 500};
|
||||||
@@ -724,7 +730,13 @@ test("update_presence_info", ({override, override_rewire}) => {
|
|||||||
|
|
||||||
// Test invalid and inaccessible user IDs.
|
// Test invalid and inaccessible user IDs.
|
||||||
const invalid_user_id = 99;
|
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);
|
assert.equal(presence.presence_info.get(invalid_user_id), undefined);
|
||||||
|
|
||||||
const inaccessible_user_id = 10;
|
const inaccessible_user_id = 10;
|
||||||
@@ -735,7 +747,13 @@ test("update_presence_info", ({override, override_rewire}) => {
|
|||||||
"Unknown user",
|
"Unknown user",
|
||||||
);
|
);
|
||||||
people._add_user(inaccessible_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);
|
assert.equal(presence.presence_info.get(inaccessible_user_id), undefined);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -461,10 +461,8 @@ test("level", ({override}) => {
|
|||||||
|
|
||||||
const server_time = 9999;
|
const server_time = 9999;
|
||||||
const info = {
|
const info = {
|
||||||
website: {
|
active_timestamp: 9999,
|
||||||
status: "active",
|
idle_timestamp: 9999,
|
||||||
timestamp: server_time,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
presence.update_info_from_event(me.user_id, info, server_time);
|
presence.update_info_from_event(me.user_id, info, server_time);
|
||||||
presence.update_info_from_event(selma.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);
|
override(activity_ui, "update_presence_info", stub.f);
|
||||||
dispatch(event);
|
dispatch(event);
|
||||||
assert.equal(stub.num_calls, 1);
|
assert.equal(stub.num_calls, 1);
|
||||||
const args = stub.get_args("user_id", "presence", "server_time");
|
const args = stub.get_args("presences");
|
||||||
assert_same(args.user_id, event.user_id);
|
assert_same(args.presences, event.presences);
|
||||||
assert_same(args.presence, event.presence);
|
|
||||||
assert_same(args.server_time, event.server_timestamp);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
run_test("reaction", ({override}) => {
|
run_test("reaction", ({override}) => {
|
||||||
|
|||||||
@@ -328,17 +328,12 @@ exports.fixtures = {
|
|||||||
|
|
||||||
presence: {
|
presence: {
|
||||||
type: "presence",
|
type: "presence",
|
||||||
email: "alice@example.com",
|
presences: {
|
||||||
user_id: 42,
|
42: {
|
||||||
presence: {
|
active_timestamp: fake_now,
|
||||||
electron: {
|
idle_timestamp: fake_now,
|
||||||
status: "active",
|
|
||||||
timestamp: fake_now,
|
|
||||||
client: "electron",
|
|
||||||
pushable: false,
|
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
server_timestamp: fake_now,
|
|
||||||
},
|
},
|
||||||
|
|
||||||
reaction__add: {
|
reaction__add: {
|
||||||
|
|||||||
@@ -315,10 +315,8 @@ test("update_info_from_event", () => {
|
|||||||
let info;
|
let info;
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
website: {
|
active_timestamp: 500,
|
||||||
status: "active",
|
idle_timestamp: 500,
|
||||||
timestamp: 500,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
presence.presence_info.delete(alice.user_id);
|
presence.presence_info.delete(alice.user_id);
|
||||||
@@ -330,10 +328,8 @@ test("update_info_from_event", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
mobile: {
|
active_timestamp: 500,
|
||||||
status: "idle",
|
idle_timestamp: 500,
|
||||||
timestamp: 510,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
presence.update_info_from_event(alice.user_id, info, 510);
|
presence.update_info_from_event(alice.user_id, info, 510);
|
||||||
|
|
||||||
@@ -343,10 +339,8 @@ test("update_info_from_event", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
info = {
|
info = {
|
||||||
mobile: {
|
active_timestamp: 500,
|
||||||
status: "idle",
|
idle_timestamp: 1000,
|
||||||
timestamp: 1000,
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
presence.update_info_from_event(alice.user_id, info, 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,
|
include_deactivated_groups=True,
|
||||||
archived_channels=True,
|
archived_channels=True,
|
||||||
empty_topic_name=True,
|
empty_topic_name=True,
|
||||||
|
simplified_presence_events=True,
|
||||||
)
|
)
|
||||||
|
|
||||||
if user_profile is not None:
|
if user_profile is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user