Skip to content

Commit 0ce4f89

Browse files
committed
Merge branch 'main' into @mbert/docs-review
2 parents 9b4aff8 + e99cf63 commit 0ce4f89

12 files changed

Lines changed: 287 additions & 65 deletions

File tree

.github/actions/publish-npm-package/action.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@ name: publish-npm-package
22
description: Build and publish react-native-gesture-handler package to npm
33
inputs:
44
release-type:
5-
description: Release type to be published (stable, commitly, beta, rc).
6-
default: "commitly"
5+
description: Release type to be published (stable, nightly, beta, rc).
6+
default: "nightly"
77
version:
88
description: Specific version to publish (usually inferred from x.y-stable branch name).
99
default: ""
@@ -31,15 +31,15 @@ runs:
3131
id: set-package-version
3232
shell: bash
3333
run: |
34-
VERSION=$(node ./scripts/release/set-package-version.js ${{ inputs.release-type == 'commitly' && '--commitly' || '' }} ${{ inputs.release-type == 'beta' && '--beta' || '' }} ${{ inputs.release-type == 'rc' && '--rc' || '' }} ${{ inputs.version != '' && format('--version ''{0}''', inputs.version) || '' }})
34+
VERSION=$(node ./scripts/release/set-package-version.js ${{ inputs.release-type == 'nightly' && '--nightly' || '' }} ${{ inputs.release-type == 'beta' && '--beta' || '' }} ${{ inputs.release-type == 'rc' && '--rc' || '' }} ${{ inputs.version != '' && format('--version ''{0}''', inputs.version) || '' }})
3535
echo "Updated package version to $VERSION"
3636
echo "version=$VERSION" >> $GITHUB_OUTPUT
3737
3838
- name: Figure out the correct npm tag
3939
id: figure-out-npm-tag
4040
shell: bash
4141
run: |
42-
if [ "${{ inputs.release-type == 'commitly' }}" = "true" ]; then
42+
if [ "${{ inputs.release-type == 'nightly' }}" = "true" ]; then
4343
TAG_ARGUMENT="--tag nightly"
4444
else
4545
if [ "${{ inputs.release-type == 'beta' || inputs.release-type == 'rc' }}" = "true" ]; then

.github/workflows/publish-release.yml

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,8 @@
11
name: Publish release to npm
22
on:
3-
# For commitlies
4-
# push:
5-
# branches:
6-
# - main
7-
# paths:
8-
# - packages/react-native-gesture-handler/**
3+
# For nightly releases
4+
schedule:
5+
- cron: '27 23 * * *' # at 23:27 every day
96
# For manual releases
107
workflow_dispatch:
118
inputs:
@@ -14,6 +11,7 @@ on:
1411
type: choice
1512
options:
1613
- stable
14+
- nightly
1715
- beta
1816
- rc
1917
default: stable
@@ -52,9 +50,9 @@ jobs:
5250
version: ${{ inputs.version }}
5351
dry-run: ${{ inputs.dry-run }}
5452

55-
- name: Publish automatic commitly release
56-
if: ${{ github.event_name == 'push' }}
53+
- name: Publish automatic nightly release
54+
if: ${{ github.event_name == 'schedule' }}
5755
uses: ./.github/actions/publish-npm-package
5856
with:
59-
release-type: 'commitly'
57+
release-type: 'nightly'
6058
dry-run: false

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerDetectorView.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
109109
}
110110

111111
for (tag in handlersToDetach) {
112-
registry.detachHandler(tag)
112+
registry.detachHandlerFromHostDetector(tag, this)
113113
nativeHandlers.remove(tag)
114114
attachedHandlers.remove(tag)
115115
}
@@ -134,7 +134,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
134134

135135
for (child in virtualChildrenToDetach) {
136136
for (tag in attachedVirtualHandlers[child]!!) {
137-
registry.detachHandler(tag)
137+
registry.detachHandlerFromHostDetector(tag, this)
138138
}
139139
attachedVirtualHandlers.remove(tag)
140140
}
@@ -182,7 +182,7 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
182182
?: throw Exception("Tried to access a non-existent registry")
183183

184184
for (tag in nativeHandlers) {
185-
registry.detachHandler(tag)
185+
registry.detachHandlerFromHostDetector(tag, this)
186186
attachedHandlers.remove(tag)
187187
}
188188
}
@@ -197,13 +197,13 @@ class RNGestureHandlerDetectorView(context: Context) : ReactViewGroup(context) {
197197
?: throw Exception("Tried to access a non-existent registry")
198198

199199
for (tag in attachedHandlers.toMutableSet()) {
200-
registry.detachHandler(tag)
200+
registry.detachHandlerFromHostDetector(tag, this)
201201
attachedHandlers.remove(tag)
202202
}
203203

204204
for (child in attachedVirtualHandlers) {
205205
for (tag in child.value) {
206-
registry.detachHandler(tag)
206+
registry.detachHandlerFromHostDetector(tag, this)
207207
}
208208
child.value.clear()
209209
}

packages/react-native-gesture-handler/android/src/main/java/com/swmansion/gesturehandler/react/RNGestureHandlerRegistry.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,8 +78,9 @@ class RNGestureHandlerRegistry : GestureHandlerRegistry {
7878
}
7979

8080
@Synchronized
81-
fun detachHandler(handlerTag: Int) {
81+
fun detachHandlerFromHostDetector(handlerTag: Int, hostDetectorView: RNGestureHandlerDetectorView?) {
8282
handlers[handlerTag]?.let {
83+
if (it.hostDetectorView != hostDetectorView) return
8384
detachHandlerInternal(it)
8485
}
8586
}

packages/react-native-gesture-handler/apple/RNGestureHandlerDetector.mm

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -53,11 +53,11 @@ - (void)willMoveToWindow:(RNGHWindow *)newWindow
5353

5454
for (const auto handler : props.handlerTags) {
5555
NSNumber *handlerTag = [NSNumber numberWithInt:handler];
56-
[handlerManager.registry detachHandlerWithTag:handlerTag];
56+
[handlerManager.registry detachHandlerWithTag:handlerTag fromHostDetector:self];
5757
}
5858
for (const auto &child : _attachedVirtualHandlers) {
5959
for (id handlerTag : child.second) {
60-
[handlerManager.registry detachHandlerWithTag:handlerTag];
60+
[handlerManager.registry detachHandlerWithTag:handlerTag fromHostDetector:self];
6161
}
6262
}
6363
_attachedVirtualHandlers.clear();
@@ -232,7 +232,7 @@ - (void)attachHandlers:(const std::vector<int> &)handlerTags
232232
}
233233

234234
for (const id tag : handlersToDetach) {
235-
[handlerManager.registry detachHandlerWithTag:tag];
235+
[handlerManager.registry detachHandlerWithTag:tag fromHostDetector:self];
236236
[attachedHandlers removeObject:tag];
237237
[_nativeHandlers removeObject:tag];
238238
}
@@ -276,7 +276,7 @@ - (void)updateVirtualChildren:(const std::vector<RNGestureHandlerDetectorVirtual
276276

277277
for (const NSNumber *tag : virtualChildrenToDetach) {
278278
for (id handlerTag : _attachedVirtualHandlers[tag.intValue]) {
279-
[handlerManager.registry detachHandlerWithTag:handlerTag];
279+
[handlerManager.registry detachHandlerWithTag:handlerTag fromHostDetector:self];
280280
}
281281
_attachedVirtualHandlers.erase(tag.intValue);
282282
}
@@ -326,7 +326,7 @@ - (void)detachNativeGestureHandlers
326326
RNGestureHandlerManager *handlerManager = [RNGestureHandlerModule handlerManagerForModuleId:_moduleId];
327327

328328
for (NSNumber *handlerTag in _nativeHandlers) {
329-
[[handlerManager registry] detachHandlerWithTag:handlerTag];
329+
[[handlerManager registry] detachHandlerWithTag:handlerTag fromHostDetector:self];
330330
[_attachedHandlers removeObject:handlerTag];
331331
}
332332
}

packages/react-native-gesture-handler/apple/RNGestureHandlerRegistry.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
withActionType:(RNGestureHandlerActionType)actionType
1818
withHostDetector:(nullable RNGHUIView *)hostDetector;
1919
- (void)detachHandlerWithTag:(nonnull NSNumber *)handlerTag;
20+
- (void)detachHandlerWithTag:(nonnull NSNumber *)handlerTag fromHostDetector:(nonnull RNGHUIView *)hostDetectorView;
2021
- (void)dropHandlerWithTag:(nonnull NSNumber *)handlerTag;
2122
- (void)dropAllHandlers;
2223

packages/react-native-gesture-handler/apple/RNGestureHandlerRegistry.m

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,9 +48,11 @@ - (void)attachHandlerWithTag:(NSNumber *)handlerTag
4848
}
4949
}
5050

51-
- (void)detachHandlerWithTag:(NSNumber *)handlerTag
51+
- (void)detachHandlerWithTag:(NSNumber *)handlerTag fromHostDetector:(RNGHUIView *)hostDetectorView
5252
{
5353
RNGestureHandler *handler = _handlers[handlerTag];
54+
if (handler.hostDetectorView != hostDetectorView)
55+
return;
5456
[handler unbindFromView];
5557
}
5658

scripts/release/__tests__/get-version.test.js

Lines changed: 46 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,13 @@ jest.mock('../version-utils', () => ({
1010
parseVersion: jest.fn(),
1111
}));
1212

13+
jest.mock('../npm-utils', () => ({
14+
getPackageVersionByTag: jest.fn(),
15+
}));
16+
1317
const { execSync } = require('child_process');
1418
const { getStableBranchVersion, getLatestVersion, getNextPreReleaseVersion, getNextStableVersion, parseVersion } = require('../version-utils');
19+
const { getPackageVersionByTag } = require('../npm-utils');
1520
const { getVersion } = require('../get-version');
1621
const { ReleaseType } = require('../parse-arguments');
1722

@@ -29,40 +34,52 @@ describe('get-version', () => {
2934
return new RealDate(...args);
3035
}
3136
};
37+
38+
// By default, simulate that the latest nightly was published with a different SHA
39+
getPackageVersionByTag.mockReturnValue('3.0.0-nightly-20260128-previoussha');
3240
});
3341

3442
afterEach(() => {
3543
global.Date = RealDate;
3644
});
3745

3846
describe('getVersion', () => {
39-
// Commitly/nightly release tests
40-
describe('commitly releases', () => {
47+
// Nightly release tests
48+
describe('nightly releases', () => {
4149
test('returns nightly version with date and SHA', () => {
42-
getLatestVersion.mockReturnValue([2, 22, 0, null]);
50+
getLatestVersion.mockReturnValue([3, 0, 0, null]);
4351
execSync.mockReturnValue(Buffer.from('abc123def456789\n'));
4452

45-
const result = getVersion(ReleaseType.COMMITLY);
53+
const result = getVersion(ReleaseType.NIGHTLY);
4654

47-
expect(result).toBe('2.23.0-nightly-20260129-abc123def');
55+
expect(result).toBe('3.1.0-nightly-20260129-abc123def');
4856
expect(getLatestVersion).toHaveBeenCalled();
4957
expect(execSync).toHaveBeenCalledWith('git rev-parse HEAD');
5058
});
5159

5260
test('increments minor version from latest', () => {
53-
getLatestVersion.mockReturnValue([2, 25, 3, null]);
61+
getLatestVersion.mockReturnValue([3, 0, 0, null]);
62+
execSync.mockReturnValue(Buffer.from('fedcba987654321\n'));
63+
64+
const result = getVersion(ReleaseType.NIGHTLY);
65+
66+
expect(result).toBe('3.1.0-nightly-20260129-fedcba987');
67+
});
68+
69+
test('overrides major 2.x release to 3.0.0 nightly', () => {
70+
getLatestVersion.mockReturnValue([2, 22, 0, null]);
5471
execSync.mockReturnValue(Buffer.from('fedcba987654321\n'));
5572

56-
const result = getVersion(ReleaseType.COMMITLY);
73+
const result = getVersion(ReleaseType.NIGHTLY);
5774

58-
expect(result).toBe('2.26.0-nightly-20260129-fedcba987');
75+
expect(result).toBe('3.0.0-nightly-20260129-fedcba987');
5976
});
6077

6178
test('uses first 9 characters of SHA', () => {
6279
getLatestVersion.mockReturnValue([2, 22, 0, null]);
6380
execSync.mockReturnValue(Buffer.from('123456789abcdef0\n'));
6481

65-
const result = getVersion(ReleaseType.COMMITLY);
82+
const result = getVersion(ReleaseType.NIGHTLY);
6683

6784
expect(result).toContain('-123456789');
6885
expect(result).not.toContain('abcdef0');
@@ -80,11 +97,29 @@ describe('get-version', () => {
8097
getLatestVersion.mockReturnValue([2, 22, 0, null]);
8198
execSync.mockReturnValue(Buffer.from('abc123def\n'));
8299

83-
const result = getVersion(ReleaseType.COMMITLY);
100+
const result = getVersion(ReleaseType.NIGHTLY);
84101

85102
expect(result).toContain('-nightly-20261205-');
86103
});
87104

105+
test('throws when latest nightly SHA matches current SHA', () => {
106+
global.Date = class extends RealDate {
107+
constructor(...args) {
108+
if (args.length === 0) {
109+
return new RealDate('2026-12-05T12:00:00Z');
110+
}
111+
return new RealDate(...args);
112+
}
113+
};
114+
getLatestVersion.mockReturnValue([2, 22, 0, null]);
115+
execSync.mockReturnValue(Buffer.from('abc123def\n'));
116+
getPackageVersionByTag.mockReturnValue('3.0.0-nightly-20261205-abc123def');
117+
118+
expect(() => getVersion(ReleaseType.NIGHTLY)).toThrow(
119+
'Latest nightly version 3.0.0-nightly-20261205-abc123def SHA abc123def is the same as current SHA abc123def'
120+
);
121+
});
122+
88123
test('pads single digit month and day', () => {
89124
global.Date = class extends RealDate {
90125
constructor(...args) {
@@ -97,7 +132,7 @@ describe('get-version', () => {
97132
getLatestVersion.mockReturnValue([2, 22, 0, null]);
98133
execSync.mockReturnValue(Buffer.from('abc123def\n'));
99134

100-
const result = getVersion(ReleaseType.COMMITLY);
135+
const result = getVersion(ReleaseType.NIGHTLY);
101136

102137
expect(result).toContain('-nightly-20260307-');
103138
});

scripts/release/__tests__/parse-arguments.test.js

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -26,10 +26,10 @@ describe('parse-arguments', () => {
2626
});
2727

2828
// Single flag tests
29-
test('returns commitly release type with --commitly flag', () => {
30-
process.argv = ['node', 'script.js', '--commitly'];
29+
test('returns nightly release type with --nightly flag', () => {
30+
process.argv = ['node', 'script.js', '--nightly'];
3131
const result = parseArguments();
32-
expect(result).toEqual({ releaseType: ReleaseType.COMMITLY, version: null });
32+
expect(result).toEqual({ releaseType: ReleaseType.NIGHTLY, version: null });
3333
});
3434

3535
test('returns beta release type with --beta flag', () => {
@@ -64,29 +64,29 @@ describe('parse-arguments', () => {
6464
});
6565

6666
// Mutual exclusivity tests
67-
test('throws error when --commitly and --beta are both provided', () => {
68-
process.argv = ['node', 'script.js', '--commitly', '--beta'];
69-
expect(() => parseArguments()).toThrow('Release flags --commitly, --beta, and --rc are mutually exclusive');
67+
test('throws error when --nightly and --beta are both provided', () => {
68+
process.argv = ['node', 'script.js', '--nightly', '--beta'];
69+
expect(() => parseArguments()).toThrow('Release flags --nightly, --beta, and --rc are mutually exclusive');
7070
});
7171

72-
test('throws error when --commitly and --rc are both provided', () => {
73-
process.argv = ['node', 'script.js', '--commitly', '--rc'];
74-
expect(() => parseArguments()).toThrow('Release flags --commitly, --beta, and --rc are mutually exclusive');
72+
test('throws error when --nightly and --rc are both provided', () => {
73+
process.argv = ['node', 'script.js', '--nightly', '--rc'];
74+
expect(() => parseArguments()).toThrow('Release flags --nightly, --beta, and --rc are mutually exclusive');
7575
});
7676

7777
test('throws error when --beta and --rc are both provided', () => {
7878
process.argv = ['node', 'script.js', '--beta', '--rc'];
79-
expect(() => parseArguments()).toThrow('Release flags --commitly, --beta, and --rc are mutually exclusive');
79+
expect(() => parseArguments()).toThrow('Release flags --nightly, --beta, and --rc are mutually exclusive');
8080
});
8181

8282
test('throws error when all three flags are provided', () => {
83-
process.argv = ['node', 'script.js', '--commitly', '--beta', '--rc'];
84-
expect(() => parseArguments()).toThrow('Release flags --commitly, --beta, and --rc are mutually exclusive');
83+
process.argv = ['node', 'script.js', '--nightly', '--beta', '--rc'];
84+
expect(() => parseArguments()).toThrow('Release flags --nightly, --beta, and --rc are mutually exclusive');
8585
});
8686

87-
// Version not allowed for commitly
88-
test('throws error when version provided for commitly release', () => {
89-
process.argv = ['node', 'script.js', '--commitly', '--version', '2.22.0'];
87+
// Version not allowed for nightly
88+
test('throws error when version provided for nightly release', () => {
89+
process.argv = ['node', 'script.js', '--nightly', '--version', '2.22.0'];
9090
expect(() => parseArguments()).toThrow();
9191
});
9292

@@ -147,7 +147,7 @@ describe('parse-arguments', () => {
147147
expect(ReleaseType.STABLE).toBe('stable');
148148
expect(ReleaseType.BETA).toBe('beta');
149149
expect(ReleaseType.RELEASE_CANDIDATE).toBe('rc');
150-
expect(ReleaseType.COMMITLY).toBe('commitly');
150+
expect(ReleaseType.NIGHTLY).toBe('nightly');
151151
});
152152
});
153153
});

0 commit comments

Comments
 (0)