mirror of
https://github.com/comit-network/xmr-btc-swap.git
synced 2025-12-17 01:24:02 -05:00
feat(gui): Remember acknowledged alerts and do not show them again
This commit is contained in:
parent
bbdae0c18c
commit
65a46a4205
5 changed files with 65 additions and 12 deletions
|
|
@ -1,14 +1,14 @@
|
|||
import { Box } from "@mui/material";
|
||||
import { Alert, AlertTitle } from "@mui/material";
|
||||
import { removeAlert } from "store/features/alertsSlice";
|
||||
import { useAppDispatch, useAppSelector } from "store/hooks";
|
||||
import { acknowledgeAlert } from "store/features/alertsSlice";
|
||||
import { useAlerts, useAppDispatch } from "store/hooks";
|
||||
|
||||
export default function ApiAlertsBox() {
|
||||
const alerts = useAppSelector((state) => state.alerts.alerts);
|
||||
const alerts = useAlerts();
|
||||
const dispatch = useAppDispatch();
|
||||
|
||||
function onRemoveAlert(id: number) {
|
||||
dispatch(removeAlert(id));
|
||||
function onAcknowledgeAlert(id: number) {
|
||||
dispatch(acknowledgeAlert(id));
|
||||
}
|
||||
|
||||
if (alerts.length === 0) return null;
|
||||
|
|
@ -20,7 +20,7 @@ export default function ApiAlertsBox() {
|
|||
variant="filled"
|
||||
severity={alert.severity}
|
||||
key={alert.id}
|
||||
onClose={() => onRemoveAlert(alert.id)}
|
||||
onClose={() => onAcknowledgeAlert(alert.id)}
|
||||
>
|
||||
<AlertTitle>{alert.title}</AlertTitle>
|
||||
{alert.body}
|
||||
|
|
|
|||
|
|
@ -17,7 +17,7 @@ import { LazyStore } from "@tauri-apps/plugin-store";
|
|||
const rootPersistConfig = {
|
||||
key: "gui-global-state-store",
|
||||
storage: sessionStorage,
|
||||
blacklist: ["settings", "conversations", "logs"],
|
||||
blacklist: ["settings", "conversations", "alerts", "logs"],
|
||||
};
|
||||
|
||||
// Use Tauri's store plugin for persistent settings
|
||||
|
|
@ -58,6 +58,12 @@ const conversationsPersistConfig = {
|
|||
storage: createTauriStorage(),
|
||||
};
|
||||
|
||||
// Persist alerts across application restarts
|
||||
const alertsPersistConfig = {
|
||||
key: "alerts",
|
||||
storage: createTauriStorage(),
|
||||
};
|
||||
|
||||
// Create a persisted version of the settings reducer
|
||||
const persistedSettingsReducer = persistReducer(
|
||||
settingsPersistConfig,
|
||||
|
|
@ -70,11 +76,18 @@ const persistedConversationsReducer = persistReducer(
|
|||
reducers.conversations,
|
||||
);
|
||||
|
||||
// Create a persisted version of the alerts reducer
|
||||
const persistedAlertsReducer = persistReducer(
|
||||
alertsPersistConfig,
|
||||
reducers.alerts,
|
||||
);
|
||||
|
||||
// Combine all reducers, using the persisted settings reducer
|
||||
const rootReducer = combineReducers({
|
||||
...reducers,
|
||||
settings: persistedSettingsReducer,
|
||||
conversations: persistedConversationsReducer,
|
||||
alerts: persistedAlertsReducer,
|
||||
});
|
||||
|
||||
// Enable persistence for the entire application state
|
||||
|
|
|
|||
|
|
@ -1,14 +1,28 @@
|
|||
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
|
||||
import { Alert } from "models/apiModel";
|
||||
import { fnv1a } from "utils/hash";
|
||||
|
||||
export interface AlertsSlice {
|
||||
alerts: Alert[];
|
||||
/// The ids of the alerts that have been acknowledged
|
||||
/// by the user and should not be shown again
|
||||
acknowledgedAlerts: AcknowledgementKey[];
|
||||
}
|
||||
|
||||
const initialState: AlertsSlice = {
|
||||
alerts: [],
|
||||
acknowledgedAlerts: [],
|
||||
};
|
||||
|
||||
/// We use the key in combination with the fnv1a hash of the title
|
||||
/// to uniquely identify an alert
|
||||
///
|
||||
/// If the title changes, the hash will change and the alert will be shown again
|
||||
interface AcknowledgementKey {
|
||||
id: number;
|
||||
titleHash: string;
|
||||
}
|
||||
|
||||
const alertsSlice = createSlice({
|
||||
name: "alerts",
|
||||
initialState,
|
||||
|
|
@ -16,13 +30,21 @@ const alertsSlice = createSlice({
|
|||
setAlerts(slice, action: PayloadAction<Alert[]>) {
|
||||
slice.alerts = action.payload;
|
||||
},
|
||||
removeAlert(slice, action: PayloadAction<number>) {
|
||||
slice.alerts = slice.alerts.filter(
|
||||
(alert) => alert.id !== action.payload,
|
||||
);
|
||||
acknowledgeAlert(slice, action: PayloadAction<number>) {
|
||||
const alertTitle = slice.alerts.find(
|
||||
(alert) => alert.id === action.payload,
|
||||
)?.title;
|
||||
|
||||
// If we cannot find the alert, we cannot acknowledge it
|
||||
if (alertTitle != null) {
|
||||
slice.acknowledgedAlerts.push({
|
||||
id: action.payload,
|
||||
titleHash: fnv1a(alertTitle),
|
||||
});
|
||||
}
|
||||
},
|
||||
},
|
||||
});
|
||||
|
||||
export const { setAlerts, removeAlert } = alertsSlice.actions;
|
||||
export const { setAlerts, acknowledgeAlert } = alertsSlice.actions;
|
||||
export default alertsSlice.reducer;
|
||||
|
|
|
|||
|
|
@ -30,6 +30,8 @@ import {
|
|||
TauriBackgroundProgress,
|
||||
TauriBitcoinSyncProgress,
|
||||
} from "models/tauriModel";
|
||||
import { Alert } from "models/apiModel";
|
||||
import { fnv1a } from "utils/hash";
|
||||
|
||||
export const useAppDispatch = () => useDispatch<AppDispatch>();
|
||||
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
|
||||
|
|
@ -327,3 +329,17 @@ export function useTotalUnreadMessagesCount(): number {
|
|||
|
||||
return totalUnreadCount;
|
||||
}
|
||||
|
||||
/// Returns all the alerts that have not been acknowledged
|
||||
export function useAlerts(): Alert[] {
|
||||
return useAppSelector((state) =>
|
||||
state.alerts.alerts.filter(
|
||||
(alert) =>
|
||||
// Check if there is an acknowledgement with
|
||||
// the same id and the same title hash
|
||||
!state.alerts.acknowledgedAlerts.some(
|
||||
(ack) => ack.id === alert.id && ack.titleHash === fnv1a(alert.title),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue