The Profile component displays user information, statistics, and betting activity within the Virtual Stadium community. It shows a user's shared bets, copy count, and engagement metrics, and can be accessed either through the Chat component's user interactions or opened manually.
The Profile component provides a detailed view of a user's activity in the Virtual Stadium community:
ProfileView directlyThis guide will walk you through each step with code examples and best practices.
Prerequisites
Managers.SDK.shared.initialize()The Profile component is independent from the Chat component. It can be displayed by providing the userJWT and userId parameters, either in response to a user interaction in Chat or by initializing it directly anywhere in your app.
Required Parameters:
userJWT String required — JWT authentication token required to authenticate the user. This is the same JWT used to initialize the Chat component. The Profile component uses this to log the user in automatically if they are not already authenticated.userId String required — The unique identifier of the user whose profile to display. This is typically provided by the Chat component's onOpenProfile callback, or any user ID known to your app.Optional Parameters:
onCopyBet ((BetPayload) -> Void)? optional — Callback invoked when a user copies a bet from the profile. Returns the BetPayload to add to your bet slip.onClose (() -> Void)? optional — Callback invoked when the user closes the profile screen. Use this to handle navigation back to the chat.chatSettings ChatSettings optional — Customization settings for theming, fonts, icons, and translations. Should match the Chat component settings for visual consistency. Default: ChatSettings()Breaking Change
In a previous version of the SDK, ProfileView did not require a JWT token and authentication was handled externally:
// ❌ Old API — no longer supported
ProfileView(
userId: selectedUserId,
onCopyBet: { betPayload in ... },
onClose: { showProfile = false },
chatSettings: ChatSettings()
Automatic Authentication
ProfileView now manages its own authentication state. When the component appears:
This means ProfileView can be used independently from ChatView without requiring a separate login step.
The Profile component is designed to overlay or navigate from the Chat component, but can also be initialized and presented independently anywhere in your application. Use state management to toggle its visibility based on user interactions.
The most common use case is opening a profile when a user taps on another user's name or avatar in the Chat component. Use the onOpenProfileHandler callback in ChatViewCallbacksVM to receive the user ID and present the profile.
ProfileView can also be initialized and presented independently from the Chat component — for example, from a leaderboard, a notification, or any other part of your app where you have a user ID available. Simply provide the same JWT token used elsewhere in your app along with the target user ID.
The Profile component displays the following information:
| Metric | Description |
|---|---|
| Bets Shared | Total number of bet slips the user has shared with the community |
| Bets Copied | Number of times other users have copied this user's bets |
For a cohesive user experience, use the same ChatSettings for both Chat and Profile components. This ensures consistent colors, fonts, and icons throughout your application.
Create a single ChatSettings instance and reuse it across both components. This maintains visual consistency and simplifies theme management.
Best Practice:
Using different ChatSettings for Chat and Profile will result in an inconsistent user experience. Always share the same configuration.
userJWT is now a required parameter. The Profile component handles authentication internally — if the user is not already logged in, the component will log them in automatically using the provided JWT before displaying the profile content.
// ✅ New API
ProfileView(
userJWT: jwt,
userId: selectedUserId,
onCopyBet: { betPayload in ... },
onClose: { showProfile = false },
chatSettings: ChatSettings()
)import SwiftUI
import VirtualStadiumSDK
struct ContentView: View {
let jwt: String
let channelId: String
@State private var showProfile = false
@State private var selectedUserId = ""
var body: some View {
NavigationView {
ZStack {
// Chat component
ChatView(
userJWT: jwt,
channelId: channelId,
supportedLanguage: .english,
callbacksVM: ChatViewCallbacksVM(
onCopyToBetslipHandler: { betPayload in
print("Bet copied: \(betPayload.id)")
},
onOpenProfileHandler: { userId in
selectedUserId = userId
showProfile = true
}
)
)
// Profile overlay
if showProfile {
ProfileView(
userJWT: jwt,
userId: selectedUserId,
onCopyBet: { betPayload in
print("Bet copied from profile: \(betPayload.id)")
},
onClose: {
showProfile = false
selectedUserId = ""
},
chatSettings: ChatSettings()
)
.transition(.move(edge: .trailing))
}
}
.navigationTitle("Chat")
.animation(.easeInOut, value: showProfile)
}
}
}import SwiftUI
import VirtualStadiumSDK
struct StandaloneProfileExample: View {
let jwt: String
let userId: String
@State private var showProfile = false
var body: some View {
Button("View Profile") {
showProfile = true
}
.sheet(isPresented: $showProfile) {
ProfileView(
userJWT: jwt,
userId: userId,
onCopyBet: { betPayload in
/**
* TODO(developer): Add bet to user's bet slip
*/
print("Bet copied from profile: \(betPayload.id)")
},
onClose: {
showProfile = false
},
chatSettings: ChatSettings()
)
}
}
}