@@ -40,6 +40,11 @@ public override string ToString()
4040 /// - iOS/Android: Vuplex WebView with embedded browser
4141 /// - macOS: Vuplex WebView with embedded browser
4242 ///
43+ /// INITIALIZATION OPTIONS:
44+ /// 1. Simple: Call InitializeWithPassport() - PassportUI handles both Passport.Init() and UI setup
45+ /// 2. Hybrid: Call InitializeWithPassport(passport) - Use existing Passport instance with UI
46+ /// 3. Traditional: Call Passport.Init() yourself, then call Init(passport) - for advanced control
47+ ///
4348 /// SETUP: When configuring the PassportUI prefab in the editor:
4449 /// - Set RawImage component's width and height to 0 in the RectTransform
4550 /// - This ensures the UI is completely hidden before initialization
@@ -83,17 +88,69 @@ public class PassportUI : MonoBehaviour
8388 [ Tooltip ( "Clear WebView cache on login for Windows WebView (Volt Unity Web Browser). Not used on other platforms." ) ]
8489 public bool clearCacheOnLogin = true ;
8590
91+ [ Header ( "Passport Configuration" ) ]
92+ [ Tooltip ( "Passport client ID from the Immutable Developer Hub" ) ]
93+ [ SerializeField ] private string clientId = "" ;
94+
95+ [ Tooltip ( "Passport environment (sandbox or production)" ) ]
96+ [ SerializeField ] private string environment = "sandbox" ;
97+
98+ [ Tooltip ( "OAuth redirect URI for authentication callbacks" ) ]
99+ [ SerializeField ] private string redirectUri = "immutablerunner://callback" ;
100+
101+ [ Tooltip ( "OAuth logout redirect URI for logout callbacks" ) ]
102+ [ SerializeField ] private string logoutRedirectUri = "immutablerunner://logout" ;
103+
86104 [ Header ( "WebView Settings" ) ]
87- [ Tooltip ( "URL to load in the WebView for authentication." ) ]
88- [ SerializeField ] private string webViewUrl = "https://auth.immutable.com/im-embedded-login-prompt?isWebView=true&client_id=YOUR_CLIENT_ID" ;
105+ [ Tooltip ( "Base URL for the WebView authentication page. The client_id parameter will be automatically appended from the Passport Configuration above." ) ]
106+ [ SerializeField ] private string webViewBaseUrl = "https://auth.immutable.com/im-embedded-login-prompt" ;
107+
108+ [ Tooltip ( "Width of the WebView in pixels. Set to 0 to use the RawImage's current width." ) ]
109+ [ SerializeField ] private int webViewWidth = 1920 ;
110+
111+ [ Tooltip ( "Height of the WebView in pixels. Set to 0 to use the RawImage's current height." ) ]
112+ [ SerializeField ] private int webViewHeight = 1080 ;
89113
90114 /// <summary>
91- /// Gets or sets the URL to load in the WebView for authentication
115+ /// Gets the complete WebView URL with the client ID automatically appended
92116 /// </summary>
93117 public string WebViewUrl
94118 {
95- get => webViewUrl ;
96- set => webViewUrl = value ;
119+ get
120+ {
121+ if ( string . IsNullOrEmpty ( clientId ) )
122+ {
123+ return webViewBaseUrl ;
124+ }
125+ return $ "{ webViewBaseUrl } ?isWebView=true&client_id={ clientId } ";
126+ }
127+ }
128+
129+ /// <summary>
130+ /// Gets or sets the base WebView URL (without client_id parameter)
131+ /// </summary>
132+ public string WebViewBaseUrl
133+ {
134+ get => webViewBaseUrl ;
135+ set => webViewBaseUrl = value ;
136+ }
137+
138+ /// <summary>
139+ /// Gets or sets the WebView width in pixels
140+ /// </summary>
141+ public int WebViewWidth
142+ {
143+ get => webViewWidth ;
144+ set => webViewWidth = value ;
145+ }
146+
147+ /// <summary>
148+ /// Gets or sets the WebView height in pixels
149+ /// </summary>
150+ public int WebViewHeight
151+ {
152+ get => webViewHeight ;
153+ set => webViewHeight = value ;
97154 }
98155
99156 // Cross-platform WebView abstraction
@@ -109,9 +166,79 @@ public string WebViewUrl
109166 private Coroutine inputActivationCoroutine ;
110167
111168 /// <summary>
112- /// Initialize PassportUI with the main Passport instance
113- /// Following the working WebViewTest pattern
169+ /// Initialize Passport and PassportUI in one call using the configured settings.
170+ /// This is the simple initialization method that handles both Passport.Init() and UI setup.
171+ /// Uses the serialized fields (clientId, environment, redirectUri, logoutRedirectUri) from the Unity Inspector.
172+ /// </summary>
173+ /// <returns>UniTask that completes when initialization is finished</returns>
174+ public async UniTask InitializeWithPassport ( )
175+ {
176+ // Validate configuration
177+ if ( string . IsNullOrEmpty ( clientId ) )
178+ {
179+ PassportLogger . Error ( $ "{ TAG } Client ID is required but not set in the Inspector") ;
180+ return ;
181+ }
182+
183+ try
184+ {
185+ PassportLogger . Info ( $ "{ TAG } Initializing Passport with client ID: { clientId } ") ;
186+
187+ // Initialize Passport using the configured settings
188+ var passport = await Passport . Init ( clientId , environment , redirectUri , logoutRedirectUri ) ;
189+
190+ // Initialize the UI with the created Passport instance
191+ Init ( passport ) ;
192+
193+ PassportLogger . Info ( $ "{ TAG } Passport and PassportUI initialized successfully") ;
194+ }
195+ catch ( Exception ex )
196+ {
197+ PassportLogger . Error ( $ "{ TAG } Failed to initialize Passport: { ex . Message } ") ;
198+ throw ;
199+ }
200+ }
201+
202+ /// <summary>
203+ /// Initialize PassportUI with an existing Passport instance in one call.
204+ /// Use this method when you already have a Passport instance from elsewhere in your code
205+ /// and just want to set up the UI component.
206+ /// </summary>
207+ /// <param name="passportInstance">The existing initialized Passport instance</param>
208+ /// <returns>UniTask that completes when UI initialization is finished</returns>
209+ public async UniTask InitializeWithPassport ( Passport passportInstance )
210+ {
211+ if ( passportInstance == null )
212+ {
213+ PassportLogger . Error ( $ "{ TAG } Passport instance cannot be null") ;
214+ return ;
215+ }
216+
217+ try
218+ {
219+ PassportLogger . Info ( $ "{ TAG } Initializing PassportUI with existing Passport instance") ;
220+
221+ // Initialize the UI with the provided Passport instance
222+ Init ( passportInstance ) ;
223+
224+ // Wait a frame to ensure initialization is complete
225+ await UniTask . Yield ( ) ;
226+
227+ PassportLogger . Info ( $ "{ TAG } PassportUI initialized successfully with existing Passport instance") ;
228+ }
229+ catch ( Exception ex )
230+ {
231+ PassportLogger . Error ( $ "{ TAG } Failed to initialize PassportUI with existing Passport: { ex . Message } ") ;
232+ throw ;
233+ }
234+ }
235+
236+ /// <summary>
237+ /// Initialize PassportUI with an existing Passport instance.
238+ /// Use this method if you want to control Passport.Init() yourself.
239+ /// Following the working WebViewTest pattern.
114240 /// </summary>
241+ /// <param name="passportInstance">The initialized Passport instance</param>
115242 public void Init ( Passport passportInstance )
116243 {
117244 if ( passportInstance == null )
@@ -185,7 +312,9 @@ private void CreateWebView()
185312 EnableRemoteDebugging = enableRemoteDebugging ,
186313 RemoteDebuggingPort = remoteDebuggingPort ,
187314 ClearCacheOnInit = clearCacheOnLogin ,
188- InitialUrl = "about:blank"
315+ InitialUrl = "about:blank" ,
316+ Width = webViewWidth > 0 ? webViewWidth : ( int ) rawImage . rectTransform . rect . width ,
317+ Height = webViewHeight > 0 ? webViewHeight : ( int ) rawImage . rectTransform . rect . height
189318 } ;
190319
191320 // Initialize WebView
@@ -483,8 +612,8 @@ public async UniTask<bool> ShowLoginUI()
483612 webView . Show ( ) ;
484613 PassportLogger . Info ( $ "{ TAG } WebView shown") ;
485614
486- webView . LoadUrl ( webViewUrl ) ;
487- PassportLogger . Info ( $ "{ TAG } Navigated to configured URL: { webViewUrl } ") ;
615+ webView . LoadUrl ( WebViewUrl ) ;
616+ PassportLogger . Info ( $ "{ TAG } Navigated to configured URL: { WebViewUrl } ") ;
488617
489618 // Return true since we successfully started the OAuth flow
490619 // The actual authentication completion is handled by the deep link system
0 commit comments