[MIRROR] TG-Chat log limits (#7719)

Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
Co-authored-by: Selis <selis@xynolabs.com>
This commit is contained in:
CHOMPStation2
2024-02-10 07:59:37 -07:00
committed by GitHub
parent 92a056ef9e
commit c5aa548bdf
13 changed files with 626 additions and 288 deletions

View File

@@ -201,13 +201,13 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
MessageNoRecipient(parsed_message)
send2adminchat() //VOREStation Add
//show it to the person adminhelping too
to_chat(C, "<span class='adminnotice'>PM to-<b>Admins</b>: [name]</span>")
to_chat(C, "<span class='pm adminnotice'>PM to-<b>Admins</b>: [name]</span>")
//send it to irc if nobody is on and tell us how many were on
var/admin_number_present = send2irc_adminless_only(initiator_ckey, name)
log_admin("Ticket #[id]: [key_name(initiator)]: [name] - heard by [admin_number_present] non-AFK admins who have +BAN.")
if(admin_number_present <= 0)
to_chat(C, "<span class='notice'>No active admins are online, your adminhelp was sent to the admin discord.</span>") //VOREStation Edit
to_chat(C, "<span class='pm notice'>No active admins are online, your adminhelp was sent to the admin discord.</span>") //VOREStation Edit
send2adminchat() //VOREStation Add
//YW EDIT START
var/list/adm = get_admin_counts()
@@ -280,7 +280,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
//won't bug irc
/datum/admin_help/proc/MessageNoRecipient(msg)
var/ref_src = "\ref[src]"
var/chat_msg = "<span class='adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> [msg]</span>"
var/chat_msg = "<span class='pm adminnotice'><span class='adminhelp'>Ticket [TicketHref("#[id]", ref_src)]</span><b>: [LinkedReplyName(ref_src)] [FullMonty(ref_src)]:</b> [msg]</span>"
AddInteraction("<font color='red'>[LinkedReplyName(ref_src)]: [msg]</font>")
//send this msg to all admins
@@ -652,7 +652,7 @@ GLOBAL_DATUM_INIT(ahelp_tickets, /datum/admin_help_tickets, new)
if(tgui_alert(usr, "You already have a ticket open. Is this for the same issue?","Duplicate?",list("Yes","No")) != "No")
if(current_ticket)
current_ticket.MessageNoRecipient(msg)
to_chat(usr, "<span class='adminnotice'>PM to-<b>Admins</b>: [msg]</span>")
to_chat(usr, "<span class='pm adminnotice'>PM to-<b>Admins</b>: [msg]</span>")
return
else
to_chat(usr, "<span class='warning'>Ticket not found, creating new one...</span>")

View File

@@ -100,7 +100,7 @@
to_chat(M, "<B>You hear a voice in your head...</B> <i>[msg]</i>")
log_admin("SubtlePM: [key_name(usr)] -> [key_name(M)] : [msg]")
msg = "<span class='adminnotice'><b> SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] :</b> [msg]</span>"
msg = "<span class='pm adminnotice'><b> SubtleMessage: [key_name_admin(usr)] -> [key_name_admin(M)] :</b> [msg]</span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","SMS") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
@@ -148,7 +148,7 @@
to_chat(M, msg)
log_admin("DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]): [msg]")
msg = "<span class='adminnotice'><b> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]):</b> [msg]<BR></span>"
msg = "<span class='pm adminnotice'><b> DirectNarrate: [key_name(usr)] to ([M.name]/[M.key]):</b> [msg]<BR></span>"
message_admins(msg)
admin_ticket_log(M, msg)
feedback_add_details("admin_verb","DIRN") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!

View File

@@ -63,10 +63,8 @@
new_mob.key = picked_client.key //Finally put them in the mob
if(organs)
new_mob.copy_from_prefs_vr()
// CHOMPEdit Start
if(LAZYLEN(new_mob.vore_organs))
new_mob.vore_selected = new_mob.vore_organs[1]
// CHOMPEdit End
log_admin("[key_name_admin(src)] has spawned [new_mob.key] as mob [new_mob.type].")
message_admins("[key_name_admin(src)] has spawned [new_mob.key] as mob [new_mob.type].", 1)

View File

@@ -6,7 +6,7 @@
// export const MAX_VISIBLE_MESSAGES = 2500; No longer a constant
// export const MAX_PERSISTED_MESSAGES = 1000; No longer a constant
export const MESSAGE_SAVE_INTERVAL = 10000;
// export const MESSAGE_SAVE_INTERVAL = 10000; No longer a constant
export const MESSAGE_PRUNE_INTERVAL = 60000;
// export const COMBINE_MAX_MESSAGES = 5; No longer a constant
// export const COMBINE_MAX_TIME_WINDOW = 5000; No longer a constant
@@ -61,7 +61,7 @@ export const MESSAGE_TYPES = [
type: MESSAGE_TYPE_NPCEMOTE, // Needs to be first
name: 'NPC Emotes / Says',
description: 'In-character emotes and says from NPCs',
selector: '.npcemote, .npcsay',
selector: '.npcemote, .npcsay :not(.radio)',
},
{
type: MESSAGE_TYPE_LOCALCHAT,
@@ -99,7 +99,7 @@ export const MESSAGE_TYPES = [
name: 'Info',
description: 'Non-urgent messages from the game and items',
selector:
'.notice:not(.pm), .adminnotice, .info, .sinister, .cult, .infoplain, .announce, .hear, .smallnotice, .holoparasite, .boldnotice',
'.notice:not(.pm), .adminnotice:not(.pm), .info, .sinister, .cult, .infoplain, .announce, .hear, .smallnotice, .holoparasite, .boldnotice',
},
{
type: MESSAGE_TYPE_WARNING,

View File

@@ -7,6 +7,7 @@
import { storage } from 'common/storage';
import DOMPurify from 'dompurify';
import { selectGame } from '../game/selectors';
import {
addHighlightSetting,
loadSettings,
@@ -29,13 +30,14 @@ import {
toggleAcceptedType,
updateMessageCount,
} from './actions';
import { MESSAGE_SAVE_INTERVAL } from './constants';
import { createMessage, serializeMessage } from './model';
import { chatRenderer } from './renderer';
import { selectChat, selectCurrentChatPage } from './selectors';
// List of blacklisted tags
const FORBID_TAGS = ['a', 'iframe', 'link', 'video'];
let storedRounds = [];
let storedLines = [];
const saveChatToStorage = async (store) => {
const state = selectChat(store.getState());
@@ -85,32 +87,49 @@ const loadChatFromStorage = async (store) => {
});
}
if (archivedMessages) {
chatRenderer.archivedMessages = archivedMessages;
/* FIXME Implement this later on
for (let archivedMessage of archivedMessages) {
if (archivedMessage.html) {
archivedMessage.html = DOMPurify.sanitize(archivedMessage.html, {
FORBID_TAGS,
});
}
}
const settings = selectSettings(store.getState());
const filteredMessages = [];
// Checks if the setting is actually set or set to -1 (infinite)
// Otherwise make it grow infinitely
if (settings.logRetainDays || settings.logRetainDays === -1) {
const limit = new Date();
limit.setDate(limit.getMinutes() - settings.logRetainDays);
if (settings.logRetainRounds) {
storedRounds = [];
storedLines = [];
let oldId = null;
let currentLine = 0;
settings.storedRounds = 0;
settings.exportStart = 0;
settings.exportEnd = 0;
for (let message of archivedMessages) {
const timestamp = new Date(message.createdAt);
timestamp.setDate(timestamp.getMinutes() - settings.logRetainDays);
if (timestamp.getDate() < limit.getDate()) {
filteredMessages.push(message);
const currentId = message.roundId;
if (currentId !== oldId) {
const round = currentId;
const line = currentLine;
storedRounds.push(round);
storedLines.push(line);
oldId = currentId;
currentLine++;
}
}
archivedMessages.length = 0;
if (storedRounds.length > settings.logRetainRounds) {
chatRenderer.archivedMessages = archivedMessages.slice(
storedLines[storedRounds.length - settings.logRetainRounds],
);
settings.storedRounds = settings.logRetainRounds;
} else {
chatRenderer.archivedMessages = archivedMessages;
}
settings.lastId = oldId;
} else {
chatRenderer.archivedMessages = archivedMessages;
}
chatRenderer.archivedMessages = filteredMessages;
*/
}
store.dispatch(loadChat(state));
};
@@ -131,21 +150,28 @@ export const chatMiddleware = (store) => {
chatRenderer.events.on('scrollTrackingChanged', (scrollTracking) => {
store.dispatch(changeScrollTracking(scrollTracking));
});
setInterval(() => {
saveChatToStorage(store);
}, MESSAGE_SAVE_INTERVAL);
return (next) => (action) => {
const { type, payload } = action;
const settings = selectSettings(store.getState());
const game = selectGame(store.getState());
settings.totalStoredMessages = chatRenderer.getStoredMessages();
settings.storedRounds = storedRounds.length;
chatRenderer.setVisualChatLimits(
settings.visibleMessageLimit,
settings.combineMessageLimit,
settings.combineIntervalLimit,
settings.logLineCount,
settings.logEnable,
settings.logLimit,
settings.storedTypes,
game.roundId,
);
if (!initialized) {
// Load the chat once settings are loaded
if (!initialized && settings.initialized) {
initialized = true;
setInterval(() => {
saveChatToStorage(store);
}, settings.saveInterval * 1000);
loadChatFromStorage(store);
}
if (type === 'chat/message') {
@@ -186,6 +212,11 @@ export const chatMiddleware = (store) => {
chatRenderer.processBatch([payload_obj.content], {
doArchive: true,
});
if (game.roundId !== settings.lastId) {
storedRounds.push(game.roundId);
storedLines.push(settings.totalStoredMessages - 1);
settings.lastId = game.roundId;
}
return;
}
if (type === loadChat.type) {
@@ -235,11 +266,21 @@ export const chatMiddleware = (store) => {
return next(action);
}
if (type === saveChatToDisk.type) {
chatRenderer.saveToDisk(settings.logLineCount);
chatRenderer.saveToDisk(
settings.logLineCount,
storedLines[storedLines.length - settings.exportEnd],
storedLines[storedLines.length - settings.exportStart],
);
return;
}
if (type === purgeChatMessageArchive.type) {
chatRenderer.purgeMessageArchive();
storedRounds = [];
storedLines = [];
settings.lastId = null;
settings.storedRounds = 0;
settings.exportStart = 0;
settings.exportEnd = 0;
return;
}
return next(action);

View File

@@ -11,6 +11,8 @@ import { MESSAGE_TYPE_INTERNAL, MESSAGE_TYPES } from './constants';
export const canPageAcceptType = (page, type) =>
type.startsWith(MESSAGE_TYPE_INTERNAL) || page.acceptedTypes[type];
export const canStoreType = (storedTypes, type) => storedTypes[type];
export const createPage = (obj) => {
let acceptedTypes = {};
@@ -43,6 +45,7 @@ export const createMainPage = () => {
export const createMessage = (payload) => ({
createdAt: Date.now(),
roundId: null,
...payload,
});
@@ -52,6 +55,7 @@ export const serializeMessage = (message, archive = false) => ({
html: archive ? message.node.outerHTML : message.html,
times: message.times,
createdAt: message.createdAt,
roundId: message.roundId,
});
export const isSameMessage = (a, b) =>

View File

@@ -6,25 +6,27 @@
import { EventEmitter } from 'common/events';
import { classes } from 'common/react';
import { render } from 'react-dom';
import { createLogger } from 'tgui/logging';
import { Tooltip } from '../../tgui/components';
import {
IMAGE_RETRY_DELAY,
IMAGE_RETRY_LIMIT,
IMAGE_RETRY_MESSAGE_AGE,
MESSAGE_PRUNE_INTERVAL,
MESSAGE_TYPES,
MESSAGE_TYPE_INTERNAL,
MESSAGE_TYPE_UNKNOWN,
MESSAGE_TYPES,
} from './constants';
import { render } from 'react-dom';
import {
canPageAcceptType,
canStoreType,
createMessage,
isSameMessage,
serializeMessage,
} from './model';
import { highlightNode, linkifyNode } from './replaceInTextNode';
import { Tooltip } from '../../tgui/components';
const logger = createLogger('chatRenderer');
@@ -132,7 +134,11 @@ class ChatRenderer {
this.visibleMessageLimit = 2500;
this.combineMessageLimit = 5;
this.combineIntervalLimit = 5;
this.exportLimit = -1;
this.exportLimit = 0;
this.logLimit = 0;
this.logEnable = true;
this.roundId = null;
this.storedTypes = {};
// Scroll handler
/** @type {HTMLElement} */
this.scrollNode = null;
@@ -375,11 +381,19 @@ class ChatRenderer {
combineMessageLimit,
combineIntervalLimit,
exportLimit,
logEnable,
logLimit,
storedTypes,
roundId,
) {
this.visibleMessageLimit = visibleMessageLimit;
this.combineMessageLimit = combineMessageLimit;
this.combineIntervalLimit = combineIntervalLimit;
this.exportLimit = exportLimit;
this.logEnable = logEnable;
this.logLimit = logLimit;
this.storedTypes = storedTypes;
this.roundId = roundId;
}
getCombinableMessage(predicate) {
@@ -561,7 +575,26 @@ class ChatRenderer {
countByType[message.type] += 1;
// TODO: Detect duplicates
this.messages.push(message);
if (doArchive) {
if (
doArchive &&
this.logEnable &&
this.storedTypes &&
canStoreType(this.storedTypes, message.type)
) {
message.roundId = this.roundId;
if (
this.logLimit > 0 &&
this.archivedMessages.length >= this.logLimit + 1
) {
this.archivedMessages = this.archivedMessages.slice(
-(this.logLimit - 1),
);
} else if (
this.logLimit > 0 &&
this.archivedMessages.length >= this.logLimit
) {
this.archivedMessages.shift();
}
this.archivedMessages.push(serializeMessage(message, true)); // TODO: Actually having a better message archiving maybe for exports?
}
if (canPageAcceptType(this.page, message.type)) {
@@ -650,7 +683,7 @@ class ChatRenderer {
});
}
saveToDisk(logLineCount) {
saveToDisk(logLineCount, startLine = 0, endLine = 0) {
// Allow only on IE11
if (Byond.IS_LTE_IE10) {
return;
@@ -672,7 +705,16 @@ class ChatRenderer {
let messagesHtml = '';
let tmpMsgArray = [];
if (logLineCount > 0) {
if (startLine || endLine) {
if (!endLine) {
tmpMsgArray = this.archivedMessages.slice(startLine);
} else {
tmpMsgArray = this.archivedMessages.slice(startLine, endLine);
}
if (logLineCount > 0) {
tmpMsgArray = tmpMsgArray.slice(-logLineCount);
}
} else if (logLineCount > 0) {
tmpMsgArray = this.archivedMessages.slice(-logLineCount);
} else {
tmpMsgArray = this.archivedMessages;

View File

@@ -10,6 +10,7 @@ import { useDispatch, useSelector } from 'tgui/backend';
import {
Box,
Button,
Collapsible,
ColorBox,
Divider,
Dropdown,
@@ -22,26 +23,30 @@ import {
Tabs,
TextArea,
} from 'tgui/components';
import { ChatPageSettings } from '../chat';
import {
purgeChatMessageArchive,
rebuildChat,
saveChatToDisk,
purgeChatMessageArchive,
} from '../chat/actions';
import { MESSAGE_TYPES } from '../chat/constants';
import { useGame } from '../game';
import { THEMES } from '../themes';
import {
changeSettingsTab,
updateSettings,
addHighlightSetting,
changeSettingsTab,
removeHighlightSetting,
updateHighlightSetting,
updateSettings,
updateToggle,
} from './actions';
import { SETTINGS_TABS, FONTS, MAX_HIGHLIGHT_SETTINGS } from './constants';
import { FONTS, MAX_HIGHLIGHT_SETTINGS, SETTINGS_TABS } from './constants';
import {
selectActiveTab,
selectSettings,
selectHighlightSettings,
selectHighlightSettingById,
selectHighlightSettings,
selectSettings,
} from './selectors';
export const SettingsPanel = (props) => {
@@ -207,6 +212,7 @@ export const MessageLimits = (props) => {
persistentMessageLimit,
combineMessageLimit,
combineIntervalLimit,
saveInterval,
} = useSelector(selectSettings);
return (
<Section>
@@ -228,13 +234,21 @@ export const MessageLimits = (props) => {
)
}
/>
&nbsp;
{visibleMessageLimit >= 5000 ? (
<Box inline fontSize="0.9em" color="red">
Impacts performance!
</Box>
) : (
''
)}
</LabeledList.Item>
<LabeledList.Item label="Amount of visually persistent lines 500-10000 (Default: 1000)">
<LabeledList.Item label="Amount of visually persistent lines 0-10000 (Default: 1000)">
<NumberInput
width="5em"
step={100}
stepPixelSize={2}
minValue={500}
minValue={0}
maxValue={10000}
value={persistentMessageLimit}
format={(value) => toFixed(value)}
@@ -246,8 +260,16 @@ export const MessageLimits = (props) => {
)
}
/>
&nbsp;
{persistentMessageLimit >= 2500 ? (
<Box inline fontSize="0.9em" color="red">
Delays initialization!
</Box>
) : (
''
)}
</LabeledList.Item>
<LabeledList.Item label="Amount of different lines in between to combine 0-10 (Default: 5)">
<LabeledList.Item label="Amount of different lines in-between to combine 0-10 (Default: 5)">
<NumberInput
width="5em"
step={1}
@@ -284,6 +306,33 @@ export const MessageLimits = (props) => {
}
/>
</LabeledList.Item>
<LabeledList.Item label="Message store interval 1-10 (Default: 10 Seconds) [Requires restart]">
<NumberInput
width="5em"
step={1}
stepPixelSize={5}
minValue={1}
maxValue={10}
value={saveInterval}
unit="s"
format={(value) => toFixed(value)}
onDrag={(e, value) =>
dispatch(
updateSettings({
saveInterval: value,
}),
)
}
/>
&nbsp;
{saveInterval <= 3 ? (
<Box inline fontSize="0.9em" color="red">
Warning, experimental! Might crash!
</Box>
) : (
''
)}
</LabeledList.Item>
</LabeledList>
</Section>
);
@@ -291,34 +340,205 @@ export const MessageLimits = (props) => {
export const ExportTab = (props) => {
const dispatch = useDispatch();
const { logRetainDays, logLineCount, totalStoredMessages } =
useSelector(selectSettings);
const game = useGame();
const {
storedRounds,
exportStart,
exportEnd,
logRetainRounds,
logEnable,
logLineCount,
logLimit,
totalStoredMessages,
storedTypes,
} = useSelector(selectSettings);
const [purgeConfirm, setPurgeConfirm] = useLocalState('purgeConfirm', 0);
const [logConfirm, setLogConfirm] = useLocalState('logConfirm', 0);
return (
<Section>
<LabeledList>
{/* FIXME: Implement this later on
<LabeledList.Item label="Days to retain logs (-1 = inf.)">
<Input
width="5em"
monospace
value={logRetainDays}
onInput={(e, value) =>
<Flex align="baseline">
{logEnable ? (
logConfirm ? (
<Button
icon="ban"
color="red"
onClick={() => {
dispatch(
updateSettings({
logEnable: false,
}),
);
setLogConfirm(false);
}}
>
Disable?
</Button>
) : (
<Button
icon="ban"
color="red"
onClick={() => {
setLogConfirm(true);
setTimeout(() => {
setLogConfirm(false);
}, 5000);
}}
>
Disable logging
</Button>
)
) : (
<Button
icon="download"
color="green"
onClick={() => {
dispatch(
updateSettings({
logRetainDays: value,
})
logEnable: true,
}),
);
}}
>
Enable logging
</Button>
)}
<Flex.Item grow={1} />
<Flex.Item color="label">Round ID:&nbsp;</Flex.Item>
<Flex.Item color={game.roundId ? '' : 'red'}>
{game.roundId ? game.roundId : 'ERROR'}
</Flex.Item>
</Flex>
{logEnable ? (
<>
<LabeledList>
<LabeledList.Item label="Amount of rounds to log (1 to 8)">
<NumberInput
width="5em"
step={1}
stepPixelSize={10}
minValue={1}
maxValue={8}
value={logRetainRounds}
format={(value) => toFixed(value)}
onDrag={(e, value) =>
dispatch(
updateSettings({
logRetainRounds: value,
}),
)
}
/>
&nbsp;
{logRetainRounds > 3 ? (
<Box inline fontSize="0.9em" color="red">
Warning, might crash!
</Box>
) : (
''
)}
</LabeledList.Item>
<LabeledList.Item label="Hardlimit for the log archive (0 = inf. to 50000)">
<NumberInput
width="5em"
step={500}
stepPixelSize={10}
minValue={0}
maxValue={50000}
value={logLimit}
format={(value) => toFixed(value)}
onDrag={(e, value) =>
dispatch(
updateSettings({
logLimit: value,
}),
)
}
/>
&nbsp;
{logLimit > 0 ? (
<Box
inline
fontSize="0.9em"
color={logLimit > 10000 ? 'red' : 'label'}
>
{logLimit > 15000
? 'Warning, might crash! Takes priority above round retention.'
: 'Takes priority above round retention.'}
</Box>
) : (
''
)}
</LabeledList.Item>
</LabeledList>
<Section>
<Collapsible mt={1} color="transparent" title="Messages to log">
{MESSAGE_TYPES.map((typeDef) => (
<Button.Checkbox
key={typeDef.type}
checked={storedTypes[typeDef.type]}
onClick={() =>
dispatch(
updateToggle({
type: typeDef.type,
}),
)
}
>
{typeDef.name}
</Button.Checkbox>
))}
</Collapsible>
</Section>
</>
) : (
''
)}
<LabeledList>
<LabeledList.Item label="Export round start (0 = curr.) / end (0 = dis.)">
<NumberInput
width="5em"
step={1}
stepPixelSize={10}
minValue={0}
maxValue={exportEnd === 0 ? 0 : exportEnd - 1}
value={exportStart}
format={(value) => toFixed(value)}
onDrag={(e, value) =>
dispatch(
updateSettings({
exportStart: value,
}),
)
}
/>
<NumberInput
width="5em"
step={1}
stepPixelSize={10}
minValue={exportStart === 0 ? 0 : exportStart + 1}
maxValue={storedRounds}
value={exportEnd}
format={(value) => toFixed(value)}
onDrag={(e, value) =>
dispatch(
updateSettings({
exportEnd: value,
}),
)
}
/>
&nbsp;
<Box inline fontSize="0.9em" color="label">
Stored Rounds:&nbsp;
</Box>
<Box inline>{storedRounds}</Box>
</LabeledList.Item>
*/}
<LabeledList.Item label="Amount of lines to export (-1 = inf.)">
<LabeledList.Item label="Amount of lines to export (0 = inf.)">
<NumberInput
width="5em"
step={100}
stepPixelSize={2}
minValue={-1}
stepPixelSize={10}
minValue={0}
maxValue={50000}
value={logLineCount}
format={(value) => toFixed(value)}

View File

@@ -8,6 +8,7 @@ import { createAction } from 'common/redux';
import { createHighlightSetting } from './model';
export const updateToggle = createAction('settings/updateToggle');
export const updateSettings = createAction('settings/update');
export const loadSettings = createAction('settings/load');
export const changeSettingsTab = createAction('settings/changeTab');

View File

@@ -13,6 +13,7 @@ import {
removeHighlightSetting,
updateHighlightSetting,
updateSettings,
updateToggle,
} from './actions';
import { FONTS_DISABLED } from './constants';
import { selectSettings } from './selectors';
@@ -63,6 +64,7 @@ export const settingsMiddleware = (store) => {
});
}
if (
type === updateToggle.type ||
type === updateSettings.type ||
type === loadSettings.type ||
type === addHighlightSetting.type ||

View File

@@ -4,6 +4,7 @@
* @license MIT
*/
import { MESSAGE_TYPES } from '../chat/constants';
import {
addHighlightSetting,
changeSettingsTab,
@@ -13,6 +14,7 @@ import {
toggleSettings,
updateHighlightSetting,
updateSettings,
updateToggle,
} from './actions';
import { FONTS, MAX_HIGHLIGHT_SETTINGS, SETTINGS_TABS } from './constants';
import { createDefaultHighlightSetting } from './model';
@@ -41,11 +43,20 @@ const initialState = {
showReconnectWarning: true,
visibleMessageLimit: 2500,
persistentMessageLimit: 1000,
saveInterval: 10,
combineMessageLimit: 5,
combineIntervalLimit: 5,
totalStoredMessages: 0,
logRetainDays: -1,
logLineCount: -1,
logRetainRounds: 2,
logEnable: true,
logLineCount: 0,
logLimit: 10000,
storedRounds: 0,
exportStart: 0,
exportEnd: 0,
lastId: null,
initialized: false,
storedTypes: {},
};
export const settingsReducer = (state = initialState, action) => {
@@ -56,6 +67,14 @@ export const settingsReducer = (state = initialState, action) => {
...payload,
};
}
if (type === updateToggle.type) {
const { type } = payload;
state.storedTypes[type] = !state.storedTypes[type];
return {
...state,
storedTypes: { ...state.storedTypes },
};
}
if (type === loadSettings.type) {
// Validate version and/or migrate state
if (!payload?.version) {
@@ -67,6 +86,17 @@ export const settingsReducer = (state = initialState, action) => {
...state,
...payload,
};
nextState.initialized = true;
let newFilters = {};
for (let typeDef of MESSAGE_TYPES) {
// alert(typeDef.type);
if (nextState.storedTypes[typeDef.type] === null) {
newFilters[typeDef.type] = true;
} else {
newFilters[typeDef.type] = nextState.storedTypes[typeDef.type];
}
}
nextState.storedTypes = newFilters;
// Lazy init the list for compatibility reasons
if (!nextState.highlightSettings) {
nextState.highlightSettings = [defaultHighlightSetting.id];

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long