Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion frontend/app/capture/details.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,16 @@ interface Friend {
username: string;
}

/**
* Render the details screen for reviewing a captured media item, editing attachments,
* configuring sharing options, and saving the entry.
*
* This component builds a MediaCapture from route params, manages attachment editing
* (including in-editor live text editing with pending item handling), sharing state
* (private, everyone, or selected friends), optimistic entry creation, and the save flow.
*
* @returns The Details screen UI for adding details to a capture, managing attachments and privacy, and submitting the entry.
*/
export default function DetailsScreen() {
const params = useLocalSearchParams();
const { captureId, type, uri, duration } = params;
Expand Down Expand Up @@ -591,4 +601,4 @@ const styles = StyleSheet.create({
fontSize: 18,
fontWeight: '600',
},
});
});
13 changes: 13 additions & 0 deletions frontend/components/capture/canvas/text-canvas-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,19 @@ interface TextCanvasItemProps {
textStyle?: { color: string; fontFamily?: string; backgroundColor?: string }
}

/**
* Renders a rounded text "badge" using the provided text and optional styling.
*
* Applies `textStyle.backgroundColor` to the container (defaults to `#000000` if not provided)
* and applies `textStyle.color` and `textStyle.fontFamily` to the text.
*
* @param text - The string to display; if falsy, the component renders `null`.
* @param textStyle - Optional visual overrides. Recognized properties:
* - `backgroundColor`: container background color
* - `color`: text color
* - `fontFamily`: text font family
* @returns A React element containing the styled text badge, or `null` when `text` is falsy.
*/
export function TextCanvasItem({ text, textStyle }: TextCanvasItemProps) {
if (!text) return null;

Expand Down
17 changes: 16 additions & 1 deletion frontend/components/capture/editor-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,21 @@ interface EditorPopoverProps {
initialText?: string;
}

/**
* Render an editor popover that lets users add text, stickers, music, or a location to a media canvas.
*
* @param isVisible - Whether the popover is currently visible
* @param onClose - Callback invoked when the popover is dismissed; receives the current text input (if any)
* @param addText - Adds a text item with style `{ color, fontFamily?, backgroundColor? }`
* @param addSticker - Adds a sticker given its URI
* @param addMusic - Adds a music tag
* @param addLocation - Adds a location string
* @param defaultTab - Optional initial active tab (`"text" | "sticker" | "music" | "location"`)
* @param onTextChange - Optional callback invoked as the text input changes
* @param onStyleChange - Optional callback invoked when text style (color, fontFamily, backgroundColor) changes
* @param initialText - Optional initial value for the text input
* @returns The popover UI element when visible, or `null` when hidden
*/
export default function EditorPopover({
isVisible,
onClose,
Expand Down Expand Up @@ -275,4 +290,4 @@ const styles = StyleSheet.create({
alignItems: "center",
justifyContent: "center",
},
});
});
9 changes: 8 additions & 1 deletion frontend/components/capture/editor/location-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,14 @@ interface LocationSearchResult {
isCurrentLocation?: boolean;
}

/**
* Renders a location search interface that lists nearby places and search results and lets the user pick a location.
*
* Displays an input for typing a query, shows a combined list containing an optional "Current" location entry and place results, indicates loading/empty states, and invokes a callback when a location is selected.
*
* @param onSelectLocation - Callback invoked with the selected location string (address) when the user chooses a location
* @returns The LocationTab component UI for searching and selecting a location
*/
export default function LocationTab({ onSelectLocation }: LocationTabProps) {
const [searchQuery, setSearchQuery] = useState("");
const debouncedQuery = useDebounce(searchQuery, 500);
Expand Down Expand Up @@ -280,4 +288,3 @@ const styles = StyleSheet.create({
fontSize: 16,
},
});

5 changes: 5 additions & 0 deletions frontend/components/capture/editor/music-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,11 @@ export default function MusicTab({ isLoading, musicQuery, onMusicQueryChange, mu
)
}

/**
* Renders the empty-state view shown when no music results are available.
*
* @returns The empty-state React element containing a music icon and the prompt "Start searching for music".
*/
function EmptyComponent() {
return (
<View style={styles.emptyContainer}>
Expand Down
18 changes: 17 additions & 1 deletion frontend/components/capture/editor/text-tab.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,22 @@ const POPULAR_COLORS = [
"#FF1493", "#00CED1", "#32CD32", "#FF4500", "#DA70D6",
];

/**
* Renders a multi-tab text editor panel for editing text, text color, background color, and font.
*
* Provides an internal tab bar with: a multiline text input (auto-focused when active), a text color picker
* (preset palette plus optional custom ColorSlider), a background color picker (same behavior), and a font selector.
*
* @param textInput - Current text value shown in the editor
* @param onTextChange - Called with the new text when the user edits the text input
* @param selectedColor - Currently selected text color (hex string)
* @param onColorChange - Called with a hex color when the text color is changed
* @param selectedFont - Currently selected font name
* @param onFontChange - Called with the font name when a font is selected
* @param selectedBackgroundColor - Currently selected background color (hex string); defaults to `#000000`
* @param onBackgroundColorChange - Optional callback called with a hex color when the background color is changed
* @returns A React element containing the internal tab bar and the active tab's content
*/
export default function TextTab({
textInput,
onTextChange,
Expand Down Expand Up @@ -379,4 +395,4 @@ const styles = StyleSheet.create({
fontFamily: 'monospace',
textAlign: 'center',
},
})
})
10 changes: 9 additions & 1 deletion frontend/components/capture/entry-attachment-list.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ const attachmentTypes: { type: MediaCanvasItemType; icon: React.ComponentType<an
{ type: "location", icon: MapPin, label: "Location" },
];

/**
* Renders a labeled horizontal list of attachment options and invokes a callback when an option is selected.
*
* Each option displays an icon inside a circular avatar with a label underneath; tapping an option calls
* `onSelectAttachment` with that option's `MediaCanvasItemType`.
*
* @param onSelectAttachment - Callback invoked with the selected attachment `type` when an option is pressed
* @returns A React element that renders the attachment selector UI
*/
export default function EntryAttachmentList({ onSelectAttachment }: EntryAttachmentListProps) {
return (
<View>
Expand Down Expand Up @@ -86,4 +95,3 @@ const styles = StyleSheet.create({
textAlign: 'center',
},
});

12 changes: 11 additions & 1 deletion frontend/components/capture/music/audio-preview-popover.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,16 @@ interface MusicPopoverProps {
music: MusicTag;
}

/**
* Render a sliding "Now Playing" popover that previews a music item and its metadata.
*
* Renders an overlay with a backdrop and an animated popover containing an AudioPreview, cover image, title, artist, and a Close action. The popover mounts only when `isVisible` is true; the overlay remains while exit animation runs.
*
* @param isVisible - Whether the popover is currently visible
* @param onClose - Callback invoked when the backdrop or Close button is pressed
* @param music - The music item to preview (expects `MusicTag` shape with `preview`, `cover`, `title`, and `artist`)
* @returns The popover JSX element, or `null` when neither visible nor provided with a music item
*/
export default function AudioPreviewPopover({ isVisible, onClose, music }: MusicPopoverProps) {

// Don't return null - let the exit animation play
Expand Down Expand Up @@ -177,4 +187,4 @@ const styles = StyleSheet.create({
fontWeight: '600',
textAlign: 'center',
},
});
});
7 changes: 7 additions & 0 deletions frontend/components/capture/music/music-list-item.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@ interface MusicListItemProps {
onPress?: (music: MusicTag) => void;
}

/**
* Render a touchable list item showing a music cover, title, artist, and an audio preview control.
*
* @param music - The music item to display (cover URI, title, artist, and preview source)
* @param onPress - Optional callback invoked with `music` when the item is pressed
* @returns The rendered list item element for the given `music`
*/
export function MusicListItem({ music, onPress }: MusicListItemProps) {
const handleMusicSelection = () => {
onPress && onPress(music);
Expand Down
13 changes: 13 additions & 0 deletions frontend/hooks/use-device-location.ts
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,19 @@ interface UseDeviceLocationResult {
clearLocation: () => void;
}

/**
* Exposes the device's current location and a list of representative places within the device's region.
*
* Provides current device location (when permissions are granted), a cached/throttled list of places derived from the device's region, loading states for both queries, any error message, and a function to clear the cached location and places.
*
* @returns An object with the following properties:
* - `location` — The resolved `LocationData` for the device, or `null` if permissions were not granted or location is unavailable.
* - `placesInState` — An array of `PlaceResult` representing places found within the device's region (may be empty).
* - `isLoading` — `true` while the device location query is loading or fetching, otherwise `false`.
* - `isLoadingPlaces` — `true` while the places-in-state query is loading, otherwise `false`.
* - `error` — A user-facing error message string when the location query fails, or `null` if there is no error.
* - `clearLocation` — A function that clears the cached device location and the cached places-in-state.
*/
export function useDeviceLocation(): UseDeviceLocationResult {
const queryClient = useQueryClient();

Expand Down
14 changes: 14 additions & 0 deletions frontend/hooks/use-media-canvas.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,20 @@ import { useRef, useState } from "react";
import { Platform, View } from "react-native";
import ViewShot, { captureRef } from "react-native-view-shot";

/**
* Manage a collection of media canvas items and provide utilities to capture the canvas as an image.
*
* @returns An object exposing:
* - `viewShotRef`: a ref to the ViewShot instance (or `null`) for capturing the rendered view.
* - `items`: the current array of `MediaCanvasItem`.
* - `addText(text, style)`: adds a text item and returns the generated numeric id.
* - `addSticker(sticker)`: adds a sticker item.
* - `addMusic(music)`: adds a music item (`MusicTag`).
* - `addLocation(location)`: adds a location item.
* - `removeElement(id)`: removes the item with the given id.
* - `updateTextItem(id, text, style)`: updates the text and style of an existing text item.
* - `saveImage()`: captures the view and returns the captured file URI prefixed with `file://` on success, or `null` on failure.
*/
export function useMediaCanvas() {
const [items, setItems] = useState<Array<MediaCanvasItem>>([]);

Expand Down
9 changes: 8 additions & 1 deletion frontend/hooks/use-places-search.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
import { useQuery } from '@tanstack/react-query';
import { PlacesSearchService, PlacesSearchCoordinates } from '@/services/places-search-service';

/**
* Searches for places matching a search term, optionally biased by coordinates.
*
* @param query - The search term to look up.
* @param options - Optional settings for the search.
* @param options.coordinates - Latitude and longitude used to bias the search results.
* @returns An object containing `places` (search results; defaults to an empty array), `isLoading` (whether the query is in progress), and `error` (any error encountered).
*/
export function usePlacesSearch(
query: string,
options: { coordinates?: PlacesSearchCoordinates } = {}
Expand All @@ -23,4 +31,3 @@ export function usePlacesSearch(
error,
};
}