mirror of
https://github.com/hanzoai/calendar.git
synced 2026-10-30 14:46:43 +00:00
478ca05246
* feat(companion): update Android booking detail page to match iOS design * feat(companion): add video icon button to Android header for join meeting * fix(companion): use eventType.description instead of booking.description Address Cubic AI review feedback - the booking description may contain Additional Notes which can cause duplicate display. The event type description is the proper source for this information. Co-Authored-By: unknown <> * Revert "fix(companion): use eventType.description instead of booking.description" This reverts commit 3e324313f2d72704ab51f723a52b2784b33e7867. * fix(companion): extract IOSPickerTrigger to platform-specific files for web compatibility * fix(companion): extract iOS pickers to platform-specific files for web compatibility Extract iOS-only native picker components from AvailabilityTab, BasicsTab, LimitsTab, RecurringTab, and LocationsList to platform-specific files to fix 'requireNativeViewManager is not available on web' error in browser extension. Each tab now has: - TabIOSPicker.ios.tsx - iOS implementation with native @expo/ui/swift-ui - TabIOSPicker.tsx - Web/Android fallback that returns null * fix(companion): fix Switch toggle thumb color for web/extension Change thumbColor condition from Platform.OS === 'android' to Platform.OS !== 'ios' so that web/extension also gets white thumb color instead of the default green. * fix(companion): fix Participants section padding for web/extension Move padding classes from AppPressable to a child View to ensure padding is properly applied on web. AnimatedPressable doesn't reliably apply className padding on web platforms. * fix(companion): fix unexpected text node error on web Change ternary operator in Hosts section from 'booking.user && (...)' to 'booking.user ? (...) : null' to prevent React Native Web from trying to render 'false' as a text node when booking.user is falsy. * fix(companion): wrap Stack.Header in iOS platform check for web compatibility The Stack.Header components are iOS-specific and cause 'Unexpected text node' errors on web. Wrap them in Platform.OS === 'ios' check to prevent rendering on web/Android where they're not supported. * fix(companion): convert all && conditionals to ternary operators for web compatibility React Native Web renders boolean 'false' from && operators as text nodes. Changed all conditional rendering patterns from 'condition && (<Component>)' to 'condition ? (<Component>) : null' to prevent 'Unexpected text node' errors. --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
72 lines
2.1 KiB
TypeScript
72 lines
2.1 KiB
TypeScript
import { Button, ContextMenu, Host } from "@expo/ui/swift-ui";
|
|
import { buttonStyle } from "@expo/ui/swift-ui/modifiers";
|
|
import { isLiquidGlassAvailable } from "expo-glass-effect";
|
|
import type React from "react";
|
|
import type { LocationItem, LocationOptionGroup } from "@/types/locations";
|
|
|
|
const getSFSymbolForType = (type: string) => {
|
|
switch (type) {
|
|
case "address":
|
|
return "mappin.and.ellipse";
|
|
case "link":
|
|
return "link";
|
|
case "phone":
|
|
return "phone";
|
|
default:
|
|
return "video";
|
|
}
|
|
};
|
|
|
|
function isLocationAlreadyAdded(locations: LocationItem[], optionValue: string): boolean {
|
|
return locations.some((loc) => {
|
|
if (loc.type === "integration" && optionValue.startsWith("integrations:")) {
|
|
return loc.integration === optionValue.replace("integrations:", "");
|
|
}
|
|
if (["address", "link", "phone"].includes(loc.type)) {
|
|
return false;
|
|
}
|
|
return loc.type === optionValue;
|
|
});
|
|
}
|
|
|
|
interface LocationsListIOSPickerProps {
|
|
isHeader?: boolean;
|
|
locationOptions: LocationOptionGroup[];
|
|
locations: LocationItem[];
|
|
onSelectOption: (value: string, label: string) => void;
|
|
trigger: React.ReactNode;
|
|
}
|
|
|
|
export function LocationsListIOSPicker({
|
|
isHeader = false,
|
|
locationOptions,
|
|
locations,
|
|
onSelectOption,
|
|
trigger,
|
|
}: LocationsListIOSPickerProps) {
|
|
return (
|
|
<Host matchContents>
|
|
<ContextMenu
|
|
modifiers={!isHeader ? [buttonStyle(isLiquidGlassAvailable() ? "glass" : "bordered")] : []}
|
|
activationMethod="singlePress"
|
|
>
|
|
<ContextMenu.Items>
|
|
{locationOptions.flatMap((group) =>
|
|
group.options
|
|
.filter((opt) => !isLocationAlreadyAdded(locations, opt.value))
|
|
.map((option) => (
|
|
<Button
|
|
key={option.value}
|
|
onPress={() => onSelectOption(option.value, option.label)}
|
|
label={option.label}
|
|
systemImage={getSFSymbolForType(option.value)}
|
|
/>
|
|
))
|
|
)}
|
|
</ContextMenu.Items>
|
|
<ContextMenu.Trigger>{trigger}</ContextMenu.Trigger>
|
|
</ContextMenu>
|
|
</Host>
|
|
);
|
|
}
|