4sp-dv 1.1.3 → 1.1.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -6,7 +6,7 @@
6
6
  <title>4SP - VERSION 5 CLIENT</title>
7
7
  <link rel="icon" type="image/png" href="https://cdn.jsdelivr.net/npm/4sp-dv@latest/images/logo.png">
8
8
 
9
- <base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.1.3/logged-in/">
9
+ <base href="https://cdn.jsdelivr.net/npm/4sp-dv@1.1.5/logged-in/">
10
10
  <script src="https://cdn.tailwindcss.com"></script>
11
11
  <link href="https://fonts.googleapis.com/css2?family=Geist:wght@100..900&display=swap" rel="stylesheet">
12
12
 
@@ -851,7 +851,7 @@
851
851
  const displayUsername = document.getElementById('display-username');
852
852
  const displayEmail = document.getElementById('display-email');
853
853
 
854
- const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.1.3/logged-in/';
854
+ const BASE_URL = 'https://cdn.jsdelivr.net/npm/4sp-dv@1.1.5/logged-in/';
855
855
 
856
856
  // Preload Logos
857
857
  const preloadImgs = [
@@ -879,6 +879,7 @@
879
879
  "messenger-v2": { "name": "Messenger", "icon": "fa-solid fa-comments", "url": "messenger-v2.html" },
880
880
  "games": { "name": "GAMES", "icon": "fa-solid fa-gamepad", "url": "games.html" },
881
881
  "velium": { "name": "Velium", "icon": "fa-solid fa-music", "url": "velium.html" },
882
+ "securly-tester": { "name": "Securly Tester", "icon": "fa-solid fa-shield-halved", "url": "securly-tester.html" },
882
883
  "settings": { "name": "Settings", "icon": "fa-solid fa-gear", "url": "settings.html" }
883
884
  };
884
885
 
@@ -891,6 +891,9 @@
891
891
 
892
892
  // --- Custom 404 Page Helper ---
893
893
  const show404 = (errorMsg = "Game content unavailable.") => {
894
+ // Ensure frame is cleared
895
+ zoneFrame.src = 'about:blank';
896
+ // Show overlay error
894
897
  const doc = zoneFrame.contentWindow.document;
895
898
  doc.open();
896
899
  doc.write(`
@@ -907,7 +910,7 @@
907
910
  </style>
908
911
  </head>
909
912
  <body>
910
- <h1>404</h1>
913
+ <h1>Load Failed</h1>
911
914
  <p><strong>${game.name}</strong> could not be loaded.<br><span style="font-size: 0.9rem; opacity: 0.7;">${errorMsg}</span></p>
912
915
  <div class="btn" onclick="window.parent.closeZoneViewer()">Return to Hub</div>
913
916
  </body>
@@ -931,7 +934,6 @@
931
934
  }
932
935
 
933
936
  // --- INJECT FAVORITE BUTTON IN PLAYER HEADER ---
934
- // Remove existing if any
935
937
  const existingFav = controls.querySelector('.player-fav-btn');
936
938
  if (existingFav) existingFav.remove();
937
939
 
@@ -946,58 +948,70 @@
946
948
  toggleFavorite(game.id);
947
949
  favBtn.classList.toggle('favorited');
948
950
  };
949
-
950
- // Prepend to controls (Left side)
951
951
  controls.prepend(favBtn);
952
952
 
953
953
  zoneNameEl.textContent = game.name;
954
-
955
- // RESET FRAME BEFORE LOAD
956
954
  zoneFrame.src = 'about:blank';
957
955
 
958
- // SECURITY: Set sandbox permissions
959
956
  const sandboxRules = 'allow-scripts allow-same-origin allow-forms allow-pointer-lock';
960
957
  zoneFrame.setAttribute('sandbox', sandboxRules);
961
958
  zoneFrame.setAttribute('allow', 'fullscreen; pointer-lock; autoplay; clipboard-write');
962
959
 
963
- // --- REVISED LOGIC FOR LOADING GAMES ---
960
+ // --- REVISED LOGIC FOR LOADING GAMES WITH RETRY ---
964
961
  const isStandardURLGame = game.category === 'StrongdogXP' || game.category === 'Others' || game.category === 'GN-Math';
965
962
 
966
- if (isStandardURLGame) {
967
- // Try fetching to see if it exists (Fixes the jsdelivr redirect bug)
963
+ const attemptLoad = async (retriesLeft) => {
968
964
  try {
965
+ // Pre-check URL validity
969
966
  const check = await fetch(game.url, { method: 'HEAD' });
970
- if (!check.ok) throw new Error("File not found");
971
- zoneFrame.src = game.url;
967
+ if (!check.ok) throw new Error(`HTTP ${check.status}`);
972
968
 
973
- // SHOW WITH ANIMATION
974
- zoneViewer.style.display = "flex";
975
- zoneViewer.classList.remove('animate-fade-out');
976
- zoneViewer.classList.add('active', 'animate-fade-in');
977
- } catch (e) {
978
- show404("The game source is broken or blocked.");
979
- }
980
- } else {
981
- fetch(`${game.url}?t=${Date.now()}`)
982
- .then(response => {
969
+ // If successful, set src
970
+ if (isStandardURLGame) {
971
+ zoneFrame.src = game.url;
972
+ // Prevent showing raw directory listing if it resolves to a folder
973
+ zoneFrame.onload = () => {
974
+ try {
975
+ const doc = zoneFrame.contentDocument;
976
+ const title = doc.title;
977
+ // UPDATED CHECK: Detects 'CDN files' specifically (as seen in screenshot) and generic directory listings
978
+ if (title.includes("CDN files") || title.includes("Index of") || title.includes("Directory listing") || (doc.body && doc.body.textContent.includes("4sp-dv CDN files"))) {
979
+ console.warn("Directory listing detected. Aborting.");
980
+ closeZoneViewer();
981
+ // Refresh the page to clear any weird state
982
+ setTimeout(() => window.location.reload(), 100);
983
+ return;
984
+ }
985
+ } catch (e) {
986
+ // Cross-origin might block access. If it's a cross-origin game that loads fine, this error is expected and ignored.
987
+ }
988
+ };
989
+ } else {
990
+ // For embedded content fetching
991
+ const response = await fetch(`${game.url}?t=${Date.now()}`);
983
992
  if (!response.ok) throw new Error(`HTTP error ${response.status}`);
984
- return response.text();
985
- })
986
- .then(html => {
993
+ const html = await response.text();
987
994
  const doc = zoneFrame.contentWindow.document;
988
995
  doc.open();
989
996
  doc.write(html);
990
997
  doc.close();
991
-
992
- // SHOW WITH ANIMATION
993
- zoneViewer.style.display = "flex";
994
- zoneViewer.classList.remove('animate-fade-out');
995
- zoneViewer.classList.add('active', 'animate-fade-in');
996
- })
997
- .catch(error => {
998
- show404(error.message);
999
- });
1000
- }
998
+ }
999
+
1000
+ zoneViewer.style.display = "flex";
1001
+ zoneViewer.classList.remove('animate-fade-out');
1002
+ zoneViewer.classList.add('active', 'animate-fade-in');
1003
+
1004
+ } catch (e) {
1005
+ console.warn(`Load failed for ${game.name}. Retries left: ${retriesLeft}`, e);
1006
+ if (retriesLeft > 0) {
1007
+ setTimeout(() => attemptLoad(retriesLeft - 1), 1000); // Retry after 1s
1008
+ } else {
1009
+ show404("The game files could not be loaded after multiple attempts.");
1010
+ }
1011
+ }
1012
+ };
1013
+
1014
+ attemptLoad(2); // Try 3 times total (1 initial + 2 retries)
1001
1015
  }
1002
1016
 
1003
1017
  function closeZoneViewer() {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "4sp-dv",
3
- "version": "1.1.3",
3
+ "version": "1.1.5",
4
4
  "description": "",
5
5
  "keywords": [],
6
6
  "homepage": "https://github.com/v5-4simpleproblems/v5-4simpleproblems-dv#readme",