@@ -14,6 +14,7 @@ namespace MCPForUnity.Editor.Services
1414 /// </summary>
1515 public class PackageUpdateService : IPackageUpdateService
1616 {
17+ private const int DefaultRequestTimeoutMs = 3000 ;
1718 private const string LastCheckDateKey = EditorPrefKeys . LastUpdateCheck ;
1819 private const string CachedVersionKey = EditorPrefKeys . LatestKnownVersion ;
1920 private const string LastBetaCheckDateKey = EditorPrefKeys . LastUpdateCheck + ".beta" ;
@@ -81,6 +82,93 @@ public UpdateCheckResult CheckForUpdate(string currentVersion)
8182 } ;
8283 }
8384
85+ /// <inheritdoc/>
86+ public UpdateCheckResult TryGetCachedResult ( string currentVersion )
87+ {
88+ bool isGitInstallation = IsGitInstallation ( ) ;
89+ string gitBranch = isGitInstallation ? GetGitUpdateBranch ( currentVersion ) : "main" ;
90+ bool useBetaChannel = isGitInstallation && string . Equals ( gitBranch , "beta" , StringComparison . OrdinalIgnoreCase ) ;
91+
92+ string lastCheckKey = isGitInstallation
93+ ? ( useBetaChannel ? LastBetaCheckDateKey : LastCheckDateKey )
94+ : LastAssetStoreCheckDateKey ;
95+ string cachedVersionKey = isGitInstallation
96+ ? ( useBetaChannel ? CachedBetaVersionKey : CachedVersionKey )
97+ : CachedAssetStoreVersionKey ;
98+
99+ string lastCheckDate = EditorPrefs . GetString ( lastCheckKey , "" ) ;
100+ string cachedLatestVersion = EditorPrefs . GetString ( cachedVersionKey , "" ) ;
101+
102+ if ( lastCheckDate == DateTime . Now . ToString ( "yyyy-MM-dd" ) && ! string . IsNullOrEmpty ( cachedLatestVersion ) )
103+ {
104+ return new UpdateCheckResult
105+ {
106+ CheckSucceeded = true ,
107+ LatestVersion = cachedLatestVersion ,
108+ UpdateAvailable = IsNewerVersion ( cachedLatestVersion , currentVersion ) ,
109+ Message = "Using cached version check"
110+ } ;
111+ }
112+
113+ return null ;
114+ }
115+
116+ /// <inheritdoc/>
117+ public UpdateCheckResult FetchAndCompare ( string currentVersion )
118+ {
119+ bool isGitInstallation = IsGitInstallation ( ) ;
120+ string gitBranch = isGitInstallation ? GetGitUpdateBranch ( currentVersion ) : "main" ;
121+ return FetchAndCompare ( currentVersion , isGitInstallation , gitBranch ) ;
122+ }
123+
124+ /// <inheritdoc/>
125+ public UpdateCheckResult FetchAndCompare ( string currentVersion , bool isGitInstallation , string gitBranch )
126+ {
127+ string latestVersion = isGitInstallation
128+ ? FetchLatestVersionFromGitHub ( gitBranch )
129+ : FetchLatestVersionFromAssetStoreJson ( ) ;
130+
131+ if ( ! string . IsNullOrEmpty ( latestVersion ) )
132+ {
133+ return new UpdateCheckResult
134+ {
135+ CheckSucceeded = true ,
136+ LatestVersion = latestVersion ,
137+ UpdateAvailable = IsNewerVersion ( latestVersion , currentVersion ) ,
138+ Message = "Successfully checked for updates"
139+ } ;
140+ }
141+
142+ return new UpdateCheckResult
143+ {
144+ CheckSucceeded = false ,
145+ UpdateAvailable = false ,
146+ Message = isGitInstallation
147+ ? "Failed to check for updates (network issue or offline)"
148+ : "Failed to check for Asset Store updates (network issue or offline)"
149+ } ;
150+ }
151+
152+ /// <inheritdoc/>
153+ public void CacheFetchResult ( string currentVersion , string fetchedVersion )
154+ {
155+ if ( string . IsNullOrEmpty ( fetchedVersion ) ) return ;
156+
157+ bool isGitInstallation = IsGitInstallation ( ) ;
158+ string gitBranch = isGitInstallation ? GetGitUpdateBranch ( currentVersion ) : "main" ;
159+ bool useBetaChannel = isGitInstallation && string . Equals ( gitBranch , "beta" , StringComparison . OrdinalIgnoreCase ) ;
160+
161+ string lastCheckKey = isGitInstallation
162+ ? ( useBetaChannel ? LastBetaCheckDateKey : LastCheckDateKey )
163+ : LastAssetStoreCheckDateKey ;
164+ string cachedVersionKey = isGitInstallation
165+ ? ( useBetaChannel ? CachedBetaVersionKey : CachedVersionKey )
166+ : CachedAssetStoreVersionKey ;
167+
168+ EditorPrefs . SetString ( lastCheckKey , DateTime . Now . ToString ( "yyyy-MM-dd" ) ) ;
169+ EditorPrefs . SetString ( cachedVersionKey , fetchedVersion ) ;
170+ }
171+
84172 /// <inheritdoc/>
85173 public bool IsNewerVersion ( string version1 , string version2 )
86174 {
@@ -196,7 +284,8 @@ private static bool IsPreReleaseVersion(string version)
196284 return version . IndexOf ( '-' , StringComparison . Ordinal ) >= 0 ;
197285 }
198286
199- private static string GetGitUpdateBranch ( string currentVersion )
287+ /// <inheritdoc/>
288+ public string GetGitUpdateBranch ( string currentVersion )
200289 {
201290 try
202291 {
@@ -265,7 +354,7 @@ protected virtual string FetchLatestVersionFromGitHub(string branch)
265354 // - More reliable - doesn't require releases to be published
266355 // - Direct source of truth from the main branch
267356
268- using ( var client = new WebClient ( ) )
357+ using ( var client = CreateWebClient ( ) )
269358 {
270359 client . Headers . Add ( "User-Agent" , "Unity-MCPForUnity-UpdateChecker" ) ;
271360 string packageJsonUrl = string . Equals ( branch , "beta" , StringComparison . OrdinalIgnoreCase )
@@ -304,7 +393,7 @@ protected virtual string FetchLatestVersionFromAssetStoreJson()
304393 {
305394 try
306395 {
307- using ( var client = new WebClient ( ) )
396+ using ( var client = CreateWebClient ( ) )
308397 {
309398 client . Headers . Add ( "User-Agent" , "Unity-MCPForUnity-AssetStoreUpdateChecker" ) ;
310399 string jsonContent = client . DownloadString ( AssetStoreVersionUrl ) ;
@@ -322,5 +411,41 @@ protected virtual string FetchLatestVersionFromAssetStoreJson()
322411 return null ;
323412 }
324413 }
414+
415+ protected virtual WebClient CreateWebClient ( )
416+ {
417+ return new TimeoutWebClient ( GetRequestTimeoutMs ( ) ) ;
418+ }
419+
420+ protected virtual int GetRequestTimeoutMs ( )
421+ {
422+ return DefaultRequestTimeoutMs ;
423+ }
424+
425+ private sealed class TimeoutWebClient : WebClient
426+ {
427+ private readonly int _timeoutMs ;
428+
429+ public TimeoutWebClient ( int timeoutMs )
430+ {
431+ _timeoutMs = timeoutMs ;
432+ }
433+
434+ protected override WebRequest GetWebRequest ( Uri address )
435+ {
436+ var request = base . GetWebRequest ( address ) ;
437+ if ( request != null )
438+ {
439+ request . Timeout = _timeoutMs ;
440+
441+ if ( request is HttpWebRequest httpRequest )
442+ {
443+ httpRequest . ReadWriteTimeout = _timeoutMs ;
444+ }
445+ }
446+
447+ return request ;
448+ }
449+ }
325450 }
326451}
0 commit comments