Merge branch 'feat/blobbi-eyes-feed' into 'main'
Enable Blobbi eye tracking on feed cards (feed-only, with touch support) Closes #249 See merge request soapbox-pub/ditto!201
This commit is contained in:
@@ -75,8 +75,18 @@ function attachGlobalMouseListener() {
|
||||
globalMouseY = e.clientY;
|
||||
};
|
||||
|
||||
const handleTouch = (e: TouchEvent) => {
|
||||
const touch = e.touches[0];
|
||||
if (touch) {
|
||||
globalMouseX = touch.clientX;
|
||||
globalMouseY = touch.clientY;
|
||||
}
|
||||
};
|
||||
|
||||
// Use capture phase for earliest possible update
|
||||
window.addEventListener('mousemove', handleMouseMove, { capture: true, passive: true });
|
||||
window.addEventListener('touchstart', handleTouch, { capture: true, passive: true });
|
||||
window.addEventListener('touchmove', handleTouch, { capture: true, passive: true });
|
||||
mouseListenerAttached = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,13 +1,19 @@
|
||||
import { useMemo } from 'react';
|
||||
import type { NostrEvent } from '@nostrify/nostrify';
|
||||
|
||||
import { BlobbiStageVisual } from '@/blobbi/ui/BlobbiStageVisual';
|
||||
import { BlobbiStageVisual, type BlobbiLookMode } from '@/blobbi/ui/BlobbiStageVisual';
|
||||
import { parseBlobbiEvent } from '@/blobbi/core/lib/blobbi';
|
||||
import { calculateProjectedDecay } from '@/blobbi/core/hooks/useProjectedBlobbiState';
|
||||
import { resolveStatusRecipe, attenuateRecipeForFeed, EMPTY_RECIPE } from '@/blobbi/ui/lib/status-reactions';
|
||||
import { buildSleepingRecipe } from '@/blobbi/ui/lib/recipe';
|
||||
|
||||
export function BlobbiStateCard({ event }: { event: NostrEvent }) {
|
||||
interface BlobbiStateCardProps {
|
||||
event: NostrEvent;
|
||||
/** Controls eye tracking behavior. Default: 'forward' (eyes look straight ahead). */
|
||||
lookMode?: BlobbiLookMode;
|
||||
}
|
||||
|
||||
export function BlobbiStateCard({ event, lookMode = 'forward' }: BlobbiStateCardProps) {
|
||||
const companion = useMemo(() => parseBlobbiEvent(event), [event]);
|
||||
|
||||
const isSleeping = companion?.state === 'sleeping';
|
||||
@@ -44,7 +50,7 @@ export function BlobbiStateCard({ event }: { event: NostrEvent }) {
|
||||
companion={companion}
|
||||
size="lg"
|
||||
animated={!isSleeping}
|
||||
lookMode="forward"
|
||||
lookMode={lookMode}
|
||||
recipe={feedRecipe}
|
||||
recipeLabel={feedRecipeLabel}
|
||||
className="size-48 sm:size-56"
|
||||
|
||||
@@ -668,7 +668,7 @@ export const NoteCard = memo(function NoteCard({
|
||||
<ProfileCardContent event={event} />
|
||||
) : isBlobbiState ? (
|
||||
<Suspense fallback={<Skeleton className="h-24 w-full rounded-lg" />}>
|
||||
<BlobbiStateCard event={event} />
|
||||
<BlobbiStateCard event={event} lookMode="follow-pointer" />
|
||||
</Suspense>
|
||||
) : (
|
||||
<TruncatedNoteContent
|
||||
|
||||
@@ -2165,7 +2165,7 @@ function PostDetailContent({ event }: { event: NostrEvent }) {
|
||||
<EncryptedLetterContent event={event} />
|
||||
) : isBlobbiState ? (
|
||||
<Suspense fallback={<Skeleton className="h-24 w-full rounded-lg" />}>
|
||||
<BlobbiStateCard event={event} />
|
||||
<BlobbiStateCard event={event} lookMode="follow-pointer" />
|
||||
</Suspense>
|
||||
) : isBadgeAward ? (
|
||||
<BadgeAwardCard event={event} />
|
||||
|
||||
Reference in New Issue
Block a user