Skip to content

Commit b80c461

Browse files
chore: define handler for frame launching
1 parent 559fa03 commit b80c461

File tree

5 files changed

+85
-34
lines changed

5 files changed

+85
-34
lines changed

packages/render/src/ui/frame.base.tsx

+35-11
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import {
77
useState,
88
} from "react";
99
import type { FrameState } from "../types";
10-
import type { UseFrameReturnValue } from "../unstable-types";
10+
import type { PartialFrameV2, UseFrameReturnValue } from "../unstable-types";
1111
import { useFreshRef } from "../hooks/use-fresh-ref";
1212
import type {
1313
FrameMessage,
@@ -17,7 +17,6 @@ import type {
1717
RootContainerDimensions,
1818
RootContainerElement,
1919
FrameButtonProps,
20-
PartialFrameV2,
2120
} from "./types";
2221
import {
2322
getErrorMessageFromFramesStackItem,
@@ -30,7 +29,7 @@ export type FrameUIComponents<TStylingProps extends Record<string, unknown>> =
3029
export type FrameUITheme<TStylingProps extends Record<string, unknown>> =
3130
Partial<FrameUIComponentStylingProps<TStylingProps>>;
3231

33-
export type AppLaunchButtonPressEvent =
32+
export type FrameUILaunchFrameButtonPressEvent =
3433
| {
3534
status: "complete";
3635
frame: FrameV2;
@@ -42,6 +41,10 @@ export type AppLaunchButtonPressEvent =
4241
frameUIState: FrameUIState;
4342
};
4443

44+
export type FrameUILaunchFrameButtonPressHandler = (
45+
event: FrameUILaunchFrameButtonPressEvent
46+
) => void;
47+
4548
export type BaseFrameUIProps<TStylingProps extends Record<string, unknown>> = {
4649
frameState:
4750
| FrameState<any, any>
@@ -81,13 +84,13 @@ export type BaseFrameUIProps<TStylingProps extends Record<string, unknown>> = {
8184
*
8285
* Only Frames v2 support this feature.
8386
*/
84-
onAppLaunchButtonPress?: (event: AppLaunchButtonPressEvent) => void;
87+
onLaunchFrameButtonPress?: FrameUILaunchFrameButtonPressHandler;
8588
/**
8689
* Called when an error occurs in onAppLaunchButtonPress
8790
*
8891
* @defaultValue console.error()
8992
*/
90-
onAppLaunchButtonPressError?: (error: Error) => void;
93+
onLaunchFrameButtonPressError?: (error: Error) => void;
9194
};
9295

9396
// eslint-disable-next-line @typescript-eslint/no-empty-function -- this is noop
@@ -113,19 +116,20 @@ export function BaseFrameUI<TStylingProps extends Record<string, unknown>>({
113116
allowPartialFrame = false,
114117
enableImageDebugging = false,
115118
onError = defaultErrorLogger,
116-
onAppLaunchButtonPressError = defaultErrorLogger,
119+
onLaunchFrameButtonPressError = defaultErrorLogger,
117120
onMessage = defaultMessageHandler,
118121
createElement = reactCreateElement,
119-
onAppLaunchButtonPress = defaultOnAppLaunchButtonPress,
122+
onLaunchFrameButtonPress = defaultOnAppLaunchButtonPress,
120123
}: BaseFrameUIProps<TStylingProps>): JSX.Element | null {
121124
const [isImageLoading, setIsImageLoading] = useState(true);
122125
const { currentFrameStackItem } = frameState;
123126
const rootRef = useRef<RootContainerElement>(null);
124127
const rootDimensionsRef = useRef<RootContainerDimensions | undefined>();
125128
const onErrorRef = useFreshRef(onError);
126-
const onAppLaunchButtonPressErrorRef = useFreshRef(
127-
onAppLaunchButtonPressError
129+
const onLaunchFrameButtonPressErrorRef = useFreshRef(
130+
onLaunchFrameButtonPressError
128131
);
132+
const onLaunchFrameButtonPressRef = useFreshRef(onLaunchFrameButtonPress);
129133

130134
const onImageLoadEnd = useCallback(() => {
131135
setIsImageLoading(false);
@@ -340,7 +344,27 @@ export function BaseFrameUI<TStylingProps extends Record<string, unknown>>({
340344
onPress() {
341345
// we don't need to track dimensions here because this button does nothing to frame stack
342346
try {
343-
onAppLaunchButtonPress(
347+
if (!("onLaunchFrameButtonPress" in frameState)) {
348+
throw new Error(
349+
"onLaunchFrameButtonPress is not implemented, you are porbably using old useFrame hook"
350+
);
351+
}
352+
353+
// call onLaunchFrameButtonPress on useFrame() hook
354+
// because that's where the core of the frame v2 message handling is implemented
355+
frameState.onLaunchFrameButtonPress(
356+
frameUiState.status === "complete"
357+
? {
358+
status: "complete",
359+
frame: frameUiState.frame,
360+
}
361+
: {
362+
status: "partial",
363+
frame: frameUiState.frame,
364+
}
365+
);
366+
367+
onLaunchFrameButtonPressRef.current(
344368
frameUiState.status === "complete"
345369
? {
346370
status: "complete",
@@ -354,7 +378,7 @@ export function BaseFrameUI<TStylingProps extends Record<string, unknown>>({
354378
}
355379
);
356380
} catch (e) {
357-
onAppLaunchButtonPressErrorRef.current(
381+
onLaunchFrameButtonPressErrorRef.current(
358382
e instanceof Error ? e : new Error(String(e))
359383
);
360384
}

packages/render/src/ui/types.ts

+1-22
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import type { Frame, FrameButton, FrameV2 } from "frames.js";
22
import type { createElement, ReactElement } from "react";
3-
import type { ParsedFrameV2 } from "frames.js/frame-parsers";
43
import type { FrameState } from "../types";
5-
import type { UseFrameReturnValue } from "../unstable-types";
4+
import type { PartialFrameV2, UseFrameReturnValue } from "../unstable-types";
65

76
/**
87
* Allows to override styling props on all component of the Frame UI
@@ -31,26 +30,6 @@ type RequiredFrameProperties = "image" | "buttons";
3130
export type PartialFrame = Omit<Partial<Frame>, RequiredFrameProperties> &
3231
Required<Pick<Frame, RequiredFrameProperties>>;
3332

34-
/**
35-
* If partial frame rendering is enabled this is the shape of the frame
36-
*/
37-
export type PartialFrameV2 = Omit<ParsedFrameV2, "imageUrl" | "button"> & {
38-
imageUrl: NonNullable<ParsedFrameV2["imageUrl"]>;
39-
button: Omit<NonNullable<ParsedFrameV2["button"]>, "action" | "title"> & {
40-
action: Omit<
41-
NonNullable<NonNullable<ParsedFrameV2["button"]>["action"]>,
42-
"url" | "title"
43-
> & {
44-
url: NonNullable<
45-
NonNullable<NonNullable<ParsedFrameV2["button"]>["action"]>["url"]
46-
>;
47-
};
48-
title: NonNullable<
49-
NonNullable<NonNullable<ParsedFrameV2["button"]>["title"]>
50-
>;
51-
};
52-
};
53-
5433
type FrameUIStateLoading = {
5534
status: "loading";
5635
id: number;

packages/render/src/ui/utils.ts

+2-1
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,12 @@ import type {
66
FrameStackRequestError,
77
} from "../types";
88
import type {
9+
PartialFrameV2,
910
FramesStackItem as UnstableFramesStackItem,
1011
FrameStackMessage as UnstableFrameStackMessage,
1112
FrameStackRequestError as UnstableFrameStackRequestError,
1213
} from "../unstable-types";
13-
import type { PartialFrame, PartialFrameV2 } from "./types";
14+
import type { PartialFrame } from "./types";
1415

1516
type FrameResultFailure = Exclude<GetFrameResult, { status: "success" }>;
1617

packages/render/src/unstable-types.ts

+43
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
import type {
22
FrameButtonLink,
33
FrameButtonTx,
4+
FrameV2,
45
SupportedParsingSpecification,
56
TransactionTargetResponse,
67
TransactionTargetResponseSendTransaction,
78
TransactionTargetResponseSignTypedDataV4,
89
} from "frames.js";
910
import type {
11+
ParsedFrameV2,
1012
ParseFramesWithReportsResult,
1113
ParseResultWithFrameworkDetails,
1214
} from "frames.js/frame-parsers";
@@ -62,6 +64,40 @@ export type ResolveSignerFunction = (
6264

6365
export type ResolveAddressFunction = () => Promise<`0x${string}` | null>;
6466

67+
/**
68+
* If partial frame rendering is enabled this is the shape of the frame
69+
*/
70+
export type PartialFrameV2 = Omit<ParsedFrameV2, "imageUrl" | "button"> & {
71+
imageUrl: NonNullable<ParsedFrameV2["imageUrl"]>;
72+
button: Omit<NonNullable<ParsedFrameV2["button"]>, "action" | "title"> & {
73+
action: Omit<
74+
NonNullable<NonNullable<ParsedFrameV2["button"]>["action"]>,
75+
"url" | "title"
76+
> & {
77+
url: NonNullable<
78+
NonNullable<NonNullable<ParsedFrameV2["button"]>["action"]>["url"]
79+
>;
80+
};
81+
title: NonNullable<
82+
NonNullable<NonNullable<ParsedFrameV2["button"]>["title"]>
83+
>;
84+
};
85+
};
86+
87+
export type LaunchFrameButtonPressEvent =
88+
| {
89+
status: "complete";
90+
frame: FrameV2;
91+
}
92+
| {
93+
status: "partial";
94+
frame: PartialFrameV2;
95+
};
96+
97+
export type LaunchFrameButtonPressFunction = (
98+
event: LaunchFrameButtonPressEvent
99+
) => void;
100+
65101
export type UseFrameOptions<
66102
TExtraDataPending = unknown,
67103
TExtraDataDone = unknown,
@@ -143,6 +179,12 @@ export type UseFrameOptions<
143179
* This function can be used to customize how the link button click is handled.
144180
*/
145181
onLinkButtonClick?: OnLinkButtonClickFunction;
182+
/**
183+
* Called when the frame button is pressed.
184+
*
185+
* Only valid for frames v2.
186+
*/
187+
onLaunchFrameButtonPress?: LaunchFrameButtonPressFunction;
146188
} & Partial<
147189
Pick<
148190
UseFetchFrameOptions,
@@ -278,6 +320,7 @@ export type UseFrameReturnValue<
278320
readonly inputText: string;
279321
setInputText: (s: string) => void;
280322
onButtonPress: ButtonPressFunction<SignerStateActionContext<any, any>>;
323+
onLaunchFrameButtonPress: LaunchFrameButtonPressFunction;
281324
readonly homeframeUrl: string | null | undefined;
282325
/**
283326
* Resets the frame state to initial frame and resolves specification and signer again

packages/render/src/unstable-use-frame.tsx

+4
Original file line numberDiff line numberDiff line change
@@ -407,6 +407,8 @@ export function useFrame_unstable<
407407
[frameStateRef, fetchFrameRef, onErrorRef, resolveAddressRef]
408408
);
409409

410+
const onLaunchFrameButtonPress = useCallback(() => {}, []);
411+
410412
const onButtonPress = useCallback(
411413
async function onButtonPress(
412414
currentFrame: Frame,
@@ -532,6 +534,7 @@ export function useFrame_unstable<
532534
homeframeUrl,
533535
framesStack: stack,
534536
currentFrameStackItem: stack[0],
537+
onLaunchFrameButtonPress,
535538
};
536539
}, [
537540
signerState,
@@ -544,5 +547,6 @@ export function useFrame_unstable<
544547
fetchFrame,
545548
homeframeUrl,
546549
stack,
550+
onLaunchFrameButtonPress,
547551
]);
548552
}

0 commit comments

Comments
 (0)