Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
S
SSBookMinigames
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Administrator
SSBookMinigames
Commits
d0cfc2ff
Commit
d0cfc2ff
authored
Apr 12, 2026
by
Yousef Sameh
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
inconnectivity loop
parent
8d528dbd
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
111 additions
and
54 deletions
+111
-54
AppRouter.cs
My project/Assets/App/Infrastructure/Core/AppRouter.cs
+92
-40
SupabaseManager.cs
My project/Assets/App/Infrastructure/Core/SupabaseManager.cs
+14
-14
HomeController.cs
My project/Assets/App/UI/HomeController.cs
+1
-0
Boot.unity
My project/Assets/AppUI/NewAppUI/Scene/Boot.unity
+2
-0
SSApiManager.cs
...oject/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
+2
-0
No files found.
My project/Assets/App/Infrastructure/Core/AppRouter.cs
View file @
d0cfc2ff
...
@@ -6,6 +6,7 @@ using Supabase.Gotrue;
...
@@ -6,6 +6,7 @@ using Supabase.Gotrue;
using
Supabase.Gotrue.Interfaces
;
using
Supabase.Gotrue.Interfaces
;
using
UnityEngine
;
using
UnityEngine
;
using
UnityEngine.SceneManagement
;
using
UnityEngine.SceneManagement
;
using
TMPro
;
public
class
AppRouter
:
MonoBehaviour
public
class
AppRouter
:
MonoBehaviour
{
{
...
@@ -15,9 +16,14 @@ public class AppRouter : MonoBehaviour
...
@@ -15,9 +16,14 @@ public class AppRouter : MonoBehaviour
[
Header
(
"Splash UI (Boot Scene Only)"
)]
[
Header
(
"Splash UI (Boot Scene Only)"
)]
[
SerializeField
]
private
GameObject
splashScreen
;
[
SerializeField
]
private
GameObject
splashScreen
;
[
SerializeField
]
private
GameObject
errorPanel
;
[
SerializeField
]
private
GameObject
errorPanel
;
[
SerializeField
]
private
TextMeshProUGUI
statusText
;
[
Header
(
"Settings"
)]
public
TransitionSettings
transitionSettings
;
public
TransitionSettings
transitionSettings
;
private
bool
_booted
;
[
Header
(
"Debug Testing"
)]
[
Tooltip
(
"Check this in the Inspector to simulate network loss and test the 'Waiting' loop."
)]
[
SerializeField
]
private
bool
simulateNetworkFailure
;
private
void
Awake
()
private
void
Awake
()
{
{
...
@@ -30,6 +36,7 @@ public class AppRouter : MonoBehaviour
...
@@ -30,6 +36,7 @@ public class AppRouter : MonoBehaviour
_instance
=
this
;
_instance
=
this
;
DontDestroyOnLoad
(
gameObject
);
DontDestroyOnLoad
(
gameObject
);
// Standard mobile optimizations
Application
.
targetFrameRate
=
Screen
.
currentResolution
.
refreshRate
;
Application
.
targetFrameRate
=
Screen
.
currentResolution
.
refreshRate
;
Screen
.
orientation
=
ScreenOrientation
.
Portrait
;
Screen
.
orientation
=
ScreenOrientation
.
Portrait
;
}
}
...
@@ -42,7 +49,7 @@ public class AppRouter : MonoBehaviour
...
@@ -42,7 +49,7 @@ public class AppRouter : MonoBehaviour
private
void
HandleBackButton
()
private
void
HandleBackButton
()
{
{
//
Don't interrupt active challenges
//
Safety: Don't let the back button break an active game session
if
(
ChallengeManager
.
Instance
!=
null
&&
ChallengeManager
.
Instance
.
IsChallengeRunning
)
if
(
ChallengeManager
.
Instance
!=
null
&&
ChallengeManager
.
Instance
.
IsChallengeRunning
)
return
;
return
;
...
@@ -66,74 +73,119 @@ public class AppRouter : MonoBehaviour
...
@@ -66,74 +73,119 @@ public class AppRouter : MonoBehaviour
var
cached
=
UserService
.
Instance
.
LoadFromCache
();
var
cached
=
UserService
.
Instance
.
LoadFromCache
();
TransitionManager
.
Instance
().
onTransitionCutPointReached
+=
HideSplash
;
TransitionManager
.
Instance
().
onTransitionCutPointReached
+=
HideSplash
;
bool
ready
=
await
SupabaseManager
.
Instance
.
Initialize
();
// --- STEP 1: Network Connection Loop ---
if
(!
ready
)
// Execution halts here until isConnected is true
{
await
EnsureNetworkConnection
();
if
(
cached
!=
null
)
{
GoToHome
();
return
;
}
ShowError
(
"Failed to connect"
);
return
;
}
// --- STEP 2: Authentication Session ---
UpdateStatus
(
"Checking session..."
);
var
authResult
=
await
SupabaseAuthentication
.
Instance
.
EnsureSession
();
var
authResult
=
await
SupabaseAuthentication
.
Instance
.
EnsureSession
();
if
(
authResult
.
IsT1
)
if
(
authResult
.
IsT1
)
// No valid session found
{
if
(
cached
!=
null
)
{
{
if
(
cached
!=
null
)
{
GoToHome
();
return
;
}
Debug
.
Log
(
"[Boot] Offline/No session, using cache."
);
GoToHome
();
return
;
}
GoToLogin
();
GoToLogin
();
return
;
return
;
}
}
// --- STEP 3: Load User Profile ---
UpdateStatus
(
"Fetching profile..."
);
var
prof
=
await
UserService
.
Instance
.
GetCurrentUser
();
var
prof
=
await
UserService
.
Instance
.
GetCurrentUser
();
prof
.
Switch
(
prof
.
Switch
(
async
success
=>
async
success
=>
{
{
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
transitionSettings
,
0f
);
UpdateStatus
(
"Welcome back!"
);
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
transitionSettings
,
0.5f
);
UserService
.
Instance
.
StartListening
();
UserService
.
Instance
.
StartListening
();
},
},
error
=>
error
=>
{
{
// If profile fetch fails but we have a cache, let them in
if
(
cached
!=
null
)
if
(
cached
!=
null
)
{
{
Debug
.
LogWarning
(
$"[Boot] Network profile fetch failed, using cache
"
);
Debug
.
LogWarning
(
$"[Boot] Profile fetch failed, falling back to cache.
"
);
GoToHome
();
GoToHome
();
}
}
else
else
{
{
Debug
.
LogError
(
$"[Boot] Failed to load user profile
:
{
error
}
"
);
Debug
.
LogError
(
$"[Boot] Critical load error
:
{
error
}
"
);
GoToLogin
();
GoToLogin
();
}
}
}
}
);
);
}
}
// ─── Auth State Listener (Safety Net Only) ───────────────────────
private
async
UniTask
EnsureNetworkConnection
()
{
bool
isConnected
=
false
;
int
attempts
=
0
;
while
(!
isConnected
)
{
attempts
++;
UpdateStatus
(
attempts
==
1
?
"Connecting..."
:
"Waiting for network..."
);
if
(
simulateNetworkFailure
)
{
Debug
.
LogWarning
(
"[TEST] simulateNetworkFailure is ON. Mocking connection failure."
);
isConnected
=
false
;
}
else
{
isConnected
=
await
SupabaseManager
.
Instance
.
Initialize
();
}
if
(!
isConnected
)
{
// Wait 3 seconds before the next heartbeat
// Uses the object's token to stop if the user quits the app
await
UniTask
.
Delay
(
TimeSpan
.
FromSeconds
(
3
),
cancellationToken
:
this
.
GetCancellationTokenOnDestroy
());
}
}
UpdateStatus
(
"Connected!"
);
await
UniTask
.
Delay
(
500
);
// Visual polish
}
private
void
UpdateStatus
(
string
message
)
{
if
(
statusText
!=
null
)
statusText
.
text
=
message
;
Debug
.
Log
(
$"[AppRouter]
{
message
}
"
);
}
// ─── Auth State Listener (Safety Net) ───────────────────────────
private
void
OnAuthStateChanged
(
IGotrueClient
<
Supabase
.
Gotrue
.
User
,
Supabase
.
Gotrue
.
Session
>
sender
,
Constants
.
AuthState
newState
)
private
void
OnAuthStateChanged
(
IGotrueClient
<
Supabase
.
Gotrue
.
User
,
Supabase
.
Gotrue
.
Session
>
sender
,
Constants
.
AuthState
newState
)
{
{
switch
(
newState
)
switch
(
newState
)
{
{
case
Constants
.
AuthState
.
SignedOut
:
case
Constants
.
AuthState
.
SignedOut
:
// Only react if WE didn't trigger the sign-out
if
(!
SupabaseAuthentication
.
Instance
.
IsLoading
)
if
(!
SupabaseAuthentication
.
Instance
.
IsLoading
)
{
{
Debug
.
LogWarning
(
"[Auth] Unexpected sign-out detected"
);
UserService
.
Instance
.
ClearUser
();
UserService
.
Instance
.
ClearUser
();
GoToLogin
();
GoToLogin
();
}
}
break
;
break
;
case
Constants
.
AuthState
.
TokenRefreshed
:
case
Constants
.
AuthState
.
TokenRefreshed
:
Debug
.
Log
(
"[Auth]
Token refreshed
"
);
Debug
.
Log
(
"[Auth]
Session token refreshed.
"
);
break
;
break
;
}
}
}
}
// ─── Navigation
───────
───────────────────────────────────────────
// ─── Navigation
Logic
───────────────────────────────────────────
public
async
static
void
GoToLogin
()
public
static
void
GoToLogin
()
{
{
TransitionManager
.
Instance
().
Transition
(
"Login"
,
_instance
.
transitionSettings
,
0f
);
TransitionManager
.
Instance
().
Transition
(
"Login"
,
_instance
.
transitionSettings
,
0f
);
}
}
public
async
static
void
GoToHome
()
public
static
void
GoToHome
()
{
{
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
_instance
.
transitionSettings
,
0f
);
TransitionManager
.
Instance
().
Transition
(
"MainMenu"
,
_instance
.
transitionSettings
,
0f
);
UserService
.
Instance
.
StartListening
();
UserService
.
Instance
.
StartListening
();
...
@@ -151,7 +203,7 @@ public class AppRouter : MonoBehaviour
...
@@ -151,7 +203,7 @@ public class AppRouter : MonoBehaviour
try
{
SSAudioManager
.
Instance
?.
StopMusic
();
}
catch
{
}
try
{
SSAudioManager
.
Instance
?.
StopMusic
();
}
catch
{
}
}
}
// ───
Helpers ───
──────────────────────────────────────────────────
// ───
UI Helpers
──────────────────────────────────────────────────
private
static
void
HideSplash
()
private
static
void
HideSplash
()
{
{
if
(
_instance
==
null
)
return
;
if
(
_instance
==
null
)
return
;
...
@@ -163,6 +215,6 @@ public class AppRouter : MonoBehaviour
...
@@ -163,6 +215,6 @@ public class AppRouter : MonoBehaviour
{
{
if
(
splashScreen
!=
null
)
splashScreen
.
SetActive
(
false
);
if
(
splashScreen
!=
null
)
splashScreen
.
SetActive
(
false
);
if
(
errorPanel
!=
null
)
errorPanel
.
SetActive
(
true
);
if
(
errorPanel
!=
null
)
errorPanel
.
SetActive
(
true
);
Debug
.
LogError
(
$"[Boot]
{
message
}
"
);
Debug
.
LogError
(
$"[Boot
Error
]
{
message
}
"
);
}
}
}
}
\ No newline at end of file
My project/Assets/App/Infrastructure/Core/SupabaseManager.cs
View file @
d0cfc2ff
...
@@ -50,23 +50,23 @@ public class SupabaseManager
...
@@ -50,23 +50,23 @@ public class SupabaseManager
client
.
Auth
.
SetPersistence
(
new
UnitySession
());
client
.
Auth
.
SetPersistence
(
new
UnitySession
());
client
.
Auth
.
Options
.
AllowUnconfirmedUserSessions
=
true
;
client
.
Auth
.
Options
.
AllowUnconfirmedUserSessions
=
true
;
//
string url = $"{SupabaseSettings.SupabaseURL}/auth/v1/settings?apikey={SupabaseSettings.SupabaseAnonKey}";
string
url
=
$"
{
SupabaseSettings
.
SupabaseURL
}
/auth/v1/settings?apikey=
{
SupabaseSettings
.
SupabaseAnonKey
}
"
;
// await client.InitializeAsync();
// await client.InitializeAsync();
//
try
try
//
{
{
//
client.Auth.Online = await _networkStatus.StartAsync(url);
client
.
Auth
.
Online
=
await
_networkStatus
.
StartAsync
(
url
);
//
}
}
//
catch (NotSupportedException)
catch
(
NotSupportedException
)
//
{
{
//
client.Auth.Online = true;
client
.
Auth
.
Online
=
true
;
//
}
}
//
catch (Exception e)
catch
(
Exception
e
)
//
{
{
//
Debug.LogWarning($"Network check failed: {e.Message}");
Debug
.
LogWarning
(
$"Network check failed:
{
e
.
Message
}
"
);
//
client.Auth.Online = false;
client
.
Auth
.
Online
=
false
;
//
}
}
// if (client.Auth.Online)
// if (client.Auth.Online)
// {
// {
...
...
My project/Assets/App/UI/HomeController.cs
View file @
d0cfc2ff
...
@@ -95,6 +95,7 @@ public class HomeController : MonoBehaviour
...
@@ -95,6 +95,7 @@ public class HomeController : MonoBehaviour
SetPlayButtonsEnabled
(
enough
);
SetPlayButtonsEnabled
(
enough
);
},
},
_
=>
SetPlayButtonsEnabled
(
false
),
_
=>
SetPlayButtonsEnabled
(
false
),
curriculumId
:
1
,
gradeId
:
user
.
Grade
,
gradeId
:
user
.
Grade
,
termId
:
user
.
Term
termId
:
user
.
Term
));
));
...
...
My project/Assets/AppUI/NewAppUI/Scene/Boot.unity
View file @
d0cfc2ff
...
@@ -166,7 +166,9 @@ MonoBehaviour:
...
@@ -166,7 +166,9 @@ MonoBehaviour:
m_EditorClassIdentifier
:
Assembly-CSharp::AppRouter
m_EditorClassIdentifier
:
Assembly-CSharp::AppRouter
splashScreen
:
{
fileID
:
90795484556287063
}
splashScreen
:
{
fileID
:
90795484556287063
}
errorPanel
:
{
fileID
:
0
}
errorPanel
:
{
fileID
:
0
}
statusText
:
{
fileID
:
0
}
transitionSettings
:
{
fileID
:
11400000
,
guid
:
91673b50629b1ae4f938d0b25135d085
,
type
:
2
}
transitionSettings
:
{
fileID
:
11400000
,
guid
:
91673b50629b1ae4f938d0b25135d085
,
type
:
2
}
simulateNetworkFailure
:
0
---
!u!1
&787965442
---
!u!1
&787965442
GameObject
:
GameObject
:
m_ObjectHideFlags
:
0
m_ObjectHideFlags
:
0
...
...
My project/Assets/ScienceStreet/Shared/Scripts/SSApiManager.cs
View file @
d0cfc2ff
...
@@ -349,6 +349,7 @@ namespace com.al_arcade.shared
...
@@ -349,6 +349,7 @@ namespace com.al_arcade.shared
// ═══════════════════════════════════════════════════
// ═══════════════════════════════════════════════════
public
IEnumerator
GetChapters
(
Action
<
ChapterInfo
[
]>
onSuccess
,
public
IEnumerator
GetChapters
(
Action
<
ChapterInfo
[
]>
onSuccess
,
Action
<
string
>
onError
,
Action
<
string
>
onError
,
int
curriculumId
=
0
,
int
subjectId
=
0
,
int
subjectId
=
0
,
int
gradeId
=
0
,
int
gradeId
=
0
,
int
termId
=
0
)
int
termId
=
0
)
...
@@ -357,6 +358,7 @@ namespace com.al_arcade.shared
...
@@ -357,6 +358,7 @@ namespace com.al_arcade.shared
if
(
subjectId
>
0
)
p
[
"subject_id"
]
=
subjectId
.
ToString
();
if
(
subjectId
>
0
)
p
[
"subject_id"
]
=
subjectId
.
ToString
();
if
(
gradeId
>
0
)
p
[
"grade_id"
]
=
gradeId
.
ToString
();
if
(
gradeId
>
0
)
p
[
"grade_id"
]
=
gradeId
.
ToString
();
if
(
termId
>
0
)
p
[
"term_id"
]
=
termId
.
ToString
();
if
(
termId
>
0
)
p
[
"term_id"
]
=
termId
.
ToString
();
if
(
curriculumId
>
0
)
p
[
"curriculum_id"
]
=
curriculumId
.
ToString
();
yield
return
GetRequest
(
"get_chapters"
,
p
,
yield
return
GetRequest
(
"get_chapters"
,
p
,
json
=>
json
=>
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment