Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -12,7 +12,7 @@ def fetch_trending_spaces(offset=0, limit=72):
|
|
12 |
try:
|
13 |
# Simple data fetching
|
14 |
url = "https://huggingface.co/api/spaces"
|
15 |
-
params = {"limit":
|
16 |
|
17 |
# Increase timeout
|
18 |
response = requests.get(url, params=params, timeout=30)
|
@@ -206,8 +206,7 @@ if __name__ == '__main__':
|
|
206 |
|
207 |
# Create index.html file
|
208 |
with open('templates/index.html', 'w', encoding='utf-8') as f:
|
209 |
-
f.write('''
|
210 |
-
<!DOCTYPE html>
|
211 |
<html lang="en">
|
212 |
<head>
|
213 |
<meta charset="UTF-8">
|
@@ -527,9 +526,12 @@ if __name__ == '__main__':
|
|
527 |
position: relative;
|
528 |
}
|
529 |
|
|
|
530 |
.grid-content iframe {
|
531 |
-
|
532 |
-
|
|
|
|
|
533 |
border: none;
|
534 |
border-radius: 0;
|
535 |
}
|
@@ -550,17 +552,18 @@ if __name__ == '__main__':
|
|
550 |
}
|
551 |
|
552 |
.error-emoji {
|
553 |
-
font-size:
|
554 |
-
margin-bottom:
|
555 |
animation: bounce 1s infinite alternate;
|
|
|
556 |
}
|
557 |
|
558 |
@keyframes bounce {
|
559 |
from {
|
560 |
-
transform: translateY(0px);
|
561 |
}
|
562 |
to {
|
563 |
-
transform: translateY(-
|
564 |
}
|
565 |
}
|
566 |
|
@@ -730,6 +733,14 @@ if __name__ == '__main__':
|
|
730 |
height: 300px;
|
731 |
}
|
732 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
733 |
</style>
|
734 |
</head>
|
735 |
<body>
|
@@ -825,7 +836,123 @@ if __name__ == '__main__':
|
|
825 |
staticModeAttempted: {}, // Track which spaces have attempted static mode
|
826 |
statsVisible: false,
|
827 |
chartInstance: null,
|
828 |
-
topOwners: []
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
829 |
};
|
830 |
|
831 |
// Random emoji list for 404 errors
|
@@ -852,90 +979,7 @@ if __name__ == '__main__':
|
|
852 |
'🍱', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍠', '🍢', '🍣',
|
853 |
'🍤', '🍥', '🥮', '🍡', '🥟', '🥠', '🥡', '🦀', '🦞', '🦐',
|
854 |
'🦑', '🦪', '🍦', '🍧', '🍨', '🍩', '🍪', '🎂', '🍰', '🧁',
|
855 |
-
'🥧', '🍫', '🍬', '🍭', '🍮', '🍯', '🍼', '🥛', '☕', '🍵'
|
856 |
-
'🍶', '🍾', '🍷', '🍸', '🍹', '🍺', '🍻', '🥂', '🥃', '🥤',
|
857 |
-
'🧃', '🧉', '🧊', '🥢', '🍽️', '🍴', '🥄', '🔪', '🏺', '🌍',
|
858 |
-
'🌎', '🌏', '🌐', '🗺️', '🗾', '🧭', '🏔️', '⛰️', '🌋', '🗻',
|
859 |
-
'🏕️', '🏖️', '🏜️', '🏝️', '🏞️', '🏟️', '🏛️', '🏗️', '🧱', '🏘️',
|
860 |
-
'🏚️', '🏠', '🏡', '🏢', '🏣', '🏤', '🏥', '🏦', '🏨', '🏩',
|
861 |
-
'🏪', '🏫', '🏬', '🏭', '🏯', '🏰', '💒', '🗼', '🗽', '⛪',
|
862 |
-
'🕌', '🛕', '🕍', '⛩️', '🕋', '⛲', '⛺', '🌁', '🌃', '🏙️',
|
863 |
-
'🌄', '🌅', '🌆', '🌇', '🌉', '♨️', '🎠', '🎡', '🎢', '💈',
|
864 |
-
'🎪', '🚂', '🚃', '🚄', '🚅', '🚆', '🚇', '🚈', '🚉', '🚊',
|
865 |
-
'🚝', '🚞', '🚋', '🚌', '🚍', '🚎', '🚐', '🚑', '🚒', '🚓',
|
866 |
-
'🚔', '🚕', '🚖', '🚗', '🚘', '🚙', '🚚', '🚛', '🚜', '🏎️',
|
867 |
-
'🏍️', '🛵', '🦽', '🦼', '🛺', '🚲', '🛴', '🛹', '🚏', '🛣️',
|
868 |
-
'🛤️', '🛢️', '⛽', '🚨', '🚥', '🚦', '🛑', '🚧', '⚓', '⛵',
|
869 |
-
'🛶', '🚤', '🛳️', '⛴️', '🛥️', '🚢', '✈️', '🛩️', '🛫', '🛬',
|
870 |
-
'🪂', '💺', '🚁', '🚟', '🚠', '🚡', '🛰️', '🚀', '🛸', '🛎️',
|
871 |
-
'🧳', '⌛', '⏳', '⌚', '⏰', '⏱️', '⏲️', '🕰️', '🕛', '🕧',
|
872 |
-
'🕐', '🕜', '🕑', '🕝', '🕒', '🕞', '🕓', '🕟', '🕔', '🕠',
|
873 |
-
'🕕', '🕡', '🕖', '🕢', '🕗', '🕣', '🕘', '🕤', '🕙', '🕥',
|
874 |
-
'🕚', '🕦', '🌑', '🌒', '🌓', '🌔', '🌕', '🌖', '🌗', '🌘',
|
875 |
-
'🌙', '🌚', '🌛', '🌜', '🌡️', '☀️', '🌝', '🌞', '🪐', '⭐',
|
876 |
-
'🌟', '🌠', '🌌', '☁️', '⛅', '⛈️', '🌤️', '🌥️', '🌦️', '🌧️',
|
877 |
-
'🌨️', '🌩️', '🌪️', '🌫️', '🌬️', '🌀', '🌈', '🌂', '☂️', '☔',
|
878 |
-
'⛱️', '⚡', '❄️', '☃️', '⛄', '☄️', '🔥', '💧', '🌊', '🎃',
|
879 |
-
'🎄', '🎆', '🎇', '🧨', '✨', '🎈', '🎉', '🎊', '🎋', '🎍',
|
880 |
-
'🎎', '🎏', '🎐', '🎑', '🧧', '🎀', '🎁', '🎗️', '🎟️', '🎫',
|
881 |
-
'🎖️', '🏆', '🏅', '🥇', '🥈', '🥉', '⚽', '⚾', '🥎', '🏀',
|
882 |
-
'🏐', '🏈', '🏉', '🎾', '🥏', '🎳', '🏏', '🏑', '🏒', '🥍',
|
883 |
-
'🏓', '🏸', '🥊', '🥋', '🥅', '⛳', '⛸️', '🎣', '🤿', '🎽',
|
884 |
-
'🎿', '🛷', '🥌', '🎯', '🪀', '🪁', '🎱', '🔮', '🧿', '🎮',
|
885 |
-
'🕹️', '🎰', '🎲', '🧩', '🧸', '♠️', '♥️', '♦️', '♣️', '♟️',
|
886 |
-
'🃏', '🀄', '🎴', '🎭', '🖼️', '🎨', '🧵', '🧶', '👓', '🕶️',
|
887 |
-
'🥽', '🥼', '🦺', '👔', '👕', '👖', '🧣', '🧤', '🧥', '🧦',
|
888 |
-
'👗', '👘', '🥻', '🩱', '🩲', '🩳', '👙', '👚', '👛', '👜',
|
889 |
-
'👝', '🛍️', '🎒', '👞', '👟', '🥾', '🥿', '👠', '👡', '🩰',
|
890 |
-
'👢', '👑', '👒', '🎩', '🎓', '🧢', '⛑️', '📿', '💄', '💍',
|
891 |
-
'💎', '🔇', '🔈', '🔉', '🔊', '📢', '📣', '📯', '🔔', '🔕',
|
892 |
-
'🎼', '🎵', '🎶', '🎙️', '🎚️', '🎛️', '🎤', '🎧', '📻', '🎷',
|
893 |
-
'🎸', '🎹', '🎺', '🎻', '🪕', '🥁', '📱', '📲', '☎️', '📞',
|
894 |
-
'📟', '📠', '🔋', '🔌', '💻', '🖥️', '🖨️', '⌨️', '🖱️', '🖲️',
|
895 |
-
'💽', '💾', '💿', '📀', '🧮', '🎥', '🎞️', '📽️', '🎬', '📺',
|
896 |
-
'📷', '📸', '📹', '📼', '🔍', '🔎', '🕯️', '💡', '🔦', '🏮',
|
897 |
-
'🪔', '📔', '📕', '📖', '📗', '📘', '📙', '📚', '📓', '📒',
|
898 |
-
'📃', '📜', '📄', '📰', '🗞️', '📑', '🔖', '🏷️', '💰', '💴',
|
899 |
-
'💵', '💶', '💷', '💸', '💳', '🧾', '💹', '✉️', '📧', '📨',
|
900 |
-
'📩', '📤', '📥', '📦', '📫', '📪', '📬', '📭', '📮', '🗳️',
|
901 |
-
'✏️', '✒️', '🖋️', '🖊️', '🖌️', '🖍️', '📝', '💼', '📁', '📂',
|
902 |
-
'🗂️', '📅', '📆', '🗒️', '🗓️', '📇', '📈', '📉', '📊', '📋',
|
903 |
-
'📌', '📍', '📎', '🖇️', '📏', '📐', '✂️', '🗃️', '🗄️', '🗑️',
|
904 |
-
'🔒', '🔓', '🔏', '🔐', '🔑', '🗝️', '🔨', '🪓', '⛏️', '⚒️',
|
905 |
-
'🛠️', '🗡️', '⚔️', '🔫', '🏹', '🛡️', '🔧', '🔩', '⚙️', '🗜️',
|
906 |
-
'⚖️', '🦯', '🔗', '⛓️', '🧰', '🧲', '⚗️', '🧪', '🧫', '🧬',
|
907 |
-
'🔬', '🔭', '📡', '💉', '🩸', '💊', '🩹', '🩺', '🚪', '🛏️',
|
908 |
-
'🛋️', '🪑', '🚽', '🚿', '🛁', '🪒', '🧴', '🧷', '🧹', '🧺',
|
909 |
-
'🧻', '🧼', '🧽', '🧯', '🛒', '🚬', '⚰️', '⚱️', '🗿', '🏧',
|
910 |
-
'🚮', '🚰', '♿', '🚹', '🚺', '🚻', '🚼', '🚾', '🛂', '🛃',
|
911 |
-
'🛄', '🛅', '⚠️', '🚸', '⛔', '🚫', '🚳', '🚭', '🚯', '🚱',
|
912 |
-
'🚷', '📵', '🔞', '☢️', '☣️', '⬆️', '↗️', '➡️', '↘️', '⬇️',
|
913 |
-
'↙️', '⬅️', '↖️', '↕️', '↔️', '↩️', '↪️', '⤴️', '⤵️', '🔃',
|
914 |
-
'🔄', '🔙', '🔚', '🔛', '🔜', '🔝', '🛐', '⚛️', '🕉️', '✡️',
|
915 |
-
'☸️', '☯️', '✝️', '☦️', '☪️', '☮️', '🕎', '🔯', '♈', '♉',
|
916 |
-
'♊', '♋', '♌', '♍', '♎', '♏', '♐', '♑', '♒', '♓', '⛎',
|
917 |
-
'🔀', '🔁', '🔂', '▶️', '⏩', '⏭️', '⏯️', '◀️', '⏪', '⏮️',
|
918 |
-
'🔼', '⏫', '🔽', '⏬', '⏸️', '⏹️', '⏺️', '⏏️', '🎦', '🔅',
|
919 |
-
'🔆', '📶', '📳', '📴', '♀️', '♂️', '⚧️', '✖️', '➕', '➖',
|
920 |
-
'➗', '♾️', '‼️', '⁉️', '❓', '❔', '❕', '❗', '〰️', '💱',
|
921 |
-
'💲', '⚕️', '♻️', '⚜️', '🔱', '📛', '🔰', '⭕', '✅', '☑️',
|
922 |
-
'✔️', '❌', '❎', '➰', '➿', '〽️', '✳️', '✴️', '❇️', '©️',
|
923 |
-
'®️', '™️', '#️⃣', '*️⃣', '0️⃣', '1️⃣', '2️⃣', '3️⃣', '4️⃣', '5️⃣',
|
924 |
-
'6️⃣', '7️⃣', '8️⃣', '9️⃣', '🔟', '🔠', '🔡', '🔢', '🔣', '🔤',
|
925 |
-
'🅰️', '🆎', '🅱️', '🆑', '🆒', '🆓', 'ℹ️', '🆔', 'Ⓜ️', '🆕',
|
926 |
-
'🆖', '🅾️', '🆗', '🅿️', '🆘', '🆙', '🆚', '🈁', '🈂️', '🈷️',
|
927 |
-
'🈶', '🈯', '🉐', '🈹', '🈚', '🈲', '🉑', '🈸', '🈴', '🈳',
|
928 |
-
'㊗️', '㊙️', '🈺', '🈵', '🔴', '🟠', '🟡', '🟢', '🔵', '🟣',
|
929 |
-
'🟤', '⚫', '⚪', '🟥', '🟧', '🟨', '🟩', '🟦', '🟪', '🟫',
|
930 |
-
'⬛', '⬜', '◼️', '◻️', '◾', '◽', '▪️', '▫️', '🔶', '🔷',
|
931 |
-
'🔸', '🔹', '🔺', '🔻', '💠', '🔘', '🔳', '🔲', '🏁', '🚩',
|
932 |
-
'🎌', '🏴', '🏳️', '🏳️🌈', '🏴☠️', '🇦🇨', '🇦🇩', '🇦🇪', '🇦🇫', '🇦🇬',
|
933 |
-
'🇦🇮', '🇦🇱', '🇦🇲', '🇦🇴', '🇦🇶', '🇦🇷', '🇦🇸', '🇦🇹', '🇦🇺', '🇦🇼',
|
934 |
-
'🇦🇽', '🇦🇿', '🇧🇦', '🇧🇧', '🇧🇩', '🇧🇪', '🇧🇫', '🇧🇬', '🇧🇭', '🇧🇮',
|
935 |
-
'🇧🇯', '🇧🇱', '🇧🇲', '🇧🇳', '🇧🇴', '🇧🇶', '🇧🇷', '🇧🇸', '🇧🇹', '🇧🇻',
|
936 |
-
'🇧🇼', '🇧🇾', '🇧🇿', '🇨🇦', '🇨🇨', '🇨🇩', '🇨🇫', '🇨🇬', '🇨🇭', '🇨🇮',
|
937 |
-
'🇨🇰', '🇨🇱', '🇨🇲', '🇨🇳', '🇨🇴', '🇨🇵', '🇨🇷', '🇨🇺', '🇨🇻', '🇨🇼',
|
938 |
-
'🇨🇽', '🇨🇾', '🇨🇿'
|
939 |
];
|
940 |
|
941 |
// Display loading indicator
|
@@ -1063,6 +1107,17 @@ if __name__ == '__main__':
|
|
1063 |
title: {
|
1064 |
display: true,
|
1065 |
text: 'Creator ID'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1066 |
}
|
1067 |
}
|
1068 |
}
|
@@ -1199,21 +1254,6 @@ if __name__ == '__main__':
|
|
1199 |
errorMessage.textContent = `"${title}" space couldn't be loaded`;
|
1200 |
errorPlaceholder.appendChild(errorMessage);
|
1201 |
|
1202 |
-
// Try static site version button
|
1203 |
-
const directStaticLink = document.createElement('a');
|
1204 |
-
directStaticLink.href = `https://${owner}-${name}.hf.space/index.html`;
|
1205 |
-
directStaticLink.target = '_blank';
|
1206 |
-
directStaticLink.textContent = 'Try Static Version';
|
1207 |
-
directStaticLink.style.color = '#3182ce';
|
1208 |
-
directStaticLink.style.marginTop = '10px';
|
1209 |
-
directStaticLink.style.display = 'inline-block';
|
1210 |
-
directStaticLink.style.padding = '8px 16px';
|
1211 |
-
directStaticLink.style.background = '#ebf8ff';
|
1212 |
-
directStaticLink.style.borderRadius = '5px';
|
1213 |
-
directStaticLink.style.fontWeight = '600';
|
1214 |
-
directStaticLink.style.marginRight = '10px';
|
1215 |
-
errorPlaceholder.appendChild(directStaticLink);
|
1216 |
-
|
1217 |
// Direct HF link
|
1218 |
const directLink = document.createElement('a');
|
1219 |
directLink.href = `https://huggingface.co/spaces/${owner}/${name}`;
|
@@ -1323,59 +1363,34 @@ if __name__ == '__main__':
|
|
1323 |
iframe.setAttribute('frameborder', '0');
|
1324 |
iframe.loading = 'lazy'; // Lazy load iframes for better performance
|
1325 |
|
|
|
|
|
|
|
|
|
1326 |
// Track this space
|
1327 |
const spaceKey = `${owner}/${name}`;
|
1328 |
-
state.
|
|
|
|
|
|
|
|
|
|
|
1329 |
|
1330 |
-
//
|
1331 |
iframe.onerror = function() {
|
1332 |
-
|
1333 |
-
|
1334 |
-
state.staticModeAttempted[spaceKey] = true;
|
1335 |
-
iframe.src = directUrl + '/index.html';
|
1336 |
-
} else {
|
1337 |
-
// If static mode also failed, show error with random emoji
|
1338 |
-
handleIframeError(iframe, owner, name, title);
|
1339 |
-
}
|
1340 |
};
|
1341 |
|
1342 |
-
//
|
1343 |
-
|
1344 |
-
|
1345 |
-
|
1346 |
-
|
1347 |
-
// Check if we got a 404 page or other error by looking for certain elements
|
1348 |
-
const isErrorPage = iframeDoc.title.includes('404') ||
|
1349 |
-
iframeDoc.body.textContent.includes('404') ||
|
1350 |
-
iframeDoc.body.textContent.includes('not found');
|
1351 |
-
|
1352 |
-
if (isErrorPage) {
|
1353 |
-
// For 404 errors, show random emoji
|
1354 |
-
if (!state.staticModeAttempted[spaceKey]) {
|
1355 |
-
// Try static mode first
|
1356 |
-
state.staticModeAttempted[spaceKey] = true;
|
1357 |
-
iframe.src = directUrl + '/index.html';
|
1358 |
-
} else {
|
1359 |
-
// If static mode already attempted and still failing, show random emoji
|
1360 |
-
handleIframeError(iframe, owner, name, title);
|
1361 |
-
}
|
1362 |
-
}
|
1363 |
-
} catch (e) {
|
1364 |
-
// Cross-origin errors are expected, this generally means the iframe loaded
|
1365 |
-
// If we need to check for static mode, we do it based on other signals
|
1366 |
-
|
1367 |
-
// We can try detecting failed loads by using a timer and checking if the iframe content is visible
|
1368 |
-
setTimeout(() => {
|
1369 |
-
// This is a basic heuristic - if the iframe still has no visible content after 5s, try static mode
|
1370 |
-
if (!state.staticModeAttempted[spaceKey] &&
|
1371 |
-
(iframe.clientHeight < 10 || iframe.clientWidth < 10)) {
|
1372 |
-
state.staticModeAttempted[spaceKey] = true;
|
1373 |
-
iframe.src = directUrl + '/index.html';
|
1374 |
-
}
|
1375 |
-
}, 5000);
|
1376 |
}
|
1377 |
-
};
|
1378 |
|
|
|
1379 |
iframeContainer.appendChild(iframe);
|
1380 |
content.appendChild(iframeContainer);
|
1381 |
|
@@ -1463,4 +1478,4 @@ if __name__ == '__main__':
|
|
1463 |
''')
|
1464 |
|
1465 |
# Use port 7860 for Huggingface Spaces
|
1466 |
-
app.run(host='0.0.0.0', port=7860)
|
|
|
12 |
try:
|
13 |
# Simple data fetching
|
14 |
url = "https://huggingface.co/api/spaces"
|
15 |
+
params = {"limit": 10000} # Get max 10000 to fetch more spaces
|
16 |
|
17 |
# Increase timeout
|
18 |
response = requests.get(url, params=params, timeout=30)
|
|
|
206 |
|
207 |
# Create index.html file
|
208 |
with open('templates/index.html', 'w', encoding='utf-8') as f:
|
209 |
+
f.write('''<!DOCTYPE html>
|
|
|
210 |
<html lang="en">
|
211 |
<head>
|
212 |
<meta charset="UTF-8">
|
|
|
526 |
position: relative;
|
527 |
}
|
528 |
|
529 |
+
/* Apply 70% scaling to iframes */
|
530 |
.grid-content iframe {
|
531 |
+
transform: scale(0.7);
|
532 |
+
transform-origin: top left;
|
533 |
+
width: 142.857%;
|
534 |
+
height: 142.857%;
|
535 |
border: none;
|
536 |
border-radius: 0;
|
537 |
}
|
|
|
552 |
}
|
553 |
|
554 |
.error-emoji {
|
555 |
+
font-size: 6rem;
|
556 |
+
margin-bottom: 1.5rem;
|
557 |
animation: bounce 1s infinite alternate;
|
558 |
+
text-shadow: 0 10px 20px rgba(0,0,0,0.1);
|
559 |
}
|
560 |
|
561 |
@keyframes bounce {
|
562 |
from {
|
563 |
+
transform: translateY(0px) scale(1);
|
564 |
}
|
565 |
to {
|
566 |
+
transform: translateY(-15px) scale(1.1);
|
567 |
}
|
568 |
}
|
569 |
|
|
|
733 |
height: 300px;
|
734 |
}
|
735 |
}
|
736 |
+
|
737 |
+
.error-emoji-detector {
|
738 |
+
position: fixed;
|
739 |
+
top: -9999px;
|
740 |
+
left: -9999px;
|
741 |
+
z-index: -1;
|
742 |
+
opacity: 0;
|
743 |
+
}
|
744 |
</style>
|
745 |
</head>
|
746 |
<body>
|
|
|
836 |
staticModeAttempted: {}, // Track which spaces have attempted static mode
|
837 |
statsVisible: false,
|
838 |
chartInstance: null,
|
839 |
+
topOwners: [],
|
840 |
+
iframeStatuses: {} // Track iframe loading status
|
841 |
+
};
|
842 |
+
|
843 |
+
// Advanced iframe loader for better error detection
|
844 |
+
const iframeLoader = {
|
845 |
+
checkQueue: {},
|
846 |
+
maxAttempts: 5, // Try multiple times
|
847 |
+
checkInterval: 5000, // Check every 5 seconds
|
848 |
+
|
849 |
+
// Start checking iframe loading status
|
850 |
+
startChecking: function(iframe, owner, name, title, spaceKey) {
|
851 |
+
// Initialize tracking
|
852 |
+
this.checkQueue[spaceKey] = {
|
853 |
+
iframe: iframe,
|
854 |
+
owner: owner,
|
855 |
+
name: name,
|
856 |
+
title: title,
|
857 |
+
attempts: 0,
|
858 |
+
status: 'loading'
|
859 |
+
};
|
860 |
+
|
861 |
+
// Start recursive checking
|
862 |
+
this.checkIframeStatus(spaceKey);
|
863 |
+
},
|
864 |
+
|
865 |
+
// Check iframe loading status
|
866 |
+
checkIframeStatus: function(spaceKey) {
|
867 |
+
if (!this.checkQueue[spaceKey]) return;
|
868 |
+
|
869 |
+
const item = this.checkQueue[spaceKey];
|
870 |
+
const iframe = item.iframe;
|
871 |
+
|
872 |
+
// If already processed, stop checking
|
873 |
+
if (item.status !== 'loading') {
|
874 |
+
delete this.checkQueue[spaceKey];
|
875 |
+
return;
|
876 |
+
}
|
877 |
+
|
878 |
+
// Increment attempt counter
|
879 |
+
item.attempts++;
|
880 |
+
|
881 |
+
try {
|
882 |
+
// 1. Check if iframe was removed from DOM
|
883 |
+
if (!iframe || !iframe.parentNode) {
|
884 |
+
delete this.checkQueue[spaceKey];
|
885 |
+
return;
|
886 |
+
}
|
887 |
+
|
888 |
+
// 2. Check if content has loaded
|
889 |
+
try {
|
890 |
+
const hasContent = iframe.contentWindow &&
|
891 |
+
iframe.contentWindow.document &&
|
892 |
+
iframe.contentWindow.document.body;
|
893 |
+
|
894 |
+
// 2.1 If content exists and has actual content loaded
|
895 |
+
if (hasContent && iframe.contentWindow.document.body.innerHTML.length > 100) {
|
896 |
+
// Check if it contains error text
|
897 |
+
const bodyText = iframe.contentWindow.document.body.textContent.toLowerCase();
|
898 |
+
if (bodyText.includes('forbidden') ||
|
899 |
+
bodyText.includes('404') ||
|
900 |
+
bodyText.includes('not found') ||
|
901 |
+
bodyText.includes('error')) {
|
902 |
+
item.status = 'error';
|
903 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
904 |
+
} else {
|
905 |
+
item.status = 'success';
|
906 |
+
}
|
907 |
+
delete this.checkQueue[spaceKey];
|
908 |
+
return;
|
909 |
+
}
|
910 |
+
} catch(e) {
|
911 |
+
// Cross-origin access errors are expected - might be normal loading
|
912 |
+
}
|
913 |
+
|
914 |
+
// 3. Check iframe's visible size
|
915 |
+
const rect = iframe.getBoundingClientRect();
|
916 |
+
if (rect.width > 50 && rect.height > 50 && item.attempts > 2) {
|
917 |
+
// If it has sufficient size, mark as success
|
918 |
+
item.status = 'success';
|
919 |
+
delete this.checkQueue[spaceKey];
|
920 |
+
return;
|
921 |
+
}
|
922 |
+
|
923 |
+
// 4. If we've reached max attempts
|
924 |
+
if (item.attempts >= this.maxAttempts) {
|
925 |
+
// Final check: is iframe visible?
|
926 |
+
if (iframe.offsetWidth > 0 && iframe.offsetHeight > 0) {
|
927 |
+
// If visible, mark as success
|
928 |
+
item.status = 'success';
|
929 |
+
} else {
|
930 |
+
// If still not visible, mark as error
|
931 |
+
item.status = 'error';
|
932 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
933 |
+
}
|
934 |
+
delete this.checkQueue[spaceKey];
|
935 |
+
return;
|
936 |
+
}
|
937 |
+
|
938 |
+
// Schedule next check with exponential backoff
|
939 |
+
const nextDelay = this.checkInterval * Math.pow(1.5, item.attempts - 1);
|
940 |
+
setTimeout(() => this.checkIframeStatus(spaceKey), nextDelay);
|
941 |
+
|
942 |
+
} catch (e) {
|
943 |
+
console.error('Error checking iframe status:', e);
|
944 |
+
|
945 |
+
// If error occurs, try a few more times
|
946 |
+
if (item.attempts >= this.maxAttempts) {
|
947 |
+
item.status = 'error';
|
948 |
+
handleIframeError(iframe, item.owner, item.name, item.title);
|
949 |
+
delete this.checkQueue[spaceKey];
|
950 |
+
} else {
|
951 |
+
// Try again
|
952 |
+
setTimeout(() => this.checkIframeStatus(spaceKey), this.checkInterval);
|
953 |
+
}
|
954 |
+
}
|
955 |
+
}
|
956 |
};
|
957 |
|
958 |
// Random emoji list for 404 errors
|
|
|
979 |
'🍱', '🍘', '🍙', '🍚', '🍛', '🍜', '🍝', '🍠', '🍢', '🍣',
|
980 |
'🍤', '🍥', '🥮', '🍡', '🥟', '🥠', '🥡', '🦀', '🦞', '🦐',
|
981 |
'🦑', '🦪', '🍦', '🍧', '🍨', '🍩', '🍪', '🎂', '🍰', '🧁',
|
982 |
+
'🥧', '🍫', '🍬', '🍭', '🍮', '🍯', '🍼', '🥛', '☕', '🍵'
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
983 |
];
|
984 |
|
985 |
// Display loading indicator
|
|
|
1107 |
title: {
|
1108 |
display: true,
|
1109 |
text: 'Creator ID'
|
1110 |
+
},
|
1111 |
+
// Ensure all labels are shown without gaps
|
1112 |
+
ticks: {
|
1113 |
+
autoSkip: false,
|
1114 |
+
font: function(context) {
|
1115 |
+
// Adjust font size to fit all labels if needed
|
1116 |
+
const defaultSize = 11;
|
1117 |
+
return {
|
1118 |
+
size: labels.length > 20 ? defaultSize - 1 : defaultSize
|
1119 |
+
};
|
1120 |
+
}
|
1121 |
}
|
1122 |
}
|
1123 |
}
|
|
|
1254 |
errorMessage.textContent = `"${title}" space couldn't be loaded`;
|
1255 |
errorPlaceholder.appendChild(errorMessage);
|
1256 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1257 |
// Direct HF link
|
1258 |
const directLink = document.createElement('a');
|
1259 |
directLink.href = `https://huggingface.co/spaces/${owner}/${name}`;
|
|
|
1363 |
iframe.setAttribute('frameborder', '0');
|
1364 |
iframe.loading = 'lazy'; // Lazy load iframes for better performance
|
1365 |
|
1366 |
+
// Unique ID for this iframe
|
1367 |
+
const iframeId = `iframe-${owner}-${name}`;
|
1368 |
+
iframe.id = iframeId;
|
1369 |
+
|
1370 |
// Track this space
|
1371 |
const spaceKey = `${owner}/${name}`;
|
1372 |
+
state.iframeStatuses[spaceKey] = 'loading';
|
1373 |
+
|
1374 |
+
// Use the advanced loader for better error detection
|
1375 |
+
iframe.onload = function() {
|
1376 |
+
iframeLoader.startChecking(iframe, owner, name, title, spaceKey);
|
1377 |
+
};
|
1378 |
|
1379 |
+
// Direct error handling
|
1380 |
iframe.onerror = function() {
|
1381 |
+
handleIframeError(iframe, owner, name, title);
|
1382 |
+
state.iframeStatuses[spaceKey] = 'error';
|
|
|
|
|
|
|
|
|
|
|
|
|
1383 |
};
|
1384 |
|
1385 |
+
// Final fallback - if nothing has happened after 30 seconds, show error
|
1386 |
+
setTimeout(() => {
|
1387 |
+
if (state.iframeStatuses[spaceKey] === 'loading') {
|
1388 |
+
handleIframeError(iframe, owner, name, title);
|
1389 |
+
state.iframeStatuses[spaceKey] = 'error';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1390 |
}
|
1391 |
+
}, 30000);
|
1392 |
|
1393 |
+
// Add iframe to container
|
1394 |
iframeContainer.appendChild(iframe);
|
1395 |
content.appendChild(iframeContainer);
|
1396 |
|
|
|
1478 |
''')
|
1479 |
|
1480 |
# Use port 7860 for Huggingface Spaces
|
1481 |
+
app.run(host='0.0.0.0', port=7860)
|