Skip to content

Commit fbbed31

Browse files
feat: add useful properties
1 parent 96dc0be commit fbbed31

File tree

5 files changed

+103
-11
lines changed

5 files changed

+103
-11
lines changed

packages/render/package.json

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,16 @@
4646
"default": "./dist/errors.cjs"
4747
}
4848
},
49+
"./helpers": {
50+
"import": {
51+
"types": "./dist/helpers.d.ts",
52+
"default": "./dist/helpers.js"
53+
},
54+
"require": {
55+
"types": "./dist/helpers.d.cts",
56+
"default": "./dist/helpers.cjs"
57+
}
58+
},
4959
"./next": {
5060
"import": {
5161
"types": "./dist/next/index.d.ts",

packages/render/src/helpers.ts

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import type {
22
ParseFramesWithReportsResult,
33
ParseResult,
44
} from "frames.js/frame-parsers";
5+
import type { PartialFrame } from "./ui/types";
56

67
export async function tryCallAsync<TResult>(
78
promiseFn: () => Promise<TResult>
@@ -51,3 +52,22 @@ export function isParseResult(value: unknown): value is ParseResult {
5152
!("farcaster" in value)
5253
);
5354
}
55+
56+
export type ParseResultWithPartialFrame = Omit<
57+
Exclude<ParseResult, { status: "success" }>,
58+
"frame"
59+
> & {
60+
frame: PartialFrame;
61+
};
62+
63+
// rename
64+
export function isPartialFrame(
65+
value: ParseResult
66+
): value is ParseResultWithPartialFrame {
67+
return (
68+
value.status === "failure" &&
69+
!!value.frame.image &&
70+
!!value.frame.buttons &&
71+
value.frame.buttons.length > 0
72+
);
73+
}

packages/render/src/unstable-types.ts

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,31 @@ export type FramesStackItem =
167167
| FrameStackMessage;
168168

169169
export type UseFrameReturnValue = {
170+
/**
171+
* The signer state is set once it is resolved (on initial frame render)
172+
*/
173+
readonly signerState: SignerStateInstance | undefined;
174+
/**
175+
* The specification is set once it is resolved (on initial frame render)
176+
*/
177+
readonly specification: SupportedParsingSpecification | undefined;
170178
fetchFrame: FetchFrameFunction;
171179
clearFrameStack: () => void;
172180
dispatchFrameStack: Dispatch<FrameReducerActions>;
173181
/** The frame at the top of the stack (at index 0) */
174-
currentFrameStackItem: FramesStackItem | undefined;
182+
readonly currentFrameStackItem: FramesStackItem | undefined;
175183
/** A stack of frames with additional context, with the most recent frame at index 0 */
176-
framesStack: FramesStack;
177-
inputText: string;
184+
readonly framesStack: FramesStack;
185+
readonly inputText: string;
178186
setInputText: (s: string) => void;
179187
onButtonPress: ButtonPressFunction<SignerStateActionContext<any, any>>;
180-
homeframeUrl: string | null | undefined;
188+
readonly homeframeUrl: string | null | undefined;
181189
onCastActionButtonPress: CastActionButtonPressFunction;
182190
onComposerActionButtonPress: ComposerActionButtonPressFunction;
191+
/**
192+
* Resets the frame state to initial frame and resolves specification and signer again
193+
*/
194+
reset: () => void;
183195
};
184196

185197
export type FramesStack = FramesStackItem[];
@@ -217,6 +229,9 @@ export type FrameReducerActions =
217229
endTime: Date;
218230
}
219231
| { action: "CLEAR" }
232+
| {
233+
action: "RESET";
234+
}
220235
| {
221236
action: "RESET_INITIAL_FRAME";
222237
parseResult: ParseFramesWithReportsResult;

packages/render/src/unstable-use-frame-state.ts

Lines changed: 44 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ export type FrameState =
3737
frameContext: FrameContext;
3838
specification: SupportedParsingSpecification;
3939
homeframeUrl: string;
40+
parseResult: ParseFramesWithReportsResult;
4041
}
4142
| {
4243
type: "not-initialized";
@@ -109,6 +110,7 @@ function createFramesStackReducer(
109110
let specification: SupportedParsingSpecification;
110111
let frameContext: FrameContext;
111112
let homeframeUrl: string;
113+
let parseResult = action.parseResult;
112114

113115
if (state.type === "not-initialized") {
114116
/**
@@ -125,7 +127,13 @@ function createFramesStackReducer(
125127
resolvedSpecification);
126128
homeframeUrl = action.pendingItem.url;
127129
} else {
128-
({ signerState, specification, frameContext, homeframeUrl } = state);
130+
({
131+
signerState,
132+
specification,
133+
frameContext,
134+
homeframeUrl,
135+
parseResult,
136+
} = state);
129137
}
130138

131139
state.stack[index] = {
@@ -143,6 +151,7 @@ function createFramesStackReducer(
143151

144152
return {
145153
...state,
154+
parseResult,
146155
signerState,
147156
frameContext,
148157
homeframeUrl,
@@ -167,6 +176,24 @@ function createFramesStackReducer(
167176
stack: state.stack.slice(),
168177
};
169178
}
179+
case "RESET": {
180+
if (state.type === "not-initialized") {
181+
return state;
182+
}
183+
184+
const { frameContext, signerState, specification } =
185+
resolveSpecificationRef.current({ parseResult: state.parseResult });
186+
187+
return {
188+
...state,
189+
stack:
190+
!!state.stack[0] && state.stack.length > 0 ? [state.stack[0]] : [],
191+
type: "initialized",
192+
frameContext,
193+
signerState,
194+
specification,
195+
};
196+
}
170197
case "RESET_INITIAL_FRAME": {
171198
const { frameContext, signerState, specification } =
172199
resolveSpecificationRef.current({ parseResult: action.parseResult });
@@ -178,6 +205,7 @@ function createFramesStackReducer(
178205
frameContext,
179206
specification,
180207
homeframeUrl: action.homeframeUrl,
208+
parseResult: action.parseResult,
181209
stack: [
182210
{
183211
request: {
@@ -292,7 +320,11 @@ export type FrameStateAPI = {
292320
response: Response;
293321
responseBody: unknown;
294322
}) => void;
295-
reset: (arg: {
323+
/**
324+
* If arg is omitted it will reset the frame stack to initial frame and resolves the specification again.
325+
* Otherwise it will set the frame state to provided values and resolve the specification.
326+
*/
327+
reset: (arg?: {
296328
homeframeUrl: string;
297329
parseResult: ParseFramesWithReportsResult;
298330
}) => void;
@@ -322,6 +354,7 @@ export function useFrameState({
322354
signerState,
323355
specification,
324356
homeframeUrl: frameUrl,
357+
parseResult,
325358
stack: [
326359
{
327360
response: new Response(JSON.stringify(frameResult), {
@@ -540,11 +573,15 @@ export function useFrameState({
540573
});
541574
},
542575
reset(arg) {
543-
dispatch({
544-
action: "RESET_INITIAL_FRAME",
545-
homeframeUrl: arg.homeframeUrl,
546-
parseResult: arg.parseResult,
547-
});
576+
if (!arg) {
577+
dispatch({ action: "RESET" });
578+
} else {
579+
dispatch({
580+
action: "RESET_INITIAL_FRAME",
581+
homeframeUrl: arg.homeframeUrl,
582+
parseResult: arg.parseResult,
583+
});
584+
}
548585
},
549586
};
550587
}, [dispatch]);

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

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -571,13 +571,20 @@ export function useFrame({
571571
);
572572

573573
const { stack } = frameState;
574+
const { signerState, specification } =
575+
frameState.type === "initialized"
576+
? frameState
577+
: { signerState: undefined, specification: undefined };
574578

575579
return useMemo(() => {
576580
return {
581+
signerState,
582+
specification,
577583
inputText,
578584
setInputText,
579585
clearFrameStack: clearFrameState,
580586
dispatchFrameStack: dispatchFrameState,
587+
reset: resetFrameState,
581588
onButtonPress,
582589
fetchFrame,
583590
homeframeUrl,
@@ -587,10 +594,13 @@ export function useFrame({
587594
onComposerActionButtonPress,
588595
};
589596
}, [
597+
signerState,
598+
specification,
590599
inputText,
591600
clearFrameState,
592601
dispatchFrameState,
593602
onButtonPress,
603+
resetFrameState,
594604
fetchFrame,
595605
homeframeUrl,
596606
stack,

0 commit comments

Comments
 (0)