new devices system prototype

This commit is contained in:
RoyceDa
2026-01-31 03:03:27 +02:00
parent 49cedac8af
commit e87518a77e
6 changed files with 75 additions and 59 deletions

View File

@@ -0,0 +1,16 @@
import { DeviceEntry } from "@/app/providers/ProtocolProvider/protocol/packets/packet.device.list";
import { Flex, Text } from "@mantine/core";
export interface DeviceVerifyProps {
device: DeviceEntry;
}
export function DeviceVerify(props: DeviceVerifyProps) {
return (
<Flex>
<Text>
New login from {props.device.deviceName}
</Text>
</Flex>
);
}

View File

@@ -8,6 +8,8 @@ import { useNavigate } from 'react-router-dom';
import { DialogsList } from '../DialogsList/DialogsList'; import { DialogsList } from '../DialogsList/DialogsList';
import { DialogsPanelHeader } from '../DialogsPanelHeader/DialogsPanelHeader'; import { DialogsPanelHeader } from '../DialogsPanelHeader/DialogsPanelHeader';
import { useDialogsList } from '@/app/providers/DialogListProvider/useDialogsList'; import { useDialogsList } from '@/app/providers/DialogListProvider/useDialogsList';
import { useVerifyRequest } from '@/app/providers/DeviceProvider/useVerifyRequest';
import { DeviceVerify } from '../DeviceVerify/DeviceVerify';
export function DialogsPanel() { export function DialogsPanel() {
const [dialogsMode, setDialogsMode] = useState<'all' | 'requests'>('all'); const [dialogsMode, setDialogsMode] = useState<'all' | 'requests'>('all');
@@ -15,6 +17,7 @@ export function DialogsPanel() {
const {dialogs} = useDialogsList(); const {dialogs} = useDialogsList();
const colors = useRosettaColors(); const colors = useRosettaColors();
const navigate = useNavigate(); const navigate = useNavigate();
const device = useVerifyRequest();
useEffect(() => { useEffect(() => {
((async () => { ((async () => {
@@ -51,6 +54,9 @@ export function DialogsPanel() {
> >
<Box> <Box>
<DialogsPanelHeader></DialogsPanelHeader> <DialogsPanelHeader></DialogsPanelHeader>
{device && (
<DeviceVerify device={device}></DeviceVerify>
)}
{requestsCount > 0 && <RequestsButton mode={dialogsMode} onClick={changeDialogMode} count={requestsCount}></RequestsButton>} {requestsCount > 0 && <RequestsButton mode={dialogsMode} onClick={changeDialogMode} count={requestsCount}></RequestsButton>}
<Divider color={colors.borderColor}></Divider> <Divider color={colors.borderColor}></Divider>
</Box> </Box>

View File

@@ -1,76 +1,31 @@
import { decodeWithPassword, encodeWithPassword } from "@/app/crypto/crypto"; import { createContext, useState } from "react";
import { useFileStorage } from "@/app/hooks/useFileStorage"; import { DeviceEntry, PacketDeviceList } from "../ProtocolProvider/protocol/packets/packet.device.list";
import { generateRandomKey } from "@/app/utils/utils"; import { usePacket } from "../ProtocolProvider/usePacket";
import { createContext, useEffect, useState } from "react";
interface DeviceProviderContextValue { interface DeviceProviderContextValue {
deviceId: string; devices: DeviceEntry[];
} }
export const DeviceProviderContext = createContext<DeviceProviderContextValue|null>(null); export const DeviceProviderContext = createContext<DeviceProviderContextValue|null>(null);
interface DeviceProviderProps { interface DeviceProviderProps {
children?: React.ReactNode; children?: React.ReactNode;
} }
export function DeviceProvider(props: DeviceProviderProps) { export function DeviceProvider(props: DeviceProviderProps) {
const [deviceId, setDeviceId] = useState<string>(""); /**
const {writeFile, readFile} = useFileStorage(); * Подключенные устройства
*/
const [devices, setDevices] = useState<DeviceEntry[]>([]);
useEffect(() => { usePacket(0x17, (packet : PacketDeviceList) => {
fetchDeviceId(); console.info("Device list update", packet.getDevices());
setDevices(packet.getDevices());
}, []); }, []);
const fetchDeviceId = async () => {
const device = await readFile("device");
if(device){
const decoded = await decodeDevice(Buffer.from(device).toString('utf-8'));
if(decoded){
setDeviceId(decoded);
return;
}
}
await createDeviceId();
}
const createDeviceId = async () => {
const newDevice = generateRandomKey(128);
const encoded = await encodeDevice(newDevice);
await writeFile("device", encoded);
setDeviceId(newDevice);
}
const decodeDevice = async (data: string) => {
const hwid = window.deviceId;
const platform = window.deviceName;
const salt = "rosetta-device-salt";
try {
const decoded = await decodeWithPassword(hwid + platform + salt, data);
return decoded;
} catch (e) {
console.error("Failed to decode device data:", e);
return null;
}
}
const encodeDevice = async (data: string) => {
const hwid = window.deviceId;
const platform = window.deviceName;
const salt = "rosetta-device-salt";
try {
const encoded = await encodeWithPassword(hwid + platform + salt, data);
return encoded;
} catch (e) {
console.error("Failed to encode device data:", e);
return null;
}
}
return ( return (
<DeviceProviderContext.Provider value={{ <DeviceProviderContext.Provider value={{
deviceId: deviceId devices: devices
}}> }}>
{props.children} {props.children}
</DeviceProviderContext.Provider> </DeviceProviderContext.Provider>

View File

@@ -0,0 +1,13 @@
import { useContext } from "react";
import { DeviceProviderContext } from "./DeviceProvider";
import { DeviceEntry } from "../ProtocolProvider/protocol/packets/packet.device.list";
export function useDevices() : DeviceEntry[] {
const context = useContext(DeviceProviderContext);
if(!context) {
throw new Error("useDevices must be used within a DeviceProvider");
}
return context.devices;
}

View File

@@ -0,0 +1,23 @@
import { useContext } from "react";
import { DeviceEntry, DeviceVerifyState } from "../ProtocolProvider/protocol/packets/packet.device.list";
import { DeviceProviderContext } from "./DeviceProvider";
/**
* Получает устройство ожидающее подтверждения, если оно есть
* @returns возвращает устройство которое сейчас ждет одобрения
* от других устройств
*/
export function useVerifyRequest() : DeviceEntry | null {
const context = useContext(DeviceProviderContext);
if(!context) {
throw new Error("useVerifyRequest must be used within a DeviceProvider");
}
const pending = context.devices.find(device => device.deviceVerify === DeviceVerifyState.NOT_VERIFIED);
if(!pending) {
return null;
}
return pending;
}

View File

@@ -24,6 +24,8 @@ import { PacketGroupInviteInfo } from "./packets/packet.group.invite.info";
import { PacketGroupJoin } from "./packets/packet.group.join"; import { PacketGroupJoin } from "./packets/packet.group.join";
import { PacketGroupLeave } from "./packets/packet.group.leave"; import { PacketGroupLeave } from "./packets/packet.group.leave";
import { PacketGroupBan } from "./packets/packet.group.ban"; import { PacketGroupBan } from "./packets/packet.group.ban";
import { PacketDeviceNew } from "./packets/packet.device.new";
import { PacketDeviceList } from "./packets/packet.device.list";
export default class Protocol extends EventEmitter { export default class Protocol extends EventEmitter {
private serverAddress: string; private serverAddress: string;
@@ -105,7 +107,7 @@ export default class Protocol extends EventEmitter {
this._supportedPackets.set(0x06, new PacketMessage()); this._supportedPackets.set(0x06, new PacketMessage());
this._supportedPackets.set(0x07, new PacketRead()); this._supportedPackets.set(0x07, new PacketRead());
this._supportedPackets.set(0x08, new PacketDelivery()); this._supportedPackets.set(0x08, new PacketDelivery());
//TODO: 0x09 this._supportedPackets.set(0x09, new PacketDeviceNew());
this._supportedPackets.set(0x0A, new PacketRequestUpdate()); this._supportedPackets.set(0x0A, new PacketRequestUpdate());
this._supportedPackets.set(0x0B, new PacketTyping()); this._supportedPackets.set(0x0B, new PacketTyping());
this._supportedPackets.set(0x0C, new PacketAvatar()); this._supportedPackets.set(0x0C, new PacketAvatar());
@@ -119,6 +121,7 @@ export default class Protocol extends EventEmitter {
this._supportedPackets.set(0x14, new PacketGroupJoin()); this._supportedPackets.set(0x14, new PacketGroupJoin());
this._supportedPackets.set(0x15, new PacketGroupLeave()); this._supportedPackets.set(0x15, new PacketGroupLeave());
this._supportedPackets.set(0x16, new PacketGroupBan()); this._supportedPackets.set(0x16, new PacketGroupBan());
this._supportedPackets.set(0x17, new PacketDeviceList());
} }
private _findWaiters(packetId: number): ((packet: Packet) => void)[] { private _findWaiters(packetId: number): ((packet: Packet) => void)[] {