Skip to content

Commit

Permalink
wip: redirect
Browse files Browse the repository at this point in the history
  • Loading branch information
tmm authored and jxom committed Feb 14, 2024
1 parent d6254b4 commit 89ea8c1
Show file tree
Hide file tree
Showing 8 changed files with 56 additions and 34 deletions.
20 changes: 7 additions & 13 deletions examples/_dev/src/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -86,23 +86,17 @@ app.frame('/action', ({ buttonValue, inputText }) => {
}
})

app.frame('/buttons', ({ buttonValue }) => {
app.frame('/buttons', (context) => {
const { buttonValue } = context
return {
image: (
<div
style={{
backgroundColor: '#2D2D2D',
display: 'flex',
fontSize: 60,
width: '100%',
height: '100%',
}}
>
{buttonValue ?? ''}
</div>
<div style={{ backgroundColor: '#2D2D2D' }}>{buttonValue ?? ''}</div>
),
intents: [
<Button action="post_redirect" value="apples">
<Button
action="post_redirect"
value="https://github.com/wevm/viem/blob/main/src/clients/createClient.ts"
>
Redirect
</Button>,
<Button.Link href="https://www.example.com">Link</Button.Link>,
Expand Down
1 change: 1 addition & 0 deletions src/components/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ export function ButtonRoot({
<meta
property={`fc:frame:button:${index}`}
content={children}
data-type={action === 'post_redirect' ? 'redirect' : undefined}
data-value={value}
/>,
<meta property={`fc:frame:button:${index}:action`} content={action} />,
Expand Down
23 changes: 17 additions & 6 deletions src/dev/components.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ function Button(props: ButtonProps) {
index: '${index}',
open: false,
target: ${target ? `'${target}'` : undefined},
url: ${type === 'link' && target ? `'${target}'` : undefined},
}`,
}
const leavingAppPrompt = (
Expand All @@ -187,11 +188,10 @@ function Button(props: ButtonProps) {
{...{
'@click.outside': 'open = false',
'@keyup.escape': 'open = false',
'x-trap.noscroll': 'open',
}}
>
<h1 class="font-bold text-base">Leaving Warpcast</h1>
<div class="text-fg2 text-sm font-mono">{target}</div>
<div class="line-clamp-2 text-fg2 text-sm font-mono" x-text="url" />
<p class="text-base leading-snug">
If you connect your wallet and the site is malicious, you may lose
funds.
Expand All @@ -208,7 +208,7 @@ function Button(props: ButtonProps) {
class="bg-er border-er rounded-md w-full text-sm text-white font-bold py-1"
target="_blank"
type="button"
x-on:click={`open = false; window.open(target, '_blank');`}
x-on:click={`open = false; window.open(url, '_blank');`}
>
<div style={{ marginTop: '1px' }}>I Understand</div>
</button>
Expand All @@ -235,6 +235,7 @@ function Button(props: ButtonProps) {
class={buttonClass}
type="button"
x-on:click={`
if (open) return
fetch(baseUrl + '/dev/redirect', {
method: 'POST',
body: JSON.stringify({
Expand All @@ -246,12 +247,15 @@ function Button(props: ButtonProps) {
'Content-Type': 'application/json',
},
})
.then(res => {
.then(async (res) => {
console.log(res)
target = 'https://example.com'
const json = await res.json()
// TODO: show error
if (!json.success) return
url = json.redirectUrl
open = true
})
.catch(error => console.log(error))
.catch((error) => console.log(error))
`}
>
<div style={{ marginTop: '2px' }}>{innerHtml}</div>
Expand Down Expand Up @@ -709,6 +713,13 @@ export function Style() {
scrollbar-color: var(--br) transparent;
scrollbar-width: thin;
}
.line-clamp-2 {
overflow: hidden;
display: -webkit-box;
-webkit-box-orient: vertical;
-webkit-line-clamp: 2;
}
`
return <style dangerouslySetInnerHTML={{ __html: styles }} />
}
8 changes: 2 additions & 6 deletions src/dev/routes.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -148,7 +148,6 @@ export function routes<
inputText,
})

console.log(postUrl)
const response = await fetch(postUrl, {
method: 'POST',
body: JSON.stringify({
Expand All @@ -175,12 +174,9 @@ export function routes<
}),
})

// TODO: Get redirect url
console.log({ response })

return c.json({
success: true,
redirectUrl: '/',
success: response.redirected,
redirectUrl: response.url,
})
},
)
Expand Down
6 changes: 6 additions & 0 deletions src/farc-base.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,12 @@ export class FarcBase<
request: c.req,
})

if (context.status === 'redirect') {
const location = context.buttonValue
if (!location) throw new Error('value required to redirect')
return c.redirect(location, 302)
}

if (context.url !== parsePath(c.req.url))
return c.redirect(
`${context.url}?previousContext=${query.previousContext}`,
Expand Down
3 changes: 2 additions & 1 deletion src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,10 @@ export type FrameContext<path extends string = string, state = unknown> = {
/**
* Status of the frame in the frame lifecycle.
* - `initial` - The frame has not yet been interacted with.
* - `redirect` - The frame has request is a redirect (button of type `'post_redirect'`).
* - `response` - The frame has been interacted with (user presses button).
*/
status: 'initial' | 'response'
status: 'initial' | 'redirect' | 'response'
trustedData?: TrustedData | undefined
untrustedData?: UntrustedData | undefined
url: Context['req']['url']
Expand Down
12 changes: 7 additions & 5 deletions src/utils/getFrameContext.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,15 @@ export async function getFrameContext<state>(
const { context, previousContext, request } = options
const { trustedData, untrustedData } = context || {}

const { buttonIndex, buttonValue, inputText, reset } = getIntentState(
// TODO: derive from untrusted data.
untrustedData,
previousContext?.intents || [],
)
const { buttonIndex, buttonValue, inputText, redirect, reset } =
getIntentState(
// TODO: derive from untrusted data.
untrustedData,
previousContext?.intents || [],
)

const status = (() => {
if (redirect) return 'redirect'
if (reset) return 'initial'
return context.status || 'initial'
})()
Expand Down
17 changes: 14 additions & 3 deletions src/utils/getIntentState.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,26 @@ export function getIntentState(
intents: readonly JSXNode[] | null,
) {
const { buttonIndex, inputText } = frameData || {}
const state = { buttonIndex, buttonValue: undefined, inputText, reset: false }
const state = {
buttonIndex,
buttonValue: undefined,
inputText,
redirect: false,
reset: false,
}
if (!intents) return state
if (buttonIndex) {
const buttonIntents = intents.filter((intent) =>
intent?.props.property.match(/fc:frame:button:\d$/),
)
const intent = buttonIntents[buttonIndex - 1]
state.buttonValue = intent.props['data-value']
if (intent.props['data-type'] === 'reset') state.reset = true
const type = intent.props['data-type']
const value = intent.props['data-value']

if (type === 'redirect') state.redirect = true
else if (type === 'reset') state.reset = true

state.buttonValue = value
}
return state
}

0 comments on commit 89ea8c1

Please sign in to comment.