update system messages

This commit is contained in:
RoyceDa
2026-01-31 02:59:35 +02:00
parent ad696616e1
commit 1a6b88fc5a
6 changed files with 97 additions and 27 deletions

View File

@@ -1,9 +1,8 @@
import { useDatabase } from "@/app/providers/DatabaseProvider/useDatabase";
import { createContext, useEffect } from "react";
import { createContext } from "react";
import { useSystemAccount } from "./useSystemAccount";
import { usePublicKey } from "../AccountProvider/usePublicKey";
import { usePrivatePlain } from "../AccountProvider/usePrivatePlain";
import { APP_VERSION, RELEASE_NOTICE } from "@/app/version";
import { chacha20Encrypt, encodeWithPassword, encrypt } from "@/app/crypto/crypto";
import { generateRandomKey } from "@/app/utils/utils";
import { DeliveredMessageState } from "../DialogProvider/DialogProvider";
@@ -11,7 +10,11 @@ import { UserInformation } from "../InformationProvider/InformationProvider";
import { useNotification } from "@/app/hooks/useNotification";
import { useDialogsList } from "../DialogListProvider/useDialogsList";
export const SystemAccountContext = createContext(null);
export interface SystemAccountContextValue {
sendMessageFromSystemAccount: (accountUsername: string, message: string) => Promise<void>;
}
export const SystemAccountContext = createContext<SystemAccountContextValue | null>(null);
export interface SystemUserInformation extends UserInformation {
avatar: string;
@@ -23,49 +26,37 @@ interface SystemAccountProviderProps {
export function SystemAccountProvider(props : SystemAccountProviderProps) {
const {runQuery} = useDatabase();
const lastNoticeVersion = localStorage.getItem("lastNoticeVersion") || "0.0.0";
const updateAccount = useSystemAccount("updates");
const publicKey = usePublicKey();
const privatePlain = usePrivatePlain();
const {updateDialog} = useDialogsList();
const notify = useNotification();
useEffect(() => {
if(publicKey == ""){
return;
const sendMessageFromSystemAccount = async (accountUsername: string, message: string) => {
const account = useSystemAccount(accountUsername);
if(!account){
throw new Error("System account not found");
}
if(lastNoticeVersion !== APP_VERSION){
sendReleaseNoticeFromUpdatesAccount();
localStorage.setItem("lastNoticeVersion", APP_VERSION);
}
}, [lastNoticeVersion, publicKey]);
const sendReleaseNoticeFromUpdatesAccount = async () => {
const message = RELEASE_NOTICE;
if(message.trim() == ""){
return;
}
const cahchaEncrypted = await chacha20Encrypt(message.trim());
const chachaEncrypted : any = await chacha20Encrypt(message.trim());
const key = Buffer.concat([
Buffer.from(cahchaEncrypted.key, "hex"),
Buffer.from(cahchaEncrypted.nonce, "hex")]);
Buffer.from(chachaEncrypted.key, "hex"),
Buffer.from(chachaEncrypted.nonce, "hex")]);
const encryptedKey = await encrypt(key.toString('binary'), publicKey);
const messageId = generateRandomKey(16);
const plainMessage = await encodeWithPassword(privatePlain, message.trim());
await runQuery(`
INSERT INTO messages
(from_public_key, to_public_key, content, timestamp, read, chacha_key, from_me, plain_message, account, message_id, delivered, attachments) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
`, [updateAccount!.publicKey, publicKey, cahchaEncrypted.ciphertext, Date.now(), 0, encryptedKey, 0, plainMessage, publicKey, messageId, DeliveredMessageState.DELIVERED, JSON.stringify([])]);
updateDialog(updateAccount!.publicKey);
`, [account.publicKey, publicKey, chachaEncrypted.ciphertext, Date.now(), 0, encryptedKey, 0, plainMessage, publicKey, messageId, DeliveredMessageState.DELIVERED, JSON.stringify([])]);
updateDialog(account.publicKey);
notify("New message", "You have a new message");
}
return (
<SystemAccountContext.Provider value={null}>
<SystemAccountContext.Provider value={{
sendMessageFromSystemAccount
}}>
{props.children}
</SystemAccountContext.Provider>
)

Binary file not shown.

After

Width:  |  Height:  |  Size: 91 KiB

View File

@@ -0,0 +1,21 @@
import { useContext } from "react";
import { SystemAccountContext } from "./SystemAccountsProvider";
/**
* Возвращает функцию для отправки системного сообщения от имени указанного системного аккаунта
*
* ВАЖНО! Данный хук отправляет сообщение в текущий залогиненный аккаунт.
* @param accountUsername имя системного аккаунта от которого необходимо отправить сообщение
* @returns
*/
export function useSendSystemMessage(accountUsername : string) {
const context = useContext(SystemAccountContext);
if(!context){
throw new Error("useSystemSend must be used within a SystemAccountProvider");
}
const send = (message: string) => {
return context.sendMessageFromSystemAccount(accountUsername, message);
}
return send;
}

View File

@@ -1,6 +1,7 @@
import { OnlineState } from "@/app/providers/ProtocolProvider/protocol/packets/packet.onlinestate";
import { SystemUserInformation } from "./SystemAccountsProvider";
import updates from './avatars/updates.png';
import safe from './avatars/safe.png';
export function useSystemAccounts() : SystemUserInformation[] {
const accounts : SystemUserInformation[] = [
@@ -11,6 +12,14 @@ export function useSystemAccounts() : SystemUserInformation[] {
username: "updates",
online: OnlineState.OFFLINE,
avatar: updates
},
{
publicKey: "0x000000000000000000000000000000000000000002",
verified: 1,
title: "Safe",
username: "safe",
online: OnlineState.OFFLINE,
avatar: safe
}
];

View File

@@ -0,0 +1,30 @@
import { useContext } from "react";
import { SystemProviderContext } from "./SystemProvider";
/**
* Информация о системе и устройстве
*/
export interface SystemInformation {
/**
* Уникальный обезличенный идентификатор устройства
*/
id: string;
/**
* Имя устройства
*/
name: string;
/**
* Операционная система устройства
*/
os: string;
}
export function useSystemInformation() : SystemInformation {
const context = useContext(SystemProviderContext);
if(!context) {
throw new Error("useSystemInformation must be used within a SystemProvider");
}
return context as SystemInformation;
}

View File

@@ -27,13 +27,32 @@ import { useDatabase } from "@/app/providers/DatabaseProvider/useDatabase";
import { useMemoryClean } from "@/app/providers/MemoryProvider/useMemoryClean";
import { useAccountProvider } from "@/app/providers/AccountProvider/useAccountProvider";
import { useLogout } from "@/app/providers/AccountProvider/useLogout";
import { useUpdateMessage } from "@/app/hooks/useUpdateMessage";
import { useDeviceMessage } from "@/app/hooks/useDeviceMessage";
export function Main() {
const { mainColor, borderColor } = useRosettaColors();
const { lg } = useRosettaBreakpoints();
const location = useLocation();
const [viewState, setViewState] = useViewPanelsState();
/**
* Слушаем диалоги в пассивном режиме
*/
useDialogFiber();
/**
* Отправляем сообщение об обновлении,
* если версия приложения изменилась
*/
useUpdateMessage();
/**
* Слушаем все сообщения на присоединение новых устройств
* к нашему аккаунту
*/
useDeviceMessage();
const { setSize, setResizeble } = useWindow();
/**