basalt-core 0.0.0-rc5 → 0.2.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/dist/cli/basalt.d.ts.map +1 -1
- package/dist/cli/basalt.js +18 -1
- package/dist/cli/basalt.js.map +1 -1
- package/dist/cli/bundle-cli.js +0 -0
- package/dist/cli/desktop.d.ts.map +1 -1
- package/dist/cli/desktop.js +53 -4
- package/dist/cli/desktop.js.map +1 -1
- package/dist/cli/packageApp.d.ts.map +1 -1
- package/dist/cli/packageApp.js +7 -1
- package/dist/cli/packageApp.js.map +1 -1
- package/dist/metro-config.d.ts.map +1 -1
- package/dist/metro-config.js +53 -5
- package/dist/metro-config.js.map +1 -1
- package/dist/src/KeyHandler.d.ts +1 -1
- package/dist/src/KeyHandler.d.ts.map +1 -1
- package/dist/src/KeyHandler.js.map +1 -1
- package/dist/src/index.d.ts +5 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/overrides/Alert.d.ts +1 -1
- package/dist/src/overrides/Alert.js +1 -1
- package/dist/src/overrides/BaseViewConfig.d.ts +10 -3
- package/dist/src/overrides/BaseViewConfig.d.ts.map +1 -1
- package/dist/src/overrides/BaseViewConfig.js +21 -3
- package/dist/src/overrides/BaseViewConfig.js.map +1 -1
- package/dist/src/overrides/Button.d.ts +81 -0
- package/dist/src/overrides/Button.d.ts.map +1 -0
- package/dist/src/overrides/Button.js +109 -0
- package/dist/src/overrides/Button.js.map +1 -0
- package/dist/src/overrides/ScrollView.d.ts +25 -2
- package/dist/src/overrides/ScrollView.d.ts.map +1 -1
- package/dist/src/overrides/ScrollView.js +64 -7
- package/dist/src/overrides/ScrollView.js.map +1 -1
- package/dist/src/overrides/Settings.d.ts +81 -0
- package/dist/src/overrides/Settings.d.ts.map +1 -0
- package/dist/src/overrides/Settings.js +120 -0
- package/dist/src/overrides/Settings.js.map +1 -0
- package/dist/src/overrides/processDecelerationRate.d.ts +20 -0
- package/dist/src/overrides/processDecelerationRate.d.ts.map +1 -0
- package/dist/src/overrides/processDecelerationRate.js +31 -0
- package/dist/src/overrides/processDecelerationRate.js.map +1 -0
- package/dist/src/useContextMenu.d.ts +57 -6
- package/dist/src/useContextMenu.d.ts.map +1 -1
- package/dist/src/useContextMenu.js +34 -1
- package/dist/src/useContextMenu.js.map +1 -1
- package/dist/tsconfig.tsbuildinfo +1 -1
- package/native/CMakeLists.txt +85 -1
- package/native/cmake/Skia.cmake +29 -6
- package/native/core/ActionSheet.cpp +75 -0
- package/native/core/ActionSheet.h +90 -0
- package/native/core/AppStateHost.cpp +76 -0
- package/native/core/AppStateHost.h +68 -0
- package/native/core/BackgroundLayers.h +282 -0
- package/native/core/BlendModes.h +67 -0
- package/native/core/CoreModules.cpp +380 -11
- package/native/core/CoreModules.h +140 -4
- package/native/core/CrashHandler.cpp +246 -0
- package/native/core/CrashHandler.h +65 -0
- package/native/core/CursorNames.h +110 -0
- package/native/core/DevMenu.cpp +6 -5
- package/native/core/DeviceMetrics.cpp +87 -0
- package/native/core/DeviceMetrics.h +80 -0
- package/native/core/Filters.h +336 -0
- package/native/core/FontFitting.h +183 -0
- package/native/core/FontScaling.h +153 -0
- package/native/core/FontVariants.h +148 -0
- package/native/core/Gradients.h +523 -0
- package/native/core/ImageAnimation.h +109 -0
- package/native/core/ImageBytes.cpp +28 -1
- package/native/core/ImageBytes.h +17 -1
- package/native/core/ImageProgress.h +85 -0
- package/native/core/LabelRegistry.h +189 -0
- package/native/core/LegacyShadow.h +90 -0
- package/native/core/LiveRegions.h +114 -0
- package/native/core/MenuModule.cpp +35 -4
- package/native/core/MountingWalk.h +125 -2
- package/native/core/PlatformServices.h +187 -3
- package/native/core/SafeAreaComponent.cpp +115 -0
- package/native/core/SafeAreaComponent.h +105 -0
- package/native/core/ScreensComponent.cpp +201 -0
- package/native/core/ScreensComponent.h +216 -0
- package/native/core/ScrollBounds.cpp +8 -0
- package/native/core/ScrollBounds.h +14 -0
- package/native/core/ScrollIndicator.h +67 -0
- package/native/core/ScrollMomentum.cpp +24 -0
- package/native/core/ScrollMomentum.h +14 -0
- package/native/core/ScrollSnap.cpp +121 -12
- package/native/core/ScrollSnap.h +45 -0
- package/native/core/ScrollVisiblePosition.cpp +68 -0
- package/native/core/ScrollVisiblePosition.h +101 -0
- package/native/core/SettingsStore.cpp +199 -0
- package/native/core/SettingsStore.h +127 -0
- package/native/core/ShadowShape.h +38 -0
- package/native/core/SkiaViewComponent.cpp +11 -0
- package/native/core/SkiaViewComponent.h +50 -0
- package/native/core/SystemLocale.cpp +103 -0
- package/native/core/SystemLocale.h +86 -0
- package/native/core/TestDialog.cpp +45 -6
- package/native/core/TestDialog.h +15 -0
- package/native/core/TextAlignments.h +240 -0
- package/native/core/TextChecking.h +133 -0
- package/native/core/TextColors.h +83 -0
- package/native/core/TextDecorations.h +101 -0
- package/native/core/TextDirection.cpp +242 -0
- package/native/core/TextDirection.h +88 -0
- package/native/core/TextHighlight.h +30 -0
- package/native/core/TextSelection.cpp +97 -0
- package/native/core/TextSelection.h +161 -0
- package/native/core/TextShadows.h +96 -0
- package/native/core/TextVerticalAlign.h +33 -0
- package/native/core/UIManagerAccess.cpp +36 -0
- package/native/core/UIManagerAccess.h +28 -0
- package/native/core/WindowBoundsCache.cpp +58 -1
- package/native/core/WindowControl.h +24 -0
- package/native/core/WritingDirections.h +52 -0
- package/native/core/portability_probe.cpp +7 -0
- package/native/tests/RenamedFontFile.h +161 -0
- package/native/tests/TestHarness.cpp +18 -0
- package/native/tests/test_action_sheet.cpp +157 -0
- package/native/tests/test_app_state.cpp +60 -0
- package/native/tests/test_background_layers.cpp +281 -0
- package/native/tests/test_blend_modes.cpp +79 -0
- package/native/tests/test_blobs.cpp +1 -1
- package/native/tests/test_device_metrics.cpp +126 -0
- package/native/tests/test_filters.cpp +271 -0
- package/native/tests/test_font_fitting.cpp +172 -0
- package/native/tests/test_font_scaling.cpp +127 -0
- package/native/tests/test_font_variants.cpp +84 -0
- package/native/tests/test_gradients.cpp +390 -0
- package/native/tests/test_image_animation.cpp +105 -0
- package/native/tests/test_image_progress.cpp +94 -0
- package/native/tests/test_label_registry.cpp +262 -0
- package/native/tests/test_legacy_shadow.cpp +165 -0
- package/native/tests/test_live_regions.cpp +108 -0
- package/native/tests/test_menu_entries.cpp +192 -0
- package/native/tests/test_momentum.cpp +45 -0
- package/native/tests/test_scroll_bounds.cpp +42 -0
- package/native/tests/test_scroll_indicator.cpp +61 -0
- package/native/tests/test_scroll_snap.cpp +129 -0
- package/native/tests/test_scroll_visible_position.cpp +121 -0
- package/native/tests/test_settings_store.cpp +257 -0
- package/native/tests/test_shadow_shape.cpp +47 -0
- package/native/tests/test_system_locale.cpp +36 -0
- package/native/tests/test_text_alignment.cpp +299 -0
- package/native/tests/test_text_checking.cpp +31 -0
- package/native/tests/test_text_colors.cpp +92 -0
- package/native/tests/test_text_decorations.cpp +100 -0
- package/native/tests/test_text_selection.cpp +168 -0
- package/native/tests/test_text_shadows.cpp +132 -0
- package/package.json +4 -2
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* `decelerationRate`, for a desktop React Native platform.
|
|
4
|
+
*
|
|
5
|
+
* Not a shim, and the same failure as `<Button>`'s: React Native's own file is
|
|
6
|
+
* two `Platform.select({ios, android})` tables with no `default`, so on
|
|
7
|
+
* `linux`, `macos` or `windows` both of the prop's documented spellings --
|
|
8
|
+
* `'normal'` and `'fast'` -- resolve to `undefined`. `BaseScrollViewProps`
|
|
9
|
+
* then keeps its own default of 0.998, so `decelerationRate="fast"` scrolled
|
|
10
|
+
* at the normal rate and nothing said otherwise. Only a raw number worked.
|
|
11
|
+
*
|
|
12
|
+
* iOS's pair, because they are the pair this platform's own fling already
|
|
13
|
+
* uses: `core/ScrollMomentum.h` names 0.998 and 0.99 as what `'normal'` and
|
|
14
|
+
* `'fast'` mean, and a per-millisecond friction factor is the same model
|
|
15
|
+
* UIScrollView and every browser use. Android's 0.985 and 0.9 are a different
|
|
16
|
+
* curve's constants and would make a fling stop in a third of the distance.
|
|
17
|
+
*
|
|
18
|
+
* @format
|
|
19
|
+
*/
|
|
20
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
+
exports.default = processDecelerationRate;
|
|
22
|
+
function processDecelerationRate(decelerationRate) {
|
|
23
|
+
if (decelerationRate === 'normal') {
|
|
24
|
+
return 0.998;
|
|
25
|
+
}
|
|
26
|
+
if (decelerationRate === 'fast') {
|
|
27
|
+
return 0.99;
|
|
28
|
+
}
|
|
29
|
+
return decelerationRate;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=processDecelerationRate.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"processDecelerationRate.js","sourceRoot":"","sources":["../../../src/overrides/processDecelerationRate.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;GAiBG;;AAEH,0CAUC;AAVD,SAAwB,uBAAuB,CAC7C,gBAA4C;IAE5C,IAAI,gBAAgB,KAAK,QAAQ,EAAE,CAAC;QAClC,OAAO,KAAK,CAAC;IACf,CAAC;IACD,IAAI,gBAAgB,KAAK,MAAM,EAAE,CAAC;QAChC,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,gBAAgB,CAAC;AAC1B,CAAC"}
|
|
@@ -63,20 +63,71 @@
|
|
|
63
63
|
* @format
|
|
64
64
|
*/
|
|
65
65
|
/**
|
|
66
|
-
* One item in a context menu
|
|
67
|
-
* handler this
|
|
66
|
+
* One item in a context menu: the four fields `entriesFrom` in
|
|
67
|
+
* `native/core/MenuModule.cpp` reads into a `MenuEntry`, plus the handler this
|
|
68
|
+
* file calls.
|
|
69
|
+
*
|
|
70
|
+
* A popup menu is a flat list on all three desktops, so there is no `submenu`
|
|
71
|
+
* and no `role` here -- nesting and the platform roles are what a menu *bar*
|
|
72
|
+
* is for, and `<Menu.Item>` is where they live.
|
|
68
73
|
*
|
|
69
74
|
* `onSelect` is the only field the native side does not see: the promise
|
|
70
75
|
* carries the index back, and this calls the handler before settling it.
|
|
71
76
|
*/
|
|
72
77
|
export type ContextMenuItem = {
|
|
73
78
|
label?: string;
|
|
74
|
-
/**
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
79
|
+
/**
|
|
80
|
+
* Drawn beside the label -- "Cmd+C", "Del". Decoration only: nothing here
|
|
81
|
+
* binds a key. Note the menu *bar* spells the same idea `accelerator`,
|
|
82
|
+
* because there it really does bind one.
|
|
83
|
+
*/
|
|
84
|
+
shortcut?: string;
|
|
78
85
|
enabled?: boolean;
|
|
79
86
|
separator?: boolean;
|
|
87
|
+
/**
|
|
88
|
+
* One of the platform roles, in Electron's spelling: `about`, `quit`, `undo`,
|
|
89
|
+
* `redo`, `cut`, `copy`, `paste`, `delete`, `selectAll`, `minimize`, `zoom`,
|
|
90
|
+
* `close`, `togglefullscreen`. The platform performs it -- the Copy that
|
|
91
|
+
* actually copies the field the person was in -- and `onSelect` still runs, so
|
|
92
|
+
* an app can both get the behaviour and hear about it.
|
|
93
|
+
*
|
|
94
|
+
* **A role this desktop cannot perform is left out of the menu**, rather than
|
|
95
|
+
* shown doing nothing. It keeps its index though: what comes back is an index
|
|
96
|
+
* into the list you passed, so adding a role that one platform lacks does not
|
|
97
|
+
* renumber the items after it.
|
|
98
|
+
*
|
|
99
|
+
* The three do not agree. macOS has all thirteen; Linux and Windows have
|
|
100
|
+
* twelve, both missing `about`, neither having a platform about panel to ask
|
|
101
|
+
* for -- that window is an app's own to show, and an ordinary item with an
|
|
102
|
+
* `onSelect` is how to open it.
|
|
103
|
+
*/
|
|
104
|
+
role?: string;
|
|
105
|
+
/**
|
|
106
|
+
* A tick or a radio mark beside the label.
|
|
107
|
+
*
|
|
108
|
+
* `checked` on its own means a checkbox, so the common case is one word. The
|
|
109
|
+
* kind is a separate field because it has to be: a GMenu item carries no
|
|
110
|
+
* checked attribute, and GTK picks a tick or a circle from the shape of the
|
|
111
|
+
* action behind it, which a boolean cannot express.
|
|
112
|
+
*
|
|
113
|
+
* `'radio'` is a drawing hint, not a capability. Windows draws a bullet and
|
|
114
|
+
* Linux a circle; macOS draws a tick, `NSMenu` having no radio item and a tick
|
|
115
|
+
* being what Apple's guidance prescribes for a chosen member of a group.
|
|
116
|
+
*
|
|
117
|
+
* A group is a run of adjacent `'radio'` items, ended by a separator or by any
|
|
118
|
+
* other kind of item. There is no group name to pass. Exclusivity is yours:
|
|
119
|
+
* the menu is built fresh each time it opens, so it draws the marks you give
|
|
120
|
+
* it and keeping one member checked is the caller's.
|
|
121
|
+
*/
|
|
122
|
+
type?: 'checkbox' | 'radio';
|
|
123
|
+
checked?: boolean;
|
|
124
|
+
/**
|
|
125
|
+
* Nested items. The parent is not choosable: it opens its children.
|
|
126
|
+
*
|
|
127
|
+
* Both a `submenu` and a `role` on one item is a mistake, and the submenu
|
|
128
|
+
* wins. A parent whose children are all roles this desktop cannot perform is
|
|
129
|
+
* left out with them, an empty submenu being a dead end rather than an item.
|
|
130
|
+
*/
|
|
80
131
|
submenu?: ReadonlyArray<ContextMenuItem>;
|
|
81
132
|
onSelect?: () => void;
|
|
82
133
|
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useContextMenu.d.ts","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAKH
|
|
1
|
+
{"version":3,"file":"useContextMenu.d.ts","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;AAKH;;;;;;;;;;;GAWG;AACH,MAAM,MAAM,eAAe,GAAG;IAC5B,KAAK,CAAC,EAAE,MAAM,CAAC;IACf;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;;;;;;;;;;;;;;OAgBG;IACH,IAAI,CAAC,EAAE,UAAU,GAAG,OAAO,CAAC;IAC5B,OAAO,CAAC,EAAE,OAAO,CAAC;IAClB;;;;;;OAMG;IACH,OAAO,CAAC,EAAE,aAAa,CAAC,eAAe,CAAC,CAAC;IACzC,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAC;CACvB,CAAC;AAEF;;;;GAIG;AACH,MAAM,MAAM,gBAAgB,GAAG;IAC7B,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,CAAC,CAAC,EAAE,MAAM,CAAC;IACX,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB,CAAC;AAYF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,SAAsC,CAAC;AAE/D,iBAAe,IAAI,CACjB,KAAK,EAAE,aAAa,CAAC,eAAe,CAAC,EACrC,KAAK,CAAC,EAAE,gBAAgB,GAAG,IAAI,GAC9B,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAoBxB;AAyCD;;;GAGG;AACH,eAAO,MAAM,WAAW;;;EAAqC,CAAC;AAE9D,MAAM,MAAM,WAAW,GAAG,OAAO,WAAW,CAAC;AAE7C,wBAAgB,cAAc,IAAI,WAAW,CAK5C"}
|
|
@@ -92,9 +92,42 @@ async function show(items, where) {
|
|
|
92
92
|
}
|
|
93
93
|
// Called before the promise settles, so that an app which only wants
|
|
94
94
|
// `onSelect` never has to await anything.
|
|
95
|
-
items
|
|
95
|
+
itemAt(items, index)?.onSelect?.();
|
|
96
96
|
return index;
|
|
97
97
|
}
|
|
98
|
+
/**
|
|
99
|
+
* The item an index names, which is its position in a pre-order walk of the
|
|
100
|
+
* whole menu: an item, then its children, then the next item, counting
|
|
101
|
+
* separators and parents.
|
|
102
|
+
*
|
|
103
|
+
* For a flat list that is the position in the array, which is what this answered
|
|
104
|
+
* when a popup could only be flat, so an index means what it has always meant.
|
|
105
|
+
* The native side numbers its items the same way; see `walkMenuEntries` in
|
|
106
|
+
* core/PlatformServices.h, which is the other half of this contract.
|
|
107
|
+
*
|
|
108
|
+
* An item the platform left out still counts, which is what lets both sides
|
|
109
|
+
* agree without this knowing which roles the platform has: the native side
|
|
110
|
+
* numbers every entry it was given and draws only the ones it can. See
|
|
111
|
+
* `menuEntryShown` beside it.
|
|
112
|
+
*/
|
|
113
|
+
function itemAt(items, index) {
|
|
114
|
+
let next = 0;
|
|
115
|
+
const walk = (level) => {
|
|
116
|
+
for (const item of level) {
|
|
117
|
+
if (next++ === index) {
|
|
118
|
+
return item;
|
|
119
|
+
}
|
|
120
|
+
if (item.submenu != null && item.submenu.length > 0) {
|
|
121
|
+
const found = walk(item.submenu);
|
|
122
|
+
if (found != null) {
|
|
123
|
+
return found;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return undefined;
|
|
128
|
+
};
|
|
129
|
+
return walk(items);
|
|
130
|
+
}
|
|
98
131
|
/**
|
|
99
132
|
* The imperative half, usable outside a component -- the same arrangement
|
|
100
133
|
* `useDialog()` and `windowControl` have.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useContextMenu.js","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;;;
|
|
1
|
+
{"version":3,"file":"useContextMenu.js","sourceRoot":"","sources":["../../src/useContextMenu.ts"],"names":[],"mappings":";AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA+DG;;;AAiLH,wCAKC;AAnLD,+CAAiD;AA4FjD,MAAM,UAAU,GAAG,kCAAmB,CAAC,GAAG,CAAmB,YAAY,CAAC,CAAC;AAE3E;;;;;GAKG;AACU,QAAA,WAAW,GAAG,UAAU,EAAE,eAAe,IAAI,IAAI,CAAC;AAE/D,KAAK,UAAU,IAAI,CACjB,KAAqC,EACrC,KAA+B;IAE/B,IAAI,CAAC,mBAAW,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QAChE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,4EAA4E;IAC5E,6EAA6E;IAC7E,2CAA2C;IAC3C,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IACzC,MAAM,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,KAAK,EAAE,KAAK,IAAI,CAAC,CAAC,CAAC;IAEzC,6EAA6E;IAC7E,8EAA8E;IAC9E,MAAM,KAAK,GAAG,MAAM,UAAW,CAAC,eAAe,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;IAC7D,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;QAClB,OAAO,IAAI,CAAC;IACd,CAAC;IACD,qEAAqE;IACrE,0CAA0C;IAC1C,MAAM,CAAC,KAAK,EAAE,KAAK,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC;IACnC,OAAO,KAAK,CAAC;AACf,CAAC;AAED;;;;;;;;;;;;;;GAcG;AACH,SAAS,MAAM,CACb,KAAqC,EACrC,KAAa;IAEb,IAAI,IAAI,GAAG,CAAC,CAAC;IACb,MAAM,IAAI,GAAG,CACX,KAAqC,EACR,EAAE;QAC/B,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,IAAI,EAAE,KAAK,KAAK,EAAE,CAAC;gBACrB,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,IAAI,CAAC,OAAO,IAAI,IAAI,IAAI,IAAI,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACpD,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACjC,IAAI,KAAK,IAAI,IAAI,EAAE,CAAC;oBAClB,OAAO,KAAK,CAAC;gBACf,CAAC;YACH,CAAC;QACH,CAAC;QACD,OAAO,SAAS,CAAC;IACnB,CAAC,CAAC;IACF,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC;AACrB,CAAC;AAED;;;GAGG;AACU,QAAA,WAAW,GAAG,MAAM,CAAC,MAAM,CAAC,EAAC,IAAI,EAAE,WAAW,EAAX,mBAAW,EAAC,CAAC,CAAC;AAI9D,SAAgB,cAAc;IAC5B,0EAA0E;IAC1E,8EAA8E;IAC9E,2BAA2B;IAC3B,OAAO,mBAAW,CAAC;AACrB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["../src/
|
|
1
|
+
{"root":["../src/DragSource.tsx","../src/DropTarget.tsx","../src/KeyHandler.tsx","../src/Menu.tsx","../src/TitleBar.tsx","../src/Window.tsx","../src/closeRequest.ts","../src/globals.d.ts","../src/index.ts","../src/quitRequest.ts","../src/resourcePath.ts","../src/responseBody.ts","../src/responseHeaders.ts","../src/titleBarState.ts","../src/useContextMenu.ts","../src/useDialog.ts","../src/useDisplays.ts","../src/useHandledKeys.ts","../src/useWindow.ts","../src/overrides/Alert.ts","../src/overrides/BaseViewConfig.ts","../src/overrides/Button.tsx","../src/overrides/Platform.d.ts","../src/overrides/Platform.linux.ts","../src/overrides/Platform.macos.ts","../src/overrides/Platform.windows.ts","../src/overrides/ReactDevToolsSettingsManager.ts","../src/overrides/RefreshControl.tsx","../src/overrides/ScrollView.tsx","../src/overrides/Settings.ts","../src/overrides/Share.ts","../src/overrides/TextInput.tsx","../src/overrides/View.tsx","../src/overrides/createPlatform.ts","../src/overrides/processDecelerationRate.ts","../src/overrides/setUpDeveloperTools.ts","../src/overrides/setUpXHR.ts","../src/overrides/upstream.d.ts","../cli/basalt.ts","../cli/bundle-cli.ts","../cli/bundleWithAssets.ts","../cli/desktop.ts","../cli/doctor.ts","../cli/init.ts","../cli/metro.ts","../cli/packageApp.ts","../cli/steps.ts","../react-native.config.js"],"version":"6.0.3"}
|
package/native/CMakeLists.txt
CHANGED
|
@@ -38,6 +38,14 @@ get_filename_component(BASALT_THIRD_PARTY "${BASALT_THIRD_PARTY}" ABSOLUTE)
|
|
|
38
38
|
# it alongside its own tests and brings its own `main`; see docs/TESTING.md.
|
|
39
39
|
set(BASALT_TEST_HARNESS ${CMAKE_CURRENT_SOURCE_DIR}/tests/TestHarness.cpp
|
|
40
40
|
CACHE INTERNAL "the toolkit-free test runner")
|
|
41
|
+
# What the harness calls and cannot define: a crashing test prints a stack
|
|
42
|
+
# rather than a silent non-zero exit. It lives in basalt_core, which a suite
|
|
43
|
+
# linking that target gets for free -- and the Windows view layer builds with
|
|
44
|
+
# no React Native and therefore no basalt_core, so that build has to compile
|
|
45
|
+
# this one file itself. Named here, beside the harness that needs it, rather
|
|
46
|
+
# than spelled as a path in the package that happens to hit the problem.
|
|
47
|
+
set(BASALT_CRASH_HANDLER ${CMAKE_CURRENT_SOURCE_DIR}/core/CrashHandler.cpp
|
|
48
|
+
CACHE INTERNAL "the crash handler the test harness installs")
|
|
41
49
|
set(BASALT_TEST_INCLUDE ${CMAKE_CURRENT_SOURCE_DIR}/tests
|
|
42
50
|
CACHE INTERNAL "where TestHarness.h lives")
|
|
43
51
|
|
|
@@ -52,13 +60,35 @@ set(BASALT_CORE_TESTS
|
|
|
52
60
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_app_paths.cpp
|
|
53
61
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scroll_animation.cpp
|
|
54
62
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_backface.cpp
|
|
63
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_gradients.cpp
|
|
64
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_label_registry.cpp
|
|
65
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_live_regions.cpp
|
|
66
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_filters.cpp
|
|
67
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_blend_modes.cpp
|
|
68
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_legacy_shadow.cpp
|
|
69
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_shadow_shape.cpp
|
|
70
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_background_layers.cpp
|
|
71
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_shadows.cpp
|
|
72
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_font_scaling.cpp
|
|
73
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_decorations.cpp
|
|
74
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_colors.cpp
|
|
75
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_font_variants.cpp
|
|
76
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_checking.cpp
|
|
55
77
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_drag_and_drop.cpp
|
|
56
78
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_quit_file.cpp
|
|
79
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_menu_entries.cpp
|
|
57
80
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_settle.cpp
|
|
58
81
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_key_events.cpp
|
|
59
82
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_js_runtime_access.cpp
|
|
60
83
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_image_cache.cpp
|
|
84
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_image_animation.cpp
|
|
85
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_image_progress.cpp
|
|
86
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_device_metrics.cpp
|
|
87
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_app_state.cpp
|
|
88
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_system_locale.cpp
|
|
89
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_font_fitting.cpp
|
|
61
90
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scroll_bounds.cpp
|
|
91
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scroll_visible_position.cpp
|
|
62
92
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scroll_indicator.cpp
|
|
63
93
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_scroll_snap.cpp
|
|
64
94
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_window_close.cpp
|
|
@@ -71,6 +101,10 @@ set(BASALT_CORE_TESTS
|
|
|
71
101
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_hover.cpp
|
|
72
102
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_momentum.cpp
|
|
73
103
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_share.cpp
|
|
104
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_settings_store.cpp
|
|
105
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_action_sheet.cpp
|
|
106
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_alignment.cpp
|
|
107
|
+
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_text_selection.cpp
|
|
74
108
|
${CMAKE_CURRENT_SOURCE_DIR}/tests/test_sourcecode.cpp
|
|
75
109
|
CACHE INTERNAL "core's own tests")
|
|
76
110
|
|
|
@@ -159,6 +193,22 @@ if(DEFINED RN_DIR)
|
|
|
159
193
|
get_property(basalt_package_installers GLOBAL PROPERTY BASALT_PACKAGE_EXPO_INSTALLERS)
|
|
160
194
|
get_property(basalt_package_core_sources GLOBAL PROPERTY BASALT_PACKAGE_CORE_SOURCES)
|
|
161
195
|
get_property(basalt_package_includes GLOBAL PROPERTY BASALT_PACKAGE_INCLUDES)
|
|
196
|
+
# And the ones that are somebody else's headers, which cannot be held to
|
|
197
|
+
# this project's warnings: Skia's trip `-Wpedantic` on a variadic macro, as
|
|
198
|
+
# React Native's own trip several, which is why those are `SYSTEM` too. A
|
|
199
|
+
# package says which of its include directories are its own and which are a
|
|
200
|
+
# dependency's.
|
|
201
|
+
get_property(basalt_package_system_includes GLOBAL PROPERTY BASALT_PACKAGE_SYSTEM_INCLUDES)
|
|
202
|
+
# And what a package wants *said* about itself, as preprocessor definitions.
|
|
203
|
+
#
|
|
204
|
+
# The hosts already have `BASALT_HAS_SKIA` and `BASALT_HAS_WORKLETS`, both set
|
|
205
|
+
# by a cmake/ file in this package for a dependency this package knows about.
|
|
206
|
+
# A capability package in somebody else's node_modules cannot reach either, and
|
|
207
|
+
# the first one that needed to is basalt-skia: whether the installed Skia is
|
|
208
|
+
# Graphite decides which of two canvases the AppKit mounting manager calls, and
|
|
209
|
+
# which surface the platform context makes. PUBLIC, so it reaches the host
|
|
210
|
+
# packages and their tests and not only core's own sources.
|
|
211
|
+
get_property(basalt_package_definitions GLOBAL PROPERTY BASALT_PACKAGE_DEFINITIONS)
|
|
162
212
|
|
|
163
213
|
# A semicolon by character code: CMake treats `;` as a list separator, and
|
|
164
214
|
# escaping it as `\;` survives into the generated file rather than becoming
|
|
@@ -203,7 +253,12 @@ if(DEFINED RN_DIR)
|
|
|
203
253
|
core/ImageCache.cpp
|
|
204
254
|
core/ScrollBounds.cpp
|
|
205
255
|
core/ScrollIndicator.cpp
|
|
256
|
+
core/AppStateHost.cpp
|
|
257
|
+
core/SystemLocale.cpp
|
|
258
|
+
core/DeviceMetrics.cpp
|
|
206
259
|
core/ScrollSnap.cpp
|
|
260
|
+
# Keeping the content still while items are inserted above it.
|
|
261
|
+
core/ScrollVisiblePosition.cpp
|
|
207
262
|
# `Appearance`, and the portable half of light-vs-dark.
|
|
208
263
|
core/AppearanceModule.cpp
|
|
209
264
|
# Blob, File and FileReader -- portable in full.
|
|
@@ -212,6 +267,8 @@ if(DEFINED RN_DIR)
|
|
|
212
267
|
core/ColorScheme.cpp
|
|
213
268
|
# Clipboard, Vibration, Alert, Linking, I18nManager, AccessibilityInfo --
|
|
214
269
|
# the core modules ReactCxxPlatform does not provide.
|
|
270
|
+
# `ActionSheetIOS`, which is a popup menu here; see the header.
|
|
271
|
+
core/ActionSheet.cpp
|
|
215
272
|
core/CoreModules.cpp
|
|
216
273
|
# <ActivityIndicator>, <Switch>, <RefreshControl> and <Modal>: the props
|
|
217
274
|
# three view layers have to read identically, plus the two shadow-node
|
|
@@ -229,6 +286,8 @@ if(DEFINED RN_DIR)
|
|
|
229
286
|
core/DebuggingOverlay.cpp
|
|
230
287
|
core/DevBundle.cpp
|
|
231
288
|
core/ExpoImageComponent.cpp
|
|
289
|
+
core/SafeAreaComponent.cpp
|
|
290
|
+
core/ScreensComponent.cpp
|
|
232
291
|
core/GestureHandlerModule.cpp
|
|
233
292
|
core/Gestures.cpp
|
|
234
293
|
# Hover: the pointer-event path React Native only has on Android.
|
|
@@ -251,14 +310,23 @@ if(DEFINED RN_DIR)
|
|
|
251
310
|
core/ScrollMomentum.cpp
|
|
252
311
|
# A share sheet for the desktops that have none; see the header.
|
|
253
312
|
core/ShareFallback.cpp
|
|
313
|
+
# `Settings`, which is a file here rather than NSUserDefaults; see the header.
|
|
314
|
+
core/SettingsStore.cpp
|
|
315
|
+
# Which way a paragraph runs when the app did not say; see the header.
|
|
316
|
+
core/TextDirection.cpp
|
|
317
|
+
# What a press and a drag mean inside selectable text; see the header.
|
|
318
|
+
core/TextSelection.cpp
|
|
254
319
|
core/SourceCodeModule.cpp
|
|
255
320
|
# Answering a modal dialog without showing one; see the header.
|
|
256
321
|
core/TestDialog.cpp
|
|
322
|
+
# What the host says when it dies, which was nothing; see the header.
|
|
323
|
+
core/CrashHandler.cpp
|
|
257
324
|
# Quitting gracefully when the harness says so, rather than on a budget
|
|
258
325
|
# fixed before launch; see the header.
|
|
259
326
|
core/TestQuitFile.cpp
|
|
260
327
|
# What a <Canvas> from @shopify/react-native-skia mounts; see the header.
|
|
261
328
|
core/SkiaPictureViewComponent.cpp
|
|
329
|
+
core/SkiaViewComponent.cpp
|
|
262
330
|
# globalThis.__turboModuleProxy, which a bridgeless runtime does not get; see
|
|
263
331
|
# the header.
|
|
264
332
|
core/TurboModuleProxy.cpp
|
|
@@ -303,7 +371,13 @@ if(DEFINED RN_DIR)
|
|
|
303
371
|
target_compile_definitions(basalt_core PUBLIC
|
|
304
372
|
BASALT_REACT_NATIVE_VERSION="${RN_VERSION}"
|
|
305
373
|
BASALT_RN_MINOR=${RN_MINOR})
|
|
374
|
+
if(basalt_package_definitions)
|
|
375
|
+
target_compile_definitions(basalt_core PUBLIC ${basalt_package_definitions})
|
|
376
|
+
endif()
|
|
306
377
|
target_include_directories(basalt_core PUBLIC core ${basalt_package_includes})
|
|
378
|
+
if(basalt_package_system_includes)
|
|
379
|
+
target_include_directories(basalt_core SYSTEM PUBLIC ${basalt_package_system_includes})
|
|
380
|
+
endif()
|
|
307
381
|
target_include_directories(basalt_core SYSTEM PUBLIC
|
|
308
382
|
${RN_DIR}/ReactCommon
|
|
309
383
|
${RN_DIR}/ReactCommon/jsi
|
|
@@ -316,7 +390,17 @@ if(DEFINED RN_DIR)
|
|
|
316
390
|
# "iosswitch" and which are ordinary portable C++ apart from the one
|
|
317
391
|
# measurement core/DesktopControls.cpp supplies. Android's needs fbjni;
|
|
318
392
|
# this one needs nothing.
|
|
319
|
-
${RN_DIR}/ReactCommon/react/renderer/components/switch/iosswitch
|
|
393
|
+
${RN_DIR}/ReactCommon/react/renderer/components/switch/iosswitch
|
|
394
|
+
# Hermes' public headers, which core already links and until now only its
|
|
395
|
+
# own directory could include. `include_directories()` in ThirdParty.cmake
|
|
396
|
+
# is directory-scoped, so a test in a *host* package linking core could
|
|
397
|
+
# call into Hermes and not include <hermes/hermes.h> -- which is what a
|
|
398
|
+
# test that wants a real jsi::Runtime needs, and the first one that wanted
|
|
399
|
+
# one is basalt-skia's. The same two directories ThirdParty.cmake names,
|
|
400
|
+
# for the same reason: RN's jsi is used rather than Hermes' vendored copy,
|
|
401
|
+
# so API/ and public/ only.
|
|
402
|
+
${HERMES_DIR}/API
|
|
403
|
+
${HERMES_DIR}/public)
|
|
320
404
|
# libcurl, because core/HttpClient.cpp is here. It used to be named only on
|
|
321
405
|
# basalt_gtk_mounting, which worked for exactly as long as the GTK host was the only
|
|
322
406
|
# thing linking core: the archive member goes unreferenced until something
|
package/native/cmake/Skia.cmake
CHANGED
|
@@ -65,9 +65,35 @@ endif()
|
|
|
65
65
|
|
|
66
66
|
if(NOT EXISTS ${SKIA_CPP_DIR}/rnskia/RNSkManager.cpp)
|
|
67
67
|
message(FATAL_ERROR
|
|
68
|
-
"no
|
|
69
|
-
"BASALT_SKIA should name an installed
|
|
70
|
-
"the one in the app's node_modules.")
|
|
68
|
+
"no React Native Skia C++ at ${SKIA_CPP_DIR}.\n"
|
|
69
|
+
"BASALT_SKIA should name an installed react-native-skia or "
|
|
70
|
+
"@shopify/react-native-skia, the one in the app's node_modules.")
|
|
71
|
+
endif()
|
|
72
|
+
|
|
73
|
+
file(READ ${SKIA_DIR}/package.json SKIA_PACKAGE_JSON)
|
|
74
|
+
string(JSON SKIA_VERSION GET "${SKIA_PACKAGE_JSON}" version)
|
|
75
|
+
|
|
76
|
+
# 3.x is a different renderer, not a newer one.
|
|
77
|
+
#
|
|
78
|
+
# It replaced Ganesh with Skia Graphite over Dawn, and this file is the Ganesh
|
|
79
|
+
# half: six of the seven Apple sources it borrows below do not exist in 3.x, and
|
|
80
|
+
# their replacement -- RNSkWindowSurface, which is portable C++ rather than
|
|
81
|
+
# Objective-C++ -- configures a CAMetalLayer or an ANativeWindow as a Dawn
|
|
82
|
+
# surface and nothing else, so neither GTK nor Win32 can use it as shipped
|
|
83
|
+
# either. backlog/compatibility.md records what each of the three would take.
|
|
84
|
+
#
|
|
85
|
+
# Said here as well as in the CLI because BASALT_SKIA can be set by hand, and
|
|
86
|
+
# the failure it saves is a bad one: `MetalContext.mm does not exist`, from a
|
|
87
|
+
# source list, naming a file nobody deleted. A version is the actual reason and
|
|
88
|
+
# this is the first place that knows it.
|
|
89
|
+
string(REGEX MATCH "^[0-9]+" SKIA_MAJOR "${SKIA_VERSION}")
|
|
90
|
+
if(SKIA_MAJOR AND SKIA_MAJOR GREATER_EQUAL 3)
|
|
91
|
+
message(FATAL_ERROR
|
|
92
|
+
"Skia ${SKIA_VERSION} at ${SKIA_DIR} is Graphite over Dawn, and this "
|
|
93
|
+
"platform's half is Ganesh.\n"
|
|
94
|
+
"Install the 2.x line -- `react-native-skia@release-2.x`, or "
|
|
95
|
+
"`@shopify/react-native-skia` -- or configure without BASALT_SKIA, "
|
|
96
|
+
"until basalt-skia carries the Graphite half.")
|
|
71
97
|
endif()
|
|
72
98
|
|
|
73
99
|
# The binaries are not in the package's `files`: they are downloaded, by the
|
|
@@ -96,9 +122,6 @@ if(NOT APPLE AND NOT WIN32 AND NOT EXISTS ${SKIA_LIBS_DIR}/libskia.a)
|
|
|
96
122
|
"its libs/linux/x86_64 here.")
|
|
97
123
|
endif()
|
|
98
124
|
|
|
99
|
-
file(READ ${SKIA_DIR}/package.json SKIA_PACKAGE_JSON)
|
|
100
|
-
string(JSON SKIA_VERSION GET "${SKIA_PACKAGE_JSON}" version)
|
|
101
|
-
|
|
102
125
|
# Every prebuilt archive the package imports on Apple, each a universal slice.
|
|
103
126
|
# Named rather than globbed: a missing one is a link error in somebody else's
|
|
104
127
|
# symbols, and a list says which we expected.
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
#include "ActionSheet.h"
|
|
2
|
+
|
|
3
|
+
#include <algorithm>
|
|
4
|
+
|
|
5
|
+
namespace basalt {
|
|
6
|
+
|
|
7
|
+
namespace {
|
|
8
|
+
|
|
9
|
+
MenuEntry disabledEntry(const std::string &label) {
|
|
10
|
+
// Assigned rather than a designated initializer, for the reason
|
|
11
|
+
// MenuEntry::separator() gives: a partial initializer list is an error under
|
|
12
|
+
// the -Werror the GTK build turns on.
|
|
13
|
+
MenuEntry entry;
|
|
14
|
+
entry.label = label;
|
|
15
|
+
entry.enabled = false;
|
|
16
|
+
return entry;
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
bool contains(const std::vector<int> &values, int value) {
|
|
20
|
+
return std::find(values.begin(), values.end(), value) != values.end();
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
} // namespace
|
|
24
|
+
|
|
25
|
+
ActionSheetMenu actionSheetMenu(const ActionSheetRequest &request) {
|
|
26
|
+
ActionSheetMenu built;
|
|
27
|
+
built.menu.x = request.x;
|
|
28
|
+
built.menu.y = request.y;
|
|
29
|
+
|
|
30
|
+
if (!request.title.empty()) {
|
|
31
|
+
built.menu.entries.push_back(disabledEntry(request.title));
|
|
32
|
+
}
|
|
33
|
+
if (!request.message.empty()) {
|
|
34
|
+
built.menu.entries.push_back(disabledEntry(request.message));
|
|
35
|
+
}
|
|
36
|
+
if (!built.menu.entries.empty()) {
|
|
37
|
+
built.menu.entries.push_back(MenuEntry::separator());
|
|
38
|
+
}
|
|
39
|
+
built.offset = static_cast<int>(built.menu.entries.size());
|
|
40
|
+
|
|
41
|
+
for (size_t index = 0; index < request.options.size(); ++index) {
|
|
42
|
+
MenuEntry entry;
|
|
43
|
+
entry.label = request.options[index];
|
|
44
|
+
entry.enabled = !contains(request.disabledIndices, static_cast<int>(index));
|
|
45
|
+
built.menu.entries.push_back(entry);
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
return built;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
std::optional<int> actionSheetChoice(const ActionSheetRequest &request,
|
|
52
|
+
const ActionSheetMenu &menu,
|
|
53
|
+
int chosen) {
|
|
54
|
+
const int count = static_cast<int>(request.options.size());
|
|
55
|
+
|
|
56
|
+
if (chosen < 0) {
|
|
57
|
+
// Dismissed. The cancel choice when the app named one, and otherwise
|
|
58
|
+
// nothing at all; see the header.
|
|
59
|
+
if (request.cancelIndex >= 0 && request.cancelIndex < count) {
|
|
60
|
+
return request.cancelIndex;
|
|
61
|
+
}
|
|
62
|
+
return std::nullopt;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const int option = chosen - menu.offset;
|
|
66
|
+
if (option < 0 || option >= count) {
|
|
67
|
+
// A header, or an index no entry of this menu has. Not reported: the app's
|
|
68
|
+
// callback takes an index into the array it passed, and there is nothing
|
|
69
|
+
// here to pass it.
|
|
70
|
+
return std::nullopt;
|
|
71
|
+
}
|
|
72
|
+
return option;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
} // namespace basalt
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
// `ActionSheetIOS`, which on a desktop is a popup menu.
|
|
2
|
+
//
|
|
3
|
+
// `ActionSheetManager` is a `get` lookup, so its absence was not a crash: the
|
|
4
|
+
// module came back null and `ActionSheetIOS.showActionSheetWithOptions` died on
|
|
5
|
+
// `invariant(RCTActionSheetManager, "ActionSheetManager doesn't exist")` at the
|
|
6
|
+
// first call. Unlike `Settings`, `Share` and `Alert`, there is no JavaScript to
|
|
7
|
+
// replace -- `ActionSheetIOS.js` has no `Platform.OS` branch at all and calls
|
|
8
|
+
// the module directly, which is why this is a module and nothing else. Worth
|
|
9
|
+
// knowing that the two shapes exist: an iOS-named API is not automatically one
|
|
10
|
+
// whose JavaScript refuses to run off iOS.
|
|
11
|
+
//
|
|
12
|
+
// ## A menu rather than a dialog
|
|
13
|
+
//
|
|
14
|
+
// An action sheet is a list of choices, one of which usually cancels, shown
|
|
15
|
+
// because of something the person just did. On a desktop that is a popup menu,
|
|
16
|
+
// and the alternative -- `presentAlert`, which this project already has -- loses
|
|
17
|
+
// more than it gains: a dialog can show the sheet's `title` and `message`, and
|
|
18
|
+
// it cannot show eight choices without looking like a mistake, cannot grey one
|
|
19
|
+
// out, and cannot be dismissed with Escape the way a menu can.
|
|
20
|
+
//
|
|
21
|
+
// So it is `presentMenu`, and the title and message go in as disabled entries
|
|
22
|
+
// at the top. That is a real desktop pattern and it moves the options down the
|
|
23
|
+
// list, which is why `offset` below exists: JavaScript numbers the array it
|
|
24
|
+
// passed, and a menu index counts every entry.
|
|
25
|
+
//
|
|
26
|
+
// ## What a desktop cannot do with it
|
|
27
|
+
//
|
|
28
|
+
// `destructiveButtonIndex` is accepted and ignored. None of the three can style
|
|
29
|
+
// one item of a popup menu as dangerous: GTK's `destructive-action` is a button
|
|
30
|
+
// class, `NSMenuItem` has no such style, and a Win32 menu item has no colour of
|
|
31
|
+
// its own. `tintColor`, `cancelButtonTintColor`, `disabledButtonTintColor` and
|
|
32
|
+
// `userInterfaceStyle` are iOS's own and are likewise ignored rather than
|
|
33
|
+
// refused, so code written for iOS runs unchanged. `disabledButtonIndices` is
|
|
34
|
+
// the one that *does* work, because a menu entry can be greyed.
|
|
35
|
+
|
|
36
|
+
#pragma once
|
|
37
|
+
|
|
38
|
+
#include "PlatformServices.h"
|
|
39
|
+
|
|
40
|
+
#include <optional>
|
|
41
|
+
#include <string>
|
|
42
|
+
#include <vector>
|
|
43
|
+
|
|
44
|
+
namespace basalt {
|
|
45
|
+
|
|
46
|
+
// What the app asked for, read off the options object once.
|
|
47
|
+
struct ActionSheetRequest {
|
|
48
|
+
std::string title;
|
|
49
|
+
std::string message;
|
|
50
|
+
std::vector<std::string> options;
|
|
51
|
+
// Indices into `options`, as `disabledButtonIndices` names them.
|
|
52
|
+
std::vector<int> disabledIndices;
|
|
53
|
+
// `cancelButtonIndex`, or -1 when the app named none. It is what a dismissal
|
|
54
|
+
// reports; see actionSheetChoice.
|
|
55
|
+
int cancelIndex{-1};
|
|
56
|
+
// Where the menu goes, in the window's coordinates. Negative means "wherever
|
|
57
|
+
// the pointer is", which is what MenuRequest means by it and what a sheet with
|
|
58
|
+
// no `anchor` wants.
|
|
59
|
+
double x{-1.0};
|
|
60
|
+
double y{-1.0};
|
|
61
|
+
};
|
|
62
|
+
|
|
63
|
+
// The popup menu an action sheet becomes, and how to read an answer back out.
|
|
64
|
+
struct ActionSheetMenu {
|
|
65
|
+
MenuRequest menu;
|
|
66
|
+
// How many entries the title, the message and their separator took, which is
|
|
67
|
+
// the difference between a menu index and the option index an app knows.
|
|
68
|
+
int offset{0};
|
|
69
|
+
};
|
|
70
|
+
|
|
71
|
+
ActionSheetMenu actionSheetMenu(const ActionSheetRequest &request);
|
|
72
|
+
|
|
73
|
+
// Which option to report for the menu index `chosen`, or nothing when the app's
|
|
74
|
+
// callback should not be called at all.
|
|
75
|
+
//
|
|
76
|
+
// Nothing, rather than -1, because that is iOS's behaviour and it is load
|
|
77
|
+
// bearing: `UIAlertController` invokes the callback from a button's handler, so
|
|
78
|
+
// a sheet that goes away without a button being pressed calls nothing, and an
|
|
79
|
+
// app that would otherwise act on "index -1" never has to.
|
|
80
|
+
//
|
|
81
|
+
// A dismissal is the one case where this platform answers something iOS does
|
|
82
|
+
// not. Escape closing a menu is far more ordinary than an iPad popover being
|
|
83
|
+
// tapped away, and an app that offered a cancel choice has already said what to
|
|
84
|
+
// do with it -- so a dismissal reports `cancelIndex` when there is one, and
|
|
85
|
+
// nothing when there is not.
|
|
86
|
+
std::optional<int> actionSheetChoice(const ActionSheetRequest &request,
|
|
87
|
+
const ActionSheetMenu &menu,
|
|
88
|
+
int chosen);
|
|
89
|
+
|
|
90
|
+
} // namespace basalt
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#include "AppStateHost.h"
|
|
2
|
+
|
|
3
|
+
#include <atomic>
|
|
4
|
+
#include <mutex>
|
|
5
|
+
|
|
6
|
+
namespace basalt {
|
|
7
|
+
|
|
8
|
+
namespace {
|
|
9
|
+
|
|
10
|
+
std::mutex &lock() {
|
|
11
|
+
static std::mutex value;
|
|
12
|
+
return value;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
std::atomic<AppStateKind> &state() {
|
|
16
|
+
// Active, not unknown: a host that never reports has still put a window on
|
|
17
|
+
// the screen, and `AppState.currentState` is read before any event can
|
|
18
|
+
// arrive. React Native has an `unknown` for a platform that cannot tell, and
|
|
19
|
+
// all three of these can.
|
|
20
|
+
static std::atomic<AppStateKind> value{AppStateKind::Active};
|
|
21
|
+
return value;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
std::function<void(AppStateKind)> &listener() {
|
|
25
|
+
static std::function<void(AppStateKind)> value;
|
|
26
|
+
return value;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
} // namespace
|
|
30
|
+
|
|
31
|
+
const char *appStateName(AppStateKind state) {
|
|
32
|
+
switch (state) {
|
|
33
|
+
case AppStateKind::Active:
|
|
34
|
+
return "active";
|
|
35
|
+
case AppStateKind::Inactive:
|
|
36
|
+
return "inactive";
|
|
37
|
+
case AppStateKind::Background:
|
|
38
|
+
return "background";
|
|
39
|
+
}
|
|
40
|
+
return "active";
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
AppStateKind appStateFor(bool focused, bool visible) {
|
|
44
|
+
if (!visible) {
|
|
45
|
+
return AppStateKind::Background;
|
|
46
|
+
}
|
|
47
|
+
return focused ? AppStateKind::Active : AppStateKind::Inactive;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
void notifyAppState(AppStateKind next) {
|
|
51
|
+
std::function<void(AppStateKind)> toCall;
|
|
52
|
+
{
|
|
53
|
+
const std::lock_guard<std::mutex> guard(lock());
|
|
54
|
+
if (state().load(std::memory_order_relaxed) == next) {
|
|
55
|
+
return;
|
|
56
|
+
}
|
|
57
|
+
state().store(next, std::memory_order_relaxed);
|
|
58
|
+
toCall = listener();
|
|
59
|
+
}
|
|
60
|
+
// Outside the lock: it emits into the JavaScript runtime, and holding a lock
|
|
61
|
+
// across that is how a deadlock is built.
|
|
62
|
+
if (toCall) {
|
|
63
|
+
toCall(next);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
AppStateKind currentAppState() {
|
|
68
|
+
return state().load(std::memory_order_relaxed);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
void setAppStateListener(std::function<void(AppStateKind)> next) {
|
|
72
|
+
const std::lock_guard<std::mutex> guard(lock());
|
|
73
|
+
listener() = std::move(next);
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
} // namespace basalt
|