milestone 21: abp list exceptions and a regex rule kind
This commit is contained in:
@@ -15,6 +15,7 @@ import { READ_ONLY_HINT, useReadOnlyConfig } from "@/features/settings/authority
|
||||
const KIND_OPTIONS = [
|
||||
{ value: "exact", label: "exact" },
|
||||
{ value: "wildcard", label: "wildcard" },
|
||||
{ value: "regex", label: "regex" },
|
||||
];
|
||||
|
||||
const ACTION_OPTIONS = [
|
||||
@@ -97,10 +98,12 @@ export default function RulesPage() {
|
||||
|
||||
function onSubmit(event: FormEvent<HTMLFormElement>) {
|
||||
event.preventDefault();
|
||||
create.mutate(
|
||||
{ group_id: groupId, pattern: pattern.trim(), kind, action },
|
||||
{ onSuccess: () => setPattern("") },
|
||||
);
|
||||
// A regex pattern is stored and matched byte for byte, so the UI must not
|
||||
// edit it: trimming here would make a UI-created rule differ from the same
|
||||
// bytes posted to /api/rules. Name-shaped kinds are normalized server-side,
|
||||
// so trimming them only spares a pasted space a 400.
|
||||
const sent = kind === "regex" ? pattern : pattern.trim();
|
||||
create.mutate({ group_id: groupId, pattern: sent, kind, action }, { onSuccess: () => setPattern("") });
|
||||
}
|
||||
|
||||
function confirmDelete() {
|
||||
@@ -173,7 +176,13 @@ export default function RulesPage() {
|
||||
required
|
||||
value={pattern}
|
||||
onChange={(event) => setPattern(event.target.value)}
|
||||
placeholder="ads.example.com or *.example.com"
|
||||
placeholder="ads.example.com, *.example.com or ^ad[0-9]+-"
|
||||
// A phone keyboard capitalizing the first letter is silent for
|
||||
// exact and wildcard (normalized server-side) but fatal for a
|
||||
// regex, which matches the lowercase query name byte for byte.
|
||||
autoCapitalize="none"
|
||||
autoCorrect="off"
|
||||
spellCheck={false}
|
||||
{...stylex.props(shared.input, shared.focusRing)}
|
||||
/>
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user