Skip to content

Commit 5a1e089

Browse files
authored
refactor: migrate ShareExtensionStack to React Navigation static config (#7413)
1 parent 0487378 commit 5a1e089

3 files changed

Lines changed: 41 additions & 30 deletions

File tree

app/definitions/navigationTypes.ts

Lines changed: 3 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
import { type NavigatorScreenParams } from '@react-navigation/core';
22
import { type NativeStackNavigationOptions } from '@react-navigation/native-stack';
33

4-
import { type TSubscriptionModel } from './ISubscription';
5-
import { type TServerModel } from './IServer';
6-
import { type IAttachment } from './IAttachment';
74
import { type MasterDetailInsideStackParamList } from '../stacks/MasterDetailStack/types';
85
import { type OutsideParamList, type InsideStackParamList } from '../stacks/types';
6+
import { type ShareInsideStackParamList } from '../stacks/ShareExtensionStack';
7+
8+
export type { ShareInsideStackParamList };
99

1010
interface INavigationProps {
1111
route?: any;
@@ -31,17 +31,3 @@ export type StackParamList = {
3131
SetUsernameStack: NavigatorScreenParams<SetUsernameStackParamList>;
3232
ShareExtensionStack: NavigatorScreenParams<ShareInsideStackParamList>;
3333
};
34-
35-
export type ShareInsideStackParamList = {
36-
ShareListView: undefined;
37-
ShareView: {
38-
attachments: IAttachment[];
39-
isShareView?: boolean;
40-
isShareExtension: boolean;
41-
serverInfo: TServerModel;
42-
text: string;
43-
room: TSubscriptionModel;
44-
thread?: any; // TODO: Change
45-
};
46-
SelectServerView: undefined;
47-
};
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { useNavigation } from '@react-navigation/native';
2+
import { type ComponentType } from 'react';
3+
4+
function withNavigation<P extends { navigation: any }>(WrappedComponent: ComponentType<P>): ComponentType<Omit<P, 'navigation'>> {
5+
// Screen-registration-only bridge: static API passes only { route } to screens, so no ref forwarding needed.
6+
const WithNavigation = (props: Omit<P, 'navigation'>) => {
7+
const navigation = useNavigation();
8+
return <WrappedComponent {...(props as P)} navigation={navigation} />;
9+
};
10+
WithNavigation.displayName = `WithNavigation(${WrappedComponent.displayName || WrappedComponent.name || 'Component'})`;
11+
return WithNavigation;
12+
}
13+
14+
export default withNavigation;

app/stacks/ShareExtensionStack.tsx

Lines changed: 24 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
1-
import { useContext } from 'react';
1+
import { useContext, type ComponentType } from 'react';
22
import { createNativeStackNavigator } from '@react-navigation/native-stack';
3+
import { type StaticParamList, type StaticScreenProps } from '@react-navigation/native';
34

45
import { ThemeContext } from '../theme';
56
import { defaultHeader, themedHeader } from '../lib/methods/helpers/navigation';
67
import SelectServerView from '../views/SelectServerView';
78
import ShareListView from '../views/ShareListView';
89
import ShareView from '../views/ShareView';
10+
import withNavigation from '../lib/navigation/withNavigation';
11+
import { type InsideStackParamList } from './types';
12+
import { type Optional } from '../definitions/utils';
913

10-
const ShareExtension = createNativeStackNavigator<any>();
11-
const ShareExtensionStack = () => {
14+
type ShareViewParams = Optional<InsideStackParamList['ShareView'], 'thread' | 'action' | 'finishShareView' | 'startShareView'>;
15+
16+
// Cast through `any` to break the navigation-prop type cycle; removing it reintroduces a real TS circular ref.
17+
const ShareListViewScreen: ComponentType<StaticScreenProps<undefined>> = withNavigation(ShareListView as any) as any;
18+
const ShareViewScreen: ComponentType<StaticScreenProps<ShareViewParams>> = withNavigation(ShareView as any) as any;
19+
20+
const ShareExtension = createNativeStackNavigator({
21+
screenOptions: defaultHeader,
22+
screens: {
23+
ShareListView: ShareListViewScreen,
24+
ShareView: ShareViewScreen,
25+
SelectServerView
26+
}
27+
}).with(({ Navigator }) => {
1228
'use memo';
1329

1430
const { theme } = useContext(ThemeContext);
31+
return <Navigator screenOptions={themedHeader(theme)} />;
32+
});
33+
34+
export type ShareInsideStackParamList = StaticParamList<typeof ShareExtension>;
1535

16-
return (
17-
<ShareExtension.Navigator screenOptions={{ ...defaultHeader, ...themedHeader(theme) }}>
18-
{/* @ts-ignore */}
19-
<ShareExtension.Screen name='ShareListView' component={ShareListView} />
20-
{/* @ts-ignore */}
21-
<ShareExtension.Screen name='ShareView' component={ShareView} />
22-
<ShareExtension.Screen name='SelectServerView' component={SelectServerView} />
23-
</ShareExtension.Navigator>
24-
);
25-
};
36+
const ShareExtensionStack = ShareExtension.getComponent();
2637

2738
export default ShareExtensionStack;

0 commit comments

Comments
 (0)