@chatwarden/player-react 0.0.0-stage → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +202 -0
- package/README.md +377 -2
- package/dist/src/Dialog.d.ts +13 -0
- package/dist/src/Dialog.d.ts.map +1 -0
- package/dist/src/Dialog.js +94 -0
- package/dist/src/Dialog.js.map +1 -0
- package/dist/src/FollowUp.d.ts +35 -0
- package/dist/src/FollowUp.d.ts.map +1 -0
- package/dist/src/FollowUp.js +69 -0
- package/dist/src/FollowUp.js.map +1 -0
- package/dist/src/MyRecord.d.ts +12 -0
- package/dist/src/MyRecord.d.ts.map +1 -0
- package/dist/src/MyRecord.js +17 -0
- package/dist/src/MyRecord.js.map +1 -0
- package/dist/src/NoticeQueue.d.ts +26 -0
- package/dist/src/NoticeQueue.d.ts.map +1 -0
- package/dist/src/NoticeQueue.js +90 -0
- package/dist/src/NoticeQueue.js.map +1 -0
- package/dist/src/Picker.d.ts +14 -0
- package/dist/src/Picker.d.ts.map +1 -0
- package/dist/src/Picker.js +14 -0
- package/dist/src/Picker.js.map +1 -0
- package/dist/src/ReportDialog.d.ts +50 -0
- package/dist/src/ReportDialog.d.ts.map +1 -0
- package/dist/src/ReportDialog.js +157 -0
- package/dist/src/ReportDialog.js.map +1 -0
- package/dist/src/RestrictedChatLine.d.ts +12 -0
- package/dist/src/RestrictedChatLine.d.ts.map +1 -0
- package/dist/src/RestrictedChatLine.js +19 -0
- package/dist/src/RestrictedChatLine.js.map +1 -0
- package/dist/src/RulesPage.d.ts +10 -0
- package/dist/src/RulesPage.d.ts.map +1 -0
- package/dist/src/RulesPage.js +17 -0
- package/dist/src/RulesPage.js.map +1 -0
- package/dist/src/client.d.ts +51 -0
- package/dist/src/client.d.ts.map +1 -0
- package/dist/src/client.js +98 -0
- package/dist/src/client.js.map +1 -0
- package/dist/src/constants.d.ts +5 -0
- package/dist/src/constants.d.ts.map +1 -0
- package/dist/src/constants.js +5 -0
- package/dist/src/constants.js.map +1 -0
- package/dist/src/format.d.ts +14 -0
- package/dist/src/format.d.ts.map +1 -0
- package/dist/src/format.js +55 -0
- package/dist/src/format.js.map +1 -0
- package/dist/src/hooks.d.ts +15 -0
- package/dist/src/hooks.d.ts.map +1 -0
- package/dist/src/hooks.js +29 -0
- package/dist/src/hooks.js.map +1 -0
- package/dist/src/i18n.d.ts +129 -0
- package/dist/src/i18n.d.ts.map +1 -0
- package/dist/src/i18n.js +167 -0
- package/dist/src/i18n.js.map +1 -0
- package/dist/src/index.d.ts +21 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +11 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/reporting.d.ts +20 -0
- package/dist/src/reporting.d.ts.map +1 -0
- package/dist/src/reporting.js +45 -0
- package/dist/src/reporting.js.map +1 -0
- package/dist/src/safeHref.d.ts +5 -0
- package/dist/src/safeHref.d.ts.map +1 -0
- package/dist/src/safeHref.js +41 -0
- package/dist/src/safeHref.js.map +1 -0
- package/dist/src/transport.d.ts +69 -0
- package/dist/src/transport.d.ts.map +1 -0
- package/dist/src/transport.js +74 -0
- package/dist/src/transport.js.map +1 -0
- package/dist/src/ui.d.ts +91 -0
- package/dist/src/ui.d.ts.map +1 -0
- package/dist/src/ui.js +116 -0
- package/dist/src/ui.js.map +1 -0
- package/package.json +73 -4
- package/src/Dialog.tsx +117 -0
- package/src/FollowUp.tsx +139 -0
- package/src/MyRecord.tsx +60 -0
- package/src/NoticeQueue.tsx +203 -0
- package/src/Picker.tsx +60 -0
- package/src/ReportDialog.tsx +304 -0
- package/src/RestrictedChatLine.tsx +42 -0
- package/src/RulesPage.tsx +49 -0
- package/src/client.ts +132 -0
- package/src/constants.ts +5 -0
- package/src/format.ts +53 -0
- package/src/hooks.ts +41 -0
- package/src/i18n.ts +187 -0
- package/src/index.ts +32 -0
- package/src/reporting.ts +51 -0
- package/src/safeHref.ts +36 -0
- package/src/styles.css +516 -0
- package/src/transport.ts +134 -0
- package/src/ui.tsx +199 -0
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { useEffect, useId, useRef, useState } from 'react';
|
|
3
|
+
import { NOTE_MAX } from './constants.js';
|
|
4
|
+
import { PlayerError } from './client.js';
|
|
5
|
+
import { Dialog } from './Dialog.js';
|
|
6
|
+
import { DETAIL_REFUSED_TEXT, FollowUp } from './FollowUp.js';
|
|
7
|
+
import { Picker } from './Picker.js';
|
|
8
|
+
import { groupReasons, readReporting } from './reporting.js';
|
|
9
|
+
import { errorText, Portal, Root, useUi } from './ui.js';
|
|
10
|
+
// One plain message for each refusal the kit has. Anything else (a refusal a newer kit adds) gets the last one.
|
|
11
|
+
const REFUSED_TEXT = {
|
|
12
|
+
duplicate: 'player.report.refused.duplicate',
|
|
13
|
+
rate: 'player.report.refused.rate',
|
|
14
|
+
self: 'player.report.refused.self',
|
|
15
|
+
not_player: 'player.report.refused.not_player',
|
|
16
|
+
off: 'player.report.refused.off',
|
|
17
|
+
suspended: 'player.report.refused.suspended',
|
|
18
|
+
reason_required: 'player.report.refused.reason_required',
|
|
19
|
+
reason_unknown: 'player.report.refused.reason_unknown',
|
|
20
|
+
};
|
|
21
|
+
/** How much of the reported message is quoted on the screen. */
|
|
22
|
+
const LINE_MAX = 280;
|
|
23
|
+
/** A failure to send as an error the components can word: anything that is not already a PlayerError is a dropped connection. */
|
|
24
|
+
const failureOf = (e) => e instanceof PlayerError ? e : new PlayerError({ status: 0, code: 'network', message: 'Could not reach the server.' });
|
|
25
|
+
/** Anything that is not a result object (undefined, null, a string) is not a success and not a crash: it reads as an unknown refusal. */
|
|
26
|
+
const resultOf = (answer, unknown) => (typeof answer === 'object' && answer !== null && !Array.isArray(answer) ? answer : unknown);
|
|
27
|
+
const quoted = (line) => {
|
|
28
|
+
const plain = (line ?? '').replace(/\s+/g, ' ').trim();
|
|
29
|
+
return plain.length > LINE_MAX ? `${plain.slice(0, LINE_MAX).trimEnd()}…` : plain;
|
|
30
|
+
};
|
|
31
|
+
/**
|
|
32
|
+
* A dialog for reporting a message or a player. How it works is the studio's setting (`reporting`, from `GET /rules`):
|
|
33
|
+
* - `one_tap` (the default): one step, "Report this message?" and a Report button. The report is filed at once and the thank-you
|
|
34
|
+
* shown; an optional "Add a reason" step then attaches a reason and a note to the same report (`onAddDetail`).
|
|
35
|
+
* - `reason_first`: the reasons in groups, then an optional note; a reason can be skipped.
|
|
36
|
+
* - `reason_required`: the same without the skip.
|
|
37
|
+
* The reason is only a hint for the moderators. Every refusal the kit can give has its own plain message. Render it when the player
|
|
38
|
+
* chooses to report, and unmount it in `onClose`.
|
|
39
|
+
*/
|
|
40
|
+
export function ReportDialog(props) {
|
|
41
|
+
const { onSubmit, onAddDetail, onClose, targetName, line, theme, className, container, returnFocusTo } = props;
|
|
42
|
+
const ui = useUi(props);
|
|
43
|
+
const { t } = ui;
|
|
44
|
+
const heading = useRef(null);
|
|
45
|
+
const picker = useRef(null);
|
|
46
|
+
// One thing on its way at a time, report or follow-up: a second click, or a second Enter, does nothing.
|
|
47
|
+
const sending = useRef(false);
|
|
48
|
+
const titleId = useId();
|
|
49
|
+
const groupName = useId();
|
|
50
|
+
const noteId = useId();
|
|
51
|
+
const hintId = useId();
|
|
52
|
+
const missingId = useId();
|
|
53
|
+
const [reason, setReason] = useState(null);
|
|
54
|
+
const [note, setNote] = useState('');
|
|
55
|
+
const [missing, setMissing] = useState(false);
|
|
56
|
+
const [busy, setBusy] = useState(false);
|
|
57
|
+
const [failure, setFailure] = useState(null);
|
|
58
|
+
const [result, setResult] = useState(null);
|
|
59
|
+
// How the follow-up after a one-tap report ended, and whether its time is up (the kit takes one until `detailUntil`).
|
|
60
|
+
const [dDone, setDDone] = useState(null);
|
|
61
|
+
const [expired, setExpired] = useState(false);
|
|
62
|
+
const screen = (() => {
|
|
63
|
+
// No `reporting` (or something that is not the payload): one tap with the dialog's own words, as when `GET /rules` cannot be loaded.
|
|
64
|
+
const read = readReporting(props.reporting) ?? { flow: 'one_tap', reasons: [], thanks: '' };
|
|
65
|
+
// A flow that asks for a reason has nothing to ask with when the list is empty: it is one tap.
|
|
66
|
+
return { flow: read.reasons.length === 0 ? 'one_tap' : read.flow, reasons: read.reasons, thanks: read.thanks.trim() };
|
|
67
|
+
})();
|
|
68
|
+
const { flow } = screen;
|
|
69
|
+
const groups = groupReasons(screen.reasons);
|
|
70
|
+
const chosen = screen.reasons.find((r) => r.id === reason);
|
|
71
|
+
// The note: when the chosen reason asks for it.
|
|
72
|
+
const showNote = chosen?.asksNote === true;
|
|
73
|
+
// The form is gone once there is an answer: focus goes back to the heading, so the answer is read and focus is not lost.
|
|
74
|
+
useEffect(() => {
|
|
75
|
+
if (result !== null)
|
|
76
|
+
heading.current?.focus();
|
|
77
|
+
}, [result]);
|
|
78
|
+
useEffect(() => {
|
|
79
|
+
if (dDone !== null)
|
|
80
|
+
heading.current?.focus();
|
|
81
|
+
}, [dDone]);
|
|
82
|
+
// The follow-up stops being offered when the kit would no longer take it.
|
|
83
|
+
const until = result?.ok === true && typeof result.detailUntil === 'number' && Number.isFinite(result.detailUntil) ? result.detailUntil : null;
|
|
84
|
+
useEffect(() => {
|
|
85
|
+
if (until === null)
|
|
86
|
+
return undefined;
|
|
87
|
+
let timer;
|
|
88
|
+
// Looks at the clock again when the time comes, so a clock that has not moved does not end the offer early.
|
|
89
|
+
const check = () => {
|
|
90
|
+
const left = until - ui.now();
|
|
91
|
+
if (left < 0)
|
|
92
|
+
setExpired(true);
|
|
93
|
+
else
|
|
94
|
+
timer = setTimeout(check, Math.min(Math.max(left + 1, 50), 2_000_000_000));
|
|
95
|
+
};
|
|
96
|
+
check();
|
|
97
|
+
return () => clearTimeout(timer);
|
|
98
|
+
}, [until]);
|
|
99
|
+
const send = async (draft) => {
|
|
100
|
+
sending.current = true;
|
|
101
|
+
setBusy(true);
|
|
102
|
+
setFailure(null);
|
|
103
|
+
try {
|
|
104
|
+
setResult(resultOf(await onSubmit(draft), { ok: false, refused: 'unknown' }));
|
|
105
|
+
}
|
|
106
|
+
catch (error) {
|
|
107
|
+
setFailure(failureOf(error));
|
|
108
|
+
}
|
|
109
|
+
finally {
|
|
110
|
+
sending.current = false;
|
|
111
|
+
setBusy(false);
|
|
112
|
+
}
|
|
113
|
+
};
|
|
114
|
+
const trimmed = note.trim();
|
|
115
|
+
const submit = (e) => {
|
|
116
|
+
e.preventDefault();
|
|
117
|
+
if (sending.current)
|
|
118
|
+
return;
|
|
119
|
+
if (flow !== 'one_tap' && reason === null) {
|
|
120
|
+
setMissing(true);
|
|
121
|
+
picker.current?.querySelector('input')?.focus();
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
const draft = flow === 'one_tap' ? {} : { reason: reason };
|
|
125
|
+
if (showNote && trimmed !== '')
|
|
126
|
+
draft.note = trimmed;
|
|
127
|
+
void send(draft);
|
|
128
|
+
};
|
|
129
|
+
const skip = () => {
|
|
130
|
+
if (sending.current)
|
|
131
|
+
return;
|
|
132
|
+
void send(showNote && trimmed !== '' ? { note: trimmed } : {});
|
|
133
|
+
};
|
|
134
|
+
const reportId = result?.ok === true && typeof result.reportId === 'string' && result.reportId !== '' ? result.reportId : null;
|
|
135
|
+
const quote = quoted(line);
|
|
136
|
+
const oneTapTitle = quote !== '' ? t('player.report.titleOneTap') : targetName === undefined ? t('player.report.titleOneTapPlayer') : t('player.report.titleOneTapNamed', { name: targetName });
|
|
137
|
+
const title = flow === 'one_tap' ? oneTapTitle : targetName === undefined ? t('player.report.title') : t('player.report.titleNamed', { name: targetName });
|
|
138
|
+
const taken = result?.ok === true;
|
|
139
|
+
const refusal = result !== null && !taken ? result : null;
|
|
140
|
+
// After an answer the heading says what happened (a question would be stale), and focus is on it.
|
|
141
|
+
const shownTitle = result === null ? title : taken ? t('player.report.titleSent') : t('player.report.titleRefused');
|
|
142
|
+
const remaining = taken && typeof result.remaining === 'number' && Number.isFinite(result.remaining) && result.remaining >= 0 ? result.remaining : null;
|
|
143
|
+
const refusedKey = (r) => {
|
|
144
|
+
const refused = r.refused;
|
|
145
|
+
return typeof refused === 'string' && Object.hasOwn(REFUSED_TEXT, refused) ? REFUSED_TEXT[refused] : 'player.report.refused.unknown';
|
|
146
|
+
};
|
|
147
|
+
const detailRefusedKey = (refused) => (Object.hasOwn(DETAIL_REFUSED_TEXT, refused) ? DETAIL_REFUSED_TEXT[refused] : 'player.report.detail.failed');
|
|
148
|
+
const detailUntil = taken && typeof result.detailUntil === 'number' && Number.isFinite(result.detailUntil) ? result.detailUntil : null;
|
|
149
|
+
const timeUp = expired || (detailUntil !== null && ui.now() > detailUntil);
|
|
150
|
+
const canFollow = taken && flow === 'one_tap' && reportId !== null && onAddDetail !== undefined && screen.reasons.length > 0 && !timeUp;
|
|
151
|
+
const needText = flow === 'reason_first' ? 'player.report.needReasonOrSkip' : 'player.report.needReason';
|
|
152
|
+
return (_jsx(Portal, { container: container, children: _jsx(Root, { theme: theme, className: className, children: _jsxs(Dialog, { labelledBy: titleId, initialFocus: heading, onEscape: () => !sending.current && onClose(), ...(returnFocusTo === undefined ? {} : { returnFocusTo }), children: [_jsx("h2", { id: titleId, ref: heading, className: "cw-title", tabIndex: -1, children: shownTitle }), _jsxs("div", { role: "status", className: "cw-live", children: [taken && (_jsxs("p", { className: "cw-result", children: [screen.thanks === '' ? t('player.report.thanks') : screen.thanks, remaining !== null && ` ${t('player.report.remaining', { count: remaining })}`] })), dDone?.ok === true && _jsx("p", { className: "cw-result", children: t('player.report.detail.added') })] }), result === null ? (_jsxs("form", { onSubmit: submit, noValidate: true, children: [_jsx("p", { className: "cw-body", children: flow === 'one_tap' ? t('player.report.oneTap.intro') : t('player.report.intro') }), quote !== '' && _jsx("blockquote", { className: "cw-quote", children: t('player.report.quote', { line: quote }) }), flow !== 'one_tap' && (_jsx(Picker, { groups: groups, name: groupName, value: reason, legend: t('player.report.legend'), invalid: missing, describedBy: missingId, fieldset: picker, onChange: (id) => {
|
|
153
|
+
setReason(id);
|
|
154
|
+
setMissing(false);
|
|
155
|
+
} })), missing && (_jsx("p", { id: missingId, className: "cw-field-error", role: "alert", children: t(needText) })), showNote && (_jsxs(_Fragment, { children: [_jsx("label", { className: "cw-label", htmlFor: noteId, children: t('player.report.note') }), _jsx("textarea", { id: noteId, className: "cw-textarea", rows: 4, maxLength: NOTE_MAX, value: note, "aria-describedby": hintId, onChange: (e) => setNote(e.target.value) }), _jsx("p", { id: hintId, className: "cw-hint", children: t('player.report.noteHint', { max: NOTE_MAX }) })] })), failure !== null && (_jsxs("p", { className: "cw-error", role: "alert", children: [t('player.report.failed'), " ", errorText(t, failure)] })), _jsxs("div", { className: "cw-actions", children: [_jsx("button", { type: "submit", className: "cw-btn cw-btn--primary", "aria-disabled": busy || undefined, "aria-busy": busy || undefined, children: flow === 'one_tap' ? t('player.report.oneTap.send') : t('player.report.send') }), flow === 'reason_first' && (_jsx("button", { type: "button", className: "cw-btn", "aria-disabled": busy || undefined, "aria-busy": busy || undefined, onClick: skip, children: t('player.report.skip') })), _jsx("button", { type: "button", className: "cw-btn", "aria-disabled": busy || undefined, onClick: () => !sending.current && onClose(), children: t('player.report.cancel') })] })] })) : (_jsxs(_Fragment, { children: [!taken && (_jsx("p", { className: "cw-error", role: "alert", children: t(refusedKey(refusal)) })), canFollow && dDone === null && (_jsx(FollowUp, { t: t, groups: groups, reportId: reportId, onAddDetail: onAddDetail, sending: sending, busy: busy, onBusy: setBusy, onDone: setDDone })), dDone !== null && !dDone.ok && (_jsx("p", { className: "cw-error", role: "alert", children: t(detailRefusedKey(dDone.refused)) })), _jsx("div", { className: "cw-actions", children: _jsx("button", { type: "button", className: "cw-btn cw-btn--primary", "aria-disabled": busy || undefined, onClick: () => !sending.current && onClose(), children: t('player.report.close') }) })] }))] }) }) }));
|
|
156
|
+
}
|
|
157
|
+
//# sourceMappingURL=ReportDialog.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"ReportDialog.js","sourceRoot":"","sources":["../../src/ReportDialog.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAG3D,OAAO,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAC1C,OAAO,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC1C,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,mBAAmB,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAE9D,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAErC,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AAE7D,OAAO,EAAE,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AA0CzD,gHAAgH;AAChH,MAAM,YAAY,GAAgD;IAChE,SAAS,EAAE,iCAAiC;IAC5C,IAAI,EAAE,4BAA4B;IAClC,IAAI,EAAE,4BAA4B;IAClC,UAAU,EAAE,kCAAkC;IAC9C,GAAG,EAAE,2BAA2B;IAChC,SAAS,EAAE,iCAAiC;IAC5C,eAAe,EAAE,uCAAuC;IACxD,cAAc,EAAE,sCAAsC;CACvD,CAAC;AAEF,gEAAgE;AAChE,MAAM,QAAQ,GAAG,GAAG,CAAC;AAErB,iIAAiI;AACjI,MAAM,SAAS,GAAG,CAAC,CAAU,EAAe,EAAE,CAC5C,CAAC,YAAY,WAAW,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,WAAW,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,6BAA6B,EAAE,CAAC,CAAC;AAEzH,yIAAyI;AACzI,MAAM,QAAQ,GAAG,CAAK,MAAe,EAAE,OAAU,EAAK,EAAE,CAAC,CAAC,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAE,MAAY,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;AAE7J,MAAM,MAAM,GAAG,CAAC,IAAwB,EAAU,EAAE;IAClD,MAAM,KAAK,GAAG,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC,IAAI,EAAE,CAAC;IACvD,OAAO,KAAK,CAAC,MAAM,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC;AACpF,CAAC,CAAC;AASF;;;;;;;;GAQG;AACH,MAAM,UAAU,YAAY,CAAC,KAAwB;IACnD,MAAM,EAAE,QAAQ,EAAE,WAAW,EAAE,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC;IAC/G,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,MAAM,OAAO,GAAG,MAAM,CAAqB,IAAI,CAAC,CAAC;IACjD,MAAM,MAAM,GAAG,MAAM,CAAsB,IAAI,CAAC,CAAC;IACjD,wGAAwG;IACxG,MAAM,OAAO,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC9B,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC;IAC1B,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,KAAK,EAAE,CAAC;IACvB,MAAM,SAAS,GAAG,KAAK,EAAE,CAAC;IAC1B,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAgB,IAAI,CAAC,CAAC;IAC1D,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACrC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAC9C,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IACxC,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAqB,IAAI,CAAC,CAAC;IACjE,MAAM,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,QAAQ,CAAsB,IAAI,CAAC,CAAC;IAChE,sHAAsH;IACtH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAyB,IAAI,CAAC,CAAC;IACjE,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAE9C,MAAM,MAAM,GAAW,CAAC,GAAG,EAAE;QAC3B,qIAAqI;QACrI,MAAM,IAAI,GAAG,aAAa,CAAC,KAAK,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,SAAkB,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC;QACrG,+FAA+F;QAC/F,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC;IACxH,CAAC,CAAC,EAAE,CAAC;IACL,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,CAAC;IACxB,MAAM,MAAM,GAAG,YAAY,CAAC,MAAM,CAAC,OAAO,CAAC,CAAC;IAC5C,MAAM,MAAM,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,MAAM,CAAC,CAAC;IAC3D,gDAAgD;IAChD,MAAM,QAAQ,GAAG,MAAM,EAAE,QAAQ,KAAK,IAAI,CAAC;IAE3C,yHAAyH;IACzH,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,MAAM,KAAK,IAAI;YAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IAChD,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IACb,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,CAAC,OAAO,EAAE,KAAK,EAAE,CAAC;IAC/C,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IACZ,0EAA0E;IAC1E,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/I,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC;QACrC,IAAI,KAAgD,CAAC;QACrD,4GAA4G;QAC5G,MAAM,KAAK,GAAG,GAAS,EAAE;YACvB,MAAM,IAAI,GAAG,KAAK,GAAG,EAAE,CAAC,GAAG,EAAE,CAAC;YAC9B,IAAI,IAAI,GAAG,CAAC;gBAAE,UAAU,CAAC,IAAI,CAAC,CAAC;;gBAC1B,KAAK,GAAG,UAAU,CAAC,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,EAAE,EAAE,CAAC,EAAE,aAAa,CAAC,CAAC,CAAC;QAClF,CAAC,CAAC;QACF,KAAK,EAAE,CAAC;QACR,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,KAAK,CAAC,CAAC;IACnC,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,MAAM,IAAI,GAAG,KAAK,EAAE,KAAkB,EAAiB,EAAE;QACvD,OAAO,CAAC,OAAO,GAAG,IAAI,CAAC;QACvB,OAAO,CAAC,IAAI,CAAC,CAAC;QACd,UAAU,CAAC,IAAI,CAAC,CAAC;QACjB,IAAI,CAAC;YACH,SAAS,CAAC,QAAQ,CAAe,MAAM,QAAQ,CAAC,KAAK,CAAC,EAAE,EAAE,EAAE,EAAE,KAAK,EAAE,OAAO,EAAE,SAAS,EAA6B,CAAC,CAAC,CAAC;QACzH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,UAAU,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;QAC/B,CAAC;gBAAS,CAAC;YACT,OAAO,CAAC,OAAO,GAAG,KAAK,CAAC;YACxB,OAAO,CAAC,KAAK,CAAC,CAAC;QACjB,CAAC;IACH,CAAC,CAAC;IAEF,MAAM,OAAO,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IAC5B,MAAM,MAAM,GAAG,CAAC,CAAY,EAAQ,EAAE;QACpC,CAAC,CAAC,cAAc,EAAE,CAAC;QACnB,IAAI,OAAO,CAAC,OAAO;YAAE,OAAO;QAC5B,IAAI,IAAI,KAAK,SAAS,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YAC1C,UAAU,CAAC,IAAI,CAAC,CAAC;YACjB,MAAM,CAAC,OAAO,EAAE,aAAa,CAAc,OAAO,CAAC,EAAE,KAAK,EAAE,CAAC;YAC7D,OAAO;QACT,CAAC;QACD,MAAM,KAAK,GAAgB,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,MAAgB,EAAE,CAAC;QAClF,IAAI,QAAQ,IAAI,OAAO,KAAK,EAAE;YAAE,KAAK,CAAC,IAAI,GAAG,OAAO,CAAC;QACrD,KAAK,IAAI,CAAC,KAAK,CAAC,CAAC;IACnB,CAAC,CAAC;IACF,MAAM,IAAI,GAAG,GAAS,EAAE;QACtB,IAAI,OAAO,CAAC,OAAO;YAAE,OAAO;QAC5B,KAAK,IAAI,CAAC,QAAQ,IAAI,OAAO,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;IACjE,CAAC,CAAC;IAEF,MAAM,QAAQ,GAAG,MAAM,EAAE,EAAE,KAAK,IAAI,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,CAAC;IAC/H,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC3B,MAAM,WAAW,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,iCAAiC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,gCAAgC,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAChM,MAAM,KAAK,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,UAAU,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,0BAA0B,EAAE,EAAE,IAAI,EAAE,UAAU,EAAE,CAAC,CAAC;IAC3J,MAAM,KAAK,GAAG,MAAM,EAAE,EAAE,KAAK,IAAI,CAAC;IAClC,MAAM,OAAO,GAAG,MAAM,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC;IAC1D,kGAAkG;IAClG,MAAM,UAAU,GAAG,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,yBAAyB,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC;IACpH,MAAM,SAAS,GAAG,KAAK,IAAI,OAAO,MAAM,CAAC,SAAS,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,SAAS,CAAC,IAAI,MAAM,CAAC,SAAS,IAAI,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC;IACxJ,MAAM,UAAU,GAAG,CAAC,CAAU,EAAc,EAAE;QAC5C,MAAM,OAAO,GAAI,CAA2B,CAAC,OAAO,CAAC;QACrD,OAAO,OAAO,OAAO,KAAK,QAAQ,IAAI,MAAM,CAAC,MAAM,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC,CAAC,CAAC,YAAY,CAAC,OAAwB,CAAC,CAAC,CAAC,CAAC,+BAA+B,CAAC;IACxJ,CAAC,CAAC;IACF,MAAM,gBAAgB,GAAG,CAAC,OAAe,EAAc,EAAE,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC,mBAAmB,EAAE,OAAO,CAAC,CAAC,CAAC,CAAE,mBAAmB,CAAC,OAAO,CAAgB,CAAC,CAAC,CAAC,6BAA6B,CAAC,CAAC;IACvL,MAAM,WAAW,GAAG,KAAK,IAAI,OAAO,MAAM,CAAC,WAAW,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC;IACvI,MAAM,MAAM,GAAG,OAAO,IAAI,CAAC,WAAW,KAAK,IAAI,IAAI,EAAE,CAAC,GAAG,EAAE,GAAG,WAAW,CAAC,CAAC;IAC3E,MAAM,SAAS,GAAG,KAAK,IAAI,IAAI,KAAK,SAAS,IAAI,QAAQ,KAAK,IAAI,IAAI,WAAW,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC;IACxI,MAAM,QAAQ,GAAe,IAAI,KAAK,cAAc,CAAC,CAAC,CAAC,gCAAgC,CAAC,CAAC,CAAC,0BAA0B,CAAC;IAErH,OAAO,CACL,KAAC,MAAM,IAAC,SAAS,EAAE,SAAS,YAC5B,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,YACtC,MAAC,MAAM,IAAC,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,KAAM,CAAC,aAAa,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,aAC3J,aAAI,EAAE,EAAE,OAAO,EAAE,GAAG,EAAE,OAAO,EAAE,SAAS,EAAC,UAAU,EAAC,QAAQ,EAAE,CAAC,CAAC,YAC7D,UAAU,GACR,EAEL,eAAK,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,SAAS,aACnC,KAAK,IAAI,CACR,aAAG,SAAS,EAAC,WAAW,aACrB,MAAM,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,sBAAsB,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,MAAM,EAChE,SAAS,KAAK,IAAI,IAAI,IAAI,CAAC,CAAC,yBAAyB,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,EAAE,IAC7E,CACL,EACA,KAAK,EAAE,EAAE,KAAK,IAAI,IAAI,YAAG,SAAS,EAAC,WAAW,YAAE,CAAC,CAAC,4BAA4B,CAAC,GAAK,IACjF,EACL,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,CACjB,gBAAM,QAAQ,EAAE,MAAM,EAAE,UAAU,mBAChC,YAAG,SAAS,EAAC,SAAS,YAAE,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,4BAA4B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,qBAAqB,CAAC,GAAK,EAC3G,KAAK,KAAK,EAAE,IAAI,qBAAY,SAAS,EAAC,UAAU,YAAE,CAAC,CAAC,qBAAqB,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,GAAc,EACzG,IAAI,KAAK,SAAS,IAAI,CACrB,KAAC,MAAM,IACL,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,CAAC,CAAC,sBAAsB,CAAC,EACjC,OAAO,EAAE,OAAO,EAChB,WAAW,EAAE,SAAS,EACtB,QAAQ,EAAE,MAAM,EAChB,QAAQ,EAAE,CAAC,EAAE,EAAE,EAAE;oCACf,SAAS,CAAC,EAAE,CAAC,CAAC;oCACd,UAAU,CAAC,KAAK,CAAC,CAAC;gCACpB,CAAC,GACD,CACH,EACA,OAAO,IAAI,CACV,YAAG,EAAE,EAAE,SAAS,EAAE,SAAS,EAAC,gBAAgB,EAAC,IAAI,EAAC,OAAO,YACtD,CAAC,CAAC,QAAQ,CAAC,GACV,CACL,EACA,QAAQ,IAAI,CACX,8BACE,gBAAO,SAAS,EAAC,UAAU,EAAC,OAAO,EAAE,MAAM,YACxC,CAAC,CAAC,oBAAoB,CAAC,GAClB,EACR,mBAAU,EAAE,EAAE,MAAM,EAAE,SAAS,EAAC,aAAa,EAAC,IAAI,EAAE,CAAC,EAAE,SAAS,EAAE,QAAQ,EAAE,KAAK,EAAE,IAAI,sBAAoB,MAAM,EAAE,QAAQ,EAAE,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,GAAI,EAC/J,YAAG,EAAE,EAAE,MAAM,EAAE,SAAS,EAAC,SAAS,YAC/B,CAAC,CAAC,wBAAwB,EAAE,EAAE,GAAG,EAAE,QAAQ,EAAE,CAAC,GAC7C,IACH,CACJ,EACA,OAAO,KAAK,IAAI,IAAI,CACnB,aAAG,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,OAAO,aACjC,CAAC,CAAC,sBAAsB,CAAC,OAAG,SAAS,CAAC,CAAC,EAAE,OAAO,CAAC,IAChD,CACL,EACD,eAAK,SAAS,EAAC,YAAY,aACzB,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,wBAAwB,mBAAgB,IAAI,IAAI,SAAS,eAAa,IAAI,IAAI,SAAS,YACpH,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,2BAA2B,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,oBAAoB,CAAC,GACvE,EACR,IAAI,KAAK,cAAc,IAAI,CAC1B,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,QAAQ,mBAAgB,IAAI,IAAI,SAAS,eAAa,IAAI,IAAI,SAAS,EAAE,OAAO,EAAE,IAAI,YACnH,CAAC,CAAC,oBAAoB,CAAC,GACjB,CACV,EAED,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,QAAQ,mBAAgB,IAAI,IAAI,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,YACpH,CAAC,CAAC,sBAAsB,CAAC,GACnB,IACL,IACD,CACR,CAAC,CAAC,CAAC,CACF,8BACG,CAAC,KAAK,IAAI,CACT,YAAG,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,OAAO,YACjC,CAAC,CAAC,UAAU,CAAC,OAAO,CAAC,CAAC,GACrB,CACL,EACA,SAAS,IAAI,KAAK,KAAK,IAAI,IAAI,CAC9B,KAAC,QAAQ,IAAC,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,WAAW,EAAE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAI,CAClJ,EACA,KAAK,KAAK,IAAI,IAAI,CAAC,KAAK,CAAC,EAAE,IAAI,CAC9B,YAAG,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,OAAO,YACjC,CAAC,CAAC,gBAAgB,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,GACjC,CACL,EACD,cAAK,SAAS,EAAC,YAAY,YACzB,iBAAQ,IAAI,EAAC,QAAQ,EAAC,SAAS,EAAC,wBAAwB,mBAAgB,IAAI,IAAI,SAAS,EAAE,OAAO,EAAE,GAAG,EAAE,CAAC,CAAC,OAAO,CAAC,OAAO,IAAI,OAAO,EAAE,YACpI,CAAC,CAAC,qBAAqB,CAAC,GAClB,GACL,IACL,CACJ,IACM,GACJ,GACE,CACV,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import type { PlayerUiProps } from './ui.js';
|
|
2
|
+
export interface RestrictedChatLineProps extends PlayerUiProps {
|
|
3
|
+
/** When the restriction ends (epoch ms), or `null` for no end. From `cw.chat.restricted(...)`. */
|
|
4
|
+
until: number | null;
|
|
5
|
+
/** `true` when a moderator turned the chat off, `false` when the automatic filter did (kind `auto`). */
|
|
6
|
+
byModerator: boolean;
|
|
7
|
+
/** The reference code to quote to a moderator, when you have one. */
|
|
8
|
+
refCode?: string;
|
|
9
|
+
}
|
|
10
|
+
/** One line for the place a chat box would be, saying why the player cannot type, until when, and who did it. */
|
|
11
|
+
export declare function RestrictedChatLine(props: RestrictedChatLineProps): import("react").JSX.Element;
|
|
12
|
+
//# sourceMappingURL=RestrictedChatLine.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RestrictedChatLine.d.ts","sourceRoot":"","sources":["../../src/RestrictedChatLine.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,uBAAwB,SAAQ,aAAa;IAC5D,kGAAkG;IAClG,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,wGAAwG;IACxG,WAAW,EAAE,OAAO,CAAC;IACrB,qEAAqE;IACrE,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,iHAAiH;AACjH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,uBAAuB,+BA2BhE"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { timeLeft, untilText } from './format.js';
|
|
3
|
+
import { Card, Root, useUi } from './ui.js';
|
|
4
|
+
/** One line for the place a chat box would be, saying why the player cannot type, until when, and who did it. */
|
|
5
|
+
export function RestrictedChatLine(props) {
|
|
6
|
+
const { until, byModerator, refCode, theme, className } = props;
|
|
7
|
+
const ui = useUi(props);
|
|
8
|
+
const { t, locale, timeZone } = ui;
|
|
9
|
+
const ends = typeof until === 'number' && Number.isFinite(until);
|
|
10
|
+
const when = ends ? untilText(until, locale, timeZone) : '';
|
|
11
|
+
const left = ends ? timeLeft(until, ui.now(), locale) : null;
|
|
12
|
+
const text = !ends
|
|
13
|
+
? t(byModerator ? 'player.restricted.moderator.noEnd' : 'player.restricted.filter.noEnd')
|
|
14
|
+
: left === null
|
|
15
|
+
? t('player.restricted.ended', { when })
|
|
16
|
+
: t(byModerator ? 'player.restricted.moderator.until' : 'player.restricted.filter.until', { when, left });
|
|
17
|
+
return (_jsx(Root, { theme: theme, className: className, children: _jsxs("p", { className: "cw-restricted", role: "status", children: [_jsx(Card, { kind: "chat" }), _jsx("span", { className: "cw-text", children: text }), refCode !== undefined && (_jsxs(_Fragment, { children: [' ', _jsx("span", { className: "cw-ref", children: t('player.restricted.ref', { code: refCode }) })] }))] }) }));
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=RestrictedChatLine.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RestrictedChatLine.js","sourceRoot":"","sources":["../../src/RestrictedChatLine.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAY5C,iHAAiH;AACjH,MAAM,UAAU,kBAAkB,CAAC,KAA8B;IAC/D,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IAChE,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,QAAQ,EAAE,GAAG,EAAE,CAAC;IACnC,MAAM,IAAI,GAAG,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;IACjE,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,SAAS,CAAC,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;IAC5D,MAAM,IAAI,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,KAAK,EAAE,EAAE,CAAC,GAAG,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC7D,MAAM,IAAI,GAAG,CAAC,IAAI;QAChB,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,gCAAgC,CAAC;QACzF,CAAC,CAAC,IAAI,KAAK,IAAI;YACb,CAAC,CAAC,CAAC,CAAC,yBAAyB,EAAE,EAAE,IAAI,EAAE,CAAC;YACxC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,mCAAmC,CAAC,CAAC,CAAC,gCAAgC,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IAE9G,OAAO,CACL,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,YACtC,aAAG,SAAS,EAAC,eAAe,EAAC,IAAI,EAAC,QAAQ,aACxC,KAAC,IAAI,IAAC,IAAI,EAAC,MAAM,GAAG,EACpB,eAAM,SAAS,EAAC,SAAS,YAAE,IAAI,GAAQ,EACtC,OAAO,KAAK,SAAS,IAAI,CACxB,8BACG,GAAG,EACJ,eAAM,SAAS,EAAC,QAAQ,YAAE,CAAC,CAAC,uBAAuB,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,GAAQ,IAC9E,CACJ,IACC,GACC,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { PlayerClient } from './client.js';
|
|
2
|
+
import type { PlayerUiProps } from './ui.js';
|
|
3
|
+
export interface RulesPageProps extends PlayerUiProps {
|
|
4
|
+
client: PlayerClient;
|
|
5
|
+
/** Change it to load the rules again. */
|
|
6
|
+
refreshKey?: number | string;
|
|
7
|
+
}
|
|
8
|
+
/** The community rules: the profile's summary and the numbered rules from `GET /rules`. Text only, never HTML. */
|
|
9
|
+
export declare function RulesPage(props: RulesPageProps): import("react").JSX.Element;
|
|
10
|
+
//# sourceMappingURL=RulesPage.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RulesPage.d.ts","sourceRoot":"","sources":["../../src/RulesPage.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAGhD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAE7C,MAAM,WAAW,cAAe,SAAQ,aAAa;IACnD,MAAM,EAAE,YAAY,CAAC;IACrB,yCAAyC;IACzC,UAAU,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;CAC9B;AAED,kHAAkH;AAClH,wBAAgB,SAAS,CAAC,KAAK,EAAE,cAAc,+BAmC9C"}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useId } from 'react';
|
|
3
|
+
import { usePlayerData } from './hooks.js';
|
|
4
|
+
import { ErrorBlock, Root, useUi } from './ui.js';
|
|
5
|
+
/** The community rules: the profile's summary and the numbered rules from `GET /rules`. Text only, never HTML. */
|
|
6
|
+
export function RulesPage(props) {
|
|
7
|
+
const { client, refreshKey, theme, className } = props;
|
|
8
|
+
const ui = useUi(props);
|
|
9
|
+
const { t } = ui;
|
|
10
|
+
const state = usePlayerData(() => client.rules(), refreshKey);
|
|
11
|
+
const titleId = useId();
|
|
12
|
+
const data = state.data;
|
|
13
|
+
return (_jsx(Root, { theme: theme, className: className, children: _jsxs("section", { className: "cw-section", "aria-labelledby": titleId, children: [_jsx("h2", { id: titleId, className: "cw-title", children: t('player.rules.title') }), state.error !== null && _jsx(ErrorBlock, { ui: ui, what: t('player.rules.loadFailed'), error: state.error, onRetry: state.reload }), data === undefined && state.error === null && (_jsx("p", { className: "cw-state", role: "status", children: t('player.rules.loading') })), data !== undefined && data.summary !== '' && _jsx("p", { className: "cw-summary", children: data.summary }), data !== undefined && data.rules.length === 0 && _jsx("p", { className: "cw-state", children: t('player.rules.empty') }), data !== undefined && data.rules.length > 0 && (
|
|
14
|
+
// The kit's own numbers, so a retired rule leaves a gap instead of renumbering the ones after it.
|
|
15
|
+
_jsx("ol", { className: "cw-rules", "aria-labelledby": titleId, children: data.rules.map((rule) => (_jsxs("li", { value: rule.number, children: [_jsx("strong", { className: "cw-rule-title", children: rule.title }), " ", _jsx("span", { className: "cw-rule-text", children: rule.text })] }, rule.number))) }))] }) }));
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=RulesPage.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"RulesPage.js","sourceRoot":"","sources":["../../src/RulesPage.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC;AAE9B,OAAO,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAC3C,OAAO,EAAE,UAAU,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AASlD,kHAAkH;AAClH,MAAM,UAAU,SAAS,CAAC,KAAqB;IAC7C,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACvD,MAAM,EAAE,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC;IACxB,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC;IACjB,MAAM,KAAK,GAAG,aAAa,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,KAAK,EAAE,EAAE,UAAU,CAAC,CAAC;IAC9D,MAAM,OAAO,GAAG,KAAK,EAAE,CAAC;IACxB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC;IAExB,OAAO,CACL,KAAC,IAAI,IAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,SAAS,YACtC,mBAAS,SAAS,EAAC,YAAY,qBAAkB,OAAO,aACtD,aAAI,EAAE,EAAE,OAAO,EAAE,SAAS,EAAC,UAAU,YAClC,CAAC,CAAC,oBAAoB,CAAC,GACrB,EACJ,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,KAAC,UAAU,IAAC,EAAE,EAAE,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,yBAAyB,CAAC,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,MAAM,GAAI,EAC7H,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,KAAK,KAAK,IAAI,IAAI,CAC7C,YAAG,SAAS,EAAC,UAAU,EAAC,IAAI,EAAC,QAAQ,YAClC,CAAC,CAAC,sBAAsB,CAAC,GACxB,CACL,EACA,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,OAAO,KAAK,EAAE,IAAI,YAAG,SAAS,EAAC,YAAY,YAAE,IAAI,CAAC,OAAO,GAAK,EACzF,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC,IAAI,YAAG,SAAS,EAAC,UAAU,YAAE,CAAC,CAAC,oBAAoB,CAAC,GAAK,EACtG,IAAI,KAAK,SAAS,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI;gBAC9C,kGAAkG;gBAClG,aAAI,SAAS,EAAC,UAAU,qBAAkB,OAAO,YAC9C,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,CACxB,cAAsB,KAAK,EAAE,IAAI,CAAC,MAAM,aACtC,iBAAQ,SAAS,EAAC,eAAe,YAAE,IAAI,CAAC,KAAK,GAAU,OAAC,eAAM,SAAS,EAAC,cAAc,YAAE,IAAI,CAAC,IAAI,GAAQ,KADlG,IAAI,CAAC,MAAM,CAEf,CACN,CAAC,GACC,CACN,IACO,GACL,CACR,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { PlayerNotice, PlayerReporting } from '@chatwarden/core';
|
|
2
|
+
import type { Transport } from './transport.js';
|
|
3
|
+
/**
|
|
4
|
+
* Why a call to the player routes failed. `status` is the HTTP status, or 0 when no answer arrived. `code` is the kit's error
|
|
5
|
+
* code (`not_found`, `rate_limited`, ...), `network` for a dropped connection, `bad_response` for an answer that is not the
|
|
6
|
+
* shape the components expect, `unexpected` for anything else, and `http_<status>` when the body is not a kit error.
|
|
7
|
+
* `retryAfter` is the seconds from a `retry-after` header (a 429).
|
|
8
|
+
*/
|
|
9
|
+
export declare class PlayerError extends Error {
|
|
10
|
+
readonly status: number;
|
|
11
|
+
readonly code: string;
|
|
12
|
+
readonly retryAfter: number | undefined;
|
|
13
|
+
constructor(init: {
|
|
14
|
+
status: number;
|
|
15
|
+
code: string;
|
|
16
|
+
message: string;
|
|
17
|
+
retryAfter?: number;
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
/** A `PlayerError` as is; anything else (a bug in the caller's code, say) becomes status 0, code `unexpected`. */
|
|
21
|
+
export declare function toPlayerError(e: unknown): PlayerError;
|
|
22
|
+
/** One rule as `GET /rules` gives it. */
|
|
23
|
+
export interface PlayerRule {
|
|
24
|
+
number: number;
|
|
25
|
+
title: string;
|
|
26
|
+
text: string;
|
|
27
|
+
}
|
|
28
|
+
/** `GET /rules`: the profile's one-line summary, the active rules and how reporting works here (`undefined` from an older server). */
|
|
29
|
+
export interface PlayerRules {
|
|
30
|
+
summary: string;
|
|
31
|
+
rules: PlayerRule[];
|
|
32
|
+
/** The flow, the reasons a player may give and the thank-you: pass it to `ReportDialog` as `reporting`. */
|
|
33
|
+
reporting?: PlayerReporting;
|
|
34
|
+
}
|
|
35
|
+
export interface PlayerClient {
|
|
36
|
+
/** `GET /notices`: notices not yet acknowledged, as the kit sends them (oldest first). */
|
|
37
|
+
notices(): Promise<PlayerNotice[]>;
|
|
38
|
+
/** `POST /notices/:id/ack`: `true` when it was this player's live notice, `false` (still a 200) when it was not, or it is gone. */
|
|
39
|
+
ack(id: string): Promise<boolean>;
|
|
40
|
+
/** `GET /record`: the player's sanctions that still apply (seen or not). */
|
|
41
|
+
record(): Promise<PlayerNotice[]>;
|
|
42
|
+
/** `GET /rules`: the summary, the numbered rules and the reporting settings. */
|
|
43
|
+
rules(): Promise<PlayerRules>;
|
|
44
|
+
}
|
|
45
|
+
export interface PlayerClientOptions {
|
|
46
|
+
/** How to reach the player routes: `fetchTransport({ baseUrl: '/player' })`, or any function with the same shape. */
|
|
47
|
+
transport: Transport;
|
|
48
|
+
}
|
|
49
|
+
/** A client over the kit's player routes. It resolves with typed values and rejects with a `PlayerError`. */
|
|
50
|
+
export declare function createPlayerClient({ transport }: PlayerClientOptions): PlayerClient;
|
|
51
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AAEtE,OAAO,KAAK,EAAE,SAAS,EAAuC,MAAM,gBAAgB,CAAC;AAErF;;;;;GAKG;AACH,qBAAa,WAAY,SAAQ,KAAK;IACpC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;gBAE5B,IAAI,EAAE;QAAE,MAAM,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,MAAM,CAAC;QAAC,OAAO,EAAE,MAAM,CAAC;QAAC,UAAU,CAAC,EAAE,MAAM,CAAA;KAAE;CAOzF;AAED,kHAAkH;AAClH,wBAAgB,aAAa,CAAC,CAAC,EAAE,OAAO,GAAG,WAAW,CAGrD;AAmDD,yCAAyC;AACzC,MAAM,WAAW,UAAU;IACzB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd;AAED,sIAAsI;AACtI,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,2GAA2G;IAC3G,SAAS,CAAC,EAAE,eAAe,CAAC;CAC7B;AAED,MAAM,WAAW,YAAY;IAC3B,0FAA0F;IAC1F,OAAO,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IACnC,mIAAmI;IACnI,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAClC,4EAA4E;IAC5E,MAAM,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;IAClC,gFAAgF;IAChF,KAAK,IAAI,OAAO,CAAC,WAAW,CAAC,CAAC;CAC/B;AAED,MAAM,WAAW,mBAAmB;IAClC,qHAAqH;IACrH,SAAS,EAAE,SAAS,CAAC;CACtB;AAED,6GAA6G;AAC7G,wBAAgB,kBAAkB,CAAC,EAAE,SAAS,EAAE,EAAE,mBAAmB,GAAG,YAAY,CAoBnF"}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
import { readReporting } from './reporting.js';
|
|
2
|
+
/**
|
|
3
|
+
* Why a call to the player routes failed. `status` is the HTTP status, or 0 when no answer arrived. `code` is the kit's error
|
|
4
|
+
* code (`not_found`, `rate_limited`, ...), `network` for a dropped connection, `bad_response` for an answer that is not the
|
|
5
|
+
* shape the components expect, `unexpected` for anything else, and `http_<status>` when the body is not a kit error.
|
|
6
|
+
* `retryAfter` is the seconds from a `retry-after` header (a 429).
|
|
7
|
+
*/
|
|
8
|
+
export class PlayerError extends Error {
|
|
9
|
+
status;
|
|
10
|
+
code;
|
|
11
|
+
retryAfter;
|
|
12
|
+
constructor(init) {
|
|
13
|
+
super(init.message);
|
|
14
|
+
this.name = 'PlayerError';
|
|
15
|
+
this.status = init.status;
|
|
16
|
+
this.code = init.code;
|
|
17
|
+
this.retryAfter = init.retryAfter;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
/** A `PlayerError` as is; anything else (a bug in the caller's code, say) becomes status 0, code `unexpected`. */
|
|
21
|
+
export function toPlayerError(e) {
|
|
22
|
+
if (e instanceof PlayerError)
|
|
23
|
+
return e;
|
|
24
|
+
return new PlayerError({ status: 0, code: 'unexpected', message: e instanceof Error ? e.message : 'Something went wrong.' });
|
|
25
|
+
}
|
|
26
|
+
const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
27
|
+
const text = (v) => typeof v === 'string';
|
|
28
|
+
function errorOf(res) {
|
|
29
|
+
const b = res.body;
|
|
30
|
+
const raw = res.headers['retry-after'];
|
|
31
|
+
const rest = raw !== undefined && /^\d{1,9}$/.test(raw) ? { retryAfter: Number(raw) } : {};
|
|
32
|
+
if (isObject(b) && text(b.error) && text(b.message))
|
|
33
|
+
return new PlayerError({ status: res.status, code: b.error, message: b.message, ...rest });
|
|
34
|
+
// A proxy's HTML page, or an empty body: say the status, never echo the body.
|
|
35
|
+
return new PlayerError({ status: res.status, code: `http_${res.status}`, message: `The server answered with status ${res.status}.`, ...rest });
|
|
36
|
+
}
|
|
37
|
+
async function send(transport, req) {
|
|
38
|
+
let res;
|
|
39
|
+
try {
|
|
40
|
+
res = await transport(req);
|
|
41
|
+
}
|
|
42
|
+
catch (e) {
|
|
43
|
+
throw new PlayerError({ status: 0, code: 'network', message: e instanceof Error && e.name === 'AbortError' ? 'The request was cancelled.' : 'Could not reach the server.' });
|
|
44
|
+
}
|
|
45
|
+
if (res.status < 200 || res.status > 299)
|
|
46
|
+
throw errorOf(res);
|
|
47
|
+
return res.body;
|
|
48
|
+
}
|
|
49
|
+
const bad = () => new PlayerError({ status: 200, code: 'bad_response', message: 'The server sent an answer these components do not understand.' });
|
|
50
|
+
/** One notice, keeping only the fields the kit documents for a player. Anything else the server sent never reaches the page. */
|
|
51
|
+
function noticeOf(raw) {
|
|
52
|
+
if (!isObject(raw) || !text(raw.id) || !text(raw.kind))
|
|
53
|
+
return null;
|
|
54
|
+
const excerpt = Array.isArray(raw.excerpt)
|
|
55
|
+
? raw.excerpt.filter(isObject).filter((l) => text(l.text) && text(l.day)).map((l) => ({ text: l.text, day: l.day }))
|
|
56
|
+
: [];
|
|
57
|
+
return {
|
|
58
|
+
id: raw.id,
|
|
59
|
+
kind: raw.kind,
|
|
60
|
+
rule: typeof raw.rule === 'number' || raw.rule === 'uncovered' ? raw.rule : null,
|
|
61
|
+
ruleLabel: text(raw.ruleLabel) ? raw.ruleLabel : null,
|
|
62
|
+
until: typeof raw.until === 'number' && Number.isFinite(raw.until) ? raw.until : null,
|
|
63
|
+
refCode: text(raw.refCode) ? raw.refCode : null,
|
|
64
|
+
excerpt,
|
|
65
|
+
createdAt: typeof raw.createdAt === 'number' && Number.isFinite(raw.createdAt) ? raw.createdAt : 0,
|
|
66
|
+
mustAcknowledge: raw.mustAcknowledge === true,
|
|
67
|
+
};
|
|
68
|
+
}
|
|
69
|
+
function noticesOf(body, key) {
|
|
70
|
+
if (!isObject(body) || !Array.isArray(body[key]))
|
|
71
|
+
throw bad();
|
|
72
|
+
return body[key].map(noticeOf).filter((n) => n !== null);
|
|
73
|
+
}
|
|
74
|
+
/** A client over the kit's player routes. It resolves with typed values and rejects with a `PlayerError`. */
|
|
75
|
+
export function createPlayerClient({ transport }) {
|
|
76
|
+
return {
|
|
77
|
+
notices: async () => noticesOf(await send(transport, { method: 'GET', path: '/notices' }), 'notices'),
|
|
78
|
+
record: async () => noticesOf(await send(transport, { method: 'GET', path: '/record' }), 'record'),
|
|
79
|
+
ack: async (id) => {
|
|
80
|
+
const body = await send(transport, { method: 'POST', path: `/notices/${encodeURIComponent(id)}/ack` });
|
|
81
|
+
if (!isObject(body) || typeof body.ok !== 'boolean')
|
|
82
|
+
throw bad();
|
|
83
|
+
return body.ok;
|
|
84
|
+
},
|
|
85
|
+
rules: async () => {
|
|
86
|
+
const body = await send(transport, { method: 'GET', path: '/rules' });
|
|
87
|
+
if (!isObject(body) || !text(body.summary) || !Array.isArray(body.rules))
|
|
88
|
+
throw bad();
|
|
89
|
+
const rules = body.rules
|
|
90
|
+
.filter(isObject)
|
|
91
|
+
.filter((r) => typeof r.number === 'number' && text(r.title) && text(r.text))
|
|
92
|
+
.map((r) => ({ number: r.number, title: r.title, text: r.text }));
|
|
93
|
+
const reporting = readReporting(body.reporting);
|
|
94
|
+
return { summary: body.summary, rules, ...(reporting === undefined ? {} : { reporting }) };
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The longest note the kit keeps (a test keeps this the same as core's `REPORT_NOTE_MAX`). */
|
|
2
|
+
export declare const NOTE_MAX = 500;
|
|
3
|
+
/** How many days a warning stays on a record (a test keeps this the same as core's notice record window). */
|
|
4
|
+
export declare const WARNING_DAYS = 90;
|
|
5
|
+
//# sourceMappingURL=constants.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,eAAO,MAAM,QAAQ,MAAM,CAAC;AAE5B,6GAA6G;AAC7G,eAAO,MAAM,YAAY,KAAK,CAAC"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** The longest note the kit keeps (a test keeps this the same as core's `REPORT_NOTE_MAX`). */
|
|
2
|
+
export const NOTE_MAX = 500;
|
|
3
|
+
/** How many days a warning stays on a record (a test keeps this the same as core's notice record window). */
|
|
4
|
+
export const WARNING_DAYS = 90;
|
|
5
|
+
//# sourceMappingURL=constants.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/constants.ts"],"names":[],"mappings":"AAAA,+FAA+F;AAC/F,MAAM,CAAC,MAAM,QAAQ,GAAG,GAAG,CAAC;AAE5B,6GAA6G;AAC7G,MAAM,CAAC,MAAM,YAAY,GAAG,EAAE,CAAC"}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A UTC day from the kit (`2027-01-15`) as the locale writes a date (`Jan 15, 2027`), in UTC whatever the viewer's zone: the kit
|
|
3
|
+
* names the day in UTC, so a notice never shows a different day than the moderator's tools. A value that is not a day comes back
|
|
4
|
+
* as it was; it is never shown as "Invalid Date".
|
|
5
|
+
*/
|
|
6
|
+
export declare function dayText(day: string, locale: string): string;
|
|
7
|
+
/** A date and time: `Jan 15, 2027, 8:30 PM`. Pass a time zone for a fixed one; the default is the viewer's. An unknown zone is ignored. */
|
|
8
|
+
export declare function untilText(at: number, locale: string, timeZone?: string): string;
|
|
9
|
+
/**
|
|
10
|
+
* How long is left until `at`, as the locale says it ("in 3 hours"): minutes under an hour (a part of a minute counts as a whole
|
|
11
|
+
* one, so a live restriction never reads "in 0 minutes"), hours under two days, then days. Null when `at` is now or has passed.
|
|
12
|
+
*/
|
|
13
|
+
export declare function timeLeft(at: number, now: number, locale: string): string | null;
|
|
14
|
+
//# sourceMappingURL=format.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.d.ts","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"AAiBA;;;;GAIG;AACH,wBAAgB,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAO3D;AAED,2IAA2I;AAC3I,wBAAgB,SAAS,CAAC,EAAE,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/E;AAED;;;GAGG;AACH,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAO/E"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
// Small pure helpers for showing days, times and waits. Times use Intl with the component's `locale`; none holds English.
|
|
2
|
+
const MIN = 60_000;
|
|
3
|
+
const HOUR = 60 * MIN;
|
|
4
|
+
const DAY = 24 * HOUR;
|
|
5
|
+
function safeLocale(locale) {
|
|
6
|
+
try {
|
|
7
|
+
return Intl.getCanonicalLocales(locale)[0] ?? 'en';
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
return 'en';
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
/** Some runtimes put a narrow no-break space before "PM". A plain space reads the same and survives a copy. */
|
|
14
|
+
const plain = (text) => text.replace(/[\u202f\u00a0]/g, ' ');
|
|
15
|
+
/**
|
|
16
|
+
* A UTC day from the kit (`2027-01-15`) as the locale writes a date (`Jan 15, 2027`), in UTC whatever the viewer's zone: the kit
|
|
17
|
+
* names the day in UTC, so a notice never shows a different day than the moderator's tools. A value that is not a day comes back
|
|
18
|
+
* as it was; it is never shown as "Invalid Date".
|
|
19
|
+
*/
|
|
20
|
+
export function dayText(day, locale) {
|
|
21
|
+
const m = /^(\d{4})-(\d{2})-(\d{2})$/.exec(day);
|
|
22
|
+
if (m === null)
|
|
23
|
+
return day;
|
|
24
|
+
const [y, mo, d] = [Number(m[1]), Number(m[2]), Number(m[3])];
|
|
25
|
+
const date = new Date(Date.UTC(y, mo - 1, d));
|
|
26
|
+
if (date.getUTCFullYear() !== y || date.getUTCMonth() !== mo - 1 || date.getUTCDate() !== d)
|
|
27
|
+
return day;
|
|
28
|
+
return new Intl.DateTimeFormat(safeLocale(locale), { dateStyle: 'medium', timeZone: 'UTC' }).format(date);
|
|
29
|
+
}
|
|
30
|
+
/** A date and time: `Jan 15, 2027, 8:30 PM`. Pass a time zone for a fixed one; the default is the viewer's. An unknown zone is ignored. */
|
|
31
|
+
export function untilText(at, locale, timeZone) {
|
|
32
|
+
const options = { dateStyle: 'medium', timeStyle: 'short' };
|
|
33
|
+
try {
|
|
34
|
+
return plain(new Intl.DateTimeFormat(safeLocale(locale), { ...options, ...(timeZone === undefined ? {} : { timeZone }) }).format(at));
|
|
35
|
+
}
|
|
36
|
+
catch {
|
|
37
|
+
return plain(new Intl.DateTimeFormat(safeLocale(locale), options).format(at));
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* How long is left until `at`, as the locale says it ("in 3 hours"): minutes under an hour (a part of a minute counts as a whole
|
|
42
|
+
* one, so a live restriction never reads "in 0 minutes"), hours under two days, then days. Null when `at` is now or has passed.
|
|
43
|
+
*/
|
|
44
|
+
export function timeLeft(at, now, locale) {
|
|
45
|
+
const left = at - now;
|
|
46
|
+
if (!(left > 0))
|
|
47
|
+
return null;
|
|
48
|
+
const rtf = new Intl.RelativeTimeFormat(safeLocale(locale), { numeric: 'always' });
|
|
49
|
+
if (left < HOUR)
|
|
50
|
+
return rtf.format(Math.max(1, Math.ceil(left / MIN)), 'minute');
|
|
51
|
+
if (left < 2 * DAY)
|
|
52
|
+
return rtf.format(Math.round(left / HOUR), 'hour');
|
|
53
|
+
return rtf.format(Math.round(left / DAY), 'day');
|
|
54
|
+
}
|
|
55
|
+
//# sourceMappingURL=format.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"format.js","sourceRoot":"","sources":["../../src/format.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { PlayerError } from './client.js';
|
|
2
|
+
export interface PlayerData<T> {
|
|
3
|
+
/** The last answer, kept when a later load fails. */
|
|
4
|
+
data: T | undefined;
|
|
5
|
+
/** The last failure, or null. Cleared when a load starts. */
|
|
6
|
+
error: PlayerError | null;
|
|
7
|
+
/** Starts the same load again. */
|
|
8
|
+
reload: () => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Runs `load` on mount, again when `refreshKey` changes, and again on `reload()`. An answer from a load that has been replaced
|
|
12
|
+
* (or from a component that is gone) is dropped, so a slow old request never overwrites a newer one.
|
|
13
|
+
*/
|
|
14
|
+
export declare function usePlayerData<T>(load: () => Promise<T>, refreshKey: unknown): PlayerData<T>;
|
|
15
|
+
//# sourceMappingURL=hooks.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../../src/hooks.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAiB,MAAM,aAAa,CAAC;AAEzD,MAAM,WAAW,UAAU,CAAC,CAAC;IAC3B,qDAAqD;IACrD,IAAI,EAAE,CAAC,GAAG,SAAS,CAAC;IACpB,6DAA6D;IAC7D,KAAK,EAAE,WAAW,GAAG,IAAI,CAAC;IAC1B,kCAAkC;IAClC,MAAM,EAAE,MAAM,IAAI,CAAC;CACpB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,CAAC,EAAE,IAAI,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,OAAO,GAAG,UAAU,CAAC,CAAC,CAAC,CAwB3F"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { useCallback, useEffect, useRef, useState } from 'react';
|
|
2
|
+
import { PlayerError, toPlayerError } from './client.js';
|
|
3
|
+
/**
|
|
4
|
+
* Runs `load` on mount, again when `refreshKey` changes, and again on `reload()`. An answer from a load that has been replaced
|
|
5
|
+
* (or from a component that is gone) is dropped, so a slow old request never overwrites a newer one.
|
|
6
|
+
*/
|
|
7
|
+
export function usePlayerData(load, refreshKey) {
|
|
8
|
+
const [state, setState] = useState({ data: undefined, error: null });
|
|
9
|
+
const [again, setAgain] = useState(0);
|
|
10
|
+
const loader = useRef(load);
|
|
11
|
+
loader.current = load;
|
|
12
|
+
useEffect(() => {
|
|
13
|
+
let live = true;
|
|
14
|
+
setState((s) => (s.error === null ? s : { ...s, error: null }));
|
|
15
|
+
loader.current().then((data) => {
|
|
16
|
+
if (live)
|
|
17
|
+
setState({ data, error: null });
|
|
18
|
+
}, (e) => {
|
|
19
|
+
if (live)
|
|
20
|
+
setState((s) => ({ data: s.data, error: toPlayerError(e) }));
|
|
21
|
+
});
|
|
22
|
+
return () => {
|
|
23
|
+
live = false;
|
|
24
|
+
};
|
|
25
|
+
}, [refreshKey, again]);
|
|
26
|
+
const reload = useCallback(() => setAgain((n) => n + 1), []);
|
|
27
|
+
return { data: state.data, error: state.error, reload };
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=hooks.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"hooks.js","sourceRoot":"","sources":["../../src/hooks.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AACjE,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAWzD;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAI,IAAsB,EAAE,UAAmB;IAC1E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAqD,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;IACzH,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5B,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;IAEtB,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,IAAI,GAAG,IAAI,CAAC;QAChB,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,GAAG,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;QAChE,MAAM,CAAC,OAAO,EAAE,CAAC,IAAI,CACnB,CAAC,IAAI,EAAE,EAAE;YACP,IAAI,IAAI;gBAAE,QAAQ,CAAC,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;QAC5C,CAAC,EACD,CAAC,CAAU,EAAE,EAAE;YACb,IAAI,IAAI;gBAAE,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,aAAa,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACzE,CAAC,CACF,CAAC;QACF,OAAO,GAAG,EAAE;YACV,IAAI,GAAG,KAAK,CAAC;QACf,CAAC,CAAC;IACJ,CAAC,EAAE,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC,CAAC;IAExB,MAAM,MAAM,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;IAC7D,OAAO,EAAE,IAAI,EAAE,KAAK,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,MAAM,EAAE,CAAC;AAC1D,CAAC"}
|