11import type { ImgHTMLAttributes } from "react" ;
22import React , { useState } from "react" ;
33import type { Frame , FrameButton } from "frames.js" ;
4- import type {
5- FrameTheme ,
6- FrameState ,
7- FrameStackMessage ,
8- FrameStackRequestError ,
9- } from "./types " ;
4+ import type { FrameTheme , FrameState } from "./types" ;
5+ import {
6+ getErrorMessageFromFramesStackItem ,
7+ getFrameParseResultFromStackItemBySpecifications ,
8+ isPartialFrameParseResult ,
9+ } from "./helpers " ;
1010
1111export const defaultTheme : Required < FrameTheme > = {
1212 buttonBg : "#fff" ,
@@ -90,22 +90,8 @@ function MessageTooltip({
9090 ) ;
9191}
9292
93- function getErrorMessageFromFramesStackItem (
94- item : FrameStackMessage | FrameStackRequestError
95- ) : string {
96- if ( item . status === "message" ) {
97- return item . message ;
98- }
99-
100- if ( item . requestError instanceof Error ) {
101- return item . requestError . message ;
102- }
103-
104- return "An error occurred" ;
105- }
106-
10793export type FrameUIProps = {
108- frameState : FrameState < any , any > ;
94+ frameState : FrameState ;
10995 theme ?: FrameTheme ;
11096 FrameImage ?: React . FC < ImgHTMLAttributes < HTMLImageElement > & { src : string } > ;
11197 allowPartialFrame ?: boolean ;
@@ -126,8 +112,9 @@ export function FrameUI({
126112 enableImageDebugging,
127113} : FrameUIProps ) : React . JSX . Element | null {
128114 const [ isImageLoading , setIsImageLoading ] = useState ( true ) ;
129- const currentFrame = frameState . currentFrameStackItem ;
130- const isLoading = currentFrame ?. status === "pending" || isImageLoading ;
115+ const { currentFrameStackItem, specifications } = frameState ;
116+ const isLoading =
117+ currentFrameStackItem ?. status === "pending" || isImageLoading ;
131118 const resolvedTheme = getThemeWithDefaults ( theme ?? { } ) ;
132119
133120 if ( ! frameState . homeframeUrl ) {
@@ -136,40 +123,50 @@ export function FrameUI({
136123 ) ;
137124 }
138125
139- if ( ! currentFrame ) {
126+ if ( ! currentFrameStackItem ) {
140127 return null ;
141128 }
142129
143- if (
144- currentFrame . status === "done" &&
145- currentFrame . frameResult . status === "failure" &&
146- ! (
147- allowPartialFrame &&
148- // Need at least image and buttons to render a partial frame
149- currentFrame . frameResult . frame . image &&
150- currentFrame . frameResult . frame . buttons
151- )
152- ) {
153- return < MessageTooltip inline message = "Invalid frame" variant = "error" /> ;
130+ // check if frame is partial and if partials are allowed
131+ if ( currentFrameStackItem . status === "done" ) {
132+ const currentFrameParseResult =
133+ getFrameParseResultFromStackItemBySpecifications (
134+ currentFrameStackItem ,
135+ specifications
136+ ) ;
137+
138+ // not a proper partial frame or partial frames are disabled
139+ if (
140+ currentFrameParseResult . status === "failure" &&
141+ ( ! allowPartialFrame ||
142+ ! isPartialFrameParseResult ( currentFrameParseResult ) )
143+ ) {
144+ return < MessageTooltip inline message = "Invalid frame" variant = "error" /> ;
145+ }
154146 }
155147
156148 let frame : Frame | Partial < Frame > | undefined ;
157149 let debugImage : string | undefined ;
158150
159- if ( currentFrame . status === "done" ) {
160- frame = currentFrame . frameResult . frame ;
151+ if ( currentFrameStackItem . status === "done" ) {
152+ const parseResult = getFrameParseResultFromStackItemBySpecifications (
153+ currentFrameStackItem ,
154+ specifications
155+ ) ;
156+
157+ frame = parseResult . frame ;
161158 debugImage = enableImageDebugging
162- ? currentFrame . frameResult . framesDebugInfo ?. image
159+ ? parseResult . framesDebugInfo ?. image
163160 : undefined ;
164161 } else if (
165- currentFrame . status === "message" ||
166- currentFrame . status === "doneRedirect"
162+ currentFrameStackItem . status === "message" ||
163+ currentFrameStackItem . status === "doneRedirect"
167164 ) {
168- frame = currentFrame . request . sourceFrame ;
169- } else if ( currentFrame . status === "requestError" ) {
165+ frame = currentFrameStackItem . request . sourceFrame ;
166+ } else if ( currentFrameStackItem . status === "requestError" ) {
170167 frame =
171- "sourceFrame" in currentFrame . request
172- ? currentFrame . request . sourceFrame
168+ "sourceFrame" in currentFrameStackItem . request
169+ ? currentFrameStackItem . request . sourceFrame
173170 : undefined ;
174171 }
175172
@@ -182,11 +179,13 @@ export function FrameUI({
182179 < div className = "relative w-full" style = { { height : "100%" } } >
183180 { " " }
184181 { /* Ensure the container fills the height */ }
185- { currentFrame . status === "message" ? (
182+ { currentFrameStackItem . status === "message" ? (
186183 < MessageTooltip
187184 inline = { ! frame || ! ( "image" in frame ) || ! frame . image }
188- message = { getErrorMessageFromFramesStackItem ( currentFrame ) }
189- variant = { currentFrame . type === "error" ? "error" : "message" }
185+ message = { getErrorMessageFromFramesStackItem ( currentFrameStackItem ) }
186+ variant = {
187+ currentFrameStackItem . type === "error" ? "error" : "message"
188+ }
190189 />
191190 ) : null }
192191 { ! ! frame && ! ! frame . image && (
0 commit comments