cdnhost 2.5.9 → 2.6.1
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.
- package/package.json +1 -1
- package/wbs.png +0 -0
- package/wbs2.png +0 -0
- package/ws_cdn.js +55 -187
- package/ws_cdnhtml.js +0 -2
- package/ws_css.css +1 -0
- package/ws_lg.js +1 -1
package/package.json
CHANGED
package/wbs.png
ADDED
|
Binary file
|
package/wbs2.png
ADDED
|
Binary file
|
package/ws_cdn.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
|
|
2
2
|
document.addEventListener('DOMContentLoaded', function() {
|
|
3
|
-
|
|
3
|
+
if (window.FHLWidgetInitialized) return;
|
|
4
|
+
window.FHLWidgetInitialized = true;
|
|
5
|
+
|
|
4
6
|
const languages = [ { code: 'ko', name: '한국어' }, { code: 'en', name: 'English' }, { code: 'es', name: 'Español' }, { code: 'hi', name: 'हिन्दी' }, { code: 'ar', name: 'العربية' }, { code: 'de', name: 'Deutsch' }, { code: 'fr', name: 'Français' }, { code: 'pt', name: 'Português' }, { code: 'bn', name: 'বাংলা' }, { code: 'ja', name: '日本語' }, { code: 'ru', name: 'Русский' }, { code: 'zh', name: '简体中文' }, { code: 'th', name: 'ไทย' }, { code: 'vi', name: 'Tiếng Việt' }, { code: 'id', name: 'Indonesia' }, { code: 'tr', name: 'Türkçe' }, { code: 'ur', name: 'اردو' }];
|
|
5
|
-
|
|
6
7
|
let fullApiItemsData = null;
|
|
7
8
|
let currentDisplayItems = [];
|
|
8
9
|
let currentPage = 1;
|
|
@@ -24,7 +25,6 @@
|
|
|
24
25
|
const languageBtn = document.getElementById('fhl-language-btn');
|
|
25
26
|
const languagePanel = document.getElementById('fhl-language-panel');
|
|
26
27
|
|
|
27
|
-
// ✨ [수정됨] `fhl-fixed-question` -> `fhl-fixed-image`로 되돌리고, 올바른 ID를 참조합니다.
|
|
28
28
|
const fixedImageBtn = document.getElementById('fhl-fixed-image');
|
|
29
29
|
const fixedChatBtn = document.getElementById('fhl-fixed-chat');
|
|
30
30
|
const fixedAdBtn = document.getElementById('fhl-fixed-ad');
|
|
@@ -92,14 +92,7 @@
|
|
|
92
92
|
});
|
|
93
93
|
};
|
|
94
94
|
|
|
95
|
-
const showToast = (message) => {
|
|
96
|
-
clearTimeout(toastTimeout);
|
|
97
|
-
toastElement.textContent = message;
|
|
98
|
-
toastElement.classList.add('visible');
|
|
99
|
-
toastTimeout = setTimeout(() => {
|
|
100
|
-
toastElement.classList.remove('visible');
|
|
101
|
-
}, 2500);
|
|
102
|
-
};
|
|
95
|
+
const showToast = (message) => { clearTimeout(toastTimeout); toastElement.textContent = message; toastElement.classList.add('visible'); toastTimeout = setTimeout(() => { toastElement.classList.remove('visible'); }, 2500); };
|
|
103
96
|
|
|
104
97
|
const applyLanguage = (langCode) => {
|
|
105
98
|
if (typeof translations === 'undefined') {
|
|
@@ -115,7 +108,7 @@
|
|
|
115
108
|
searchClose.setAttribute('aria-label', t.closeSearch);
|
|
116
109
|
languageBtn.setAttribute('aria-label', t.changeLanguage);
|
|
117
110
|
searchAddBtn.setAttribute('aria-label', 'Copy Widget Code');
|
|
118
|
-
fixedImageBtn.setAttribute('aria-label', t.images);
|
|
111
|
+
fixedImageBtn.setAttribute('aria-label', t.images);
|
|
119
112
|
fixedChatBtn.setAttribute('aria-label', t.characterChat);
|
|
120
113
|
fixedAdBtn.setAttribute('aria-label', t.ads);
|
|
121
114
|
|
|
@@ -156,6 +149,10 @@
|
|
|
156
149
|
}
|
|
157
150
|
};
|
|
158
151
|
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
|
|
155
|
+
|
|
159
156
|
const createIconItem = (item, type = 'default') => {
|
|
160
157
|
const link = document.createElement('a');
|
|
161
158
|
|
|
@@ -180,11 +177,7 @@
|
|
|
180
177
|
|
|
181
178
|
if (type === 'search') {
|
|
182
179
|
link.addEventListener('mousedown', () => {
|
|
183
|
-
fetch('update_view_count.php', {
|
|
184
|
-
method: 'POST',
|
|
185
|
-
headers: { 'Content-Type': 'application/json' },
|
|
186
|
-
body: JSON.stringify({ url: item.url })
|
|
187
|
-
}).catch(console.error);
|
|
180
|
+
fetch('https://isai.kr/update_view_count.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ url: item.url }) }).catch(console.error);
|
|
188
181
|
});
|
|
189
182
|
link.target = '_blank';
|
|
190
183
|
}
|
|
@@ -277,49 +270,17 @@
|
|
|
277
270
|
return link;
|
|
278
271
|
};
|
|
279
272
|
|
|
280
|
-
const appendNextPage = () => {
|
|
281
|
-
if (isLoadingNextPage) return;
|
|
282
|
-
isLoadingNextPage = true;
|
|
283
|
-
const startIndex = (currentPage - 1) * ITEMS_PER_PAGE;
|
|
284
|
-
const endIndex = currentPage * ITEMS_PER_PAGE;
|
|
285
|
-
if (startIndex >= currentDisplayItems.length) {
|
|
286
|
-
isLoadingNextPage = false;
|
|
287
|
-
return;
|
|
288
|
-
}
|
|
289
|
-
const itemsToAppend = currentDisplayItems.slice(startIndex, endIndex);
|
|
290
|
-
itemsToAppend.forEach(item => {
|
|
291
|
-
searchResultsContainer.appendChild(createIconItem(item, 'search'));
|
|
292
|
-
});
|
|
293
|
-
currentPage++;
|
|
294
|
-
isLoadingNextPage = false;
|
|
295
|
-
};
|
|
296
273
|
|
|
297
|
-
const renderInitialResults = (items) => {
|
|
298
|
-
searchResultsContainer.innerHTML = '';
|
|
299
|
-
currentPage = 1;
|
|
300
|
-
currentDisplayItems = items;
|
|
301
|
-
appendNextPage();
|
|
302
|
-
};
|
|
303
274
|
|
|
304
|
-
const openSearch = async () => {
|
|
305
|
-
widgetContainer.classList.add('search-mode');
|
|
306
|
-
widgetWrapper.classList.add('search-mode');
|
|
307
|
-
searchInput.focus();
|
|
308
|
-
if (fullApiItemsData === null) {
|
|
309
|
-
try {
|
|
310
|
-
const response = await fetch('appapi2.php');
|
|
311
|
-
if (!response.ok) throw new Error('API 응답 오류');
|
|
312
|
-
fullApiItemsData = await response.json();
|
|
313
|
-
} catch (error) {
|
|
314
|
-
console.error('전체 앱 목록 로드 실패:', error);
|
|
315
|
-
searchResultsContainer.innerHTML = '<p>목록 로드 실패</p>';
|
|
316
|
-
fullApiItemsData = [];
|
|
317
|
-
return;
|
|
318
|
-
}
|
|
319
|
-
}
|
|
320
|
-
renderInitialResults(fullApiItemsData);
|
|
321
|
-
};
|
|
322
275
|
|
|
276
|
+
|
|
277
|
+
|
|
278
|
+
|
|
279
|
+
|
|
280
|
+
const appendNextPage = () => { if (isLoadingNextPage) return; isLoadingNextPage = true; const startIndex = (currentPage - 1) * ITEMS_PER_PAGE; const endIndex = currentPage * ITEMS_PER_PAGE; if (startIndex >= currentDisplayItems.length) { isLoadingNextPage = false; return; } const itemsToAppend = currentDisplayItems.slice(startIndex, endIndex); itemsToAppend.forEach(item => { searchResultsContainer.appendChild(createIconItem(item, 'search')); }); currentPage++; isLoadingNextPage = false; };
|
|
281
|
+
const renderInitialResults = (items) => { searchResultsContainer.innerHTML = ''; currentPage = 1; currentDisplayItems = items; appendNextPage(); };
|
|
282
|
+
const openSearch = async () => { widgetContainer.classList.add('search-mode'); widgetWrapper.classList.add('search-mode'); searchInput.focus(); if (fullApiItemsData === null) { try { const response = await fetch('https://isai.kr/appapi2.php'); if (!response.ok) throw new Error('API 응답 오류'); fullApiItemsData = await response.json(); } catch (error) { console.error('전체 앱 목록 로드 실패:', error); searchResultsContainer.innerHTML = '<p>목록 로드 실패</p>'; fullApiItemsData = []; return; } } renderInitialResults(fullApiItemsData); };
|
|
283
|
+
|
|
323
284
|
const initialRender = () => {
|
|
324
285
|
const t = translations[currentLang] || translations['en'];
|
|
325
286
|
const initialItemsData = [
|
|
@@ -333,165 +294,72 @@
|
|
|
333
294
|
{ name: t.psychology, url: 'https://simpong.oduc.kr/', img: 'http://cdn.jsdelivr.net/npm/cdnhost@2.2.0/_simpong.png' },
|
|
334
295
|
{ name: t.ads, url: 'https://gig.snapp.im/', icon: 'ph-currency-circle-dollar' },
|
|
335
296
|
];
|
|
336
|
-
|
|
337
297
|
listContainer.innerHTML = '';
|
|
338
298
|
const storedItems = shortcutManager.get();
|
|
339
299
|
let combinedItems = [...initialItemsData];
|
|
340
300
|
combinedItems.splice(2, 0, ...storedItems);
|
|
341
|
-
|
|
342
|
-
combinedItems.forEach(item => {
|
|
343
|
-
const isLocal = storedItems.some(stored => stored.url === item.url);
|
|
344
|
-
const itemType = isLocal && !item.icon && !item.img ? 'local' : 'default';
|
|
345
|
-
listContainer.appendChild(createIconItem(item, itemType));
|
|
346
|
-
});
|
|
347
|
-
|
|
301
|
+
combinedItems.forEach(item => { const isLocal = storedItems.some(stored => stored.url === item.url); const itemType = isLocal && !item.icon && !item.img ? 'local' : 'default'; listContainer.appendChild(createIconItem(item, itemType)); });
|
|
348
302
|
checkScrollability();
|
|
349
303
|
updateAllWidgetLinks();
|
|
350
304
|
};
|
|
351
305
|
|
|
352
|
-
const updateScrollIndicator = () => {
|
|
353
|
-
|
|
354
|
-
const maxScrollLeft = listContainer.scrollWidth - listContainer.clientWidth;
|
|
355
|
-
if (maxScrollLeft <= 0) return;
|
|
356
|
-
const scrollFraction = scrollLeft / maxScrollLeft;
|
|
357
|
-
const trackWidth = indicatorTrack.clientWidth;
|
|
358
|
-
const indicatorWidth = scrollIndicator.clientWidth;
|
|
359
|
-
const maxIndicatorLeft = trackWidth - indicatorWidth;
|
|
360
|
-
const indicatorLeft = scrollFraction * maxIndicatorLeft;
|
|
361
|
-
scrollIndicator.style.transform = `translateY(-50%) translateX(${indicatorLeft}px)`;
|
|
362
|
-
};
|
|
363
|
-
|
|
364
|
-
const checkScrollability = () => {
|
|
365
|
-
const isScrollable = listContainer.scrollWidth > listContainer.clientWidth;
|
|
366
|
-
widgetContainer.classList.toggle('scrollable', isScrollable);
|
|
367
|
-
if (isScrollable) updateScrollIndicator();
|
|
368
|
-
};
|
|
369
|
-
|
|
306
|
+
const updateScrollIndicator = () => { const scrollLeft = listContainer.scrollLeft; const maxScrollLeft = listContainer.scrollWidth - listContainer.clientWidth; if (maxScrollLeft <= 0) return; const scrollFraction = scrollLeft / maxScrollLeft; const trackWidth = indicatorTrack.clientWidth; const indicatorWidth = scrollIndicator.clientWidth; const maxIndicatorLeft = trackWidth - indicatorWidth; const indicatorLeft = scrollFraction * maxIndicatorLeft; scrollIndicator.style.transform = `translateY(-50%) translateX(${indicatorLeft}px)`; };
|
|
307
|
+
const checkScrollability = () => { const isScrollable = listContainer.scrollWidth > listContainer.clientWidth; widgetContainer.classList.toggle('scrollable', isScrollable); if (isScrollable) updateScrollIndicator(); };
|
|
370
308
|
let isDragging = false;
|
|
371
|
-
const handleDragMove = (e) => {
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
const maxScrollLeft = listContainer.scrollWidth - listContainer.clientWidth;
|
|
376
|
-
let positionRatio = (e.clientX - trackRect.left) / trackRect.width;
|
|
377
|
-
positionRatio = Math.max(0, Math.min(1, positionRatio));
|
|
378
|
-
listContainer.scrollLeft = positionRatio * maxScrollLeft;
|
|
379
|
-
};
|
|
380
|
-
const handleDragEnd = () => {
|
|
381
|
-
if (!isDragging) return;
|
|
382
|
-
isDragging = false;
|
|
383
|
-
document.removeEventListener('mousemove', handleDragMove);
|
|
384
|
-
document.removeEventListener('mouseup', handleDragEnd);
|
|
385
|
-
};
|
|
386
|
-
|
|
387
|
-
indicatorTrack.addEventListener('mousedown', (e) => {
|
|
388
|
-
isDragging = true;
|
|
389
|
-
handleDragMove(e);
|
|
390
|
-
document.addEventListener('mousemove', handleDragMove);
|
|
391
|
-
document.addEventListener('mouseup', handleDragEnd);
|
|
392
|
-
});
|
|
393
|
-
|
|
394
|
-
const closeSearch = () => {
|
|
395
|
-
widgetContainer.classList.remove('search-mode');
|
|
396
|
-
widgetWrapper.classList.remove('search-mode');
|
|
397
|
-
searchInput.value = '';
|
|
398
|
-
searchResultsContainer.innerHTML = '';
|
|
399
|
-
};
|
|
400
|
-
|
|
309
|
+
const handleDragMove = (e) => { if (!isDragging) return; e.preventDefault(); const trackRect = indicatorTrack.getBoundingClientRect(); const maxScrollLeft = listContainer.scrollWidth - listContainer.clientWidth; let positionRatio = (e.clientX - trackRect.left) / trackRect.width; positionRatio = Math.max(0, Math.min(1, positionRatio)); listContainer.scrollLeft = positionRatio * maxScrollLeft; };
|
|
310
|
+
const handleDragEnd = () => { if (!isDragging) return; isDragging = false; document.removeEventListener('mousemove', handleDragMove); document.removeEventListener('mouseup', handleDragEnd); };
|
|
311
|
+
indicatorTrack.addEventListener('mousedown', (e) => { isDragging = true; handleDragMove(e); document.addEventListener('mousemove', handleDragMove); document.addEventListener('mouseup', handleDragEnd); });
|
|
312
|
+
const closeSearch = () => { widgetContainer.classList.remove('search-mode'); widgetWrapper.classList.remove('search-mode'); searchInput.value = ''; searchResultsContainer.innerHTML = ''; };
|
|
401
313
|
let hideTimeout = null;
|
|
402
314
|
widgetContainer.addEventListener('mouseenter', () => { clearTimeout(hideTimeout); });
|
|
403
315
|
widgetContainer.addEventListener('mouseleave', () => { hideTimeout = setTimeout(() => { widgetContainer.classList.add('hidden'); }, 6000); });
|
|
404
|
-
|
|
405
|
-
document.addEventListener('click', (e) => {
|
|
406
|
-
if (!languagePanel.contains(e.target) && !languageBtn.contains(e.target)) {
|
|
407
|
-
languagePanel.classList.remove('visible');
|
|
408
|
-
}
|
|
409
|
-
if (!widgetContainer.classList.contains('hidden') || widgetContainer.contains(e.target)) {
|
|
410
|
-
return;
|
|
411
|
-
}
|
|
412
|
-
widgetContainer.classList.remove('hidden');
|
|
413
|
-
clearTimeout(hideTimeout);
|
|
414
|
-
hideTimeout = setTimeout(() => {
|
|
415
|
-
widgetContainer.classList.add('hidden');
|
|
416
|
-
}, 6000);
|
|
417
|
-
});
|
|
418
|
-
|
|
316
|
+
document.addEventListener('click', (e) => { if (!languagePanel.contains(e.target) && !languageBtn.contains(e.target)) { languagePanel.classList.remove('visible'); } if (!widgetContainer.classList.contains('hidden') || widgetContainer.contains(e.target)) { return; } widgetContainer.classList.remove('hidden'); clearTimeout(hideTimeout); hideTimeout = setTimeout(() => { widgetContainer.classList.add('hidden'); }, 6000); });
|
|
419
317
|
listContainer.addEventListener('scroll', updateScrollIndicator);
|
|
420
318
|
window.addEventListener('resize', checkScrollability);
|
|
421
|
-
|
|
422
319
|
searchTrigger.addEventListener('click', openSearch);
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
languagePanel.classList.toggle('visible');
|
|
427
|
-
});
|
|
428
|
-
|
|
429
|
-
searchInput.addEventListener('input', function() {
|
|
430
|
-
if (!fullApiItemsData) return;
|
|
431
|
-
const searchTerm = this.value.toLowerCase().trim();
|
|
432
|
-
const filteredItems = fullApiItemsData.filter(item => item.name.toLowerCase().includes(searchTerm));
|
|
433
|
-
renderInitialResults(filteredItems);
|
|
434
|
-
});
|
|
435
|
-
|
|
436
|
-
searchResultsContainer.addEventListener('scroll', () => {
|
|
437
|
-
const isAtBottom = searchResultsContainer.scrollTop + searchResultsContainer.clientHeight >= searchResultsContainer.scrollHeight - 10;
|
|
438
|
-
if (isAtBottom) {
|
|
439
|
-
appendNextPage();
|
|
440
|
-
}
|
|
441
|
-
});
|
|
442
|
-
|
|
320
|
+
languageBtn.addEventListener('click', (e) => { e.stopPropagation(); languagePanel.classList.toggle('visible'); });
|
|
321
|
+
searchInput.addEventListener('input', function() { if (!fullApiItemsData) return; const searchTerm = this.value.toLowerCase().trim(); const filteredItems = fullApiItemsData.filter(item => item.name.toLowerCase().includes(searchTerm)); renderInitialResults(filteredItems); });
|
|
322
|
+
searchResultsContainer.addEventListener('scroll', () => { const isAtBottom = searchResultsContainer.scrollTop + searchResultsContainer.clientHeight >= searchResultsContainer.scrollHeight - 10; if (isAtBottom) { appendNextPage(); } });
|
|
443
323
|
searchClose.addEventListener('click', closeSearch);
|
|
324
|
+
document.addEventListener('keydown', (e) => { if (e.key === 'Escape' && widgetWrapper.classList.contains('search-mode')) { closeSearch(); } });
|
|
444
325
|
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
326
|
+
const addCurrentPageToWidget = async (e) => {
|
|
327
|
+
e.preventDefault();
|
|
328
|
+
const t = translations[currentLang] || translations['en'];
|
|
329
|
+
const baseUrl = getProcessedUrl(window.location.href);
|
|
330
|
+
let iconName = document.title || t.currentPage;
|
|
331
|
+
try {
|
|
332
|
+
const response = await fetch(`https://isai.kr/get_title.php?url=${encodeURIComponent(baseUrl)}`);
|
|
333
|
+
if (response.ok) { const data = await response.json(); if (data.title) { iconName = data.title; } }
|
|
334
|
+
} catch (error) { console.error('Failed to fetch title:', error); }
|
|
335
|
+
const newIcon = { name: iconName, url: baseUrl };
|
|
336
|
+
let storedItems = shortcutManager.get();
|
|
337
|
+
const isAlreadyAdded = storedItems.some(item => getProcessedUrl(item.url) === getProcessedUrl(newIcon.url));
|
|
338
|
+
if (!isAlreadyAdded) {
|
|
339
|
+
if (storedItems.length >= 10) { storedItems.shift(); }
|
|
340
|
+
storedItems.push(newIcon);
|
|
341
|
+
shortcutManager.set(storedItems);
|
|
342
|
+
try { await fetch('https://isai.kr/register_app.php', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify(newIcon) }); } catch (error) { console.error('DB 등록/갱신 실패:', error); }
|
|
343
|
+
initialRender();
|
|
344
|
+
if (widgetWrapper.classList.contains('search-mode')) { closeSearch(); }
|
|
345
|
+
} else {
|
|
346
|
+
showToast(t.alreadyAdded);
|
|
448
347
|
}
|
|
449
|
-
}
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
const addCurrentPageToWidget=async e=>{e.preventDefault();const _s=["get_title.php?url=","ok","json","title","POST","Content-Type","application/json","register_app.php","DB 등록/갱신 실패:","Failed to fetch title:","some","shift","push","length","get","set","preventDefault","search-mode","contains","classList","closeSearch","initialRender","alreadyAdded"],_=(i)=>_s[i];try{const a=(translations&&translations[currentLang])?translations[currentLang]:translations.en,b=getProcessedUrl(window.location.href);let c=document.title||a.currentPage;try{const d=await fetch(`${_(0)}${encodeURIComponent(b)}`);if(d&&d.status&&d.status>=200&&d.status<300){const eJson=await d[_(2)]();if(eJson&&eJson[_(3)])c=eJson[_(3)];}}catch(errFetchTitle){console.error(_(9),errFetchTitle);}const newIcon={name:c,url:b},sm=shortcutManager;let stored=sm[_(14)]();if(!Array.isArray(stored))stored=[];const isAdded=stored[_(10)](it=>getProcessedUrl(it.url)===getProcessedUrl(newIcon.url));if(!isAdded){if(stored[_(13)]>=10)stored[_(11)]();stored[_(12)](newIcon);sm[_(15)](stored);try{await fetch(_(7),{method:_(4),headers:{[_(5)]:_(6)},body:JSON.stringify(newIcon)});}catch(errDb){console.error(_(8),errDb);}if(typeof window[_(20)]==="function")window[_(20)]();const ww=widgetWrapper;if(ww&&ww[_(19)]&&ww[_(19)][_(18)](_(17)))if(typeof closeSearch==="function")closeSearch();}else showToast(a[_(21)]);}catch(fatal){console.error("addCurrentPageToWidget error:",fatal);}};
|
|
348
|
+
};
|
|
455
349
|
|
|
456
350
|
const copyWidgetScript = (e) => {
|
|
457
351
|
e.preventDefault();
|
|
458
352
|
const textToCopy = "<script src='https://cdn.jsdelivr.net/npm/cdnhost@latest/ws_cdn.js'><\/script>";
|
|
459
353
|
const t = translations[currentLang] || translations['en'];
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
const textArea = document.createElement("textarea");
|
|
463
|
-
textArea.value = textToCopy;
|
|
464
|
-
textArea.style.position = "fixed";
|
|
465
|
-
textArea.style.top = 0;
|
|
466
|
-
textArea.style.left = "-9999px";
|
|
467
|
-
document.body.appendChild(textArea);
|
|
468
|
-
textArea.focus();
|
|
469
|
-
textArea.select();
|
|
470
|
-
try {
|
|
471
|
-
document.execCommand('copy');
|
|
472
|
-
showToast(t.codeCopied);
|
|
473
|
-
} catch (err) {
|
|
474
|
-
console.error('Fallback: Oops, unable to copy', err);
|
|
475
|
-
}
|
|
476
|
-
document.body.removeChild(textArea);
|
|
477
|
-
};
|
|
478
|
-
|
|
479
|
-
if (navigator.clipboard && window.isSecureContext) {
|
|
480
|
-
navigator.clipboard.writeText(textToCopy).then(() => {
|
|
481
|
-
showToast(t.codeCopied);
|
|
482
|
-
}).catch(() => {
|
|
483
|
-
fallbackCopy();
|
|
484
|
-
});
|
|
485
|
-
} else {
|
|
486
|
-
fallbackCopy();
|
|
487
|
-
}
|
|
354
|
+
const fallbackCopy = () => { const textArea = document.createElement("textarea"); textArea.value = textToCopy; textArea.style.position = "fixed"; textArea.style.top = 0; textArea.style.left = "-9999px"; document.body.appendChild(textArea); textArea.focus(); textArea.select(); try { document.execCommand('copy'); showToast(t.codeCopied); } catch (err) { console.error('Fallback: Oops, unable to copy', err); } document.body.removeChild(textArea); };
|
|
355
|
+
if (navigator.clipboard && window.isSecureContext) { navigator.clipboard.writeText(textToCopy).then(() => { showToast(t.codeCopied); }).catch(() => { fallbackCopy(); }); } else { fallbackCopy(); }
|
|
488
356
|
};
|
|
489
357
|
|
|
490
358
|
addToHomeBtn.addEventListener('click', addCurrentPageToWidget);
|
|
491
359
|
searchAddBtn.addEventListener('click', copyWidgetScript);
|
|
492
360
|
|
|
493
361
|
shortcutManager.syncFromURL();
|
|
494
|
-
shortcutManager.get();
|
|
362
|
+
shortcutManager.get();
|
|
495
363
|
|
|
496
364
|
populateLanguagePanel();
|
|
497
365
|
applyLanguage(currentLang);
|
package/ws_cdnhtml.js
CHANGED
|
@@ -15,7 +15,6 @@ const widgetHTML = `
|
|
|
15
15
|
<div class="fhl-icon-bar" id="fhl-icon-bar">
|
|
16
16
|
<button class="fhl-icon-display" id="fhl-search-trigger"><i class="ph-bold ph-magnifying-glass"></i></button>
|
|
17
17
|
<div class="fhl-list-container" id="fhl-list-container"></div>
|
|
18
|
-
<!-- ✨ [수정됨] 언어 버튼이 다시 추가되었습니다. -->
|
|
19
18
|
<button class="fhl-icon-display" id="fhl-language-btn"><i class="ph-bold ph-globe"></i></button>
|
|
20
19
|
<a href="#" id="fhl-add-to-home-btn" class="fhl-icon-display"><i class="ph-bold ph-download-simple"></i></a>
|
|
21
20
|
</div>
|
|
@@ -26,7 +25,6 @@ const widgetHTML = `
|
|
|
26
25
|
</div>
|
|
27
26
|
<div class="fhl-search-content">
|
|
28
27
|
<div class="fhl-search-results" id="fhl-search-results"></div>
|
|
29
|
-
<!-- ✨ [수정됨] 모든 고정 아이콘에 ID가 추가되고, 아이콘이 원래대로 복원되었습니다. -->
|
|
30
28
|
<div class="fhl-fixed-panel">
|
|
31
29
|
<a href="#" id="fhl-search-add-btn" class="fhl-fixed-item"><i class="ph-bold ph-download-simple"></i></a>
|
|
32
30
|
<a href="#" id="fhl-fixed-image" class="fhl-fixed-item"><i class="ph-bold ph-image"></i></a>
|
package/ws_css.css
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
|
|
1
2
|
.fhl-widget-wrapper *, .fhl-widget-wrapper *::before, .fhl-widget-wrapper *::after { box-sizing: border-box; }
|
|
2
3
|
.fhl-widget-container { position: fixed; z-index: 1000; bottom: 20px; left: 50%; transform: translateX(-50%) translateY(0); display: flex; flex-direction: column; align-items: center; width: calc(100% - 30px); max-width: 460px; pointer-events: auto; transition: opacity 0.4s ease-in-out, transform 0.4s ease-in-out; }
|
|
3
4
|
.fhl-widget-container.hidden { opacity: 0; transform: translateX(-50%) translateY(20px); pointer-events: none; }
|
package/ws_lg.js
CHANGED
|
@@ -16,5 +16,5 @@ const translations = {
|
|
|
16
16
|
vi: { search: 'Tìm kiếm', question: 'Câu hỏi', forum: 'Diễn đàn', blog: 'Blog', characterChat: 'Trò chuyện nhân vật', translate: 'Dịch', tarot: 'Tarot', psychology: 'Tâm lý học', ads: 'Quảng cáo', openSearch: 'Mở tìm kiếm', addToWidget: 'Thêm vào tiện ích', closeSearch: 'Đóng tìm kiếm', changeLanguage: 'Đổi ngôn ngữ', images: 'Hình ảnh', searchPlaceholder: 'Tìm kiếm...', alreadyAdded: 'Trang này đã được thêm vào tiện ích.', currentPage: 'Trang hiện tại', codeCopied: 'Đã sao chép mã. Vui lòng dán vào trang web của bạn.' },
|
|
17
17
|
id: { search: 'Cari', question: 'Pertanyaan', forum: 'Forum', blog: 'Blog', characterChat: 'Obrolan Karakter', translate: 'Terjemahkan', tarot: 'Tarot', psychology: 'Psikologi', ads: 'Iklan', openSearch: 'Buka Pencarian', addToWidget: 'Tambah ke Widget', closeSearch: 'Tutup Pencarian', changeLanguage: 'Ubah Bahasa', images: 'Gambar', searchPlaceholder: 'Cari...', alreadyAdded: 'Halaman ini sudah ditambahkan ke widget.', currentPage: 'Halaman Saat Ini', codeCopied: 'Kode disalin. Silakan tempel di situs Anda.' },
|
|
18
18
|
tr: { search: 'Ara', question: 'Soru', forum: 'Forum', blog: 'Blog', characterChat: 'Karakter Sohbeti', translate: 'Çevir', tarot: 'Tarot', psychology: 'Psikoloji', ads: 'Reklamlar', openSearch: 'Aramayı Aç', addToWidget: 'Widget\'a Ekle', closeSearch: 'Aramayı Kapat', changeLanguage: 'Dili Değiştir', images: 'Görseller', searchPlaceholder: 'Ara...', alreadyAdded: 'Bu sayfa zaten widget\'a eklenmiş.', currentPage: 'Mevcut Sayfa', codeCopied: 'Kod kopyalandı. Lütfen sitenize yapıştırın.' },
|
|
19
|
-
ur: { search: 'تلاش', question: 'سوال', forum: 'فورم', blog: 'بلاگ', characterChat: 'کردار چیٹ', translate: 'ترجمہ', tarot: 'ٹیرو', psychology: 'نفسیات', ads: 'اشتہارات', openSearch: 'تلاش کھولیں', addToWidget: 'ویجیٹ میں شامل کریں', closeSearch: 'تلاش بند کریں', changeLanguage: 'زبان تبدیل کریں', images: 'تصاویر', searchPlaceholder: 'تلاش کریں...', alreadyAdded: 'یہ صفحہ پہلے ہی
|
|
19
|
+
ur: { search: 'تلاش', question: 'سوال', forum: 'فورم', blog: 'بلاگ', characterChat: 'کردار چیٹ', translate: 'ترجمہ', tarot: 'ٹیرو', psychology: 'نفسیات', ads: 'اشتہارات', openSearch: 'تلاش کھولیں', addToWidget: 'ویجیٹ میں شامل کریں', closeSearch: 'تلاش بند کریں', changeLanguage: 'زبان تبدیل کریں', images: 'تصاویر', searchPlaceholder: 'تلاش کریں...', alreadyAdded: 'یہ صفحہ پہلے ہی ویجیট میں شامل ہے۔', currentPage: 'موجودہ صفحہ', codeCopied: 'کوڈ کاپی ہوگیا ہے۔ براہ کرم اسے اپنی سائٹ پر چسپاں کریں۔' }
|
|
20
20
|
};
|