Skip to content

Commit 69a857a

Browse files
authored
feat(companion): Multi-browser extension support (Chrome, Firefox, Safari, Edge, Brave) and fix text node errors (calcom#26063)
* feat(companion): add multi-browser OAuth support for extension - Add browser-specific OAuth client ID and redirect URI configuration - Support Chrome, Firefox, Safari, Edge, and Brave browsers - Add build scripts for each browser target (ext:build-{browser}) - Fix Brave Shields compatibility for production builds - Add EXTENSION_SETUP.md documentation BREAKING CHANGE: None - backward compatible with existing Chrome config * fix(companion): replace && conditional rendering with ternary operators Replace all `{condition && (<Component />)}` patterns with explicit `{condition ? (<Component />) : null}` syntax across the companion app. This fixes "Unexpected text node: . A text node cannot be a child of a <View>" errors that occur with react-native-css-interop when using && conditional rendering in React Native web builds. Files updated: - app/event-type-detail.tsx (16) - app/booking-detail.tsx (10) - app/(tabs)/bookings.tsx (8) - app/(tabs)/availability.tsx (6) - app/availability-detail.tsx (5) - app/(tabs)/(event-types)/index.tsx (4) - components/event-type-detail/tabs/LimitsTab.tsx (9) - components/event-type-detail/tabs/BasicsTab.tsx (3) - components/event-type-detail/tabs/AdvancedTab.tsx (3) - components/event-type-detail/tabs/RecurringTab.tsx (1) - components/event-type-detail/tabs/AvailabilityTab.tsx (1) - components/event-type-list-item/EventTypeListItem.ios.tsx (3) - components/BookingActionsModal.tsx (2) - components/Tooltip.tsx (1) - components/LocationsList.tsx (1) - components/Header.tsx (1) - components/EmptyScreen.tsx (1) * correct command for edge * dont break ci * deslop ai
1 parent af4a10c commit 69a857a

25 files changed

Lines changed: 853 additions & 410 deletions

companion/.env.example

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,38 @@ EXPO_PUBLIC_CALCOM_OAUTH_CLIENT_ID=your_oauth_client_id_here
33

44
EXPO_PUBLIC_CALCOM_OAUTH_REDIRECT_URI=your_oauth_redirect_uri_here
55

6+
# =============================================================================
7+
# OAUTH REDIRECT URL FORMATS BY BROWSER
8+
# =============================================================================
9+
#
10+
# | Browser | Redirect URL Format | Notes |
11+
# |---------|------------------------------------------------------------------|----------------------------------------------------|
12+
# | Chrome | https://<id>.chromiumapp.org/oauth/callback | Get ID from `chrome://extensions` |
13+
# | Brave | https://<id>.chromiumapp.org/oauth/callback | Same extension package as Chrome |
14+
# | Edge | https://<id>.chromiumapp.org/oauth/callback | Different ID from Chrome |
15+
# | Firefox | https://<uuid>.extensions.allizom.org/oauth/callback | UUID from `browser.identity.getRedirectURL()` |
16+
# | Safari | https://<team>.<bundle>.appextension/oauth/callback | Check Xcode project configuration |
17+
#
18+
# =============================================================================
19+
20+
# =============================================================================
21+
# FIREFOX OAUTH CONFIG
22+
# =============================================================================
23+
EXPO_PUBLIC_CALCOM_OAUTH_CLIENT_ID_FIREFOX=
24+
EXPO_PUBLIC_CALCOM_OAUTH_REDIRECT_URI_FIREFOX=
25+
26+
# =============================================================================
27+
# SAFARI OAUTH CONFIG
28+
# =============================================================================
29+
EXPO_PUBLIC_CALCOM_OAUTH_CLIENT_ID_SAFARI=
30+
EXPO_PUBLIC_CALCOM_OAUTH_REDIRECT_URI_SAFARI=
31+
32+
# =============================================================================
33+
# EDGE OAUTH CONFIG
34+
# =============================================================================
35+
EXPO_PUBLIC_CALCOM_OAUTH_CLIENT_ID_EDGE=
36+
EXPO_PUBLIC_CALCOM_OAUTH_REDIRECT_URI_EDGE=
37+
638
# ===========================================
739
# CACHE CONFIGURATION (all values in MINUTES)
840
# ===========================================

companion/app/(tabs)/(event-types)/index.tsx

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -690,17 +690,17 @@ export default function EventTypes() {
690690
activeOpacity={1}
691691
onPress={(e) => e.stopPropagation()}
692692
>
693-
{selectedEventType && (
693+
{selectedEventType ? (
694694
<>
695695
<View className="border-b border-gray-200 p-6">
696696
<Text className="mb-2 text-lg font-semibold text-gray-900">
697697
{selectedEventType.title}
698698
</Text>
699-
{selectedEventType.description && (
699+
{selectedEventType.description ? (
700700
<Text className="text-sm text-gray-600">
701701
{normalizeMarkdown(selectedEventType.description)}
702702
</Text>
703-
)}
703+
) : null}
704704
</View>
705705

706706
<View className="p-2">
@@ -759,7 +759,7 @@ export default function EventTypes() {
759759
</TouchableOpacity>
760760
</View>
761761
</>
762-
)}
762+
) : null}
763763
</TouchableOpacity>
764764
</TouchableOpacity>
765765
</FullScreenModal>
@@ -844,12 +844,12 @@ export default function EventTypes() {
844844
Delete Event Type
845845
</Text>
846846
<Text className="text-sm leading-5 text-gray-600">
847-
{eventTypeToDelete && (
847+
{eventTypeToDelete ? (
848848
<>
849849
This will permanently delete the "{eventTypeToDelete.title}" event type.
850850
This action cannot be undone.
851851
</>
852-
)}
852+
) : null}
853853
</Text>
854854
</View>
855855
</View>
@@ -881,13 +881,13 @@ export default function EventTypes() {
881881
</FullScreenModal>
882882

883883
{/* Toast for Web Platform */}
884-
{showToast && (
884+
{showToast ? (
885885
<View className="absolute bottom-8 left-1/2 z-50 -translate-x-1/2 transform">
886886
<View className="rounded-full bg-gray-800 px-6 py-3 shadow-lg">
887887
<Text className="text-sm font-medium text-white">{toastMessage}</Text>
888888
</View>
889889
</View>
890-
)}
890+
) : null}
891891
</>
892892
);
893893
}

companion/app/(tabs)/availability.tsx

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -273,11 +273,11 @@ export default function Availability() {
273273
<View className="mr-4 flex-1">
274274
<View className="mb-1 flex-row flex-wrap items-center">
275275
<Text className="text-base font-semibold text-[#333]">{schedule.name}</Text>
276-
{schedule.isDefault && (
276+
{schedule.isDefault ? (
277277
<View className="ml-2 rounded bg-[#666] px-2 py-0.5">
278278
<Text className="text-xs font-semibold text-white">Default</Text>
279279
</View>
280-
)}
280+
) : null}
281281
</View>
282282

283283
{schedule.availability && schedule.availability.length > 0 ? (
@@ -360,7 +360,7 @@ export default function Availability() {
360360
<Header />
361361

362362
{/* Empty state - no schedules */}
363-
{showEmptyState && (
363+
{showEmptyState ? (
364364
<View className="flex-1 bg-gray-50" style={{ paddingBottom: 100 }}>
365365
<ScrollView
366366
contentContainerStyle={{
@@ -380,10 +380,10 @@ export default function Availability() {
380380
/>
381381
</ScrollView>
382382
</View>
383-
)}
383+
) : null}
384384

385385
{/* Search bar and content for non-empty states */}
386-
{!showEmptyState && (
386+
{!showEmptyState ? (
387387
<>
388388
<View className="flex-row items-center gap-3 border-b border-gray-300 bg-gray-100 px-4 py-2">
389389
<TextInput
@@ -406,7 +406,7 @@ export default function Availability() {
406406
</View>
407407

408408
{/* Search empty state */}
409-
{showSearchEmptyState && (
409+
{showSearchEmptyState ? (
410410
<View className="flex-1 bg-gray-50" style={{ paddingBottom: 100 }}>
411411
<ScrollView
412412
contentContainerStyle={{
@@ -424,10 +424,10 @@ export default function Availability() {
424424
/>
425425
</ScrollView>
426426
</View>
427-
)}
427+
) : null}
428428

429429
{/* Schedules list */}
430-
{showList && (
430+
{showList ? (
431431
<View className="flex-1 px-2 pt-4 md:px-4">
432432
<View className="flex-1 overflow-hidden rounded-lg border border-[#E5E5EA] bg-white">
433433
<FlatList
@@ -440,9 +440,9 @@ export default function Availability() {
440440
/>
441441
</View>
442442
</View>
443-
)}
443+
) : null}
444444
</>
445-
)}
445+
) : null}
446446

447447
{/* Create Schedule Modal */}
448448
<FullScreenModal
@@ -536,7 +536,7 @@ export default function Availability() {
536536
{/* Actions List */}
537537
<View className="p-2">
538538
{/* Set as Default - only show if not already default */}
539-
{selectedSchedule && !selectedSchedule.isDefault && (
539+
{selectedSchedule && !selectedSchedule.isDefault ? (
540540
<>
541541
<TouchableOpacity
542542
onPress={() => {
@@ -553,7 +553,7 @@ export default function Availability() {
553553

554554
<View className="mx-4 my-2 h-px bg-gray-200" />
555555
</>
556-
)}
556+
) : null}
557557

558558
{/* Duplicate */}
559559
<TouchableOpacity

0 commit comments

Comments
 (0)