@forthtilliath/react-native-kit 0.17.1 → 0.19.0
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/README.md +54 -15
- package/dist/components/picker/PhotoPicker.d.ts +16 -29
- package/dist/components/picker/PhotoPicker.d.ts.map +1 -1
- package/dist/components/picker/PhotoPicker.js +48 -81
- package/dist/components/picker/PhotoPicker.styles.d.ts +63 -0
- package/dist/components/picker/PhotoPicker.styles.d.ts.map +1 -0
- package/dist/components/picker/PhotoPicker.styles.js +59 -0
- package/dist/components/picker/QuantityStepper.d.ts +38 -29
- package/dist/components/picker/QuantityStepper.d.ts.map +1 -1
- package/dist/components/picker/QuantityStepper.js +101 -74
- package/dist/components/picker/QuantityStepper.styles.d.ts +59 -0
- package/dist/components/picker/QuantityStepper.styles.d.ts.map +1 -0
- package/dist/components/picker/QuantityStepper.styles.js +46 -0
- package/dist/components/settings/UpdateSettingsScreen.d.ts +5 -1
- package/dist/components/settings/UpdateSettingsScreen.d.ts.map +1 -1
- package/dist/components/settings/UpdateSettingsScreen.js +3 -3
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts +2 -0
- package/dist/components/settings/UpdateSettingsScreen.styles.d.ts.map +1 -1
- package/dist/components/theme/BackgroundPicker.d.ts +46 -0
- package/dist/components/theme/BackgroundPicker.d.ts.map +1 -0
- package/dist/components/theme/BackgroundPicker.js +79 -0
- package/dist/components/theme/findBackground.d.ts +20 -0
- package/dist/components/theme/findBackground.d.ts.map +1 -0
- package/dist/components/theme/findBackground.js +12 -0
- package/dist/components/theme/index.d.ts +2 -0
- package/dist/components/theme/index.d.ts.map +1 -1
- package/dist/components/theme/index.js +2 -0
- package/dist/hooks/index.d.ts +1 -0
- package/dist/hooks/index.d.ts.map +1 -1
- package/dist/hooks/index.js +1 -0
- package/dist/hooks/usePressRepeat.d.ts +31 -0
- package/dist/hooks/usePressRepeat.d.ts.map +1 -0
- package/dist/hooks/usePressRepeat.js +47 -0
- package/package.json +5 -5
|
@@ -1,60 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState } from "react";
|
|
2
|
+
import { useEffect, useRef, useState } from "react";
|
|
3
3
|
import { Pressable, Text, TextInput, View } from "react-native";
|
|
4
|
+
import { usePressRepeat } from "../../hooks/usePressRepeat.js";
|
|
4
5
|
import { useKitLocale } from "../../i18n/locale.js";
|
|
5
6
|
import { mergeSlotStyles } from "../../utils/helpers/mergeSlotStyles.js";
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
flexDirection: "row",
|
|
21
|
-
alignItems: "center",
|
|
22
|
-
gap: 6,
|
|
23
|
-
},
|
|
24
|
-
button: {
|
|
25
|
-
width: 40,
|
|
26
|
-
height: 40,
|
|
27
|
-
borderRadius: 20,
|
|
28
|
-
backgroundColor: "#2563eb",
|
|
29
|
-
alignItems: "center",
|
|
30
|
-
justifyContent: "center",
|
|
31
|
-
},
|
|
32
|
-
buttonDisabled: { opacity: 0.35 },
|
|
33
|
-
buttonText: {
|
|
34
|
-
color: "#ffffff",
|
|
35
|
-
fontSize: 22,
|
|
36
|
-
fontWeight: "700",
|
|
37
|
-
lineHeight: 26,
|
|
38
|
-
},
|
|
39
|
-
input: {
|
|
40
|
-
width: 52,
|
|
41
|
-
height: 40,
|
|
42
|
-
borderRadius: 8,
|
|
43
|
-
borderWidth: 1,
|
|
44
|
-
borderColor: "#d4d4d4",
|
|
45
|
-
color: "#111111",
|
|
46
|
-
fontSize: 18,
|
|
47
|
-
fontWeight: "700",
|
|
48
|
-
textAlign: "center",
|
|
49
|
-
padding: 0,
|
|
50
|
-
},
|
|
51
|
-
};
|
|
7
|
+
import { defaultA11yLabels, defaultStyles, } from "./QuantityStepper.styles.js";
|
|
8
|
+
/** Keeps the digits, and a leading "-" when negatives are allowed. */
|
|
9
|
+
function sanitize(text, allowsNegative) {
|
|
10
|
+
const digits = text.replace(/\D/g, "");
|
|
11
|
+
return allowsNegative && text.trimStart().startsWith("-")
|
|
12
|
+
? `-${digits}`
|
|
13
|
+
: digits;
|
|
14
|
+
}
|
|
15
|
+
/** Characters a bound takes in the field; 15 digits (+ "-") if unbounded. */
|
|
16
|
+
function lengthOf(bound) {
|
|
17
|
+
if (Number.isFinite(bound))
|
|
18
|
+
return String(bound).length;
|
|
19
|
+
return bound < 0 ? 16 : 15;
|
|
20
|
+
}
|
|
52
21
|
/**
|
|
53
|
-
* A whole-number counter from `min` (0) to `max`: −/+ buttons to adjust
|
|
54
|
-
* (optionally faster on long press
|
|
55
|
-
* type a large number in one go (
|
|
56
|
-
* clamped). A typed value
|
|
57
|
-
* `min
|
|
22
|
+
* A whole-number counter from `min` (0) to `max`: −/+ buttons to adjust by
|
|
23
|
+
* `step` (optionally faster on long press, or repeating while held), and a
|
|
24
|
+
* numeric field in the middle to type a large number in one go (other
|
|
25
|
+
* characters are dropped, the result is clamped). A typed value that is not a
|
|
26
|
+
* number yet or below `min` (an empty field, a lone "-", the "2" of "25" with
|
|
27
|
+
* `min={10}`) stays as typed until the field loses focus. A negative `min`
|
|
28
|
+
* allows negative values (penalties, defeat tokens…); `-Infinity`/`Infinity`
|
|
29
|
+
* remove a bound.
|
|
58
30
|
*
|
|
59
31
|
* @example
|
|
60
32
|
* ```tsx
|
|
@@ -62,40 +34,95 @@ const defaultStyles = {
|
|
|
62
34
|
*
|
|
63
35
|
* <QuantityStepper value={count} onChange={setCount} label="Croissants" />
|
|
64
36
|
* <QuantityStepper value={bans} onChange={setBans} label="Bannissements" min={1} max={40} longPressStep={5} />
|
|
37
|
+
* <QuantityStepper value={score} onChange={setScore} label="Points" min={-Infinity} max={Infinity} step={4} repeatOnHold onStep={tapFeedback} />
|
|
65
38
|
* ```
|
|
66
39
|
*/
|
|
67
|
-
export function QuantityStepper({ value, onChange, label, min = 0, max = 999, longPressStep, locale, a11yLabels, styles, }) {
|
|
40
|
+
export function QuantityStepper({ value, onChange, label, min = 0, max = 999, step = 1, onStep, longPressStep, repeatOnHold = false, locale, a11yLabels, styles, }) {
|
|
68
41
|
const labels = { ...defaultA11yLabels[useKitLocale(locale)], ...a11yLabels };
|
|
69
42
|
const merged = mergeSlotStyles(defaultStyles, styles);
|
|
70
43
|
const atMin = value <= min;
|
|
71
44
|
const atMax = value >= max;
|
|
45
|
+
const allowsNegative = min < 0;
|
|
72
46
|
// Field text not sent yet: clamping it to `min` on every keystroke would
|
|
73
47
|
// make any number starting below `min` impossible to type.
|
|
74
48
|
const [draft, setDraft] = useState(null);
|
|
49
|
+
const repeat = usePressRepeat();
|
|
50
|
+
// Value during a repeat, ahead of the `value` prop until the parent
|
|
51
|
+
// re-renders with each onChange.
|
|
52
|
+
const valueRef = useRef(value);
|
|
53
|
+
useEffect(() => {
|
|
54
|
+
valueRef.current = value;
|
|
55
|
+
}, [value]);
|
|
56
|
+
const clamp = (n) => Math.min(max, Math.max(min, n));
|
|
75
57
|
function set(next) {
|
|
76
58
|
setDraft(null);
|
|
77
|
-
onChange(
|
|
59
|
+
onChange(clamp(next));
|
|
60
|
+
}
|
|
61
|
+
/** A −/+ press: moves by `delta`; `false` when a bound stopped it. */
|
|
62
|
+
function stepBy(delta) {
|
|
63
|
+
const next = clamp(valueRef.current + delta);
|
|
64
|
+
if (next === valueRef.current)
|
|
65
|
+
return false;
|
|
66
|
+
valueRef.current = next;
|
|
67
|
+
set(next);
|
|
68
|
+
onStep?.(next);
|
|
69
|
+
return true;
|
|
70
|
+
}
|
|
71
|
+
function startRepeat(direction) {
|
|
72
|
+
repeat.start(() => {
|
|
73
|
+
// A button disabled at its bound may never report the release.
|
|
74
|
+
if (!stepBy(direction * step))
|
|
75
|
+
repeat.stop();
|
|
76
|
+
});
|
|
77
|
+
}
|
|
78
|
+
// Held: repeat from press-in to press-out. Otherwise: one step per tap,
|
|
79
|
+
// and `longPressStep` on long press.
|
|
80
|
+
const tapsOnly = !repeatOnHold;
|
|
81
|
+
const jumps = tapsOnly && longPressStep !== undefined;
|
|
82
|
+
// A tap starts from the rendered value, even if the parent ignored the
|
|
83
|
+
// previous onChange.
|
|
84
|
+
function tap(delta) {
|
|
85
|
+
valueRef.current = value;
|
|
86
|
+
stepBy(delta);
|
|
78
87
|
}
|
|
79
|
-
return (_jsxs(View, { style: merged.row, children: [_jsx(Pressable, { style: [merged.button, atMin && merged.buttonDisabled], onPress:
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
:
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
88
|
+
return (_jsxs(View, { style: merged.row, children: [_jsx(Pressable, { style: [merged.button, atMin && merged.buttonDisabled], onPress: tapsOnly
|
|
89
|
+
? () => {
|
|
90
|
+
tap(-step);
|
|
91
|
+
}
|
|
92
|
+
: undefined, onLongPress: jumps
|
|
93
|
+
? () => {
|
|
94
|
+
tap(-longPressStep);
|
|
95
|
+
}
|
|
96
|
+
: undefined, onPressIn: repeatOnHold
|
|
97
|
+
? () => {
|
|
98
|
+
startRepeat(-1);
|
|
99
|
+
}
|
|
100
|
+
: undefined, onPressOut: repeatOnHold ? repeat.stop : undefined, disabled: atMin, hitSlop: 6, accessibilityRole: "button", accessibilityLabel: labels.decrease(label), children: _jsx(Text, { style: merged.buttonText, children: "\u2212" }) }), _jsx(TextInput, { style: merged.input, value: draft ?? String(value), onChangeText: (text) => {
|
|
101
|
+
const cleaned = sanitize(text, allowsNegative);
|
|
102
|
+
const typed = Number(cleaned);
|
|
103
|
+
if (cleaned === "" || cleaned === "-" || typed < min) {
|
|
104
|
+
setDraft(cleaned);
|
|
105
|
+
}
|
|
89
106
|
else
|
|
90
|
-
set(
|
|
107
|
+
set(typed);
|
|
91
108
|
}, onBlur: () => {
|
|
92
|
-
if (draft
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
set(
|
|
96
|
-
},
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
109
|
+
if (draft === null)
|
|
110
|
+
return;
|
|
111
|
+
// Nothing typed yet: back to 0, or to the nearest bound.
|
|
112
|
+
set(draft === "" || draft === "-" ? 0 : Number(draft));
|
|
113
|
+
},
|
|
114
|
+
// "number-pad" has no "-" key on Android.
|
|
115
|
+
keyboardType: allowsNegative ? "numeric" : "number-pad", selectTextOnFocus: true, maxLength: Math.max(lengthOf(min), lengthOf(max)), accessibilityLabel: labels.input(label) }), _jsx(Pressable, { style: [merged.button, atMax && merged.buttonDisabled], onPress: tapsOnly
|
|
116
|
+
? () => {
|
|
117
|
+
tap(step);
|
|
118
|
+
}
|
|
119
|
+
: undefined, onLongPress: jumps
|
|
120
|
+
? () => {
|
|
121
|
+
tap(longPressStep);
|
|
122
|
+
}
|
|
123
|
+
: undefined, onPressIn: repeatOnHold
|
|
124
|
+
? () => {
|
|
125
|
+
startRepeat(1);
|
|
126
|
+
}
|
|
127
|
+
: undefined, onPressOut: repeatOnHold ? repeat.stop : undefined, disabled: atMax, hitSlop: 6, accessibilityRole: "button", accessibilityLabel: labels.increase(label), children: _jsx(Text, { style: merged.buttonText, children: "+" }) })] }));
|
|
101
128
|
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
import type { KitLocale } from "../../i18n/locale.js";
|
|
3
|
+
/** Per-slot style overrides for {@link QuantityStepper}, each merged after its default. */
|
|
4
|
+
export interface QuantityStepperStyles {
|
|
5
|
+
/** The row: − button, field, + button. */
|
|
6
|
+
row?: StyleProp<ViewStyle>;
|
|
7
|
+
/** Both round buttons. */
|
|
8
|
+
button?: StyleProp<ViewStyle>;
|
|
9
|
+
/** Added on top of `button` for "−" at `min` and "+" at `max`. */
|
|
10
|
+
buttonDisabled?: StyleProp<ViewStyle>;
|
|
11
|
+
/** The "−" / "+" glyphs. */
|
|
12
|
+
buttonText?: StyleProp<TextStyle>;
|
|
13
|
+
/** The numeric field in the middle (its text color included). */
|
|
14
|
+
input?: StyleProp<TextStyle>;
|
|
15
|
+
}
|
|
16
|
+
/** Screen-reader labels of the three controls, built from the stepper's `label`. */
|
|
17
|
+
export interface QuantityStepperA11yLabels {
|
|
18
|
+
decrease: (label: string) => string;
|
|
19
|
+
increase: (label: string) => string;
|
|
20
|
+
input: (label: string) => string;
|
|
21
|
+
}
|
|
22
|
+
export declare const defaultA11yLabels: Record<KitLocale, QuantityStepperA11yLabels>;
|
|
23
|
+
export declare const defaultStyles: {
|
|
24
|
+
row: {
|
|
25
|
+
flexDirection: "row";
|
|
26
|
+
alignItems: "center";
|
|
27
|
+
gap: number;
|
|
28
|
+
};
|
|
29
|
+
button: {
|
|
30
|
+
width: number;
|
|
31
|
+
height: number;
|
|
32
|
+
borderRadius: number;
|
|
33
|
+
backgroundColor: string;
|
|
34
|
+
alignItems: "center";
|
|
35
|
+
justifyContent: "center";
|
|
36
|
+
};
|
|
37
|
+
buttonDisabled: {
|
|
38
|
+
opacity: number;
|
|
39
|
+
};
|
|
40
|
+
buttonText: {
|
|
41
|
+
color: string;
|
|
42
|
+
fontSize: number;
|
|
43
|
+
fontWeight: "700";
|
|
44
|
+
lineHeight: number;
|
|
45
|
+
};
|
|
46
|
+
input: {
|
|
47
|
+
width: number;
|
|
48
|
+
height: number;
|
|
49
|
+
borderRadius: number;
|
|
50
|
+
borderWidth: number;
|
|
51
|
+
borderColor: string;
|
|
52
|
+
color: string;
|
|
53
|
+
fontSize: number;
|
|
54
|
+
fontWeight: "700";
|
|
55
|
+
textAlign: "center";
|
|
56
|
+
padding: number;
|
|
57
|
+
};
|
|
58
|
+
};
|
|
59
|
+
//# sourceMappingURL=QuantityStepper.styles.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"QuantityStepper.styles.d.ts","sourceRoot":"","sources":["../../../src/components/picker/QuantityStepper.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,2FAA2F;AAC3F,MAAM,WAAW,qBAAqB;IACpC,0CAA0C;IAC1C,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,0BAA0B;IAC1B,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,kEAAkE;IAClE,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,4BAA4B;IAC5B,UAAU,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAClC,iEAAiE;IACjE,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;CAC9B;AAED,oFAAoF;AACpF,MAAM,WAAW,yBAAyB;IACxC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,QAAQ,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;IACpC,KAAK,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,MAAM,CAAC;CAClC;AAED,eAAO,MAAM,iBAAiB,EAAE,MAAM,CAAC,SAAS,EAAE,yBAAyB,CAW1E,CAAC;AAEF,eAAO,MAAM,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAiCzB,CAAC"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
export const defaultA11yLabels = {
|
|
2
|
+
fr: {
|
|
3
|
+
decrease: (label) => `Retirer : ${label}`,
|
|
4
|
+
increase: (label) => `Ajouter : ${label}`,
|
|
5
|
+
input: (label) => `Quantité : ${label}`,
|
|
6
|
+
},
|
|
7
|
+
en: {
|
|
8
|
+
decrease: (label) => `Decrease: ${label}`,
|
|
9
|
+
increase: (label) => `Increase: ${label}`,
|
|
10
|
+
input: (label) => `Quantity: ${label}`,
|
|
11
|
+
},
|
|
12
|
+
};
|
|
13
|
+
export const defaultStyles = {
|
|
14
|
+
row: {
|
|
15
|
+
flexDirection: "row",
|
|
16
|
+
alignItems: "center",
|
|
17
|
+
gap: 6,
|
|
18
|
+
},
|
|
19
|
+
button: {
|
|
20
|
+
width: 40,
|
|
21
|
+
height: 40,
|
|
22
|
+
borderRadius: 20,
|
|
23
|
+
backgroundColor: "#2563eb",
|
|
24
|
+
alignItems: "center",
|
|
25
|
+
justifyContent: "center",
|
|
26
|
+
},
|
|
27
|
+
buttonDisabled: { opacity: 0.35 },
|
|
28
|
+
buttonText: {
|
|
29
|
+
color: "#ffffff",
|
|
30
|
+
fontSize: 22,
|
|
31
|
+
fontWeight: "700",
|
|
32
|
+
lineHeight: 26,
|
|
33
|
+
},
|
|
34
|
+
input: {
|
|
35
|
+
width: 52,
|
|
36
|
+
height: 40,
|
|
37
|
+
borderRadius: 8,
|
|
38
|
+
borderWidth: 1,
|
|
39
|
+
borderColor: "#d4d4d4",
|
|
40
|
+
color: "#111111",
|
|
41
|
+
fontSize: 18,
|
|
42
|
+
fontWeight: "700",
|
|
43
|
+
textAlign: "center",
|
|
44
|
+
padding: 0,
|
|
45
|
+
},
|
|
46
|
+
};
|
|
@@ -7,7 +7,11 @@ export interface UpdateSettingsScreenProps {
|
|
|
7
7
|
checkForUpdate: () => Promise<UpdateSettingsScreenRelease | null>;
|
|
8
8
|
/** Positive when `a` is newer than `b`, e.g. semver comparison. */
|
|
9
9
|
compareVersions: (a: string, b: string) => number;
|
|
10
|
-
|
|
10
|
+
/**
|
|
11
|
+
* Receives the release's `apkSha256`: pass it on as
|
|
12
|
+
* `expectedSha256` so a swapped or damaged APK is never installed.
|
|
13
|
+
*/
|
|
14
|
+
downloadAndInstallApk: (apkUrl: string, onProgress?: (fraction: number) => void, apkSha256?: string) => Promise<void>;
|
|
11
15
|
/** Omit to not show a version history section at all. */
|
|
12
16
|
fetchReleaseHistory?: () => Promise<UpdateSettingsScreenHistoryEntry[]>;
|
|
13
17
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpdateSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UpdateSettingsScreen.tsx"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC3B,MAAM,kCAAkC,CAAC;AAI1C,YAAY,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAU1C,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,cAAc,EAAE,MAAM,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAAC;IAClE,mEAAmE;IACnE,eAAe,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,
|
|
1
|
+
{"version":3,"file":"UpdateSettingsScreen.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UpdateSettingsScreen.tsx"],"names":[],"mappings":"AAKA,OAAO,EAEL,KAAK,SAAS,EAEf,MAAM,sBAAsB,CAAC;AAG9B,OAAO,KAAK,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,EAC3B,MAAM,kCAAkC,CAAC;AAI1C,YAAY,EACV,gCAAgC,EAChC,0BAA0B,EAC1B,2BAA2B,EAC3B,0BAA0B,GAC3B,MAAM,kCAAkC,CAAC;AAU1C,MAAM,WAAW,yBAAyB;IACxC,cAAc,EAAE,MAAM,CAAC;IACvB,wEAAwE;IACxE,cAAc,EAAE,MAAM,OAAO,CAAC,2BAA2B,GAAG,IAAI,CAAC,CAAC;IAClE,mEAAmE;IACnE,eAAe,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,KAAK,MAAM,CAAC;IAClD;;;OAGG;IACH,qBAAqB,EAAE,CACrB,MAAM,EAAE,MAAM,EACd,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,EACvC,SAAS,CAAC,EAAE,MAAM,KACf,OAAO,CAAC,IAAI,CAAC,CAAC;IACnB,yDAAyD;IACzD,mBAAmB,CAAC,EAAE,MAAM,OAAO,CAAC,gCAAgC,EAAE,CAAC,CAAC;IACxE;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,0BAA0B,CAAC;IACpC;;;OAGG;IACH,MAAM,CAAC,EAAE,SAAS,CAAC;IACnB,MAAM,CAAC,EAAE,0BAA0B,CAAC;CACrC;AAQD,wBAAgB,oBAAoB,CAAC,EACnC,cAAc,EACd,cAAc,EACd,eAAe,EACf,qBAAqB,EACrB,mBAAmB,EACnB,UAAU,EAAE,gBAAgB,EAC5B,MAAM,EACN,MAAM,EACN,MAAM,GACP,EAAE,yBAAyB,+BA8J3B"}
|
|
@@ -52,12 +52,12 @@ export function UpdateSettingsScreen({ currentVersion, checkForUpdate, compareVe
|
|
|
52
52
|
void handleCheckForUpdate();
|
|
53
53
|
// eslint-disable-next-line @eslint-react/exhaustive-deps -- runs once on mount by design; handleCheckForUpdate is expected to be stable enough for the screen's lifetime.
|
|
54
54
|
}, []);
|
|
55
|
-
async function handleInstall(apkUrl) {
|
|
55
|
+
async function handleInstall({ apkUrl, apkSha256, }) {
|
|
56
56
|
setUpdateState({ status: "downloading", progress: 0 });
|
|
57
57
|
try {
|
|
58
58
|
await downloadAndInstallApk(apkUrl, (progress) => {
|
|
59
59
|
setUpdateState({ status: "downloading", progress });
|
|
60
|
-
});
|
|
60
|
+
}, apkSha256);
|
|
61
61
|
setUpdateState({ status: "idle" });
|
|
62
62
|
}
|
|
63
63
|
catch {
|
|
@@ -74,6 +74,6 @@ export function UpdateSettingsScreen({ currentVersion, checkForUpdate, compareVe
|
|
|
74
74
|
updateState.status !== "downloading" && (_jsx(Pressable, { style: [merged.button, isBusy && merged.buttonDisabled], onPress: () => {
|
|
75
75
|
void handleCheckForUpdate();
|
|
76
76
|
}, disabled: isBusy, accessibilityRole: "button", accessibilityLabel: t.checkButton, children: updateState.status === "checking" ? (_jsx(ActivityIndicator, { color: activityIndicatorColor })) : (_jsx(Text, { style: merged.buttonText, children: t.checkButton })) })), updateState.status === "up-to-date" && (_jsx(Text, { style: merged.helpText, children: t.upToDate })), updateState.status === "error" && (_jsx(Text, { style: merged.errorText, children: updateState.message })), updateState.status === "available" && (_jsxs(View, { style: merged.updateAvailableBox, children: [_jsx(Text, { style: merged.updateAvailableTitle, children: t.availableTitle(updateState.release.version) }), updateState.release.notes ? (_jsx(ChangelogNotes, { notes: updateState.release.notes, styles: merged.notes })) : null, _jsx(Pressable, { style: merged.button, onPress: () => {
|
|
77
|
-
void handleInstall(updateState.release
|
|
77
|
+
void handleInstall(updateState.release);
|
|
78
78
|
}, accessibilityRole: "button", accessibilityLabel: t.installButtonAccessibilityLabel(updateState.release.version), children: _jsx(Text, { style: merged.buttonText, children: t.installButton(updateState.release.version) }) })] })), updateState.status === "downloading" && (_jsxs(View, { style: merged.updateAvailableBox, children: [_jsx(Text, { style: merged.helpText, children: t.downloadingLabel(Math.round(updateState.progress * 100)) }), _jsx(Text, { style: merged.helpText, children: t.downloadingHint })] })), releaseHistory && releaseHistory.length > 0 && (_jsx(UpdateSettingsScreenHistory, { releaseHistory: releaseHistory, historyTitle: t.historyTitle, dateLocale: dateLocale, notesStyles: notesStyles, styles: merged }))] }));
|
|
79
79
|
}
|
|
@@ -4,6 +4,8 @@ export interface UpdateSettingsScreenRelease {
|
|
|
4
4
|
version: string;
|
|
5
5
|
notes: string;
|
|
6
6
|
apkUrl: string;
|
|
7
|
+
/** SHA-256 of the APK, handed back to `downloadAndInstallApk`. */
|
|
8
|
+
apkSha256?: string;
|
|
7
9
|
}
|
|
8
10
|
export interface UpdateSettingsScreenHistoryEntry {
|
|
9
11
|
version: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"UpdateSettingsScreen.styles.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UpdateSettingsScreen.styles.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAEpE,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,wCAAwC,CAAC;AAInF,MAAM,WAAW,2BAA2B;IAC1C,OAAO,EAAE,MAAM,CAAC;IAChB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"UpdateSettingsScreen.styles.d.ts","sourceRoot":"","sources":["../../../src/components/settings/UpdateSettingsScreen.styles.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { StyleProp, TextStyle, ViewStyle } from "react-native";
|
|
2
|
+
import type { BackgroundOption } from "./findBackground.js";
|
|
3
|
+
export type { BackgroundOption } from "./findBackground.js";
|
|
4
|
+
export interface BackgroundPickerStyles {
|
|
5
|
+
/** The wrapping row of swatches. */
|
|
6
|
+
row?: StyleProp<ViewStyle>;
|
|
7
|
+
/** One option: swatch + label. */
|
|
8
|
+
option?: StyleProp<ViewStyle>;
|
|
9
|
+
swatch?: StyleProp<ViewStyle>;
|
|
10
|
+
/** Added on top of `swatch` for the chosen one. */
|
|
11
|
+
swatchSelected?: StyleProp<ViewStyle>;
|
|
12
|
+
card?: StyleProp<ViewStyle>;
|
|
13
|
+
/** The round badge holding the check mark. */
|
|
14
|
+
check?: StyleProp<ViewStyle>;
|
|
15
|
+
label?: StyleProp<TextStyle>;
|
|
16
|
+
labelSelected?: StyleProp<TextStyle>;
|
|
17
|
+
checkIconColor?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface BackgroundPickerProps<T extends BackgroundOption> {
|
|
20
|
+
options: readonly T[];
|
|
21
|
+
/** Id of the chosen option. */
|
|
22
|
+
value: string;
|
|
23
|
+
/** Receives the chosen option — add a haptic tick here if wanted. */
|
|
24
|
+
onChange: (option: T) => void;
|
|
25
|
+
styles?: BackgroundPickerStyles;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Radio group of background swatches: each one draws the page and a card in
|
|
29
|
+
* the colours on offer, the chosen one outlined with a check mark. Pair it
|
|
30
|
+
* with `findBackground` (`./findBackground`) to read the saved id, and check each palette's
|
|
31
|
+
* contrast with `contrastRatio` from `@forthtilliath/ts-kit/color`.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```tsx
|
|
35
|
+
* <BackgroundPicker
|
|
36
|
+
* options={[
|
|
37
|
+
* { id: "night", label: "Bleu nuit", page: "#0f172a", card: "#1e293b" },
|
|
38
|
+
* { id: "felt", label: "Tapis vert", page: "#0b1f15", card: "#112c1e" },
|
|
39
|
+
* ]}
|
|
40
|
+
* value={settings.background}
|
|
41
|
+
* onChange={(option) => { selectFeedback(); save(option.id); }}
|
|
42
|
+
* />
|
|
43
|
+
* ```
|
|
44
|
+
*/
|
|
45
|
+
export declare function BackgroundPicker<T extends BackgroundOption>({ options, value, onChange, styles, }: BackgroundPickerProps<T>): import("react").JSX.Element;
|
|
46
|
+
//# sourceMappingURL=BackgroundPicker.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BackgroundPicker.d.ts","sourceRoot":"","sources":["../../../src/components/theme/BackgroundPicker.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAE,SAAS,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AAMpE,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,YAAY,EAAE,gBAAgB,EAAE,MAAM,qBAAqB,CAAC;AAE5D,MAAM,WAAW,sBAAsB;IACrC,oCAAoC;IACpC,GAAG,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC3B,kCAAkC;IAClC,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,MAAM,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC9B,mDAAmD;IACnD,cAAc,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACtC,IAAI,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC5B,8CAA8C;IAC9C,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,KAAK,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IAC7B,aAAa,CAAC,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACrC,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED,MAAM,WAAW,qBAAqB,CAAC,CAAC,SAAS,gBAAgB;IAC/D,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC;IACtB,+BAA+B;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,qEAAqE;IACrE,QAAQ,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,IAAI,CAAC;IAC9B,MAAM,CAAC,EAAE,sBAAsB,CAAC;CACjC;AAwCD;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,gBAAgB,CAAC,CAAC,SAAS,gBAAgB,EAAE,EAC3D,OAAO,EACP,KAAK,EACL,QAAQ,EACR,MAAM,GACP,EAAE,qBAAqB,CAAC,CAAC,CAAC,+BAoD1B"}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Pressable, Text, View } from "react-native";
|
|
3
|
+
import { Ionicons } from "@expo/vector-icons";
|
|
4
|
+
import { mergeSlotStyles } from "../../utils/helpers/mergeSlotStyles.js";
|
|
5
|
+
const defaultStyles = {
|
|
6
|
+
row: { flexDirection: "row", flexWrap: "wrap", gap: 8 },
|
|
7
|
+
option: {
|
|
8
|
+
flexGrow: 1,
|
|
9
|
+
flexBasis: "22%",
|
|
10
|
+
alignItems: "center",
|
|
11
|
+
gap: 4,
|
|
12
|
+
},
|
|
13
|
+
swatch: {
|
|
14
|
+
width: "100%",
|
|
15
|
+
aspectRatio: 1,
|
|
16
|
+
borderRadius: 12,
|
|
17
|
+
borderWidth: 2,
|
|
18
|
+
borderColor: "#d4d4d4",
|
|
19
|
+
padding: 8,
|
|
20
|
+
justifyContent: "flex-end",
|
|
21
|
+
},
|
|
22
|
+
swatchSelected: { borderColor: "#2563eb" },
|
|
23
|
+
card: { height: "45%", borderRadius: 6, borderWidth: 1 },
|
|
24
|
+
check: {
|
|
25
|
+
position: "absolute",
|
|
26
|
+
top: 4,
|
|
27
|
+
right: 4,
|
|
28
|
+
width: 22,
|
|
29
|
+
height: 22,
|
|
30
|
+
borderRadius: 11,
|
|
31
|
+
backgroundColor: "#2563eb",
|
|
32
|
+
alignItems: "center",
|
|
33
|
+
justifyContent: "center",
|
|
34
|
+
},
|
|
35
|
+
label: {
|
|
36
|
+
color: "#6b7280",
|
|
37
|
+
fontSize: 13,
|
|
38
|
+
fontWeight: "600",
|
|
39
|
+
},
|
|
40
|
+
labelSelected: { color: "#111827" },
|
|
41
|
+
};
|
|
42
|
+
/**
|
|
43
|
+
* Radio group of background swatches: each one draws the page and a card in
|
|
44
|
+
* the colours on offer, the chosen one outlined with a check mark. Pair it
|
|
45
|
+
* with `findBackground` (`./findBackground`) to read the saved id, and check each palette's
|
|
46
|
+
* contrast with `contrastRatio` from `@forthtilliath/ts-kit/color`.
|
|
47
|
+
*
|
|
48
|
+
* @example
|
|
49
|
+
* ```tsx
|
|
50
|
+
* <BackgroundPicker
|
|
51
|
+
* options={[
|
|
52
|
+
* { id: "night", label: "Bleu nuit", page: "#0f172a", card: "#1e293b" },
|
|
53
|
+
* { id: "felt", label: "Tapis vert", page: "#0b1f15", card: "#112c1e" },
|
|
54
|
+
* ]}
|
|
55
|
+
* value={settings.background}
|
|
56
|
+
* onChange={(option) => { selectFeedback(); save(option.id); }}
|
|
57
|
+
* />
|
|
58
|
+
* ```
|
|
59
|
+
*/
|
|
60
|
+
export function BackgroundPicker({ options, value, onChange, styles, }) {
|
|
61
|
+
const merged = mergeSlotStyles(defaultStyles, styles);
|
|
62
|
+
const checkIconColor = styles?.checkIconColor ?? "#ffffff";
|
|
63
|
+
return (_jsx(View, { style: merged.row, accessibilityRole: "radiogroup", children: options.map((option) => {
|
|
64
|
+
const selected = option.id === value;
|
|
65
|
+
return (_jsxs(Pressable, { style: merged.option, onPress: () => {
|
|
66
|
+
onChange(option);
|
|
67
|
+
}, accessibilityRole: "radio", accessibilityState: { checked: selected }, accessibilityLabel: option.label, children: [_jsxs(View, { style: [
|
|
68
|
+
merged.swatch,
|
|
69
|
+
{ backgroundColor: option.page },
|
|
70
|
+
selected && merged.swatchSelected,
|
|
71
|
+
], children: [_jsx(View, { style: [
|
|
72
|
+
merged.card,
|
|
73
|
+
{
|
|
74
|
+
backgroundColor: option.card,
|
|
75
|
+
borderColor: option.cardBorder ?? option.card,
|
|
76
|
+
},
|
|
77
|
+
] }), selected && (_jsx(View, { style: merged.check, children: _jsx(Ionicons, { name: "checkmark", size: 14, color: checkIconColor }) }))] }), _jsx(Text, { style: [merged.label, selected && merged.labelSelected], numberOfLines: 1, children: option.label })] }, option.id));
|
|
78
|
+
}) }));
|
|
79
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/** One background on offer to `BackgroundPicker`, drawn as a page with a card on it. */
|
|
2
|
+
export interface BackgroundOption {
|
|
3
|
+
id: string;
|
|
4
|
+
/** Shown under the swatch and read by screen readers. */
|
|
5
|
+
label: string;
|
|
6
|
+
/** The page colour. */
|
|
7
|
+
page: string;
|
|
8
|
+
/** The card drawn on the page. */
|
|
9
|
+
card: string;
|
|
10
|
+
/** The card's border. Defaults to `card`. */
|
|
11
|
+
cardBorder?: string;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* The option with this id, or the first one (the original background) if the
|
|
15
|
+
* id is unknown — a background removed since it was saved, or none saved yet.
|
|
16
|
+
*
|
|
17
|
+
* @throws {RangeError} If `options` is empty.
|
|
18
|
+
*/
|
|
19
|
+
export declare function findBackground<T extends BackgroundOption>(options: readonly T[], id: string | null | undefined): T;
|
|
20
|
+
//# sourceMappingURL=findBackground.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"findBackground.d.ts","sourceRoot":"","sources":["../../../src/components/theme/findBackground.ts"],"names":[],"mappings":"AAAA,wFAAwF;AACxF,MAAM,WAAW,gBAAgB;IAC/B,EAAE,EAAE,MAAM,CAAC;IACX,yDAAyD;IACzD,KAAK,EAAE,MAAM,CAAC;IACd,uBAAuB;IACvB,IAAI,EAAE,MAAM,CAAC;IACb,kCAAkC;IAClC,IAAI,EAAE,MAAM,CAAC;IACb,6CAA6C;IAC7C,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED;;;;;GAKG;AACH,wBAAgB,cAAc,CAAC,CAAC,SAAS,gBAAgB,EACvD,OAAO,EAAE,SAAS,CAAC,EAAE,EACrB,EAAE,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,GAC5B,CAAC,CAIH"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The option with this id, or the first one (the original background) if the
|
|
3
|
+
* id is unknown — a background removed since it was saved, or none saved yet.
|
|
4
|
+
*
|
|
5
|
+
* @throws {RangeError} If `options` is empty.
|
|
6
|
+
*/
|
|
7
|
+
export function findBackground(options, id) {
|
|
8
|
+
const found = options.find((option) => option.id === id) ?? options[0];
|
|
9
|
+
if (!found)
|
|
10
|
+
throw new RangeError("findBackground needs at least one option");
|
|
11
|
+
return found;
|
|
12
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/components/theme/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,qBAAqB,CAAC;AACpC,cAAc,sBAAsB,CAAC;AACrC,cAAc,6BAA6B,CAAC;AAC5C,cAAc,8BAA8B,CAAC;AAC7C,cAAc,kBAAkB,CAAC"}
|
package/dist/hooks/index.d.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/hooks/index.ts"],"names":[],"mappings":"AAAA,cAAc,yBAAyB,CAAC;AACxC,cAAc,8BAA8B,CAAC;AAC7C,cAAc,qBAAqB,CAAC;AACpC,cAAc,qBAAqB,CAAC"}
|
package/dist/hooks/index.js
CHANGED
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
/** Timings of {@link usePressRepeat}, in milliseconds. */
|
|
2
|
+
export interface PressRepeatTimings {
|
|
3
|
+
/** Hold time before the first repeat. @defaultValue 450 */
|
|
4
|
+
initialDelay?: number;
|
|
5
|
+
/** Interval between repeats at first. @defaultValue 180 */
|
|
6
|
+
interval?: number;
|
|
7
|
+
/** Repeat time after which repeats speed up. @defaultValue 1200 */
|
|
8
|
+
accelerateAfter?: number;
|
|
9
|
+
/** Interval between repeats once sped up. @defaultValue 60 */
|
|
10
|
+
fastInterval?: number;
|
|
11
|
+
}
|
|
12
|
+
/**
|
|
13
|
+
* Repeats an action while a button is held, faster and faster — the way a
|
|
14
|
+
* counter's −/+ reach large values quickly. `start` runs the action at once,
|
|
15
|
+
* then again every `interval` after `initialDelay`, every `fastInterval`
|
|
16
|
+
* after `accelerateAfter`; `stop` ends it (also done on unmount).
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* ```tsx
|
|
20
|
+
* const repeat = usePressRepeat();
|
|
21
|
+
* <Pressable
|
|
22
|
+
* onPressIn={() => repeat.start(() => setCount((n) => n + 1))}
|
|
23
|
+
* onPressOut={repeat.stop}
|
|
24
|
+
* />
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
export declare function usePressRepeat({ initialDelay, interval, accelerateAfter, fastInterval, }?: PressRepeatTimings): {
|
|
28
|
+
start: (action: () => void) => void;
|
|
29
|
+
stop: () => void;
|
|
30
|
+
};
|
|
31
|
+
//# sourceMappingURL=usePressRepeat.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"usePressRepeat.d.ts","sourceRoot":"","sources":["../../src/hooks/usePressRepeat.ts"],"names":[],"mappings":"AAEA,0DAA0D;AAC1D,MAAM,WAAW,kBAAkB;IACjC,2DAA2D;IAC3D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,2DAA2D;IAC3D,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,mEAAmE;IACnE,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,8DAA8D;IAC9D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAcD;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,cAAc,CAAC,EAC7B,YAAkB,EAClB,QAAc,EACd,eAAsB,EACtB,YAAiB,GAClB,GAAE,kBAAuB;oBAeD,MAAM,IAAI;;EAclC"}
|