This commit is contained in:
rosetta
2026-01-30 05:01:05 +02:00
commit 83f38dc63f
327 changed files with 18725 additions and 0 deletions

View File

@@ -0,0 +1,36 @@
@keyframes failVibrate {
0%, 100% {
left: 0px;
}
20%, 60% {
left: -2px;
}
40%, 80% {
left: 2px;
}
}
@keyframes skeletonPulse {
0% {
color: var(--mantine-primary-color-0);
}
50% {
color: var(--mantine-primary-color-2);
}
100% {
color: var(--mantine-primary-color-0);
}
}
.mention {
user-select: auto;
}
.skeleton {
animation: skeletonPulse 1.5s infinite;
}
.fail_vibrate {
position: relative;
animation: failVibrate 0.3s linear;
}

View File

@@ -0,0 +1,86 @@
import { usePrivateKeyHash } from "@/app/providers/AccountProvider/usePrivateKeyHash";
import { PacketSearch, PacketSearchUser } from "@/app/providers/ProtocolProvider/protocol/packets/packet.search";
import { usePacket } from "@/app/providers/ProtocolProvider/usePacket";
import { useSender } from "@/app/providers/ProtocolProvider/useSender";
import { Anchor } from "@mantine/core";
import { useState } from "react";
import classes from './UserMention.module.css';
import { cx } from "@/app/utils/style";
import { useNavigate } from "react-router-dom";
export interface UserMentionProps {
username: string;
color?: string;
}
export function UserMention(props : UserMentionProps) {
const send = useSender();
const privateKey = usePrivateKeyHash();
const [loading, setLoading] = useState(false);
const [fail, setFail] = useState(false);
const [vibrate, setVibrate] = useState(false);
const navigate = useNavigate();
usePacket(0x03, (packet: PacketSearch) => {
if(!loading){
return;
}
if(fail){
vibrateCall();
return;
}
setLoading(false);
let users = packet.getUsers();
if(users.length <= 0){
vibrateCall();
setFail(true);
return;
}
const user = findMatchuser(users);
if(!user){
vibrateCall();
setFail(true);
return;
}
navigate(`/main/chat/${user.publicKey}`);
}, [props.username, loading, fail]);
const findMatchuser = (users: PacketSearchUser[]) => {
for(let user of users){
if(user.username === props.username.replace('@', '')){
return user;
}
}
return null;
}
const onClick = () => {
if(fail){
vibrateCall();
return;
}
let packet = new PacketSearch();
packet.setSearch(props.username.replace('@', ''));
packet.setPrivateKey(privateKey);
send(packet);
setLoading(true);
}
const vibrateCall = () => {
if(vibrate){
return;
}
setVibrate(true);
setTimeout(() => {
setVibrate(false);
}, 300);
}
return (
<Anchor className={cx(
classes.mention,
loading && classes.skeleton,
vibrate && classes.fail_vibrate
)} onClick={onClick} c={props.color} size="sm">{props.username}</Anchor>
);
}