{"id":18,"date":"2026-05-10T09:43:37","date_gmt":"2026-05-10T09:43:37","guid":{"rendered":"https:\/\/tinbamien.com\/?page_id=18"},"modified":"2026-05-10T09:43:37","modified_gmt":"2026-05-10T09:43:37","slug":"lay-lan-luot","status":"publish","type":"page","link":"https:\/\/tinbamien.com\/?page_id=18","title":{"rendered":"l\u1ea5y l\u1ea7n l\u01b0\u1ee3t"},"content":{"rendered":"\n<!DOCTYPE html>\n<html lang=\"vi\">\n<head>\n    <meta charset=\"UTF-8\">\n    <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no\">\n    <title>Cloud Content Manager v13<\/title>\n    <script src=\"https:\/\/cdn.tailwindcss.com\"><\/script>\n    \n    <style>\n        body { \n            -webkit-tap-highlight-color: transparent; \n            margin: 0; \n            padding: 0; \n            background-color: #f1f5f9; \n            font-family: 'Inter', system-ui, -apple-system, sans-serif;\n            overscroll-behavior-y: contain;\n            color: #1e293b;\n        }\n        .app-container { max-width: 500px; margin: 0 auto; padding: 20px; }\n        \n        .card { \n            background: white; \n            border-radius: 1.5rem; \n            padding: 1.5rem; \n            border: 1px solid #e2e8f0; \n            box-shadow: 0 10px 25px -5px rgba(0,0,0,0.05); \n            margin-bottom: 1.5rem; \n        }\n\n        .btn-primary { \n            width: 100%; \n            background: #2563eb; \n            color: white; \n            padding: 1.25rem; \n            border-radius: 1rem; \n            font-weight: 800; \n            cursor: pointer; \n            border: none; \n            transition: all 0.2s cubic-bezier(0.4, 0, 0.2, 1);\n            box-shadow: 0 4px 12px rgba(37, 99, 235, 0.2);\n            text-transform: uppercase;\n            display: flex;\n            align-items: center;\n            justify-content: center;\n            gap: 10px;\n        }\n        .btn-primary:active { transform: scale(0.97); background: #1d4ed8; }\n        \n        .result-card { \n            background: #ffffff; \n            border-radius: 2rem; \n            padding: 1.5rem; \n            display: none; \n            animation: slideUp 0.4s cubic-bezier(0.16, 1, 0.3, 1);\n            box-shadow: 0 20px 40px -10px rgba(0, 0, 0, 0.1);\n            border: 2px solid #e2e8f0;\n        }\n\n        @keyframes slideUp { \n            from { opacity: 0; transform: translateY(20px); } \n            to { opacity: 1; transform: translateY(0); } \n        }\n\n        .content-display-box {\n            background: #f8fafc;\n            border: 1px solid #e2e8f0;\n            border-radius: 1rem;\n            padding: 1rem;\n            min-height: 100px;\n            white-space: pre-wrap; \/* Quan tr\u1ecdng: Gi\u1eef nguy\u00ean xu\u1ed1ng d\u00f2ng *\/\n            word-break: break-word;\n            font-size: 0.95rem;\n            line-height: 1.5;\n            color: #334155;\n            margin-bottom: 1rem;\n        }\n\n        .download-bar {\n            background: #ecfdf5;\n            border: 1px solid #a7f3d0;\n            padding: 1rem;\n            border-radius: 1rem;\n            display: flex;\n            align-items: center;\n            justify-content: space-between;\n        }\n\n        textarea { \n            width: 100%; \n            height: 180px; \n            padding: 1rem; \n            background: #f8fafc; \n            border: 2px solid #e2e8f0; \n            border-radius: 1rem; \n            font-size: 14px; \n            outline: none; \n            margin-bottom: 1rem; \n            resize: none; \n            transition: border-color 0.2s;\n        }\n        textarea:focus { border-color: #2563eb; background: white; }\n\n        .toast { \n            position: fixed; bottom: 30px; left: 50%; transform: translateX(-50%); \n            background: #1e293b; color: white; padding: 12px 24px; \n            border-radius: 50px; font-size: 13px; font-weight: 600; display: none; z-index: 1000; \n        }\n        \n        .status-badge {\n            display: inline-flex;\n            align-items: center;\n            background: white;\n            padding: 4px 12px;\n            border-radius: 99px;\n            border: 1px solid #e2e8f0;\n            font-size: 11px;\n            font-weight: 700;\n            text-transform: uppercase;\n        }\n        .dot { width: 8px; height: 8px; border-radius: 50%; margin-right: 6px; }\n    <\/style>\n<\/head>\n<body>\n    <div class=\"app-container\">\n        <!-- Header -->\n        <div class=\"flex justify-between items-center mb-6\">\n            <div>\n                <h1 class=\"text-xl font-black text-slate-800 tracking-tight\">Cloud Manager<\/h1>\n                <div class=\"status-badge mt-1\">\n                    <span id=\"status-dot\" class=\"dot bg-slate-300\"><\/span>\n                    <span id=\"sync-text\" class=\"text-slate-500\">\u0110ang k\u1ebft n\u1ed1i&#8230;<\/span>\n                <\/div>\n            <\/div>\n            <div class=\"text-right\">\n                <span id=\"line-count\" class=\"bg-slate-800 text-white px-3 py-1 rounded-lg text-[10px] font-black shadow-lg uppercase\">0 M\u1ee5c<\/span>\n            <\/div>\n        <\/div>\n\n        <!-- Input Area -->\n        <div class=\"card\">\n            <p class=\"text-[11px] font-bold text-slate-400 uppercase mb-2 tracking-widest px-1\">D\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o (N\u1ed9i dung | Link)<\/p>\n            <textarea id=\"input-list\" placeholder=\"N\u1ed9i dung d\u00f2ng 1&#10;N\u1ed9i dung d\u00f2ng 2 | https:\/\/link-tai-ve.com&#10;&#10;-- Ph\u00e2n c\u00e1ch c\u00e1c m\u1ee5c b\u1eb1ng 2 l\u1ea7n xu\u1ed1ng d\u00f2ng --\"><\/textarea>\n            <button id=\"next-btn\" class=\"btn-primary\">\n                <span>L\u1ea5y d\u1eef li\u1ec7u ti\u1ebfp theo<\/span>\n                <svg width=\"20\" height=\"20\" viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"3\" stroke-linecap=\"round\" stroke-linejoin=\"round\"><polyline points=\"13 17 18 12 13 7\"><\/polyline><polyline points=\"6 17 11 12 6 7\"><\/polyline><\/svg>\n            <\/button>\n        <\/div>\n\n        <!-- Result Area -->\n        <div id=\"result-area\" class=\"result-card\">\n            <div class=\"mb-4\">\n                <div class=\"flex justify-between items-center mb-2\">\n                    <span class=\"text-[10px] font-black text-slate-400 uppercase tracking-widest\">N\u1ed9i dung hi\u1ec3n th\u1ecb<\/span>\n                    <button id=\"copy-content\" class=\"text-[10px] font-bold text-blue-600 uppercase\">Sao ch\u00e9p n\u1ed9i dung<\/button>\n                <\/div>\n                <div id=\"content-display\" class=\"content-display-box\">&#8212;<\/div>\n            <\/div>\n\n            <div class=\"download-bar\">\n                <div class=\"overflow-hidden flex-1 mr-4\">\n                    <p class=\"text-[9px] text-emerald-600 font-black uppercase tracking-widest mb-1\">T\u1ec7p \u0111\u00ednh k\u00e8m<\/p>\n                    <p id=\"link-display\" class=\"text-xs font-bold truncate text-emerald-800 italic\">Ch\u01b0a c\u00f3 link<\/p>\n                <\/div>\n                <button id=\"download-btn\" class=\"bg-emerald-600 text-white px-6 py-3 rounded-xl text-xs font-black shadow-md active:scale-90 transition-transform\">T\u1ea2I V\u1ec0<\/button>\n            <\/div>\n        <\/div>\n\n        <div id=\"error-help\" class=\"mt-4 p-4 bg-red-50 border border-red-100 rounded-2xl hidden text-[11px] text-red-500 leading-relaxed\">\n            <b>L\u1ed7i Firebase:<\/b> Kh\u00f4ng th\u1ec3 k\u1ebft n\u1ed1i v\u1edbi d\u1ef1 \u00e1n hiep&#8211;3. Vui l\u00f2ng ki\u1ec3m tra quy\u1ec1n truy c\u1eadp Firestore.\n        <\/div>\n    <\/div>\n\n    <div id=\"toast\" class=\"toast\">\u0110\u00c3 SAO CH\u00c9P<\/div>\n\n    <script type=\"module\">\n        import { initializeApp } from \"https:\/\/www.gstatic.com\/firebasejs\/11.0.1\/firebase-app.js\";\n        import { getAuth, signInAnonymously, onAuthStateChanged } from \"https:\/\/www.gstatic.com\/firebasejs\/11.0.1\/firebase-auth.js\";\n        import { getFirestore, doc, setDoc, onSnapshot } from \"https:\/\/www.gstatic.com\/firebasejs\/11.0.1\/firebase-firestore.js\";\n\n        const firebaseConfig = {\n            apiKey: \"AIzaSyDUy50OlaitdvyhIqowwKZL53m4suwZxME\",\n            authDomain: \"hiep--3.firebaseapp.com\",\n            projectId: \"hiep--3\",\n            storageBucket: \"hiep--3.firebasestorage.app\",\n            appId: \"1:916863840087:web:b3af001ccf32b0114f5812\"\n        };\n\n        const APP_ID = 'hiep-download-manager-v13';\n        let db, auth, currentUser, saveDebounce, currentDownloadLink = '';\n\n        \/\/ --- Core Functions ---\n        const init = async () => {\n            try {\n                const app = initializeApp(firebaseConfig);\n                auth = getAuth(app);\n                db = getFirestore(app);\n\n                onAuthStateChanged(auth, (user) => {\n                    if (user) {\n                        currentUser = user;\n                        document.getElementById('status-dot').className = 'dot bg-emerald-500 shadow-[0_0_8px_#10b981]';\n                        document.getElementById('sync-text').innerText = 'Tr\u1ef1c tuy\u1ebfn';\n                        setupSync();\n                    } else {\n                        signInAnonymously(auth).catch(() => {\n                            document.getElementById('error-help').classList.remove('hidden');\n                        });\n                    }\n                });\n            } catch (e) { console.error(e); }\n        };\n\n        function setupSync() {\n            onSnapshot(doc(db, 'clouds', APP_ID), (docSnap) => {\n                const area = document.getElementById('input-list');\n                if (docSnap.exists() && document.activeElement !== area) {\n                    area.value = docSnap.data().list || '';\n                    updateItemCount();\n                }\n            });\n        }\n\n        async function syncToCloud(content) {\n            if (!currentUser) return;\n            try { \n                await setDoc(doc(db, 'clouds', APP_ID), { \n                    list: content, \n                    updatedAt: Date.now() \n                }, { merge: true }); \n            } catch (e) { console.error(\"Sync Error:\", e); }\n        }\n\n        \/\/ --- Helper: Parsing Content ---\n        function updateItemCount() {\n            const val = document.getElementById('input-list').value.trim();\n            \/\/ T\u00e1ch c\u00e1c m\u1ee5c b\u1eb1ng d\u1ea5u c\u00e1ch tr\u1ed1ng (2 l\u1ea7n xu\u1ed1ng d\u00f2ng)\n            const items = val ? val.split(\/\\n\\s*\\n\/) : [];\n            document.getElementById('line-count').innerText = items.length + ' M\u1ee4C';\n        }\n\n        function showToast(msg) {\n            const t = document.getElementById('toast');\n            t.innerText = msg;\n            t.style.display = 'block';\n            setTimeout(() => t.style.display = 'none', 1500);\n        }\n\n        \/\/ --- Event Listeners ---\n        document.addEventListener('DOMContentLoaded', () => {\n            init();\n            const area = document.getElementById('input-list');\n\n            area.oninput = () => {\n                updateItemCount();\n                clearTimeout(saveDebounce);\n                saveDebounce = setTimeout(() => syncToCloud(area.value), 1000);\n            };\n\n            document.getElementById('next-btn').onclick = () => {\n                const rawValue = area.value.trim();\n                if (!rawValue) return;\n\n                \/\/ T\u00e1ch c\u00e1c m\u1ee5c b\u1eb1ng t\u1ed5 h\u1ee3p 2 l\u1ea7n xu\u1ed1ng d\u00f2ng tr\u1edf l\u00ean\n                const items = rawValue.split(\/\\n\\s*\\n\/);\n                const currentItem = items.shift();\n                const remainder = items.join('\\n\\n');\n\n                area.value = remainder;\n                syncToCloud(remainder);\n                updateItemCount();\n\n                \/\/ X\u1eed l\u00fd m\u1ee5c hi\u1ec7n t\u1ea1i: T\u00e1ch n\u1ed9i dung v\u00e0 link b\u1eb1ng d\u1ea5u | cu\u1ed1i c\u00f9ng\n                \/\/ Regex n\u00e0y t\u00ecm d\u1ea5u | cu\u1ed1i c\u00f9ng trong chu\u1ed7i\n                const lastPipeIndex = currentItem.lastIndexOf('|');\n                \n                let content = '';\n                let link = '';\n\n                if (lastPipeIndex !== -1) {\n                    content = currentItem.substring(0, lastPipeIndex).trim();\n                    link = currentItem.substring(lastPipeIndex + 1).trim();\n                } else {\n                    \/\/ N\u1ebfu kh\u00f4ng c\u00f3 d\u1ea5u |, coi to\u00e0n b\u1ed9 l\u00e0 n\u1ed9i dung\n                    content = currentItem.trim();\n                    link = '';\n                }\n\n                \/\/ Hi\u1ec3n th\u1ecb k\u1ebft qu\u1ea3\n                document.getElementById('content-display').innerText = content;\n                currentDownloadLink = link;\n                document.getElementById('link-display').innerText = link || 'Kh\u00f4ng c\u00f3 link';\n                \n                const resultArea = document.getElementById('result-area');\n                resultArea.style.display = 'block';\n                resultArea.scrollIntoView({ behavior: 'smooth' });\n            };\n\n            document.getElementById('download-btn').onclick = () => {\n                if (currentDownloadLink && (currentDownloadLink.startsWith('http') || currentDownloadLink.includes('.'))) {\n                    let finalUrl = currentDownloadLink;\n                    if (!finalUrl.startsWith('http')) finalUrl = 'https:\/\/' + finalUrl;\n\n                    \/\/ T\u1ef1 \u0111\u1ed9ng nh\u1eadn di\u1ec7n v\u00e0 chuy\u1ec3n \u0111\u1ed5i link Google Drive sang d\u1ea1ng t\u1ea3i tr\u1ef1c ti\u1ebfp (kh\u00f4ng qua trang preview)\n                    if (finalUrl.includes('drive.google.com')) {\n                        const fileIdMatch = finalUrl.match(\/\\\/d\\\/([^\\\/]+)\/) || finalUrl.match(\/id=([^\\&]+)\/);\n                        if (fileIdMatch && fileIdMatch[1]) {\n                            finalUrl = `https:\/\/drive.google.com\/uc?export=download&id=${fileIdMatch[1]}`;\n                        }\n                    }\n\n                    \/\/ S\u1eed d\u1ee5ng th\u1ebb anchor \u1ea9n v\u1edbi thu\u1ed9c t\u00ednh download \u0111\u1ec3 k\u00edch ho\u1ea1t tr\u00ecnh t\u1ea3i c\u1ee7a tr\u00ecnh duy\u1ec7t\n                    const downloadAnchor = document.createElement('a');\n                    downloadAnchor.href = finalUrl;\n                    downloadAnchor.setAttribute('download', ''); \n                    downloadAnchor.setAttribute('target', '_self'); \/\/ C\u1ed1 g\u1eafng gi\u1eef nguy\u00ean tab hi\u1ec7n t\u1ea1i\n                    downloadAnchor.style.display = 'none';\n                    document.body.appendChild(downloadAnchor);\n                    downloadAnchor.click();\n                    document.body.removeChild(downloadAnchor);\n                    \n                    showToast('\u0110ANG B\u1eaeT \u0110\u1ea6U T\u1ea2I V\u1ec0');\n                } else {\n                    showToast('LINK KH\u00d4NG H\u1ee2P L\u1ec6');\n                }\n            };\n\n            document.getElementById('copy-content').onclick = () => {\n                const text = document.getElementById('content-display').innerText;\n                const el = document.createElement('textarea');\n                el.value = text;\n                document.body.appendChild(el);\n                el.select();\n                document.execCommand('copy');\n                document.body.removeChild(el);\n                showToast('\u0110\u00c3 CH\u00c9P N\u1ed8I DUNG');\n            };\n        });\n    <\/script>\n<\/body>\n<\/html>\n\n\n\n<p class=\"wp-block-paragraph\"><\/p>\n","protected":false},"excerpt":{"rendered":"<div class=\"mh-excerpt\"><p>Cloud Content Manager v13 Cloud Manager \u0110ang k\u1ebft n\u1ed1i&#8230; 0 M\u1ee5c D\u1eef li\u1ec7u \u0111\u1ea7u v\u00e0o (N\u1ed9i dung | Link) L\u1ea5y d\u1eef li\u1ec7u ti\u1ebfp theo N\u1ed9i <a class=\"mh-excerpt-more\" href=\"https:\/\/tinbamien.com\/?page_id=18\" title=\"l\u1ea5y l\u1ea7n l\u01b0\u1ee3t\">[&#8230;]<\/a><\/p>\n<\/div>","protected":false},"author":1,"featured_media":0,"parent":0,"menu_order":0,"comment_status":"closed","ping_status":"closed","template":"","meta":{"footnotes":""},"class_list":["post-18","page","type-page","status-publish","hentry"],"_links":{"self":[{"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/pages\/18","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/pages"}],"about":[{"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/types\/page"}],"author":[{"embeddable":true,"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/tinbamien.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=18"}],"version-history":[{"count":1,"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/pages\/18\/revisions"}],"predecessor-version":[{"id":19,"href":"https:\/\/tinbamien.com\/index.php?rest_route=\/wp\/v2\/pages\/18\/revisions\/19"}],"wp:attachment":[{"href":"https:\/\/tinbamien.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=18"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}