mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 07:24:52 +09:00
101 lines
3.1 KiB
TypeScript
101 lines
3.1 KiB
TypeScript
import React, { useCallback, useContext, useSyncExternalStore } from "react";
|
|
import { Tag } from "antd";
|
|
import ControlContext from "../components/ControlContext";
|
|
|
|
import * as lib from "@clusterio/lib";
|
|
|
|
export function getUserStats(user: lib.UserDetails, instanceId?: number) {
|
|
if (instanceId === undefined) {
|
|
return user.playerStats;
|
|
}
|
|
return user.instanceStats.get(instanceId);
|
|
}
|
|
|
|
export function isUserOnline(user: lib.UserDetails, instanceId?: number) {
|
|
if (instanceId === undefined) {
|
|
return user.instances && user.instances.size > 0;
|
|
}
|
|
return user.instances && user.instances.has(instanceId);
|
|
}
|
|
|
|
export function calculateFirstSeen(user: lib.UserDetails, instanceId?: number) {
|
|
const stats = getUserStats(user, instanceId);
|
|
return stats?.firstJoinAt?.getTime();
|
|
}
|
|
|
|
export function calculateLastSeen(user: lib.UserDetails, instanceId?: number) {
|
|
const stats = getUserStats(user, instanceId);
|
|
if (!stats) {
|
|
return undefined;
|
|
}
|
|
if (stats.lastLeaveAt && stats.lastLeaveAt.getTime() > (stats.lastJoinAt?.getTime() ?? 0)) {
|
|
return stats.lastLeaveAt.getTime();
|
|
}
|
|
if (stats.lastJoinAt) {
|
|
return stats.lastJoinAt.getTime();
|
|
}
|
|
return undefined;
|
|
}
|
|
|
|
export function formatFirstSeen(user: lib.UserDetails, instanceId?: number) {
|
|
const firstSeen = calculateFirstSeen(user, instanceId);
|
|
if (firstSeen === undefined) {
|
|
return undefined;
|
|
}
|
|
return new Date(firstSeen).toLocaleString();
|
|
}
|
|
|
|
export function formatLastSeen(user: lib.UserDetails, instanceId?: number) {
|
|
if (user.instances && [...user.instances].some(id => instanceId === undefined || id === instanceId)) {
|
|
return <Tag color="green">Online</Tag>;
|
|
}
|
|
let lastSeen = calculateLastSeen(user, instanceId);
|
|
if (lastSeen === undefined) {
|
|
return undefined;
|
|
}
|
|
return new Date(lastSeen).toLocaleString();
|
|
}
|
|
|
|
export function sortFirstSeen(
|
|
userA: lib.UserDetails,
|
|
userB: lib.UserDetails,
|
|
instanceIdA?: number,
|
|
instanceIdB?: number
|
|
) {
|
|
const firstSeenA = calculateFirstSeen(userA, instanceIdA) || 0;
|
|
const firstSeenB = calculateFirstSeen(userB, instanceIdB) || 0;
|
|
return firstSeenA - firstSeenB;
|
|
}
|
|
|
|
export function sortLastSeen(
|
|
userA: lib.UserDetails,
|
|
userB: lib.UserDetails,
|
|
instanceIdA?: number,
|
|
instanceIdB?: number
|
|
) {
|
|
function epoch(user: lib.UserDetails, instanceId?: number) {
|
|
return user.instances && [...user.instances].some(id => instanceId === undefined || id === instanceId);
|
|
}
|
|
|
|
let epochA = epoch(userA, instanceIdA);
|
|
let epochB = epoch(userB, instanceIdB);
|
|
if (epochA !== epochB) {
|
|
return Number(epochA) - Number(epochB);
|
|
}
|
|
|
|
let lastSeenA = calculateLastSeen(userA, instanceIdA) || 0;
|
|
let lastSeenB = calculateLastSeen(userB, instanceIdB) || 0;
|
|
return lastSeenA - lastSeenB;
|
|
}
|
|
|
|
export function useUser(name?: string) {
|
|
const [users, synced] = useUsers();
|
|
return [name !== undefined ? users.get(name.toLowerCase()) : undefined, synced] as const;
|
|
}
|
|
|
|
export function useUsers() {
|
|
const control = useContext(ControlContext);
|
|
const subscribe = useCallback((callback: () => void) => control.users.subscribe(callback), [control]);
|
|
return useSyncExternalStore(subscribe, () => control.users.getSnapshot());
|
|
}
|