new devices system prototype
This commit is contained in:
16
app/components/DeviceVerify/DeviceVerify.tsx
Normal file
16
app/components/DeviceVerify/DeviceVerify.tsx
Normal 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>
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -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>
|
||||||
|
|||||||
@@ -1,10 +1,9 @@
|
|||||||
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);
|
||||||
@@ -14,63 +13,19 @@ interface DeviceProviderProps {
|
|||||||
}
|
}
|
||||||
|
|
||||||
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>
|
||||||
|
|||||||
13
app/providers/DeviceProvider/useDevices.ts
Normal file
13
app/providers/DeviceProvider/useDevices.ts
Normal 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;
|
||||||
|
}
|
||||||
23
app/providers/DeviceProvider/useVerifyRequest.ts
Normal file
23
app/providers/DeviceProvider/useVerifyRequest.ts
Normal 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;
|
||||||
|
}
|
||||||
@@ -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)[] {
|
||||||
|
|||||||
Reference in New Issue
Block a user