From 26f7e01880b736ebb311d2d34fa11c7c4f9e9e4c Mon Sep 17 00:00:00 2001 From: Dhairyashil Date: Tue, 13 Jan 2026 03:05:07 +0530 Subject: [PATCH 1/7] checkpoint 1 --- .../(event-types)/event-type-detail.tsx | 39 ++++--------- .../app/(tabs)/(event-types)/index.ios.tsx | 28 ++++++---- companion/app/(tabs)/(event-types)/index.tsx | 28 ++++++---- .../event-type-detail/tabs/BasicsTab.tsx | 18 +++++- .../EventTypeListItem.ios.tsx | 1 + .../EventTypeListItem.tsx | 1 + .../EventTypeListItemParts.tsx | 27 +++++++-- .../extension/entrypoints/background/index.ts | 1 + companion/extension/entrypoints/content.ts | 55 ++++++++++++------- companion/extension/lib/linkedin.ts | 6 +- companion/services/calcom.ts | 14 ----- companion/services/types/event-types.types.ts | 3 + 12 files changed, 130 insertions(+), 91 deletions(-) diff --git a/companion/app/(tabs)/(event-types)/event-type-detail.tsx b/companion/app/(tabs)/(event-types)/event-type-detail.tsx index fd1b7baea0b205..6ea284b9d25c30 100644 --- a/companion/app/(tabs)/(event-types)/event-type-detail.tsx +++ b/companion/app/(tabs)/(event-types)/event-type-detail.tsx @@ -147,7 +147,7 @@ export default function EventTypeDetail() { const [eventDescription, setEventDescription] = useState(description || ""); const [eventSlug, setEventSlug] = useState(slug || ""); const [eventDuration, setEventDuration] = useState(duration || "30"); - const [username, setUsername] = useState("username"); + const [username, _setUsername] = useState("username"); const [allowMultipleDurations, setAllowMultipleDurations] = useState(false); const [locations, setLocations] = useState([]); const [_locationAddress, setLocationAddress] = useState(""); @@ -177,6 +177,7 @@ export default function EventTypeDetail() { const [conferencingOptions, setConferencingOptions] = useState([]); const [conferencingLoading, setConferencingLoading] = useState(false); const [eventTypeData, setEventTypeData] = useState(null); + const [bookingUrl, setBookingUrl] = useState(""); const [saving, setSaving] = useState(false); const [beforeEventBuffer, setBeforeEventBuffer] = useState("No buffer time"); const [afterEventBuffer, setAfterEventBuffer] = useState("No buffer time"); @@ -456,6 +457,7 @@ export default function EventTypeDetail() { if (eventType.description) setEventDescription(eventType.description); if (eventType.lengthInMinutes) setEventDuration(eventType.lengthInMinutes.toString()); if (eventType.hidden !== undefined) setIsHidden(eventType.hidden); + if (eventType.bookingUrl) setBookingUrl(eventType.bookingUrl); // Load schedule ID - this will be used by fetchSchedules to select the correct schedule if (eventType.scheduleId) { @@ -853,18 +855,6 @@ export default function EventTypeDetail() { fetchConferencingOptions(); }, [fetchConferencingOptions, fetchEventTypeData]); - useEffect(() => { - const fetchUsername = async () => { - try { - const userUsername = await CalComAPIService.getUsername(); - setUsername(userUsername); - } catch (error) { - safeLogError("Failed to fetch username:", error); - } - }; - fetchUsername(); - }, []); - const formatTime = (time: string) => { // Handle different time formats that might come from the API // Extract conditionals outside try/catch for React Compiler @@ -945,29 +935,19 @@ export default function EventTypeDetail() { }; const handlePreview = async () => { - const eventTypeSlug = eventSlug || "preview"; - let link: string; - try { - link = await CalComAPIService.buildEventTypeLink(eventTypeSlug); - } catch (error) { - safeLogError("Failed to generate preview link:", error); - showErrorAlert("Error", "Failed to generate preview link. Please try again."); + if (!bookingUrl) { + showErrorAlert("Error", "Booking URL not available. Please save the event type first."); return; } - await openInAppBrowser(link, "event type preview"); + await openInAppBrowser(bookingUrl, "event type preview"); }; const handleCopyLink = async () => { - const eventTypeSlug = eventSlug || "event-link"; - let link: string; - try { - link = await CalComAPIService.buildEventTypeLink(eventTypeSlug); - } catch (error) { - safeLogError("Failed to copy link:", error); - showErrorAlert("Error", "Failed to copy link. Please try again."); + if (!bookingUrl) { + showErrorAlert("Error", "Booking URL not available. Please save the event type first."); return; } - await Clipboard.setStringAsync(link); + await Clipboard.setStringAsync(bookingUrl); showSuccessAlert("Success", "Link copied!"); }; @@ -1433,6 +1413,7 @@ export default function EventTypeDetail() { onUpdateLocation={handleUpdateLocation} locationOptions={getLocationOptionsForDropdown()} conferencingLoading={conferencingLoading} + bookingUrl={bookingUrl} /> ) : null} diff --git a/companion/app/(tabs)/(event-types)/index.ios.tsx b/companion/app/(tabs)/(event-types)/index.ios.tsx index 8c9898b7ac3e21..c4e8fb57dc3d64 100644 --- a/companion/app/(tabs)/(event-types)/index.ios.tsx +++ b/companion/app/(tabs)/(event-types)/index.ios.tsx @@ -1,6 +1,6 @@ -import { Button, ContextMenu, Host, HStack, Image as SwiftUIImage } from "@expo/ui/swift-ui"; +import { Button, Host, Image as SwiftUIImage } from "@expo/ui/swift-ui"; import * as Haptics from "expo-haptics"; -import { buttonStyle, controlSize, fixedSize, frame, padding } from "@expo/ui/swift-ui/modifiers"; +import { buttonStyle, controlSize, frame, padding } from "@expo/ui/swift-ui/modifiers"; import { Ionicons } from "@expo/vector-icons"; import * as Clipboard from "expo-clipboard"; import { isLiquidGlassAvailable } from "expo-glass-effect"; @@ -28,7 +28,7 @@ import { useUserProfile, } from "@/hooks"; import { useEventTypeFilter } from "@/hooks/useEventTypeFilter"; -import { CalComAPIService, type EventType } from "@/services/calcom"; +import type { EventType } from "@/services/calcom"; import { showErrorAlert, showSuccessAlert } from "@/utils/alerts"; import { openInAppBrowser } from "@/utils/browser"; import { getAvatarUrl } from "@/utils/getAvatarUrl"; @@ -111,9 +111,12 @@ export default function EventTypesIOS() { }; const handleCopyLink = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); - await Clipboard.setStringAsync(link); + await Clipboard.setStringAsync(eventType.bookingUrl); showSuccessAlert("Link Copied", "Event type link copied!"); } catch { showErrorAlert("Error", "Failed to copy link. Please try again."); @@ -121,11 +124,14 @@ export default function EventTypesIOS() { }; const _handleShare = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); await Share.share({ message: `Book a meeting: ${eventType.title}`, - url: link, + url: eventType.bookingUrl, }); } catch { showErrorAlert("Error", "Failed to share link. Please try again."); @@ -226,10 +232,12 @@ export default function EventTypesIOS() { }; const handlePreview = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); - // For mobile, use in-app browser - await openInAppBrowser(link, "event type preview"); + await openInAppBrowser(eventType.bookingUrl, "event type preview"); } catch { console.error("Failed to open preview"); showErrorAlert("Error", "Failed to open preview. Please try again."); diff --git a/companion/app/(tabs)/(event-types)/index.tsx b/companion/app/(tabs)/(event-types)/index.tsx index 246b8ed04ddc58..0830851c3061f8 100644 --- a/companion/app/(tabs)/(event-types)/index.tsx +++ b/companion/app/(tabs)/(event-types)/index.tsx @@ -37,7 +37,7 @@ import { useEventTypes, } from "@/hooks"; import { useEventTypeFilter } from "@/hooks/useEventTypeFilter"; -import { CalComAPIService, type EventType } from "@/services/calcom"; +import type { EventType } from "@/services/calcom"; import { showErrorAlert, showSuccessAlert } from "@/utils/alerts"; import { openInAppBrowser } from "@/utils/browser"; import { getEventDuration } from "@/utils/getEventDuration"; @@ -133,10 +133,12 @@ export default function EventTypes() { }; const handleCopyLink = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); - await Clipboard.setStringAsync(link); - + await Clipboard.setStringAsync(eventType.bookingUrl); showSuccessAlert("Link Copied", "Event type link copied!"); } catch { showErrorAlert("Error", "Failed to copy link. Please try again."); @@ -144,11 +146,14 @@ export default function EventTypes() { }; const _handleShare = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); await Share.share({ message: `Book a meeting: ${eventType.title}`, - url: link, + url: eventType.bookingUrl, }); } catch { showErrorAlert("Error", "Failed to share link. Please try again."); @@ -280,14 +285,15 @@ export default function EventTypes() { }; const handlePreview = async (eventType: EventType) => { + if (!eventType.bookingUrl) { + showErrorAlert("Error", "Booking URL not available for this event type."); + return; + } try { - const link = await CalComAPIService.buildEventTypeLink(eventType.slug); - // Open in browser if (Platform.OS === "web") { - window.open(link, "_blank"); + window.open(eventType.bookingUrl, "_blank"); } else { - // For mobile, use in-app browser - await openInAppBrowser(link, "event type preview"); + await openInAppBrowser(eventType.bookingUrl, "event type preview"); } } catch { console.error("Failed to open preview"); diff --git a/companion/components/event-type-detail/tabs/BasicsTab.tsx b/companion/components/event-type-detail/tabs/BasicsTab.tsx index 73f12b17e3d0c4..712497619dd6a6 100644 --- a/companion/components/event-type-detail/tabs/BasicsTab.tsx +++ b/companion/components/event-type-detail/tabs/BasicsTab.tsx @@ -37,6 +37,7 @@ interface BasicsTabProps { onUpdateLocation: (locationId: string, updates: Partial) => void; locationOptions: LocationOptionGroup[]; conferencingLoading: boolean; + bookingUrl?: string; } // Section header @@ -253,7 +254,22 @@ export const BasicsTab: React.FC = (props) => { URL - cal.com/{props.username}/ + {(() => { + // Parse bookingUrl to get domain prefix (e.g., "i.cal.com/" or "cal.com/username/") + if (props.bookingUrl) { + try { + const url = new URL(props.bookingUrl); + // Get path without the last segment (slug) + const pathParts = url.pathname.split("/").filter(Boolean); + pathParts.pop(); // Remove slug + const prefix = pathParts.length > 0 ? `/${pathParts.join("/")}/` : "/"; + return `${url.hostname}${prefix}`; + } catch { + // fallback + } + } + return `cal.com/${props.username}/`; + })()} {title} @@ -36,10 +54,11 @@ export function EventTypeDescription({ normalizedDescription }: EventTypeDescrip interface EventTypeLinkProps { username?: string; slug: string; + bookingUrl?: string; } -export function EventTypeLink({ username, slug }: EventTypeLinkProps) { - const linkText = username ? `/${username}/${slug}` : `/${slug}`; +export function EventTypeLink({ username, slug, bookingUrl }: EventTypeLinkProps) { + const linkText = getDisplayUrl(bookingUrl, username, slug); return {linkText}; } diff --git a/companion/extension/entrypoints/background/index.ts b/companion/extension/entrypoints/background/index.ts index d48cf40b192624..a8db6627405878 100644 --- a/companion/extension/entrypoints/background/index.ts +++ b/companion/extension/entrypoints/background/index.ts @@ -278,6 +278,7 @@ function getTabsAPI(): typeof chrome.tabs | null { function getActionAPI(): typeof chrome.action | null { const api = getBrowserAPI(); // Safari uses browserAction (Manifest V2), Chrome uses action (Manifest V3) + // biome-ignore lint/suspicious/noExplicitAny: Safari's browserAction API is not in Chrome types return api?.action || (api as any)?.browserAction || null; } diff --git a/companion/extension/entrypoints/content.ts b/companion/extension/entrypoints/content.ts index 1422a85e8013e6..f178c91c721eee 100644 --- a/companion/extension/entrypoints/content.ts +++ b/companion/extension/entrypoints/content.ts @@ -833,6 +833,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }> = []; if (isCacheValid && eventTypesCache) { @@ -874,6 +875,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }>; } ).data @@ -889,6 +891,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }>; } ).data; @@ -1075,9 +1078,11 @@ export default defineContentScript({ previewBtn.addEventListener("click", (e) => { e.stopPropagation(); - const bookingUrl = `https://cal.com/${ - eventType.users?.[0]?.username || "user" - }/${eventType.slug}`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${ + eventType.users?.[0]?.username || "user" + }/${eventType.slug}`; window.open(bookingUrl, "_blank"); }); previewBtn.addEventListener("mouseenter", () => { @@ -1117,9 +1122,11 @@ export default defineContentScript({ copyBtn.addEventListener("click", (e) => { e.stopPropagation(); // Copy to clipboard - const bookingUrl = `https://cal.com/${ - eventType.users?.[0]?.username || "user" - }/${eventType.slug}`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${ + eventType.users?.[0]?.username || "user" + }/${eventType.slug}`; navigator.clipboard .writeText(bookingUrl) .then(() => { @@ -1285,11 +1292,12 @@ export default defineContentScript({ function insertEventTypeLink(eventType: { slug: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }): void { // Construct the Cal.com booking link - const bookingUrl = `https://cal.com/${eventType.users?.[0]?.username || "user"}/${ - eventType.slug - }`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; // Try to insert at cursor position in the compose field const inserted = insertTextAtCursor(bookingUrl); @@ -1312,11 +1320,12 @@ export default defineContentScript({ function _copyEventTypeLink(eventType: { slug: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }): void { // Construct the Cal.com booking link - const bookingUrl = `https://cal.com/${eventType.users?.[0]?.username || "user"}/${ - eventType.slug - }`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; // Try to insert at cursor position in the compose field const inserted = insertTextAtCursor(bookingUrl); @@ -1574,6 +1583,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }> = []; if (isCacheValid && eventTypesCache) { @@ -1615,6 +1625,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }>; } ).data @@ -1630,6 +1641,7 @@ export default defineContentScript({ duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }>; } ).data; @@ -1815,9 +1827,9 @@ export default defineContentScript({ previewBtn.addEventListener("click", (e) => { e.stopPropagation(); - const bookingUrl = `https://cal.com/${ - eventType.users?.[0]?.username || "user" - }/${eventType.slug}`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; window.open(bookingUrl, "_blank"); }); previewBtn.addEventListener("mouseenter", () => { @@ -1857,9 +1869,9 @@ export default defineContentScript({ copyBtn.addEventListener("click", (e) => { e.stopPropagation(); // Copy to clipboard - const bookingUrl = `https://cal.com/${ - eventType.users?.[0]?.username || "user" - }/${eventType.slug}`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; navigator.clipboard .writeText(bookingUrl) .then(() => { @@ -2025,11 +2037,12 @@ export default defineContentScript({ function insertEventTypeLink(eventType: { slug: string; users?: Array<{ username?: string }>; + bookingUrl?: string; }) { // Construct the Cal.com booking link - const bookingUrl = `https://cal.com/${eventType.users?.[0]?.username || "user"}/${ - eventType.slug - }`; + const bookingUrl = + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; // Try to insert at cursor position in the message field const inserted = insertTextAtCursor(bookingUrl); diff --git a/companion/extension/lib/linkedin.ts b/companion/extension/lib/linkedin.ts index f3daf7a906de39..4e10603bd41b12 100644 --- a/companion/extension/lib/linkedin.ts +++ b/companion/extension/lib/linkedin.ts @@ -115,6 +115,7 @@ interface EventType { duration?: number; description?: string; users?: Array<{ username?: string }>; + bookingUrl?: string; } interface ButtonSize { @@ -664,7 +665,10 @@ export function initLinkedInIntegration() { } function buildBookingUrl(eventType: EventType): string { - return `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}`; + return ( + eventType.bookingUrl || + `https://cal.com/${eventType.users?.[0]?.username || "user"}/${eventType.slug}` + ); } function handleFetchError(error: unknown, menu: HTMLElement, tooltipsToCleanup: HTMLElement[]) { diff --git a/companion/services/calcom.ts b/companion/services/calcom.ts index 74b7a2df6ced66..720c83645ed708 100644 --- a/companion/services/calcom.ts +++ b/companion/services/calcom.ts @@ -318,18 +318,6 @@ async function getUserProfile(): Promise { return _userProfilePromise; } -// Get cached username or fetch if not available -async function getUsername(): Promise { - const profile = await getUserProfile(); - return profile.username; -} - -// Build shareable link for event type -async function buildEventTypeLink(eventTypeSlug: string): Promise { - const username = await getUsername(); - return `https://cal.com/${username}/${eventTypeSlug}`; -} - // Clear cached profile (useful for logout) function clearUserProfile(): void { _userProfile = null; @@ -1672,8 +1660,6 @@ export const CalComAPIService = { getCurrentUser, updateUserProfile, getUserProfile, - getUsername, - buildEventTypeLink, clearUserProfile, testRawBookingsAPI, deleteEventType, diff --git a/companion/services/types/event-types.types.ts b/companion/services/types/event-types.types.ts index 0cb6f1a494d959..bd63ee3c19ce01 100644 --- a/companion/services/types/event-types.types.ts +++ b/companion/services/types/event-types.types.ts @@ -278,6 +278,9 @@ export interface EventType { // Optimized slots (API V2) showOptimizedSlots?: boolean; + + // Booking URL (API V2) - full booking URL for this event type + bookingUrl?: string; } export interface CreateEventTypeInput { From 8f668abd10b554f44df656cda04e485168c420c3 Mon Sep 17 00:00:00 2001 From: Dhairyashil Date: Tue, 13 Jan 2026 03:15:40 +0530 Subject: [PATCH 2/7] checkpoint 2 --- companion/components/event-type-detail/tabs/BasicsTab.tsx | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/companion/components/event-type-detail/tabs/BasicsTab.tsx b/companion/components/event-type-detail/tabs/BasicsTab.tsx index 712497619dd6a6..81251d1657161d 100644 --- a/companion/components/event-type-detail/tabs/BasicsTab.tsx +++ b/companion/components/event-type-detail/tabs/BasicsTab.tsx @@ -262,7 +262,11 @@ export const BasicsTab: React.FC = (props) => { // Get path without the last segment (slug) const pathParts = url.pathname.split("/").filter(Boolean); pathParts.pop(); // Remove slug - const prefix = pathParts.length > 0 ? `/${pathParts.join("/")}/` : "/"; + // Compute prefix outside try/catch for React Compiler + let prefix = "/"; + if (pathParts.length > 0) { + prefix = `/${pathParts.join("/")}/`; + } return `${url.hostname}${prefix}`; } catch { // fallback From c19907064c3d3d7b3cbf5fe93f899806aa038a84 Mon Sep 17 00:00:00 2001 From: Dhairyashil Date: Tue, 13 Jan 2026 03:34:46 +0530 Subject: [PATCH 3/7] update extension header --- .../(availability)/availability-detail.tsx | 2 +- companion/app/(tabs)/(bookings)/index.ios.tsx | 4 +- companion/app/(tabs)/(bookings)/index.tsx | 9 +++- .../(event-types)/event-type-detail.tsx | 5 +- companion/app/(tabs)/(event-types)/index.tsx | 2 + companion/components/Header.tsx | 49 ++++++++++--------- 6 files changed, 42 insertions(+), 29 deletions(-) diff --git a/companion/app/(tabs)/(availability)/availability-detail.tsx b/companion/app/(tabs)/(availability)/availability-detail.tsx index f31ab0aecb2a4c..ca62bc228c6b52 100644 --- a/companion/app/(tabs)/(availability)/availability-detail.tsx +++ b/companion/app/(tabs)/(availability)/availability-detail.tsx @@ -88,7 +88,7 @@ export default function AvailabilityDetail() { marginRight: -8, }} > - + diff --git a/companion/app/(tabs)/(bookings)/index.ios.tsx b/companion/app/(tabs)/(bookings)/index.ios.tsx index 7f6e4d83d0e7c0..36e57d70f09ff5 100644 --- a/companion/app/(tabs)/(bookings)/index.ios.tsx +++ b/companion/app/(tabs)/(bookings)/index.ios.tsx @@ -62,7 +62,7 @@ export default function Bookings() { label: currentFilterOption?.label || "Filter", labelStyle: { fontWeight: "600", - color: "#007AFF", + color: "#000000", }, menu: { title: "Filter by Status", @@ -123,7 +123,7 @@ export default function Bookings() { }, labelStyle: { fontWeight: "600", - color: "#007AFF", + color: "#000000", }, menu: { title: menuItems.length > 0 ? "Filter by Event Type" : "No Event Types", diff --git a/companion/app/(tabs)/(bookings)/index.tsx b/companion/app/(tabs)/(bookings)/index.tsx index aec5e06d3d2e4d..d6e8c7ec748526 100644 --- a/companion/app/(tabs)/(bookings)/index.tsx +++ b/companion/app/(tabs)/(bookings)/index.tsx @@ -62,11 +62,16 @@ export default function Bookings() { diff --git a/companion/app/(tabs)/(event-types)/event-type-detail.tsx b/companion/app/(tabs)/(event-types)/event-type-detail.tsx index 6ea284b9d25c30..4905e9bf80f045 100644 --- a/companion/app/(tabs)/(event-types)/event-type-detail.tsx +++ b/companion/app/(tabs)/(event-types)/event-type-detail.tsx @@ -1259,7 +1259,10 @@ export default function EventTypeDetail() { {/* Tab Navigation Dropdown Menu */} - + {tabs.find((tab) => tab.id === activeTab)?.label ?? "Basics"} diff --git a/companion/app/(tabs)/(event-types)/index.tsx b/companion/app/(tabs)/(event-types)/index.tsx index 0830851c3061f8..ec7c486a73b5b5 100644 --- a/companion/app/(tabs)/(event-types)/index.tsx +++ b/companion/app/(tabs)/(event-types)/index.tsx @@ -449,6 +449,7 @@ export default function EventTypes() { /> @@ -513,6 +514,7 @@ export default function EventTypes() { /> diff --git a/companion/components/Header.tsx b/companion/components/Header.tsx index 3d2d5db3bc6cc5..665b2ac8f3a250 100644 --- a/companion/components/Header.tsx +++ b/companion/components/Header.tsx @@ -103,11 +103,14 @@ export function Header({ {filterOptions && filterOptions.length > 0 && onFilterChange && ( - - + + {activeFilterLabel} - + @@ -143,11 +146,11 @@ export function Header({ {option.label} @@ -165,11 +168,11 @@ export function Header({ - + {/* Badge for active filters */} {eventTypeFilterConfig.activeFilterCount > 0 && ( @@ -206,12 +209,12 @@ export function Header({ : "text-outline" } size={16} - color={eventTypeFilterConfig.sortBy === "alphabetical" ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.sortBy === "alphabetical" ? "#000000" : "#666"} /> @@ -228,12 +231,12 @@ export function Header({ : "calendar-outline" } size={16} - color={eventTypeFilterConfig.sortBy === "newest" ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.sortBy === "newest" ? "#000000" : "#666"} /> @@ -250,12 +253,12 @@ export function Header({ : "time-outline" } size={16} - color={eventTypeFilterConfig.sortBy === "duration" ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.sortBy === "duration" ? "#000000" : "#666"} /> @@ -286,12 +289,12 @@ export function Header({ : "eye-off-outline" } size={16} - color={eventTypeFilterConfig.filters.hiddenOnly ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.filters.hiddenOnly ? "#000000" : "#666"} /> @@ -307,12 +310,12 @@ export function Header({ eventTypeFilterConfig.filters.paidOnly ? "checkmark-circle" : "cash-outline" } size={16} - color={eventTypeFilterConfig.filters.paidOnly ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.filters.paidOnly ? "#000000" : "#666"} /> @@ -330,12 +333,12 @@ export function Header({ : "people-outline" } size={16} - color={eventTypeFilterConfig.filters.seatedOnly ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.filters.seatedOnly ? "#000000" : "#666"} /> @@ -356,13 +359,13 @@ export function Header({ } size={16} color={ - eventTypeFilterConfig.filters.requiresConfirmationOnly ? "#007AFF" : "#666" + eventTypeFilterConfig.filters.requiresConfirmationOnly ? "#000000" : "#666" } /> @@ -382,12 +385,12 @@ export function Header({ : "repeat-outline" } size={16} - color={eventTypeFilterConfig.filters.recurringOnly ? "#007AFF" : "#666"} + color={eventTypeFilterConfig.filters.recurringOnly ? "#000000" : "#666"} /> From b05a537413ab99b286e827cc704288babb368f0b Mon Sep 17 00:00:00 2001 From: Dhairyashil Date: Tue, 13 Jan 2026 03:52:20 +0530 Subject: [PATCH 4/7] fix some minor ios ui bugs --- .../(tabs)/(event-types)/event-type-detail.tsx | 16 +++++++++------- companion/app/profile-sheet.ios.tsx | 2 +- companion/app/profile-sheet.tsx | 2 +- .../event-type-detail/tabs/AdvancedTab.tsx | 4 ++-- .../event-type-detail/tabs/BasicsTab.tsx | 4 ++-- .../event-type-detail/tabs/LimitsTab.tsx | 4 ++-- .../event-type-detail/tabs/RecurringTab.tsx | 4 ++-- 7 files changed, 19 insertions(+), 17 deletions(-) diff --git a/companion/app/(tabs)/(event-types)/event-type-detail.tsx b/companion/app/(tabs)/(event-types)/event-type-detail.tsx index 4905e9bf80f045..f732e53e6dc7d1 100644 --- a/companion/app/(tabs)/(event-types)/event-type-detail.tsx +++ b/companion/app/(tabs)/(event-types)/event-type-detail.tsx @@ -2326,15 +2326,17 @@ export default function EventTypeDetail() { Hidden - + + + diff --git a/companion/app/profile-sheet.ios.tsx b/companion/app/profile-sheet.ios.tsx index b08381b1317105..2f85b575290177 100644 --- a/companion/app/profile-sheet.ios.tsx +++ b/companion/app/profile-sheet.ios.tsx @@ -147,7 +147,7 @@ export default function ProfileSheet() { }} > {/* Profile Header */} - + {isLoading ? ( diff --git a/companion/app/profile-sheet.tsx b/companion/app/profile-sheet.tsx index c2f84263268f8f..0ad0aa5e69f889 100644 --- a/companion/app/profile-sheet.tsx +++ b/companion/app/profile-sheet.tsx @@ -124,7 +124,7 @@ export default function ProfileSheet() { contentContainerStyle={{ paddingBottom: insets.bottom + 20 }} > {/* Profile Header */} - + {isLoading ? ( diff --git a/companion/components/event-type-detail/tabs/AdvancedTab.tsx b/companion/components/event-type-detail/tabs/AdvancedTab.tsx index cd07f39424f22e..0a009da1ccba25 100644 --- a/companion/components/event-type-detail/tabs/AdvancedTab.tsx +++ b/companion/components/event-type-detail/tabs/AdvancedTab.tsx @@ -138,7 +138,7 @@ function SettingRow({ ) : null} - + {title} - + ) : null} - + ) : null} - + Date: Mon, 12 Jan 2026 22:36:20 +0000 Subject: [PATCH 5/7] fix(companion): restore username fetching for URL fallback display Addresses Cubic AI review feedback (confidence 9/10): The username was hardcoded to 'username' but still used by BasicsTab as a fallback for URL display when bookingUrl is unavailable. This restores the useEffect that fetches the actual username from CalComAPIService.getUsername(). Co-Authored-By: unknown <> --- .../app/(tabs)/(event-types)/event-type-detail.tsx | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/companion/app/(tabs)/(event-types)/event-type-detail.tsx b/companion/app/(tabs)/(event-types)/event-type-detail.tsx index f732e53e6dc7d1..cbef9d914941ac 100644 --- a/companion/app/(tabs)/(event-types)/event-type-detail.tsx +++ b/companion/app/(tabs)/(event-types)/event-type-detail.tsx @@ -147,7 +147,7 @@ export default function EventTypeDetail() { const [eventDescription, setEventDescription] = useState(description || ""); const [eventSlug, setEventSlug] = useState(slug || ""); const [eventDuration, setEventDuration] = useState(duration || "30"); - const [username, _setUsername] = useState("username"); + const [username, setUsername] = useState("username"); const [allowMultipleDurations, setAllowMultipleDurations] = useState(false); const [locations, setLocations] = useState([]); const [_locationAddress, setLocationAddress] = useState(""); @@ -855,6 +855,18 @@ export default function EventTypeDetail() { fetchConferencingOptions(); }, [fetchConferencingOptions, fetchEventTypeData]); + useEffect(() => { + const fetchUsername = async () => { + try { + const userUsername = await CalComAPIService.getUsername(); + setUsername(userUsername); + } catch (error) { + safeLogError("Failed to fetch username:", error); + } + }; + fetchUsername(); + }, []); + const formatTime = (time: string) => { // Handle different time formats that might come from the API // Extract conditionals outside try/catch for React Compiler From 3dd928a3119c85cbec4d79dc3aceebf0eb11e840 Mon Sep 17 00:00:00 2001 From: Dhairyashil Date: Tue, 13 Jan 2026 04:10:26 +0530 Subject: [PATCH 6/7] complete devins code change --- companion/services/calcom.ts | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/companion/services/calcom.ts b/companion/services/calcom.ts index 720c83645ed708..21f5230df4467a 100644 --- a/companion/services/calcom.ts +++ b/companion/services/calcom.ts @@ -1651,6 +1651,12 @@ async function deleteEventTypePrivateLink(eventTypeId: number, linkId: number): } } +// Helper to get username +async function getUsername(): Promise { + const profile = await getUserProfile(); + return profile.username; +} + // Export as object to satisfy noStaticOnlyClass rule export const CalComAPIService = { setAccessToken, @@ -1660,6 +1666,7 @@ export const CalComAPIService = { getCurrentUser, updateUserProfile, getUserProfile, + getUsername, clearUserProfile, testRawBookingsAPI, deleteEventType, From 161a777b0c69817e9c7572ab4b21b97943482afb Mon Sep 17 00:00:00 2001 From: tomerqodo Date: Sun, 25 Jan 2026 12:01:39 +0200 Subject: [PATCH 7/7] update pr --- companion/app/(tabs)/(event-types)/event-type-detail.tsx | 1 - companion/components/event-type-detail/tabs/BasicsTab.tsx | 2 +- companion/extension/entrypoints/content.ts | 1 - companion/services/calcom.ts | 8 ++++++-- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/companion/app/(tabs)/(event-types)/event-type-detail.tsx b/companion/app/(tabs)/(event-types)/event-type-detail.tsx index cbef9d914941ac..46aa4cfd6b6981 100644 --- a/companion/app/(tabs)/(event-types)/event-type-detail.tsx +++ b/companion/app/(tabs)/(event-types)/event-type-detail.tsx @@ -457,7 +457,6 @@ export default function EventTypeDetail() { if (eventType.description) setEventDescription(eventType.description); if (eventType.lengthInMinutes) setEventDuration(eventType.lengthInMinutes.toString()); if (eventType.hidden !== undefined) setIsHidden(eventType.hidden); - if (eventType.bookingUrl) setBookingUrl(eventType.bookingUrl); // Load schedule ID - this will be used by fetchSchedules to select the correct schedule if (eventType.scheduleId) { diff --git a/companion/components/event-type-detail/tabs/BasicsTab.tsx b/companion/components/event-type-detail/tabs/BasicsTab.tsx index 43cab9ec9e73d1..1fde5c49cce674 100644 --- a/companion/components/event-type-detail/tabs/BasicsTab.tsx +++ b/companion/components/event-type-detail/tabs/BasicsTab.tsx @@ -267,7 +267,7 @@ export const BasicsTab: React.FC = (props) => { if (pathParts.length > 0) { prefix = `/${pathParts.join("/")}/`; } - return `${url.hostname}${prefix}`; + return `${url.protocol}//${url.hostname}${prefix}`; } catch { // fallback } diff --git a/companion/extension/entrypoints/content.ts b/companion/extension/entrypoints/content.ts index f178c91c721eee..892cb907b4e306 100644 --- a/companion/extension/entrypoints/content.ts +++ b/companion/extension/entrypoints/content.ts @@ -1123,7 +1123,6 @@ export default defineContentScript({ e.stopPropagation(); // Copy to clipboard const bookingUrl = - eventType.bookingUrl || `https://cal.com/${ eventType.users?.[0]?.username || "user" }/${eventType.slug}`; diff --git a/companion/services/calcom.ts b/companion/services/calcom.ts index 21f5230df4467a..2af939d9bb7727 100644 --- a/companion/services/calcom.ts +++ b/companion/services/calcom.ts @@ -1653,8 +1653,12 @@ async function deleteEventTypePrivateLink(eventTypeId: number, linkId: number): // Helper to get username async function getUsername(): Promise { - const profile = await getUserProfile(); - return profile.username; + try { + const profile = await getUserProfile(); + return profile.username; + } catch (error) { + throw new Error("Failed to get username"); + } } // Export as object to satisfy noStaticOnlyClass rule