From aac5bb2024b9b17895c72a980d2200289f59f6de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Michal=20Kvasnic=CC=8Ca=CC=81k?= Date: Fri, 25 Oct 2024 10:24:58 +0200 Subject: [PATCH] feat: add useful properties --- packages/render/src/helpers.ts | 20 ++++++++ packages/render/src/unstable-types.ts | 23 +++++++-- .../render/src/unstable-use-frame-state.ts | 49 ++++++++++++++++--- packages/render/src/unstable-use-frame.tsx | 10 ++++ 4 files changed, 91 insertions(+), 11 deletions(-) diff --git a/packages/render/src/helpers.ts b/packages/render/src/helpers.ts index c15af174..3346cc3b 100644 --- a/packages/render/src/helpers.ts +++ b/packages/render/src/helpers.ts @@ -2,6 +2,7 @@ import type { ParseFramesWithReportsResult, ParseResult, } from "frames.js/frame-parsers"; +import type { PartialFrame } from "./ui/types"; export async function tryCallAsync( promiseFn: () => Promise @@ -51,3 +52,22 @@ export function isParseResult(value: unknown): value is ParseResult { !("farcaster" in value) ); } + +export type ParseResultWithPartialFrame = Omit< + Exclude, + "frame" +> & { + frame: PartialFrame; +}; + +// rename +export function isPartialFrame( + value: ParseResult +): value is ParseResultWithPartialFrame { + return ( + value.status === "failure" && + !!value.frame.image && + !!value.frame.buttons && + value.frame.buttons.length > 0 + ); +} diff --git a/packages/render/src/unstable-types.ts b/packages/render/src/unstable-types.ts index ec9b722a..21f4f79a 100644 --- a/packages/render/src/unstable-types.ts +++ b/packages/render/src/unstable-types.ts @@ -167,19 +167,31 @@ export type FramesStackItem = | FrameStackMessage; export type UseFrameReturnValue = { + /** + * The signer state is set once it is resolved (on initial frame render) + */ + readonly signerState: SignerStateInstance | undefined; + /** + * The specification is set once it is resolved (on initial frame render) + */ + readonly specification: SupportedParsingSpecification | undefined; fetchFrame: FetchFrameFunction; clearFrameStack: () => void; dispatchFrameStack: Dispatch; /** The frame at the top of the stack (at index 0) */ - currentFrameStackItem: FramesStackItem | undefined; + readonly currentFrameStackItem: FramesStackItem | undefined; /** A stack of frames with additional context, with the most recent frame at index 0 */ - framesStack: FramesStack; - inputText: string; + readonly framesStack: FramesStack; + readonly inputText: string; setInputText: (s: string) => void; onButtonPress: ButtonPressFunction>; - homeframeUrl: string | null | undefined; + readonly homeframeUrl: string | null | undefined; onCastActionButtonPress: CastActionButtonPressFunction; onComposerActionButtonPress: ComposerActionButtonPressFunction; + /** + * Resets the frame state to initial frame and resolves specification and signer again + */ + reset: () => void; }; export type FramesStack = FramesStackItem[]; @@ -217,6 +229,9 @@ export type FrameReducerActions = endTime: Date; } | { action: "CLEAR" } + | { + action: "RESET"; + } | { action: "RESET_INITIAL_FRAME"; parseResult: ParseFramesWithReportsResult; diff --git a/packages/render/src/unstable-use-frame-state.ts b/packages/render/src/unstable-use-frame-state.ts index 247e8ebb..f9600923 100644 --- a/packages/render/src/unstable-use-frame-state.ts +++ b/packages/render/src/unstable-use-frame-state.ts @@ -37,6 +37,7 @@ export type FrameState = frameContext: FrameContext; specification: SupportedParsingSpecification; homeframeUrl: string; + parseResult: ParseFramesWithReportsResult; } | { type: "not-initialized"; @@ -109,6 +110,7 @@ function createFramesStackReducer( let specification: SupportedParsingSpecification; let frameContext: FrameContext; let homeframeUrl: string; + let parseResult = action.parseResult; if (state.type === "not-initialized") { /** @@ -125,7 +127,13 @@ function createFramesStackReducer( resolvedSpecification); homeframeUrl = action.pendingItem.url; } else { - ({ signerState, specification, frameContext, homeframeUrl } = state); + ({ + signerState, + specification, + frameContext, + homeframeUrl, + parseResult, + } = state); } state.stack[index] = { @@ -143,6 +151,7 @@ function createFramesStackReducer( return { ...state, + parseResult, signerState, frameContext, homeframeUrl, @@ -167,6 +176,22 @@ function createFramesStackReducer( stack: state.stack.slice(), }; } + case "RESET": { + if (state.type === "not-initialized") { + return state; + } + + const { frameContext, signerState, specification } = + resolveSpecificationRef.current({ parseResult: state.parseResult }); + + return { + ...state, + type: "initialized", + frameContext, + signerState, + specification, + }; + } case "RESET_INITIAL_FRAME": { const { frameContext, signerState, specification } = resolveSpecificationRef.current({ parseResult: action.parseResult }); @@ -178,6 +203,7 @@ function createFramesStackReducer( frameContext, specification, homeframeUrl: action.homeframeUrl, + parseResult: action.parseResult, stack: [ { request: { @@ -292,7 +318,11 @@ export type FrameStateAPI = { response: Response; responseBody: unknown; }) => void; - reset: (arg: { + /** + * If arg is omitted it will reset the frame stack to initial frame and resolves the specification again. + * Otherwise it will set the frame state to provided values and resolve the specification. + */ + reset: (arg?: { homeframeUrl: string; parseResult: ParseFramesWithReportsResult; }) => void; @@ -322,6 +352,7 @@ export function useFrameState({ signerState, specification, homeframeUrl: frameUrl, + parseResult, stack: [ { response: new Response(JSON.stringify(frameResult), { @@ -540,11 +571,15 @@ export function useFrameState({ }); }, reset(arg) { - dispatch({ - action: "RESET_INITIAL_FRAME", - homeframeUrl: arg.homeframeUrl, - parseResult: arg.parseResult, - }); + if (!arg) { + dispatch({ action: "RESET" }); + } else { + dispatch({ + action: "RESET_INITIAL_FRAME", + homeframeUrl: arg.homeframeUrl, + parseResult: arg.parseResult, + }); + } }, }; }, [dispatch]); diff --git a/packages/render/src/unstable-use-frame.tsx b/packages/render/src/unstable-use-frame.tsx index b76b3f06..8bb1587c 100644 --- a/packages/render/src/unstable-use-frame.tsx +++ b/packages/render/src/unstable-use-frame.tsx @@ -571,13 +571,20 @@ export function useFrame({ ); const { stack } = frameState; + const { signerState, specification } = + frameState.type === "initialized" + ? frameState + : { signerState: undefined, specification: undefined }; return useMemo(() => { return { + signerState, + specification, inputText, setInputText, clearFrameStack: clearFrameState, dispatchFrameStack: dispatchFrameState, + reset: resetFrameState, onButtonPress, fetchFrame, homeframeUrl, @@ -587,10 +594,13 @@ export function useFrame({ onComposerActionButtonPress, }; }, [ + signerState, + specification, inputText, clearFrameState, dispatchFrameState, onButtonPress, + resetFrameState, fetchFrame, homeframeUrl, stack,