Merge branch 'main' into shreyas-formatting

This commit is contained in:
Shreyaschorge
2025-07-14 18:55:06 +05:30
34 changed files with 2479 additions and 829 deletions

View File

@@ -1,11 +1,12 @@
'use client';
import { useCallback, useState } from 'react';
import { type Haptics } from '@farcaster/frame-sdk';
import { useMiniApp } from '@neynar/react';
import { Button } from '../Button';
import { ShareButton } from '../Share';
import { SignIn } from '../wallet/SignIn';
import { useCallback, useState } from "react";
import { useMiniApp } from "@neynar/react";
import { ShareButton } from "../Share";
import { Button } from "../Button";
import { SignIn } from "../wallet/SignIn";
import { type Haptics } from "@farcaster/miniapp-sdk";
import { NeynarAuthButton } from '../NeynarAuthButton/index';
/**
* ActionsTab component handles mini app actions like sharing, notifications, and haptic feedback.
@@ -50,7 +51,7 @@ export function ActionsTab() {
* @returns Promise that resolves when the notification is sent or fails
*/
const sendFarcasterNotification = useCallback(async () => {
setNotificationState(prev => ({ ...prev, sendStatus: '' }));
setNotificationState((prev) => ({ ...prev, sendStatus: '' }));
if (!notificationDetails || !context) {
return;
}
@@ -65,19 +66,22 @@ export function ActionsTab() {
}),
});
if (response.status === 200) {
setNotificationState(prev => ({ ...prev, sendStatus: 'Success' }));
setNotificationState((prev) => ({ ...prev, sendStatus: 'Success' }));
return;
} else if (response.status === 429) {
setNotificationState(prev => ({ ...prev, sendStatus: 'Rate limited' }));
setNotificationState((prev) => ({
...prev,
sendStatus: 'Rate limited',
}));
return;
}
const responseText = await response.text();
setNotificationState(prev => ({
setNotificationState((prev) => ({
...prev,
sendStatus: `Error: ${responseText}`,
}));
} catch (error) {
setNotificationState(prev => ({
setNotificationState((prev) => ({
...prev,
sendStatus: `Error: ${error}`,
}));
@@ -94,11 +98,11 @@ export function ActionsTab() {
if (context?.user?.fid) {
const userShareUrl = `${process.env.NEXT_PUBLIC_URL}/share/${context.user.fid}`;
await navigator.clipboard.writeText(userShareUrl);
setNotificationState(prev => ({ ...prev, shareUrlCopied: true }));
setNotificationState((prev) => ({ ...prev, shareUrlCopied: true }));
setTimeout(
() =>
setNotificationState(prev => ({ ...prev, shareUrlCopied: false })),
2000,
setNotificationState((prev) => ({ ...prev, shareUrlCopied: false })),
2000
);
}
}, [context?.user?.fid]);
@@ -119,10 +123,10 @@ export function ActionsTab() {
// --- Render ---
return (
<div className="space-y-3 px-6 w-full max-w-md mx-auto">
<div className='space-y-3 px-6 w-full max-w-md mx-auto'>
{/* Share functionality */}
<ShareButton
buttonText="Share Mini App"
buttonText='Share Mini App'
cast={{
text: 'Check out this awesome frame @1 @2 @3! 🚀🪐',
bestFriends: true,
@@ -130,36 +134,39 @@ export function ActionsTab() {
`${process.env.NEXT_PUBLIC_URL}/share/${context?.user?.fid || ''}`,
],
}}
className="w-full"
className='w-full'
/>
{/* Authentication */}
<SignIn />
{/* Neynar Authentication */}
<NeynarAuthButton />
{/* Mini app actions */}
<Button
onClick={() =>
actions.openUrl('https://www.youtube.com/watch?v=dQw4w9WgXcQ')
}
className="w-full"
className='w-full'
>
Open Link
</Button>
<Button onClick={actions.addMiniApp} disabled={added} className="w-full">
<Button onClick={actions.addMiniApp} disabled={added} className='w-full'>
Add Mini App to Client
</Button>
{/* Notification functionality */}
{notificationState.sendStatus && (
<div className="text-sm w-full">
<div className='text-sm w-full'>
Send notification result: {notificationState.sendStatus}
</div>
)}
<Button
onClick={sendFarcasterNotification}
disabled={!notificationDetails}
className="w-full"
className='w-full'
>
Send notification
</Button>
@@ -168,24 +175,24 @@ export function ActionsTab() {
<Button
onClick={copyUserShareUrl}
disabled={!context?.user?.fid}
className="w-full"
className='w-full'
>
{notificationState.shareUrlCopied ? 'Copied!' : 'Copy share URL'}
</Button>
{/* Haptic feedback controls */}
<div className="space-y-2">
<label className="block text-sm font-medium text-gray-700 dark:text-gray-300">
<div className='space-y-2'>
<label className='block text-sm font-medium text-gray-700 dark:text-gray-300'>
Haptic Intensity
</label>
<select
value={selectedHapticIntensity}
onChange={e =>
onChange={(e) =>
setSelectedHapticIntensity(
e.target.value as Haptics.ImpactOccurredType,
e.target.value as Haptics.ImpactOccurredType
)
}
className="w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-primary"
className='w-full px-3 py-2 border border-gray-300 dark:border-gray-600 rounded-md bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 focus:outline-none focus:ring-2 focus:ring-primary'
>
<option value={'light'}>Light</option>
<option value={'medium'}>Medium</option>
@@ -193,10 +200,10 @@ export function ActionsTab() {
<option value={'soft'}>Soft</option>
<option value={'rigid'}>Rigid</option>
</select>
<Button onClick={triggerHapticFeedback} className="w-full">
<Button onClick={triggerHapticFeedback} className='w-full'>
Trigger Haptic Feedback
</Button>
</div>
</div>
);
}
}