검증게시판 단계 추가

This commit is contained in:
Macbook
2026-05-28 16:24:14 +09:00
parent f64dc1e983
commit 7e3644cb62
375 changed files with 4539 additions and 251294 deletions
@@ -28,6 +28,7 @@ import {
} from '../utils/tradeAlertSound';
import { getUiPreferences, patchUiPreferences } from '../utils/uiPreferencesDb';
import { useAppSettings } from '../hooks/useAppSettings';
const MAX_HISTORY = 300;
/** 팝업 대기열 최대 건수 (페이지 슬라이딩) */
const MAX_TOAST_QUEUE = 50;
@@ -60,7 +61,7 @@ interface TradeNotificationContextValue {
deleteUnreadNotifications: () => Promise<void>;
/** 알림 목록 전체 삭제 */
deleteAllNotifications: () => Promise<void>;
refreshHistory: () => Promise<void>;
refreshHistory: (opts?: { serverOnly?: boolean; rawServerList?: boolean }) => Promise<void>;
detailSignal: TradeSignalInfo | null;
/** 상세 모달을 화면 중앙에 표시 (알림 목록에서 열 때) */
detailCentered: boolean;
@@ -126,6 +127,8 @@ interface ProviderProps {
soundEnabled?: boolean;
/** 알림음 ID */
soundId?: string;
/** 로그인·게스트 전환 시 app-settings 재로드 키 */
settingsSessionKey?: number;
}
export const TradeNotificationProvider: React.FC<ProviderProps> = ({
@@ -133,7 +136,9 @@ export const TradeNotificationProvider: React.FC<ProviderProps> = ({
popupEnabled,
soundEnabled = true,
soundId = 'bell',
settingsSessionKey = 0,
}) => {
const { isLoaded: settingsLoaded } = useAppSettings(settingsSessionKey);
const alertSoundId = normalizeTradeAlertSoundId(soundId) as TradeAlertSoundId;
const [readIds, setReadIds] = useState<Set<string>>(() => loadReadIds());
const readIdsRef = useRef(readIds);
@@ -150,15 +155,15 @@ export const TradeNotificationProvider: React.FC<ProviderProps> = ({
[allNotifications],
);
const refreshHistory = useCallback(async () => {
const refreshHistory = useCallback(async (opts?: { serverOnly?: boolean; rawServerList?: boolean }) => {
try {
const dtos = await loadTradeSignals();
/** dismiss 직후 비동기 완료 시 state readIds가 늦게 반영되는 것 방지 */
const read = loadReadIds();
const hidden = loadHiddenIds();
const read = opts?.rawServerList ? new Set<string>() : loadReadIds();
const hidden = opts?.rawServerList ? new Set<string>() : loadHiddenIds();
const items = dtos
.map(d => dtoToItem(d, read))
.filter(item => !hidden.has(item.id));
.filter(item => opts?.rawServerList || !hidden.has(item.id));
let newlyArrived: TradeNotificationItem[] = [];
@@ -167,6 +172,12 @@ export const TradeNotificationProvider: React.FC<ProviderProps> = ({
item => !item.isRead && !prev.some(p => p.id === item.id),
);
if (opts?.serverOnly || opts?.rawServerList) {
return items
.sort((a, b) => b.receivedAt - a.receivedAt)
.slice(0, MAX_HISTORY);
}
const map = new Map<string, TradeNotificationItem>();
for (const n of items) {
const wasRead = read.has(n.id) || prev.find(p => p.id === n.id)?.isRead;
@@ -199,8 +210,9 @@ export const TradeNotificationProvider: React.FC<ProviderProps> = ({
}, [popupEnabled, soundEnabled, alertSoundId]);
useEffect(() => {
void refreshHistory();
}, [refreshHistory]);
if (!settingsLoaded) return;
void refreshHistory({ serverOnly: true, rawServerList: true });
}, [refreshHistory, settingsLoaded, settingsSessionKey]);
const markAsRead = useCallback((id: string) => {
setReadIds(prev => {