mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-24 20:47:43 +01:00
port highlight enable toggle [No GBP] (#19375)
* port highlight enable toggle * . * .
This commit is contained in:
@@ -176,6 +176,7 @@ class ChatRenderer {
|
||||
highlightWholeMessage: boolean;
|
||||
highlightBlacklist: boolean;
|
||||
blacklistregex: RegExp;
|
||||
enabled: boolean;
|
||||
}[]
|
||||
| null;
|
||||
databaseBackendEnabled: boolean;
|
||||
@@ -288,6 +289,7 @@ class ChatRenderer {
|
||||
const highlightWholeMessage = setting.highlightWholeMessage;
|
||||
const matchWord = setting.matchWord;
|
||||
const matchCase = setting.matchCase;
|
||||
const enabled = setting.enabled;
|
||||
const allowedRegex = /^[a-zа-яё0-9_\-$/^[\s\]\\]+$/gi;
|
||||
const regexEscapeCharacters = /[!#$%^&*)(+=.<>{}[\]:;'"|~`_\-\\/]/g;
|
||||
// Reset lastIndex so it does not mess up the next word
|
||||
@@ -397,6 +399,7 @@ class ChatRenderer {
|
||||
this.highlightParsers = [];
|
||||
}
|
||||
this.highlightParsers.push({
|
||||
enabled,
|
||||
highlightWords,
|
||||
highlightRegex,
|
||||
highlightColor,
|
||||
@@ -640,31 +643,32 @@ class ChatRenderer {
|
||||
|
||||
// Highlight text
|
||||
if (!message.avoidHighlighting && this.highlightParsers) {
|
||||
this.highlightParsers.map((parser) => {
|
||||
const ourUser = node.getElementsByClassName('name');
|
||||
const isEmote = node.getElementsByClassName('emote');
|
||||
if (
|
||||
!(
|
||||
parser.highlightBlacklist &&
|
||||
parser.blacklistregex &&
|
||||
((ourUser.length > 0 &&
|
||||
parser.blacklistregex.test(ourUser[0].textContent)) ||
|
||||
(isEmote.length > 0 &&
|
||||
parser.blacklistregex.test(isEmote[0].textContent)))
|
||||
)
|
||||
) {
|
||||
const highlighted = highlightNode(
|
||||
node,
|
||||
parser.highlightRegex,
|
||||
parser.highlightWords,
|
||||
(text) => createHighlightNode(text, parser.highlightColor),
|
||||
);
|
||||
if (highlighted && parser.highlightWholeMessage) {
|
||||
node.className += ' ChatMessage--highlighted';
|
||||
this.highlightParsers
|
||||
.filter((parser) => parser.enabled)
|
||||
.forEach((parser) => {
|
||||
const ourUser = node.getElementsByClassName('name');
|
||||
const isEmote = node.getElementsByClassName('emote');
|
||||
if (
|
||||
!(
|
||||
parser.highlightBlacklist &&
|
||||
parser.blacklistregex &&
|
||||
((ourUser.length > 0 &&
|
||||
parser.blacklistregex.test(ourUser[0].textContent)) ||
|
||||
(isEmote.length > 0 &&
|
||||
parser.blacklistregex.test(isEmote[0].textContent)))
|
||||
)
|
||||
) {
|
||||
const highlighted = highlightNode(
|
||||
node,
|
||||
parser.highlightRegex,
|
||||
parser.highlightWords,
|
||||
(text) => createHighlightNode(text, parser.highlightColor),
|
||||
);
|
||||
if (highlighted && parser.highlightWholeMessage) {
|
||||
node.className += ' ChatMessage--highlighted';
|
||||
}
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
});
|
||||
}
|
||||
// Linkify text
|
||||
const linkifyNodes = node.querySelectorAll('.linkify');
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
import { useAtomValue } from 'jotai';
|
||||
import { useMemo } from 'react';
|
||||
import {
|
||||
Box,
|
||||
Button,
|
||||
@@ -14,7 +15,7 @@ import { settingsAtom } from '../atoms';
|
||||
import { MAX_HIGHLIGHT_SETTINGS } from '../constants';
|
||||
import { useHighlights } from '../use-highlights';
|
||||
|
||||
export const TextHighlightSettings = (props) => {
|
||||
export function TextHighlightSettings(props) {
|
||||
const {
|
||||
highlights: { highlightSettings },
|
||||
addHighlight,
|
||||
@@ -59,9 +60,25 @@ export const TextHighlightSettings = (props) => {
|
||||
</Box>
|
||||
</Section>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
const TextHighlightSetting = (props) => {
|
||||
const oneCharacterRegex = /^(\[.*\]|\\.|.)$/;
|
||||
|
||||
function extractRegex(highlight: string): string | null {
|
||||
if (
|
||||
highlight.charAt(0) !== '/' ||
|
||||
highlight.charAt(highlight.length - 1) !== '/'
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
const expr = highlight.substring(1, highlight.length - 1);
|
||||
if (oneCharacterRegex.test(expr)) {
|
||||
return null;
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
function TextHighlightSetting(props) {
|
||||
const { id, ...rest } = props;
|
||||
const {
|
||||
highlights: { highlightSettingById },
|
||||
@@ -69,6 +86,7 @@ const TextHighlightSetting = (props) => {
|
||||
removeHighlight,
|
||||
} = useHighlights();
|
||||
const {
|
||||
enabled,
|
||||
highlightColor,
|
||||
highlightText,
|
||||
blacklistText,
|
||||
@@ -77,6 +95,22 @@ const TextHighlightSetting = (props) => {
|
||||
matchWord,
|
||||
matchCase,
|
||||
} = highlightSettingById[id];
|
||||
|
||||
const highlightRegex = useMemo(
|
||||
() => extractRegex(highlightText),
|
||||
[highlightText],
|
||||
);
|
||||
|
||||
const isRegexValid = useMemo(() => {
|
||||
if (!highlightRegex) return true;
|
||||
try {
|
||||
new RegExp(highlightRegex, 'g');
|
||||
return true;
|
||||
} catch {
|
||||
return false;
|
||||
}
|
||||
}, [highlightRegex]);
|
||||
|
||||
return (
|
||||
<Stack.Item {...rest}>
|
||||
<Stack mb={1} color="label" align="baseline">
|
||||
@@ -104,11 +138,26 @@ const TextHighlightSetting = (props) => {
|
||||
</Button.Confirm>
|
||||
</Stack.Item>
|
||||
)}
|
||||
<Stack.Item>
|
||||
<Button.Checkbox
|
||||
checked={!!enabled}
|
||||
mr="5px"
|
||||
onClick={() =>
|
||||
updateHighlight({
|
||||
id,
|
||||
enabled: !enabled,
|
||||
})
|
||||
}
|
||||
>
|
||||
Enabled
|
||||
</Button.Checkbox>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow />
|
||||
<Stack.Item>
|
||||
<Button.Checkbox
|
||||
checked={highlightBlacklist}
|
||||
tooltip="If this option is selected, you can blacklist senders not to highlight their messages."
|
||||
disabled={!!highlightRegex}
|
||||
mr="5px"
|
||||
onClick={() =>
|
||||
updateHighlight({
|
||||
@@ -185,6 +234,7 @@ const TextHighlightSetting = (props) => {
|
||||
height="3em"
|
||||
value={highlightText}
|
||||
placeholder="Put words to highlight here. Separate terms with commas, i.e. (term1, term2, term3)"
|
||||
style={{ border: isRegexValid ? '' : '1px solid red' }}
|
||||
onBlur={(value) =>
|
||||
updateHighlight({
|
||||
id,
|
||||
@@ -208,4 +258,4 @@ const TextHighlightSetting = (props) => {
|
||||
)}
|
||||
</Stack.Item>
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -46,6 +46,7 @@ export const defaultHighlightSetting: HighlightSetting = {
|
||||
highlightWholeMessage: true,
|
||||
matchWord: false,
|
||||
matchCase: false,
|
||||
enabled: true,
|
||||
};
|
||||
|
||||
export const defaultHighlights: HighlightState = {
|
||||
|
||||
@@ -60,6 +60,17 @@ function migrateHighlights(next: HighlightState): HighlightState {
|
||||
draft.highlightText ?? defaultHighlightSetting.highlightText;
|
||||
}
|
||||
|
||||
// Ensure that all highlights have the "enabled" var,
|
||||
// setting it to true if it doesn't exist.
|
||||
for (const id in draft.highlightSettingById) {
|
||||
if (
|
||||
draft.highlightSettingById[id] &&
|
||||
draft.highlightSettingById[id].enabled === undefined
|
||||
) {
|
||||
draft.highlightSettingById[id].enabled = true;
|
||||
}
|
||||
}
|
||||
|
||||
return draft;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,6 +47,7 @@ export type HighlightSetting = {
|
||||
id: string;
|
||||
matchCase: boolean;
|
||||
matchWord: boolean;
|
||||
enabled: boolean;
|
||||
};
|
||||
|
||||
export type HighlightState = {
|
||||
|
||||
@@ -40,14 +40,13 @@ export const setGradientSpace = (
|
||||
space: number,
|
||||
) => {
|
||||
let found = false;
|
||||
gradient?.map((entry) => {
|
||||
gradient?.forEach((entry) => {
|
||||
if (typeof entry === 'object') {
|
||||
if (Object.keys(entry)[0] === 'space') {
|
||||
entry.space = space;
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
return undefined;
|
||||
});
|
||||
if (!found) {
|
||||
gradient.push({ space: space });
|
||||
|
||||
+2
-12
@@ -56,18 +56,8 @@ export const VoreContentsPanel = (props: {
|
||||
}, [contents]);
|
||||
|
||||
function bellyValueToName(value: string) {
|
||||
const bellyName = bellyDropdownNames
|
||||
?.map((entry) => {
|
||||
if (entry.value === value) {
|
||||
return entry.displayText;
|
||||
}
|
||||
return undefined;
|
||||
})
|
||||
.filter((value) => value !== undefined);
|
||||
if (Array.isArray(bellyName) && bellyName.length) {
|
||||
return bellyName[0];
|
||||
}
|
||||
return '';
|
||||
const entry = bellyDropdownNames?.find((entry) => entry.value === value);
|
||||
return entry ? entry.displayText : '';
|
||||
}
|
||||
|
||||
const contentSearch = createSearch<ContentData>(
|
||||
|
||||
Reference in New Issue
Block a user