@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,129 @@
|
|
|
1
|
+
export declare const en: {
|
|
2
|
+
readonly 'player.error.network': "Could not reach the server. Check your connection and try again.";
|
|
3
|
+
readonly 'player.error.unauthorized': "You are signed out. Sign in again, then try again.";
|
|
4
|
+
readonly 'player.error.forbidden': "This account cannot do that.";
|
|
5
|
+
readonly 'player.error.notFound': "That could not be found.";
|
|
6
|
+
readonly 'player.error.rateLimited': "Too many requests. Try again in a moment.";
|
|
7
|
+
readonly 'player.error.rateLimited.after.one': "Too many requests. Try again in {count} second.";
|
|
8
|
+
readonly 'player.error.rateLimited.after.other': "Too many requests. Try again in {count} seconds.";
|
|
9
|
+
readonly 'player.error.server': "The server had a problem. Try again in a moment.";
|
|
10
|
+
readonly 'player.error.generic': "Something went wrong.";
|
|
11
|
+
readonly 'player.state.retry': "Try again";
|
|
12
|
+
readonly 'player.notices.loadFailed': "We could not check for notices.";
|
|
13
|
+
readonly 'player.notice.title.warning': "You have a warning";
|
|
14
|
+
readonly 'player.notice.title.chat': "Your chat is turned off";
|
|
15
|
+
readonly 'player.notice.title.area': "You cannot join public rooms";
|
|
16
|
+
readonly 'player.notice.title.ban': "You are banned";
|
|
17
|
+
readonly 'player.notice.title.report_outcome': "Thanks for your report";
|
|
18
|
+
readonly 'player.notice.title.fallback': "A message from the moderators";
|
|
19
|
+
readonly 'player.notice.body.warning': "A moderator gave you a warning for something you wrote. You can keep playing.";
|
|
20
|
+
readonly 'player.notice.body.chat': "A moderator turned off your chat. You can still play.";
|
|
21
|
+
readonly 'player.notice.body.area': "A moderator stopped you joining public rooms and matchmaking. You can still play in private rooms.";
|
|
22
|
+
readonly 'player.notice.body.ban': "A moderator banned you from playing.";
|
|
23
|
+
readonly 'player.notice.body.report_outcome': "A moderator looked at your report and took action. We do not share what was done.";
|
|
24
|
+
readonly 'player.notice.body.fallback': "There is a new message about your account.";
|
|
25
|
+
readonly 'player.notice.position': "Notice {n} of {total}";
|
|
26
|
+
readonly 'player.notice.rule': "Rule";
|
|
27
|
+
readonly 'player.notice.given': "Given";
|
|
28
|
+
readonly 'player.notice.until': "Until";
|
|
29
|
+
readonly 'player.notice.ended': "Ended";
|
|
30
|
+
readonly 'player.notice.noEnd': "No end date";
|
|
31
|
+
readonly 'player.notice.onRecordUntil': "On your record until";
|
|
32
|
+
readonly 'player.notice.untilLeft': "{when} ({left})";
|
|
33
|
+
readonly 'player.notice.ref': "Reference";
|
|
34
|
+
readonly 'player.notice.refHint': "Quote this code if you contact us.";
|
|
35
|
+
readonly 'player.notice.lines': "Your messages that led to this";
|
|
36
|
+
readonly 'player.notice.todo.warning': "Press Acknowledge to confirm you saw this.";
|
|
37
|
+
readonly 'player.notice.acknowledge': "Acknowledge";
|
|
38
|
+
readonly 'player.notice.gotIt': "Got it";
|
|
39
|
+
readonly 'player.notice.appeal': "Think this is a mistake?";
|
|
40
|
+
readonly 'player.notice.ackFailed': "Your notice is still here.";
|
|
41
|
+
readonly 'player.notice.closeForNow': "Close for now";
|
|
42
|
+
readonly 'player.record.title': "Your record";
|
|
43
|
+
readonly 'player.record.loading': "Loading your record";
|
|
44
|
+
readonly 'player.record.loadFailed': "We could not load your record.";
|
|
45
|
+
readonly 'player.record.intro': "This is what is on your record now. A warning stays for {days} days.";
|
|
46
|
+
readonly 'player.record.empty': "Your record is clear. Nothing is on it right now.";
|
|
47
|
+
readonly 'player.record.kind.warning': "Warning";
|
|
48
|
+
readonly 'player.record.kind.chat': "Chat restriction";
|
|
49
|
+
readonly 'player.record.kind.area': "Public rooms restriction";
|
|
50
|
+
readonly 'player.record.kind.ban': "Ban";
|
|
51
|
+
readonly 'player.record.kind.fallback': "Notice";
|
|
52
|
+
readonly 'player.rules.title': "Community rules";
|
|
53
|
+
readonly 'player.rules.loading': "Loading the rules";
|
|
54
|
+
readonly 'player.rules.loadFailed': "We could not load the rules.";
|
|
55
|
+
readonly 'player.rules.empty': "No rules are published yet.";
|
|
56
|
+
readonly 'player.restricted.moderator.until': "A moderator turned off your chat until {when} ({left}).";
|
|
57
|
+
readonly 'player.restricted.moderator.noEnd': "A moderator turned off your chat. It does not end on its own.";
|
|
58
|
+
readonly 'player.restricted.filter.until': "Your chat is off until {when} ({left}). The automatic filter caught a message.";
|
|
59
|
+
readonly 'player.restricted.filter.noEnd': "Your chat is off. It does not end on its own. The automatic filter caught a message.";
|
|
60
|
+
readonly 'player.restricted.ended': "Your chat is back on. The restriction ended {when}.";
|
|
61
|
+
readonly 'player.restricted.ref': "Reference {code}";
|
|
62
|
+
readonly 'player.report.title': "Report a player";
|
|
63
|
+
readonly 'player.report.titleNamed': "Report {name}";
|
|
64
|
+
readonly 'player.report.intro': "Tell us what happened and a moderator will look at it.";
|
|
65
|
+
readonly 'player.report.legend': "What happened?";
|
|
66
|
+
readonly 'player.report.titleOneTap': "Report this message?";
|
|
67
|
+
readonly 'player.report.titleOneTapNamed': "Report {name}?";
|
|
68
|
+
readonly 'player.report.titleOneTapPlayer': "Report this player?";
|
|
69
|
+
readonly 'player.report.titleSent': "Report sent";
|
|
70
|
+
readonly 'player.report.titleRefused': "Couldn't send the report";
|
|
71
|
+
readonly 'player.report.oneTap.intro': "We will pass it to the moderators. You do not need to say why.";
|
|
72
|
+
readonly 'player.report.oneTap.send': "Report";
|
|
73
|
+
readonly 'player.report.quote': "“{line}”";
|
|
74
|
+
readonly 'player.report.skip': "Skip and report";
|
|
75
|
+
readonly 'player.report.needReason': "Choose a reason.";
|
|
76
|
+
readonly 'player.report.needReasonOrSkip': "Choose what happened, or skip.";
|
|
77
|
+
readonly 'player.report.addReason': "Add a reason";
|
|
78
|
+
readonly 'player.report.addReasonHint': "This helps, but the moderators decide what it really is. You can add this for a few minutes after you report.";
|
|
79
|
+
readonly 'player.report.detail.legend': "What was it about?";
|
|
80
|
+
readonly 'player.report.detail.send': "Add to my report";
|
|
81
|
+
readonly 'player.report.detail.need': "Choose a reason or write a note.";
|
|
82
|
+
readonly 'player.report.detail.added': "Added. Thanks.";
|
|
83
|
+
readonly 'player.report.detail.failed': "We could not add that.";
|
|
84
|
+
readonly 'player.report.detail.refused.off': "Adding to a report is not available right now.";
|
|
85
|
+
readonly 'player.report.detail.refused.not_found': "We cannot find that report any more.";
|
|
86
|
+
readonly 'player.report.detail.refused.not_reporter': "Only the player who sent a report can add to it.";
|
|
87
|
+
readonly 'player.report.detail.refused.too_late': "It is too late to add to this report. We still have the report.";
|
|
88
|
+
readonly 'player.report.detail.refused.already_added': "You already added to this report.";
|
|
89
|
+
readonly 'player.report.detail.refused.reason_unknown': "That reason is not available any more. Your report is still with us.";
|
|
90
|
+
readonly 'player.report.note': "Add a note (optional)";
|
|
91
|
+
readonly 'player.report.noteHint': "A moderator will read this. Up to {max} characters. Do not include passwords or personal details.";
|
|
92
|
+
readonly 'player.report.send': "Send report";
|
|
93
|
+
readonly 'player.report.cancel': "Cancel";
|
|
94
|
+
readonly 'player.report.close': "Close";
|
|
95
|
+
readonly 'player.report.failed': "Your report was not sent.";
|
|
96
|
+
readonly 'player.report.thanks': "Thanks. We got your report.";
|
|
97
|
+
readonly 'player.report.remaining.zero': "You have no more reports left today.";
|
|
98
|
+
readonly 'player.report.remaining.one': "You can send {count} more report today.";
|
|
99
|
+
readonly 'player.report.remaining.other': "You can send {count} more reports today.";
|
|
100
|
+
readonly 'player.report.refused.duplicate': "You already reported this player here. We have your report.";
|
|
101
|
+
readonly 'player.report.refused.rate': "You have sent as many reports as you can today. You can send more tomorrow.";
|
|
102
|
+
readonly 'player.report.refused.self': "You cannot report yourself.";
|
|
103
|
+
readonly 'player.report.refused.not_player': "We cannot find that player any more. They may have left.";
|
|
104
|
+
readonly 'player.report.refused.off': "Reports are not available right now. Try again later.";
|
|
105
|
+
readonly 'player.report.refused.suspended': "You cannot send reports from this account for now.";
|
|
106
|
+
readonly 'player.report.refused.reason_required': "This report needs a reason. Close this and report again to choose one.";
|
|
107
|
+
readonly 'player.report.refused.reason_unknown': "That reason is not available any more. Close this and report again.";
|
|
108
|
+
readonly 'player.report.refused.unknown': "We could not take that report.";
|
|
109
|
+
};
|
|
110
|
+
/** A catalog: keys to English (or translated) text. Any object of strings will do. */
|
|
111
|
+
export type PlayerCatalog = Readonly<Record<string, string>>;
|
|
112
|
+
type PluralForm = 'zero' | 'one' | 'two' | 'few' | 'many' | 'other';
|
|
113
|
+
type BaseKey<K extends string> = K extends `${infer B}.${PluralForm}` ? B : K;
|
|
114
|
+
/** Every key a component may ask for: the English catalog's keys with the plural suffix taken off. */
|
|
115
|
+
export type PlayerText = BaseKey<keyof typeof en>;
|
|
116
|
+
export type PlayerParams = Readonly<Record<string, string | number>>;
|
|
117
|
+
/** The `t` the components take: a key and optional values, always a string back. */
|
|
118
|
+
export type PlayerT = (key: PlayerText, params?: PlayerParams) => string;
|
|
119
|
+
/**
|
|
120
|
+
* Builds the `t` function for a catalog and a locale.
|
|
121
|
+
* - `{name}` is replaced by `params.name`; a name with no value stays as written; a value is never expanded again.
|
|
122
|
+
* - Numbers are formatted for the locale (`1,234`).
|
|
123
|
+
* - With a numeric `count`, the plural form for the locale is used (`key.one`, `key.other`, ...), `key.zero` for 0 if it
|
|
124
|
+
* exists, and `key.other` when the locale's form is missing.
|
|
125
|
+
* - A key with no text comes back as the key itself, so a gap in a translation is visible instead of blank.
|
|
126
|
+
*/
|
|
127
|
+
export declare function createT(catalog: PlayerCatalog, locale?: string): PlayerT;
|
|
128
|
+
export {};
|
|
129
|
+
//# sourceMappingURL=i18n.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.d.ts","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAYA,eAAO,MAAM,EAAE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAmHL,CAAC;AAEX,sFAAsF;AACtF,MAAM,MAAM,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC;AAE7D,KAAK,UAAU,GAAG,MAAM,GAAG,KAAK,GAAG,KAAK,GAAG,KAAK,GAAG,MAAM,GAAG,OAAO,CAAC;AACpE,KAAK,OAAO,CAAC,CAAC,SAAS,MAAM,IAAI,CAAC,SAAS,GAAG,MAAM,CAAC,IAAI,UAAU,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC;AAE9E,sGAAsG;AACtG,MAAM,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,OAAO,EAAE,CAAC,CAAC;AAElD,MAAM,MAAM,YAAY,GAAG,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAC,CAAC,CAAC;AAErE,oFAAoF;AACpF,MAAM,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE,UAAU,EAAE,MAAM,CAAC,EAAE,YAAY,KAAK,MAAM,CAAC;AAIzE;;;;;;;GAOG;AACH,wBAAgB,OAAO,CAAC,OAAO,EAAE,aAAa,EAAE,MAAM,SAAO,GAAG,OAAO,CAiCtE"}
|
package/dist/src/i18n.js
ADDED
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Every word the player components show is a key in this catalog; components never hold English.
|
|
2
|
+
//
|
|
3
|
+
// Key naming: `player.<area>.<thing>[.<detail>]`, lower camel case segments, for example `player.notice.title.warning`.
|
|
4
|
+
// Areas: error, state, notice, notices, record, rules, restricted, report.
|
|
5
|
+
// Plural forms add the CLDR category as the last segment: `player.report.remaining.one`, `.other`. A caller asks for the base
|
|
6
|
+
// key with a numeric `count` (`t('player.report.remaining', { count: 3 })`); `.zero` is used for 0 when it exists.
|
|
7
|
+
// `{name}` marks a value to fill in. To translate, spread this catalog over yours so a missing key falls back to English:
|
|
8
|
+
// `createT({ ...en, ...de }, 'de')`.
|
|
9
|
+
//
|
|
10
|
+
// The copy is written for a player in the middle of a game: second person, sentence case, plain words, and never shaming. It says
|
|
11
|
+
// what happened, until when, and what the player can do.
|
|
12
|
+
export const en = {
|
|
13
|
+
'player.error.network': 'Could not reach the server. Check your connection and try again.',
|
|
14
|
+
'player.error.unauthorized': 'You are signed out. Sign in again, then try again.',
|
|
15
|
+
'player.error.forbidden': 'This account cannot do that.',
|
|
16
|
+
'player.error.notFound': 'That could not be found.',
|
|
17
|
+
'player.error.rateLimited': 'Too many requests. Try again in a moment.',
|
|
18
|
+
'player.error.rateLimited.after.one': 'Too many requests. Try again in {count} second.',
|
|
19
|
+
'player.error.rateLimited.after.other': 'Too many requests. Try again in {count} seconds.',
|
|
20
|
+
'player.error.server': 'The server had a problem. Try again in a moment.',
|
|
21
|
+
'player.error.generic': 'Something went wrong.',
|
|
22
|
+
'player.state.retry': 'Try again',
|
|
23
|
+
'player.notices.loadFailed': 'We could not check for notices.',
|
|
24
|
+
'player.notice.title.warning': 'You have a warning',
|
|
25
|
+
'player.notice.title.chat': 'Your chat is turned off',
|
|
26
|
+
'player.notice.title.area': 'You cannot join public rooms',
|
|
27
|
+
'player.notice.title.ban': 'You are banned',
|
|
28
|
+
'player.notice.title.report_outcome': 'Thanks for your report',
|
|
29
|
+
'player.notice.title.fallback': 'A message from the moderators',
|
|
30
|
+
'player.notice.body.warning': 'A moderator gave you a warning for something you wrote. You can keep playing.',
|
|
31
|
+
'player.notice.body.chat': 'A moderator turned off your chat. You can still play.',
|
|
32
|
+
'player.notice.body.area': 'A moderator stopped you joining public rooms and matchmaking. You can still play in private rooms.',
|
|
33
|
+
'player.notice.body.ban': 'A moderator banned you from playing.',
|
|
34
|
+
'player.notice.body.report_outcome': 'A moderator looked at your report and took action. We do not share what was done.',
|
|
35
|
+
'player.notice.body.fallback': 'There is a new message about your account.',
|
|
36
|
+
'player.notice.position': 'Notice {n} of {total}',
|
|
37
|
+
'player.notice.rule': 'Rule',
|
|
38
|
+
'player.notice.given': 'Given',
|
|
39
|
+
'player.notice.until': 'Until',
|
|
40
|
+
'player.notice.ended': 'Ended',
|
|
41
|
+
'player.notice.noEnd': 'No end date',
|
|
42
|
+
'player.notice.onRecordUntil': 'On your record until',
|
|
43
|
+
'player.notice.untilLeft': '{when} ({left})',
|
|
44
|
+
'player.notice.ref': 'Reference',
|
|
45
|
+
'player.notice.refHint': 'Quote this code if you contact us.',
|
|
46
|
+
'player.notice.lines': 'Your messages that led to this',
|
|
47
|
+
'player.notice.todo.warning': 'Press Acknowledge to confirm you saw this.',
|
|
48
|
+
'player.notice.acknowledge': 'Acknowledge',
|
|
49
|
+
'player.notice.gotIt': 'Got it',
|
|
50
|
+
'player.notice.appeal': 'Think this is a mistake?',
|
|
51
|
+
'player.notice.ackFailed': 'Your notice is still here.',
|
|
52
|
+
'player.notice.closeForNow': 'Close for now',
|
|
53
|
+
'player.record.title': 'Your record',
|
|
54
|
+
'player.record.loading': 'Loading your record',
|
|
55
|
+
'player.record.loadFailed': 'We could not load your record.',
|
|
56
|
+
'player.record.intro': 'This is what is on your record now. A warning stays for {days} days.',
|
|
57
|
+
'player.record.empty': 'Your record is clear. Nothing is on it right now.',
|
|
58
|
+
'player.record.kind.warning': 'Warning',
|
|
59
|
+
'player.record.kind.chat': 'Chat restriction',
|
|
60
|
+
'player.record.kind.area': 'Public rooms restriction',
|
|
61
|
+
'player.record.kind.ban': 'Ban',
|
|
62
|
+
'player.record.kind.fallback': 'Notice',
|
|
63
|
+
'player.rules.title': 'Community rules',
|
|
64
|
+
'player.rules.loading': 'Loading the rules',
|
|
65
|
+
'player.rules.loadFailed': 'We could not load the rules.',
|
|
66
|
+
'player.rules.empty': 'No rules are published yet.',
|
|
67
|
+
'player.restricted.moderator.until': 'A moderator turned off your chat until {when} ({left}).',
|
|
68
|
+
'player.restricted.moderator.noEnd': 'A moderator turned off your chat. It does not end on its own.',
|
|
69
|
+
'player.restricted.filter.until': 'Your chat is off until {when} ({left}). The automatic filter caught a message.',
|
|
70
|
+
'player.restricted.filter.noEnd': 'Your chat is off. It does not end on its own. The automatic filter caught a message.',
|
|
71
|
+
'player.restricted.ended': 'Your chat is back on. The restriction ended {when}.',
|
|
72
|
+
'player.restricted.ref': 'Reference {code}',
|
|
73
|
+
'player.report.title': 'Report a player',
|
|
74
|
+
'player.report.titleNamed': 'Report {name}',
|
|
75
|
+
'player.report.intro': 'Tell us what happened and a moderator will look at it.',
|
|
76
|
+
'player.report.legend': 'What happened?',
|
|
77
|
+
'player.report.titleOneTap': 'Report this message?',
|
|
78
|
+
'player.report.titleOneTapNamed': 'Report {name}?',
|
|
79
|
+
'player.report.titleOneTapPlayer': 'Report this player?',
|
|
80
|
+
'player.report.titleSent': 'Report sent',
|
|
81
|
+
'player.report.titleRefused': "Couldn't send the report",
|
|
82
|
+
'player.report.oneTap.intro': 'We will pass it to the moderators. You do not need to say why.',
|
|
83
|
+
'player.report.oneTap.send': 'Report',
|
|
84
|
+
'player.report.quote': '“{line}”',
|
|
85
|
+
'player.report.skip': 'Skip and report',
|
|
86
|
+
'player.report.needReason': 'Choose a reason.',
|
|
87
|
+
'player.report.needReasonOrSkip': 'Choose what happened, or skip.',
|
|
88
|
+
'player.report.addReason': 'Add a reason',
|
|
89
|
+
'player.report.addReasonHint': 'This helps, but the moderators decide what it really is. You can add this for a few minutes after you report.',
|
|
90
|
+
'player.report.detail.legend': 'What was it about?',
|
|
91
|
+
'player.report.detail.send': 'Add to my report',
|
|
92
|
+
'player.report.detail.need': 'Choose a reason or write a note.',
|
|
93
|
+
'player.report.detail.added': 'Added. Thanks.',
|
|
94
|
+
'player.report.detail.failed': 'We could not add that.',
|
|
95
|
+
'player.report.detail.refused.off': 'Adding to a report is not available right now.',
|
|
96
|
+
'player.report.detail.refused.not_found': 'We cannot find that report any more.',
|
|
97
|
+
'player.report.detail.refused.not_reporter': 'Only the player who sent a report can add to it.',
|
|
98
|
+
'player.report.detail.refused.too_late': 'It is too late to add to this report. We still have the report.',
|
|
99
|
+
'player.report.detail.refused.already_added': 'You already added to this report.',
|
|
100
|
+
'player.report.detail.refused.reason_unknown': 'That reason is not available any more. Your report is still with us.',
|
|
101
|
+
'player.report.note': 'Add a note (optional)',
|
|
102
|
+
'player.report.noteHint': 'A moderator will read this. Up to {max} characters. Do not include passwords or personal details.',
|
|
103
|
+
'player.report.send': 'Send report',
|
|
104
|
+
'player.report.cancel': 'Cancel',
|
|
105
|
+
'player.report.close': 'Close',
|
|
106
|
+
'player.report.failed': 'Your report was not sent.',
|
|
107
|
+
'player.report.thanks': 'Thanks. We got your report.',
|
|
108
|
+
'player.report.remaining.zero': 'You have no more reports left today.',
|
|
109
|
+
'player.report.remaining.one': 'You can send {count} more report today.',
|
|
110
|
+
'player.report.remaining.other': 'You can send {count} more reports today.',
|
|
111
|
+
'player.report.refused.duplicate': 'You already reported this player here. We have your report.',
|
|
112
|
+
'player.report.refused.rate': 'You have sent as many reports as you can today. You can send more tomorrow.',
|
|
113
|
+
'player.report.refused.self': 'You cannot report yourself.',
|
|
114
|
+
'player.report.refused.not_player': 'We cannot find that player any more. They may have left.',
|
|
115
|
+
'player.report.refused.off': 'Reports are not available right now. Try again later.',
|
|
116
|
+
'player.report.refused.suspended': 'You cannot send reports from this account for now.',
|
|
117
|
+
'player.report.refused.reason_required': 'This report needs a reason. Close this and report again to choose one.',
|
|
118
|
+
'player.report.refused.reason_unknown': 'That reason is not available any more. Close this and report again.',
|
|
119
|
+
'player.report.refused.unknown': 'We could not take that report.',
|
|
120
|
+
};
|
|
121
|
+
const isCount = (v) => typeof v === 'number' && Number.isFinite(v);
|
|
122
|
+
/**
|
|
123
|
+
* Builds the `t` function for a catalog and a locale.
|
|
124
|
+
* - `{name}` is replaced by `params.name`; a name with no value stays as written; a value is never expanded again.
|
|
125
|
+
* - Numbers are formatted for the locale (`1,234`).
|
|
126
|
+
* - With a numeric `count`, the plural form for the locale is used (`key.one`, `key.other`, ...), `key.zero` for 0 if it
|
|
127
|
+
* exists, and `key.other` when the locale's form is missing.
|
|
128
|
+
* - A key with no text comes back as the key itself, so a gap in a translation is visible instead of blank.
|
|
129
|
+
*/
|
|
130
|
+
export function createT(catalog, locale = 'en') {
|
|
131
|
+
let numbers;
|
|
132
|
+
let plurals;
|
|
133
|
+
try {
|
|
134
|
+
numbers = new Intl.NumberFormat(locale);
|
|
135
|
+
plurals = new Intl.PluralRules(locale);
|
|
136
|
+
}
|
|
137
|
+
catch {
|
|
138
|
+
numbers = new Intl.NumberFormat('en');
|
|
139
|
+
plurals = new Intl.PluralRules('en');
|
|
140
|
+
}
|
|
141
|
+
const has = (key) => Object.hasOwn(catalog, key);
|
|
142
|
+
return (key, params) => {
|
|
143
|
+
let template;
|
|
144
|
+
const count = params?.count;
|
|
145
|
+
if (isCount(count)) {
|
|
146
|
+
const form = count === 0 && has(`${key}.zero`) ? 'zero' : plurals.select(count);
|
|
147
|
+
for (const candidate of [`${key}.${form}`, `${key}.other`]) {
|
|
148
|
+
if (has(candidate)) {
|
|
149
|
+
template = catalog[candidate];
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
template ??= has(key) ? catalog[key] : undefined;
|
|
155
|
+
if (template === undefined)
|
|
156
|
+
return key;
|
|
157
|
+
if (params === undefined)
|
|
158
|
+
return template;
|
|
159
|
+
return template.replace(/\{([a-zA-Z]+)\}/g, (whole, name) => {
|
|
160
|
+
if (!Object.hasOwn(params, name))
|
|
161
|
+
return whole;
|
|
162
|
+
const value = params[name];
|
|
163
|
+
return typeof value === 'number' ? numbers.format(value) : String(value);
|
|
164
|
+
});
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
//# sourceMappingURL=i18n.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"i18n.js","sourceRoot":"","sources":["../../src/i18n.ts"],"names":[],"mappings":"AAAA,iGAAiG;AACjG,EAAE;AACF,wHAAwH;AACxH,2EAA2E;AAC3E,8HAA8H;AAC9H,mHAAmH;AACnH,0HAA0H;AAC1H,qCAAqC;AACrC,EAAE;AACF,kIAAkI;AAClI,yDAAyD;AAEzD,MAAM,CAAC,MAAM,EAAE,GAAG;IAChB,sBAAsB,EAAE,kEAAkE;IAC1F,2BAA2B,EAAE,oDAAoD;IACjF,wBAAwB,EAAE,8BAA8B;IACxD,uBAAuB,EAAE,0BAA0B;IACnD,0BAA0B,EAAE,2CAA2C;IACvE,oCAAoC,EAAE,iDAAiD;IACvF,sCAAsC,EAAE,kDAAkD;IAC1F,qBAAqB,EAAE,kDAAkD;IACzE,sBAAsB,EAAE,uBAAuB;IAE/C,oBAAoB,EAAE,WAAW;IAEjC,2BAA2B,EAAE,iCAAiC;IAE9D,6BAA6B,EAAE,oBAAoB;IACnD,0BAA0B,EAAE,yBAAyB;IACrD,0BAA0B,EAAE,8BAA8B;IAC1D,yBAAyB,EAAE,gBAAgB;IAC3C,oCAAoC,EAAE,wBAAwB;IAC9D,8BAA8B,EAAE,+BAA+B;IAC/D,4BAA4B,EAAE,+EAA+E;IAC7G,yBAAyB,EAAE,uDAAuD;IAClF,yBAAyB,EAAE,oGAAoG;IAC/H,wBAAwB,EAAE,sCAAsC;IAChE,mCAAmC,EAAE,mFAAmF;IACxH,6BAA6B,EAAE,4CAA4C;IAC3E,wBAAwB,EAAE,uBAAuB;IACjD,oBAAoB,EAAE,MAAM;IAC5B,qBAAqB,EAAE,OAAO;IAC9B,qBAAqB,EAAE,OAAO;IAC9B,qBAAqB,EAAE,OAAO;IAC9B,qBAAqB,EAAE,aAAa;IACpC,6BAA6B,EAAE,sBAAsB;IACrD,yBAAyB,EAAE,iBAAiB;IAC5C,mBAAmB,EAAE,WAAW;IAChC,uBAAuB,EAAE,oCAAoC;IAC7D,qBAAqB,EAAE,gCAAgC;IACvD,4BAA4B,EAAE,4CAA4C;IAC1E,2BAA2B,EAAE,aAAa;IAC1C,qBAAqB,EAAE,QAAQ;IAC/B,sBAAsB,EAAE,0BAA0B;IAClD,yBAAyB,EAAE,4BAA4B;IACvD,2BAA2B,EAAE,eAAe;IAE5C,qBAAqB,EAAE,aAAa;IACpC,uBAAuB,EAAE,qBAAqB;IAC9C,0BAA0B,EAAE,gCAAgC;IAC5D,qBAAqB,EAAE,sEAAsE;IAC7F,qBAAqB,EAAE,mDAAmD;IAC1E,4BAA4B,EAAE,SAAS;IACvC,yBAAyB,EAAE,kBAAkB;IAC7C,yBAAyB,EAAE,0BAA0B;IACrD,wBAAwB,EAAE,KAAK;IAC/B,6BAA6B,EAAE,QAAQ;IAEvC,oBAAoB,EAAE,iBAAiB;IACvC,sBAAsB,EAAE,mBAAmB;IAC3C,yBAAyB,EAAE,8BAA8B;IACzD,oBAAoB,EAAE,6BAA6B;IAEnD,mCAAmC,EAAE,yDAAyD;IAC9F,mCAAmC,EAAE,+DAA+D;IACpG,gCAAgC,EAAE,gFAAgF;IAClH,gCAAgC,EAAE,sFAAsF;IACxH,yBAAyB,EAAE,qDAAqD;IAChF,uBAAuB,EAAE,kBAAkB;IAE3C,qBAAqB,EAAE,iBAAiB;IACxC,0BAA0B,EAAE,eAAe;IAC3C,qBAAqB,EAAE,wDAAwD;IAC/E,sBAAsB,EAAE,gBAAgB;IACxC,2BAA2B,EAAE,sBAAsB;IACnD,gCAAgC,EAAE,gBAAgB;IAClD,iCAAiC,EAAE,qBAAqB;IACxD,yBAAyB,EAAE,aAAa;IACxC,4BAA4B,EAAE,0BAA0B;IACxD,4BAA4B,EAAE,gEAAgE;IAC9F,2BAA2B,EAAE,QAAQ;IACrC,qBAAqB,EAAE,UAAU;IACjC,oBAAoB,EAAE,iBAAiB;IACvC,0BAA0B,EAAE,kBAAkB;IAC9C,gCAAgC,EAAE,gCAAgC;IAClE,yBAAyB,EAAE,cAAc;IACzC,6BAA6B,EAAE,+GAA+G;IAC9I,6BAA6B,EAAE,oBAAoB;IACnD,2BAA2B,EAAE,kBAAkB;IAC/C,2BAA2B,EAAE,kCAAkC;IAC/D,4BAA4B,EAAE,gBAAgB;IAC9C,6BAA6B,EAAE,wBAAwB;IACvD,kCAAkC,EAAE,gDAAgD;IACpF,wCAAwC,EAAE,sCAAsC;IAChF,2CAA2C,EAAE,kDAAkD;IAC/F,uCAAuC,EAAE,iEAAiE;IAC1G,4CAA4C,EAAE,mCAAmC;IACjF,6CAA6C,EAAE,sEAAsE;IACrH,oBAAoB,EAAE,uBAAuB;IAC7C,wBAAwB,EAAE,mGAAmG;IAC7H,oBAAoB,EAAE,aAAa;IACnC,sBAAsB,EAAE,QAAQ;IAChC,qBAAqB,EAAE,OAAO;IAC9B,sBAAsB,EAAE,2BAA2B;IACnD,sBAAsB,EAAE,6BAA6B;IACrD,8BAA8B,EAAE,sCAAsC;IACtE,6BAA6B,EAAE,yCAAyC;IACxE,+BAA+B,EAAE,0CAA0C;IAC3E,iCAAiC,EAAE,6DAA6D;IAChG,4BAA4B,EAAE,6EAA6E;IAC3G,4BAA4B,EAAE,6BAA6B;IAC3D,kCAAkC,EAAE,0DAA0D;IAC9F,2BAA2B,EAAE,uDAAuD;IACpF,iCAAiC,EAAE,oDAAoD;IACvF,uCAAuC,EAAE,wEAAwE;IACjH,sCAAsC,EAAE,qEAAqE;IAC7G,+BAA+B,EAAE,gCAAgC;CACzD,CAAC;AAgBX,MAAM,OAAO,GAAG,CAAC,CAAU,EAAe,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC;AAEzF;;;;;;;GAOG;AACH,MAAM,UAAU,OAAO,CAAC,OAAsB,EAAE,MAAM,GAAG,IAAI;IAC3D,IAAI,OAA0B,CAAC;IAC/B,IAAI,OAAyB,CAAC;IAC9B,IAAI,CAAC;QACH,OAAO,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QACxC,OAAO,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,CAAC;IACzC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,GAAG,IAAI,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;QACtC,OAAO,GAAG,IAAI,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IACvC,CAAC;IACD,MAAM,GAAG,GAAG,CAAC,GAAW,EAAW,EAAE,CAAC,MAAM,CAAC,MAAM,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC;IAElE,OAAO,CAAC,GAAG,EAAE,MAAM,EAAE,EAAE;QACrB,IAAI,QAA4B,CAAC;QACjC,MAAM,KAAK,GAAG,MAAM,EAAE,KAAK,CAAC;QAC5B,IAAI,OAAO,CAAC,KAAK,CAAC,EAAE,CAAC;YACnB,MAAM,IAAI,GAAG,KAAK,KAAK,CAAC,IAAI,GAAG,CAAC,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;YAChF,KAAK,MAAM,SAAS,IAAI,CAAC,GAAG,GAAG,IAAI,IAAI,EAAE,EAAE,GAAG,GAAG,QAAQ,CAAC,EAAE,CAAC;gBAC3D,IAAI,GAAG,CAAC,SAAS,CAAC,EAAE,CAAC;oBACnB,QAAQ,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC;oBAC9B,MAAM;gBACR,CAAC;YACH,CAAC;QACH,CAAC;QACD,QAAQ,KAAK,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QACjD,IAAI,QAAQ,KAAK,SAAS;YAAE,OAAO,GAAG,CAAC;QACvC,IAAI,MAAM,KAAK,SAAS;YAAE,OAAO,QAAQ,CAAC;QAC1C,OAAO,QAAQ,CAAC,OAAO,CAAC,kBAAkB,EAAE,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;YAClE,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,MAAM,EAAE,IAAI,CAAC;gBAAE,OAAO,KAAK,CAAC;YAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC;YAC3B,OAAO,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;QAC3E,CAAC,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export declare const VERSION = "0.1.2";
|
|
2
|
+
export { NoticeQueue } from './NoticeQueue.js';
|
|
3
|
+
export type { NoticeQueueProps } from './NoticeQueue.js';
|
|
4
|
+
export { MyRecord } from './MyRecord.js';
|
|
5
|
+
export type { MyRecordProps } from './MyRecord.js';
|
|
6
|
+
export { RulesPage } from './RulesPage.js';
|
|
7
|
+
export type { RulesPageProps } from './RulesPage.js';
|
|
8
|
+
export { ReportDialog } from './ReportDialog.js';
|
|
9
|
+
export type { ReportFollowUp, ReportDialogProps, ReportDraft } from './ReportDialog.js';
|
|
10
|
+
export { RestrictedChatLine } from './RestrictedChatLine.js';
|
|
11
|
+
export type { RestrictedChatLineProps } from './RestrictedChatLine.js';
|
|
12
|
+
export { createPlayerClient, PlayerError, toPlayerError } from './client.js';
|
|
13
|
+
export type { PlayerClient, PlayerClientOptions, PlayerRule, PlayerRules } from './client.js';
|
|
14
|
+
export { fetchTransport, routerTransport } from './transport.js';
|
|
15
|
+
export type { FetchTransportOptions, RouterRequest, RouterResponse, RouterTransportOptions, Transport, TransportRequest, TransportResponse, } from './transport.js';
|
|
16
|
+
export { createT, en } from './i18n.js';
|
|
17
|
+
export type { PlayerCatalog, PlayerParams, PlayerT, PlayerText } from './i18n.js';
|
|
18
|
+
export type { PlayerUiProps } from './ui.js';
|
|
19
|
+
export { dayText, timeLeft, untilText } from './format.js';
|
|
20
|
+
export type { NoticeKind, PlayerNotice, PlayerReporting, ReportDetailResult, ReportFlow, ReportRefusal, ReportResult } from '@chatwarden/core';
|
|
21
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,OAAO,UAAU,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAC/C,YAAY,EAAE,gBAAgB,EAAE,MAAM,kBAAkB,CAAC;AACzD,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AACzC,YAAY,EAAE,aAAa,EAAE,MAAM,eAAe,CAAC;AACnD,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAC3C,YAAY,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AACrD,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AACjD,YAAY,EAAE,cAAc,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACxF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAC7D,YAAY,EAAE,uBAAuB,EAAE,MAAM,yBAAyB,CAAC;AAEvE,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC7E,YAAY,EAAE,YAAY,EAAE,mBAAmB,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAC9F,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AACjE,YAAY,EACV,qBAAqB,EACrB,aAAa,EACb,cAAc,EACd,sBAAsB,EACtB,SAAS,EACT,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,gBAAgB,CAAC;AAExB,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AACxC,YAAY,EAAE,aAAa,EAAE,YAAY,EAAE,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AAClF,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AAE3D,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,eAAe,EAAE,kBAAkB,EAAE,UAAU,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,kBAAkB,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export const VERSION = '0.1.2';
|
|
2
|
+
export { NoticeQueue } from './NoticeQueue.js';
|
|
3
|
+
export { MyRecord } from './MyRecord.js';
|
|
4
|
+
export { RulesPage } from './RulesPage.js';
|
|
5
|
+
export { ReportDialog } from './ReportDialog.js';
|
|
6
|
+
export { RestrictedChatLine } from './RestrictedChatLine.js';
|
|
7
|
+
export { createPlayerClient, PlayerError, toPlayerError } from './client.js';
|
|
8
|
+
export { fetchTransport, routerTransport } from './transport.js';
|
|
9
|
+
export { createT, en } from './i18n.js';
|
|
10
|
+
export { dayText, timeLeft, untilText } from './format.js';
|
|
11
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,OAAO,GAAG,OAAO,CAAC;AAE/B,OAAO,EAAE,WAAW,EAAE,MAAM,kBAAkB,CAAC;AAE/C,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC,OAAO,EAAE,SAAS,EAAE,MAAM,gBAAgB,CAAC;AAE3C,OAAO,EAAE,YAAY,EAAE,MAAM,mBAAmB,CAAC;AAEjD,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE7E,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,gBAAgB,CAAC;AAWjE,OAAO,EAAE,OAAO,EAAE,EAAE,EAAE,MAAM,WAAW,CAAC;AAGxC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { PlayerReporting } from '@chatwarden/core';
|
|
2
|
+
/**
|
|
3
|
+
* The reporting payload of `GET /rules` as the dialog may rely on it. Anything that is not the documented shape is dropped: a
|
|
4
|
+
* reason needs a text id and label; the hint and group default to `''` and `asksNote` to false; an unknown flow is `one_tap` (the
|
|
5
|
+
* default); a field the server should not send (a rule mapping, an enabled flag) is never copied. `undefined` when there is no
|
|
6
|
+
* list of reasons at all (an older server, or something that is not the payload).
|
|
7
|
+
*/
|
|
8
|
+
export declare function readReporting(raw: unknown): PlayerReporting | undefined;
|
|
9
|
+
export type ReasonItem = PlayerReporting['reasons'][number];
|
|
10
|
+
/** A heading (`''` for none) and the reasons under it. */
|
|
11
|
+
export interface ReasonGroup {
|
|
12
|
+
name: string;
|
|
13
|
+
items: ReasonItem[];
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* The reasons grouped for the screen: a group is where its first reason is in the list, "Something else" (`other`) is always
|
|
17
|
+
* last, and a group with no name has no heading.
|
|
18
|
+
*/
|
|
19
|
+
export declare function groupReasons(reasons: readonly ReasonItem[]): ReasonGroup[];
|
|
20
|
+
//# sourceMappingURL=reporting.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporting.d.ts","sourceRoot":"","sources":["../../src/reporting.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAc,MAAM,kBAAkB,CAAC;AAOpE;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,eAAe,GAAG,SAAS,CAQvE;AAED,MAAM,MAAM,UAAU,GAAG,eAAe,CAAC,SAAS,CAAC,CAAC,MAAM,CAAC,CAAC;AAE5D,0DAA0D;AAC1D,MAAM,WAAW,WAAW;IAC1B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,UAAU,EAAE,CAAC;CACrB;AAED;;;GAGG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,SAAS,UAAU,EAAE,GAAG,WAAW,EAAE,CAe1E"}
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const FLOWS = ['one_tap', 'reason_first', 'reason_required'];
|
|
2
|
+
const isObject = (v) => typeof v === 'object' && v !== null && !Array.isArray(v);
|
|
3
|
+
const text = (v) => typeof v === 'string';
|
|
4
|
+
/**
|
|
5
|
+
* The reporting payload of `GET /rules` as the dialog may rely on it. Anything that is not the documented shape is dropped: a
|
|
6
|
+
* reason needs a text id and label; the hint and group default to `''` and `asksNote` to false; an unknown flow is `one_tap` (the
|
|
7
|
+
* default); a field the server should not send (a rule mapping, an enabled flag) is never copied. `undefined` when there is no
|
|
8
|
+
* list of reasons at all (an older server, or something that is not the payload).
|
|
9
|
+
*/
|
|
10
|
+
export function readReporting(raw) {
|
|
11
|
+
if (!isObject(raw) || !Array.isArray(raw.reasons))
|
|
12
|
+
return undefined;
|
|
13
|
+
const reasons = raw.reasons
|
|
14
|
+
.filter(isObject)
|
|
15
|
+
.filter((r) => text(r.id) && r.id !== '' && text(r.label) && r.label !== '')
|
|
16
|
+
.map((r) => ({ id: r.id, label: r.label, hint: text(r.hint) ? r.hint : '', group: text(r.group) ? r.group : '', asksNote: r.asksNote === true }));
|
|
17
|
+
const flow = FLOWS.find((f) => f === raw.flow) ?? 'one_tap';
|
|
18
|
+
return { flow, reasons, thanks: text(raw.thanks) ? raw.thanks : '' };
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* The reasons grouped for the screen: a group is where its first reason is in the list, "Something else" (`other`) is always
|
|
22
|
+
* last, and a group with no name has no heading.
|
|
23
|
+
*/
|
|
24
|
+
export function groupReasons(reasons) {
|
|
25
|
+
const groups = [];
|
|
26
|
+
for (const r of reasons) {
|
|
27
|
+
if (r.id === 'other')
|
|
28
|
+
continue;
|
|
29
|
+
const into = groups.find((g) => g.name === r.group);
|
|
30
|
+
if (into === undefined)
|
|
31
|
+
groups.push({ name: r.group, items: [r] });
|
|
32
|
+
else
|
|
33
|
+
into.items.push(r);
|
|
34
|
+
}
|
|
35
|
+
const other = reasons.find((r) => r.id === 'other');
|
|
36
|
+
if (other !== undefined) {
|
|
37
|
+
const last = groups.at(-1);
|
|
38
|
+
if (last !== undefined && last.name === '')
|
|
39
|
+
last.items.push(other);
|
|
40
|
+
else
|
|
41
|
+
groups.push({ name: '', items: [other] });
|
|
42
|
+
}
|
|
43
|
+
return groups;
|
|
44
|
+
}
|
|
45
|
+
//# sourceMappingURL=reporting.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"reporting.js","sourceRoot":"","sources":["../../src/reporting.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
/** Whether an address may become a link: `https:` (with a host), or a relative address on this site. */
|
|
2
|
+
export declare function isSafeHref(href: string): boolean;
|
|
3
|
+
/** The address for an appeal link (trimmed), or null when it is not safe to link to. `http:` is refused: https only. */
|
|
4
|
+
export declare function safeHref(url: string | undefined): string | null;
|
|
5
|
+
//# sourceMappingURL=safeHref.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeHref.d.ts","sourceRoot":"","sources":["../../src/safeHref.ts"],"names":[],"mappings":"AAWA,wGAAwG;AACxG,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAiBhD;AAED,wHAAwH;AACxH,wBAAgB,QAAQ,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,GAAG,IAAI,CAG/D"}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
// The rule for a link address, copied from `@chatwarden/hub-react` (its `isSafeHref`, which guards links in policy documents).
|
|
2
|
+
// The two packages never import each other, so this is a copy; test/safe-href.test.ts runs both on one table.
|
|
3
|
+
function hasControlOrSpace(text) {
|
|
4
|
+
for (const ch of text) {
|
|
5
|
+
const c = ch.codePointAt(0);
|
|
6
|
+
if (c <= 0x20 || (c >= 0x7f && c <= 0x9f))
|
|
7
|
+
return true;
|
|
8
|
+
}
|
|
9
|
+
return false;
|
|
10
|
+
}
|
|
11
|
+
/** Whether an address may become a link: `https:` (with a host), or a relative address on this site. */
|
|
12
|
+
export function isSafeHref(href) {
|
|
13
|
+
// A control character or space inside an address is how `java\tscript:` slips past a scheme check: refuse them all.
|
|
14
|
+
const s = href.trim();
|
|
15
|
+
if (s === '' || hasControlOrSpace(s) || /\s/u.test(s))
|
|
16
|
+
return false;
|
|
17
|
+
// A browser reads `\` as `/`, so `/\evil.example` is `//evil.example`, a different site: refuse a backslash anywhere, and a
|
|
18
|
+
// slash that is followed by another slash or by anything that could be read as one.
|
|
19
|
+
if (s.includes('\\') || /^\/[\s/]/u.test(s))
|
|
20
|
+
return false;
|
|
21
|
+
// An address that carries an entity is not one an adopter wrote: refuse.
|
|
22
|
+
if (/&#?\w+;/.test(s))
|
|
23
|
+
return false;
|
|
24
|
+
const scheme = /^([^/?#]*):/.exec(s);
|
|
25
|
+
if (scheme === null)
|
|
26
|
+
return true;
|
|
27
|
+
try {
|
|
28
|
+
const url = new URL(s);
|
|
29
|
+
return url.protocol === 'https:' && url.hostname !== '';
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
return false;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
/** The address for an appeal link (trimmed), or null when it is not safe to link to. `http:` is refused: https only. */
|
|
36
|
+
export function safeHref(url) {
|
|
37
|
+
if (typeof url !== 'string')
|
|
38
|
+
return null;
|
|
39
|
+
return isSafeHref(url) ? url.trim() : null;
|
|
40
|
+
}
|
|
41
|
+
//# sourceMappingURL=safeHref.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"safeHref.js","sourceRoot":"","sources":["../../src/safeHref.ts"],"names":[],"mappings":"AAAA,+HAA+H;AAC/H,8GAA8G;AAE9G,SAAS,iBAAiB,CAAC,IAAY;IACrC,KAAK,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC;QACtB,MAAM,CAAC,GAAG,EAAE,CAAC,WAAW,CAAC,CAAC,CAAW,CAAC;QACtC,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC;YAAE,OAAO,IAAI,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,wGAAwG;AACxG,MAAM,UAAU,UAAU,CAAC,IAAY;IACrC,oHAAoH;IACpH,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;IACtB,IAAI,CAAC,KAAK,EAAE,IAAI,iBAAiB,CAAC,CAAC,CAAC,IAAI,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpE,4HAA4H;IAC5H,oFAAoF;IACpF,IAAI,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,IAAI,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IAC1D,yEAAyE;IACzE,IAAI,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,MAAM,GAAG,aAAa,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;IACrC,IAAI,MAAM,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IACjC,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC;QACvB,OAAO,GAAG,CAAC,QAAQ,KAAK,QAAQ,IAAI,GAAG,CAAC,QAAQ,KAAK,EAAE,CAAC;IAC1D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,KAAK,CAAC;IACf,CAAC;AACH,CAAC;AAED,wHAAwH;AACxH,MAAM,UAAU,QAAQ,CAAC,GAAuB;IAC9C,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,IAAI,CAAC;IACzC,OAAO,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;AAC7C,CAAC"}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* One call to the player routes. `path` is the route path with no prefix (`/notices`); the transport adds whatever prefix its
|
|
3
|
+
* server uses. `query` values that are `undefined` are left out. `body` is sent as JSON.
|
|
4
|
+
*
|
|
5
|
+
* This is the same shape `@chatwarden/hub-react` uses for the staff routes. It is written out here so this package does not
|
|
6
|
+
* depend on that one; a test keeps the two assignable to each other.
|
|
7
|
+
*/
|
|
8
|
+
export interface TransportRequest {
|
|
9
|
+
method: string;
|
|
10
|
+
path: string;
|
|
11
|
+
query?: Record<string, string | number | undefined>;
|
|
12
|
+
body?: unknown;
|
|
13
|
+
/** Lets the caller abandon the call (fetch only; the in-page router answers at once). */
|
|
14
|
+
signal?: AbortSignal;
|
|
15
|
+
/** Lets the call finish after the page is gone (fetch `keepalive`). Ignored by the in-page router. */
|
|
16
|
+
keepalive?: boolean;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* What came back: any HTTP status is an answer, not an error. `headers` are lower-case. `body` is the parsed JSON, a string
|
|
20
|
+
* for a text document, or null when there was none.
|
|
21
|
+
*/
|
|
22
|
+
export interface TransportResponse {
|
|
23
|
+
status: number;
|
|
24
|
+
headers: Record<string, string>;
|
|
25
|
+
body: unknown;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* How the components reach the player routes. It resolves with the response whatever the status, and rejects only when no
|
|
29
|
+
* answer arrived (a dropped connection, a handler that threw); the client turns that into a `network` error.
|
|
30
|
+
*/
|
|
31
|
+
export type Transport = (req: TransportRequest) => Promise<TransportResponse>;
|
|
32
|
+
/** What `routerTransport` sends to a `createRouter(...)` handler: the kit's `KitRequest`, written out structurally. */
|
|
33
|
+
export interface RouterRequest {
|
|
34
|
+
method: string;
|
|
35
|
+
path: string;
|
|
36
|
+
query: Record<string, string>;
|
|
37
|
+
headers: Record<string, string>;
|
|
38
|
+
body: undefined;
|
|
39
|
+
rawBody?: string;
|
|
40
|
+
}
|
|
41
|
+
/** What a `createRouter(...)` handler answers: the kit's `KitResponse`, written out structurally. */
|
|
42
|
+
export interface RouterResponse {
|
|
43
|
+
status: number;
|
|
44
|
+
headers?: Record<string, string>;
|
|
45
|
+
body: unknown;
|
|
46
|
+
}
|
|
47
|
+
export interface RouterTransportOptions {
|
|
48
|
+
/** Sent with every request, for an `identify` hook that reads a header. */
|
|
49
|
+
headers?: Record<string, string>;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* A transport that calls `createRouter(playerRoutes(...))` directly, in the same process: no network. A demo and this
|
|
53
|
+
* package's tests use it, so the components run the real player routes. A response body goes through JSON on the way out, so
|
|
54
|
+
* the components see exactly what a fetch would deliver.
|
|
55
|
+
*/
|
|
56
|
+
export declare function routerTransport(handle: (req: RouterRequest) => Promise<RouterResponse>, options?: RouterTransportOptions): Transport;
|
|
57
|
+
export interface FetchTransportOptions {
|
|
58
|
+
/** Where the player routes are mounted: `https://host/player` or `/player`. No trailing slash needed. */
|
|
59
|
+
baseUrl: string;
|
|
60
|
+
/** Sent with every request (a session token, for example). */
|
|
61
|
+
headers?: Record<string, string>;
|
|
62
|
+
/** `include` sends cookies to another origin. Default: the browser's (`same-origin`). */
|
|
63
|
+
credentials?: RequestCredentials;
|
|
64
|
+
/** For tests, or a polyfill. Default: the global `fetch`. */
|
|
65
|
+
fetch?: typeof fetch;
|
|
66
|
+
}
|
|
67
|
+
/** The default transport for a real game: `fetch` against the routes your server mounts. */
|
|
68
|
+
export declare function fetchTransport(options: FetchTransportOptions): Transport;
|
|
69
|
+
//# sourceMappingURL=transport.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/transport.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,WAAW,gBAAgB;IAC/B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAAC,CAAC;IACpD,IAAI,CAAC,EAAE,OAAO,CAAC;IACf,yFAAyF;IACzF,MAAM,CAAC,EAAE,WAAW,CAAC;IACrB,sGAAsG;IACtG,SAAS,CAAC,EAAE,OAAO,CAAC;CACrB;AAED;;;GAGG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,OAAO,CAAC;CACf;AAED;;;GAGG;AACH,MAAM,MAAM,SAAS,GAAG,CAAC,GAAG,EAAE,gBAAgB,KAAK,OAAO,CAAC,iBAAiB,CAAC,CAAC;AAE9E,uHAAuH;AACvH,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,qGAAqG;AACrG,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,IAAI,EAAE,OAAO,CAAC;CACf;AAeD,MAAM,WAAW,sBAAsB;IACrC,2EAA2E;IAC3E,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAClC;AAED;;;;GAIG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,aAAa,KAAK,OAAO,CAAC,cAAc,CAAC,EAAE,OAAO,GAAE,sBAA2B,GAAG,SAAS,CAexI;AAED,MAAM,WAAW,qBAAqB;IACpC,yGAAyG;IACzG,OAAO,EAAE,MAAM,CAAC;IAChB,8DAA8D;IAC9D,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,yFAAyF;IACzF,WAAW,CAAC,EAAE,kBAAkB,CAAC;IACjC,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACtB;AAED,4FAA4F;AAC5F,wBAAgB,cAAc,CAAC,OAAO,EAAE,qBAAqB,GAAG,SAAS,CA8BxE"}
|