@@ -11,7 +11,12 @@ const outputConsole = document.getElementById('output-console');
1111const clearConsoleBtn = document . getElementById ( 'clear-console' ) ;
1212const refreshFilesBtn = document . getElementById ( 'refresh-files' ) ;
1313
14+ const CACHE_KEY = 'php_repos_cache' ;
15+ const CACHE_DURATION = 5 * 60 * 1000 ; // 5 minutes
16+
1417let currentCode = '' ;
18+ let currentActiveFile = null ;
19+ let displayedFilesJSON = '' ;
1520
1621// Initialize
1722document . addEventListener ( 'DOMContentLoaded' , ( ) => {
@@ -20,6 +25,8 @@ document.addEventListener('DOMContentLoaded', () => {
2025 // Refresh button
2126 if ( refreshFilesBtn ) {
2227 refreshFilesBtn . addEventListener ( 'click' , ( ) => {
28+ // Force refresh: clear cache and fetch
29+ localStorage . removeItem ( CACHE_KEY ) ;
2330 fetchFiles ( ) ;
2431 } ) ;
2532 }
@@ -28,25 +35,46 @@ document.addEventListener('DOMContentLoaded', () => {
2835// Fetch files from GitHub
2936async function fetchFiles ( isBackground = false ) {
3037 if ( ! isBackground ) {
31- fileListEl . innerHTML = '<div class="loading-spinner"><div class="spinner"></div></div>' ;
38+ // checks if we already have files displayed (optimization)
39+ if ( fileListEl . children . length === 0 || fileListEl . querySelector ( '.loading-spinner' ) ) {
40+ fileListEl . innerHTML = '<div class="loading-spinner"><div class="spinner"></div></div>' ;
41+ }
3242 }
3343
3444 let data = [ ] ;
45+ let usedCache = false ;
3546
3647 try {
37- // Add timestamp to query to prevent aggressive caching
38- // Rate Limit Note: 60 requests/hour for unauthenticated IPs.
39- // Polling every 60s consumes this entirely. Ideally, increase interval or use auth.
40- const response = await fetch ( `${ API_URL } ?t=${ new Date ( ) . getTime ( ) } ` , {
41- cache : 'no-store'
42- } ) ;
48+ // 1. Try LocalStorage Cache first
49+ const cached = localStorage . getItem ( CACHE_KEY ) ;
50+ if ( cached ) {
51+ const parsed = JSON . parse ( cached ) ;
52+ if ( Date . now ( ) - parsed . timestamp < CACHE_DURATION ) {
53+ // Cache is valid
54+ data = parsed . data ;
55+ usedCache = true ;
56+ if ( ! isBackground ) console . log ( 'Using cached file list.' ) ;
57+ }
58+ }
4359
44- if ( ! response . ok ) throw new Error ( `GitHub API Error: ${ response . status } ` ) ;
45- data = await response . json ( ) ;
60+ // 2. Data not in cache or expired, fetch from API
61+ if ( ! usedCache ) {
62+ // Remove timestamp to allow browser-level caching (304 Not Modified)
63+ const response = await fetch ( API_URL ) ;
64+
65+ if ( ! response . ok ) throw new Error ( `GitHub API Error: ${ response . status } ` ) ;
66+ data = await response . json ( ) ;
67+
68+ // Save to cache
69+ localStorage . setItem ( CACHE_KEY , JSON . stringify ( {
70+ timestamp : Date . now ( ) ,
71+ data : data
72+ } ) ) ;
73+ }
4674
4775 } catch ( error ) {
4876 if ( ! isBackground ) {
49- console . warn ( 'GitHub API failed, using fallback file list.' , error ) ;
77+ console . warn ( 'GitHub API failed or limit reached , using fallback file list.' , error ) ;
5078 }
5179
5280 // Fallback file list to ensure the site works even if API rate limit is hit
@@ -105,8 +133,8 @@ async function fetchFiles(isBackground = false) {
105133 } ) ;
106134}
107135
108- // Poll for updates every 60 seconds
109- setInterval ( ( ) => fetchFiles ( true ) , 60000 ) ;
136+ // Poll for updates every 5 minutes (reduced from 60s to save API calls)
137+ setInterval ( ( ) => fetchFiles ( true ) , 300000 ) ;
110138
111139// Load specific file content
112140async function loadFile ( file , element ) {
0 commit comments