Meta Description" name="description" />
<!DOCTYPE html>
<html lang="id">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
<title>Projeck Sampingan - Pro Editor</title>
<!-- Menggunakan Font Awesome untuk Ikon -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css">
<style>
:root {
--primary: #6c5ce7;
--secondary: #00cec9;
--bg-dark: #1e1e2e;
--bg-card: #2d2d44;
--text-main: #ffffff;
--text-muted: #a0a0b0;
--danger: #ff7675;
--success: #00b894;
--nav-height: 60px;
--header-height: 60px;
}
* {
box-sizing: border-box;
-webkit-tap-highlight-color: transparent;
}
body {
margin: 0;
padding: 0;
font-family: 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
background-color: #121212;
color: var(--text-main);
overflow: hidden; /* Mencegah scroll body, kita scroll konten */
height: 100vh;
display: flex;
justify-content: center;
}
/* Container utama menyerupai layar HP */
#app-container {
width: 100%;
max-width: 480px; /* Batas lebar seperti HP */
height: 100%;
background-color: var(--bg-dark);
display: flex;
flex-direction: column;
position: relative;
box-shadow: 0 0 20px rgba(0,0,0,0.5);
}
/* --- HEADER --- */
header {
height: var(--header-height);
background-color: var(--bg-card);
display: flex;
align-items: center;
justify-content: space-between;
padding: 0 15px;
box-shadow: 0 2px 10px rgba(0,0,0,0.2);
z-index: 100;
}
.app-logo {
font-weight: bold;
font-size: 1.1rem;
color: var(--primary);
display: flex;
align-items: center;
gap: 8px;
}
.header-controls {
display: flex;
gap: 15px;
align-items: center;
}
.network-status {
font-size: 0.8rem;
padding: 4px 8px;
border-radius: 10px;
background: #333;
}
.online { color: var(--success); }
.offline { color: var(--danger); }
.lang-select {
background: transparent;
border: 1px solid var(--primary);
color: var(--text-main);
padding: 4px;
border-radius: 4px;
font-size: 0.8rem;
}
/* --- MAIN CONTENT AREA --- */
main {
flex: 1;
overflow-y: auto;
position: relative;
padding-bottom: var(--nav-height); /* Space for bottom nav */
}
.view {
display: none;
padding: 15px;
animation: fadeIn 0.3s ease;
}
.view.active {
display: block;
}
@keyframes fadeIn {
from { opacity: 0; transform: translateY(10px); }
to { opacity: 1; transform: translateY(0); }
}
/* --- HOME / PROFILE --- */
.profile-card {
background: var(--bg-card);
border-radius: 15px;
padding: 20px;
text-align: center;
margin-bottom: 20px;
position: relative;
overflow: hidden;
}
.profile-card::before {
content: '';
position: absolute;
top: 0; left: 0; width: 100%; height: 80px;
background: linear-gradient(45deg, var(--primary), var(--secondary));
z-index: 0;
}
.avatar-container {
position: relative;
z-index: 1;
width: 80px;
height: 80px;
margin: 0 auto 10px;
border-radius: 50%;
border: 3px solid var(--bg-card);
overflow: hidden;
background: #000;
}
.avatar-container img {
width: 100%;
height: 100%;
object-fit: cover;
}
.profile-name {
font-size: 1.2rem;
font-weight: bold;
margin-bottom: 5px;
position: relative;
z-index: 1;
}
.profile-role {
color: var(--text-muted);
font-size: 0.9rem;
position: relative;
z-index: 1;
}
.btn {
background: var(--primary);
color: white;
border: none;
padding: 10px 20px;
border-radius: 8px;
cursor: pointer;
font-size: 0.9rem;
transition: 0.2s;
margin-top: 10px;
display: inline-flex;
align-items: center;
gap: 8px;
}
.btn:active { transform: scale(0.95); }
.btn-outline { background: transparent; border: 1px solid var(--primary); color: var(--primary); }
.btn-danger { background: var(--danger); }
/* --- TEMPLATES GRID --- */
.grid-container {
display: grid;
grid-template-columns: repeat(2, 1fr);
gap: 10px;
}
.template-item {
background: var(--bg-card);
border-radius: 8px;
overflow: hidden;
position: relative;
aspect-ratio: 9/16;
cursor: pointer;
}
.template-item img {
width: 100%;
height: 100%;
object-fit: cover;
transition: 0.3s;
}
.template-item:hover img { transform: scale(1.05); }
.template-overlay {
position: absolute;
bottom: 0; left: 0; width: 100%;
padding: 10px;
background: linear-gradient(to top, rgba(0,0,0,0.8), transparent);
font-size: 0.8rem;
}
/* --- PROJECTS LIST --- */
.project-item {
background: var(--bg-card);
padding: 15px;
border-radius: 10px;
margin-bottom: 10px;
display: flex;
justify-content: space-between;
align-items: center;
}
.project-info h4 { margin: 0 0 5px 0; font-size: 1rem; }
.project-info p { margin: 0; color: var(--text-muted); font-size: 0.8rem; }
/* --- EDITOR INTERFACE --- */
#editor-view {
padding: 0;
height: 100%;
display: flex;
flex-direction: column;
background: #000;
}
.editor-preview {
flex: 1;
display: flex;
align-items: center;
justify-content: center;
position: relative;
background: #000;
}
#preview-media {
max-width: 100%;
max-height: 60vh;
display: block;
}
.editor-controls {
background: var(--bg-card);
padding: 15px;
border-radius: 15px 15px 0 0;
}
.control-group { margin-bottom: 15px; }
.control-group label { display: block; font-size: 0.8rem; margin-bottom: 5px; color: var(--text-muted); }
input[type="range"] {
width: 100%;
accent-color: var(--primary);
}
.time-display {
font-family: monospace;
font-size: 1.2rem;
color: var(--secondary);
text-align: center;
margin: 10px 0;
}
/* --- HISTORY & SETTINGS --- */
.history-list {
list-style: none;
padding: 0;
}
.history-list li {
background: var(--bg-card);
padding: 10px;
margin-bottom: 8px;
border-radius: 5px;
border-left: 3px solid var(--secondary);
display: flex;
justify-content: space-between;
font-size: 0.85rem;
}
.setting-item {
display: flex;
justify-content: space-between;
align-items: center;
padding: 15px;
background: var(--bg-card);
margin-bottom: 10px;
border-radius: 8px;
}
/* --- BOTTOM NAV --- */
nav {
position: absolute;
bottom: 0;
width: 100%;
height: var(--nav-height);
background: var(--bg-card);
display: flex;
justify-content: space-around;
align-items: center;
border-top: 1px solid #333;
z-index: 100;
}
.nav-item {
color: var(--text-muted);
text-align: center;
font-size: 0.7rem;
cursor: pointer;
width: 20%;
}
.nav-item i {
font-size: 1.2rem;
display: block;
margin-bottom: 4px;
}
.nav-item.active {
color: var(--primary);
}
/* --- MODAL --- */
.modal {
position: fixed;
top: 0; left: 0; width: 100%; height: 100%;
background: rgba(0,0,0,0.8);
display: flex;
justify-content: center;
align-items: center;
z-index: 1000;
opacity: 0;
pointer-events: none;
transition: 0.3s;
}
.modal.open { opacity: 1; pointer-events: all; }
.modal-content {
background: var(--bg-card);
padding: 20px;
border-radius: 15px;
width: 90%;
max-width: 400px;
}
.form-group { margin-bottom: 15px; }
.form-group input { width: 100%; padding: 10px; border-radius: 5px; border: none; background: #444; color: white; }
/* Toast Notification */
.toast {
position: fixed;
bottom: 80px;
left: 50%;
transform: translateX(-50%);
background: rgba(50, 50, 50, 0.9);
color: white;
padding: 10px 20px;
border-radius: 20px;
font-size: 0.9rem;
z-index: 2000;
display: none;
}
</style>
</head>
<body>
<div id="app-container">
<!-- HEADER -->
<header>
<div class="app-logo">
<i class="fas fa-layer-group"></i> <span data-i18n="appName">Projeck Sampingan</span>
</div>
<div class="header-controls">
<div id="net-status" class="network-status online"><i class="fas fa-wifi"></i></div>
<select id="lang-switch" class="lang-select" onchange="changeLanguage(this.value)">
<option value="id">ID</option>
<option value="en">EN</option>
<option value="jp">JP</option>
</select>
</div>
</header>
<!-- MAIN VIEWS -->
<main>
<!-- 1. HOME / PROFILE -->
<section id="view-home" class="view active">
<div class="profile-card">
<div class="avatar-container">
<img id="user-avatar" src="https://picsum.photos/seed/user/200/200" alt="Profile">
</div>
<h3 id="display-name" class="profile-name">Pengguna Pro</h3>
<p class="profile-role" data-i18n="roleLabel">Video Editor & Designer</p>
<button class="btn btn-outline" onclick="openProfileModal()" data-i18n="editProfile">Edit Profil</button>
</div>
<h3 style="margin-bottom: 10px;" data-i18n="workingOn">Sedang Dikerjakan</h3>
<div id="home-project-list">
<!-- Projects injected here -->
<div class="project-item">
<div class="project-info">
<h4>Iklan Makanan.mp4</h4>
<p>Durasi: 4:20 • HD</p>
</div>
<button class="btn" onclick="openEditor('video')"><i class="fas fa-edit"></i></button>
</div>
</div>
</section>
<!-- 2. TEMPLATES -->
<section id="view-templates" class="view">
<div style="display:flex; justify-content:space-between; align-items:center; margin-bottom:15px;">
<h3 data-i18n="templates">Rekomendasi Tema</h3>
<span style="font-size:0.8rem; color:var(--text-muted)">300 Models</span>
</div>
<div class="grid-container" id="templates-grid">
<!-- 300 items generated by JS -->
</div>
</section>
<!-- 3. PROJECTS -->
<section id="view-projects" class="view">
<div style="margin-bottom: 15px;">
<button class="btn" onclick="createNewProject()" style="width:100%">
<i class="fas fa-plus"></i> <span data-i18n="newProject">Projeck Baru</span>
</button>
</div>
<div id="all-projects-list">
<!-- Full list here -->
</div>
</section>
<!-- 4. HISTORY -->
<section id="view-history" class="view">
<h3 data-i18n="history">Riwayat Aktivitas</h3>
<ul class="history-list" id="history-log">
<!-- Logs -->
</ul>
</section>
<!-- 5. SETTINGS -->
<section id="view-settings" class="view">
<h3 data-i18n="settings">Pengaturan</h3>
<div class="setting-item">
<span data-i18n="hdMode">Mode Kualitas HD</span>
<input type="checkbox" checked id="setting-hd">
</div>
<div class="setting-item">
<span data-i18n="offlineSave">Simpan Offline</span>
<input type="checkbox" checked id="setting-offline">
</div>
<div class="setting-item">
<span data-i18n="maxDuration">Durasi Maksimal</span>
<span style="color:var(--primary)">10 Menit</span>
</div>
<div style="margin-top: 20px;">
<button class="btn btn-danger" onclick="clearData()" style="width:100%">
<i class="fas fa-trash"></i> <span data-i18n="clearData">Hapus Data</span>
</button>
</div>
</section>
<!-- EDITOR VIEW (Overlay) -->
<section id="editor-view" class="view">
<div style="padding: 10px; background: #222; display:flex; justify-content:space-between;">
<button class="btn btn-outline" onclick="closeEditor()" style="padding: 5px 10px;">
<i class="fas fa-arrow-left"></i> Back
</button>
<span style="align-self:center; font-weight:bold;" id="editor-title">Edit Project</span>
<button class="btn" style="padding: 5px 10px; background:var(--success)" onclick="saveProject()">
<i class="fas fa-save"></i> Save
</button>
</div>
<div class="editor-preview">
<!-- Mock Video/Image Preview -->
<div id="preview-container" style="position:relative;">
<img id="preview-media" src="https://picsum.photos/seed/edit/400/600" style="filter: brightness(100%) contrast(100%) grayscale(0%);">
<div style="position:absolute; bottom:10px; right:10px; background:rgba(0,0,0,0.7); padding:5px; border-radius:5px; font-size:0.8rem">10:00 / 00:00</div>
</div>
</div>
<div class="editor-controls">
<div class="time-display" id="current-time">00:00:00</div>
<div class="control-group">
<label data-i18n="brightness">Kecerahan (Brightness)</label>
<input type="range" min="0" max="200" value="100" oninput="applyFilter('brightness', this.value)">
</div>
<div class="control-group">
<label data-i18n="contrast">Kontras (Contrast)</label>
<input type="range" min="0" max="200" value="100" oninput="applyFilter('contrast', this.value)">
</div>
<div class="control-group">
<label data-i18n="saturation">Saturasi (Saturation)</label>
<input type="range" min="0" max="200" value="100" oninput="applyFilter('saturate', this.value)">
</div>
<div style="display:grid; grid-template-columns: 1fr 1fr 1fr; gap:10px; margin-top:15px;">
<button class="btn btn-outline" style="margin:0"><i class="fas fa-cut"></i> Trim</button>
<button class="btn btn-outline" style="margin:0"><i class="fas fa-music"></i> Audio</button>
<button class="btn btn-outline" style="margin:0"><i class="fas fa-font"></i> Text</button>
</div>
</div>
</section>
</main>
<!-- BOTTOM NAVIGATION -->
<nav>
<div class="nav-item active" onclick="switchTab('home', this)">
<i class="fas fa-home"></i> <span data-i18n="navHome">Beranda</span>
</div>
<div class="nav-item" onclick="switchTab('projects', this)">
<i class="fas fa-folder-open"></i> <span data-i18n="navProject">Projeck</span>
</div>
<div class="nav-item" onclick="switchTab('templates', this)">
<i class="fas fa-shapes"></i> <span data-i18n="navTemplate">Templet</span>
</div>
<div class="nav-item" onclick="switchTab('history', this)">
<i class="fas fa-history"></i> <span data-i18n="navHistory">Riwayat</span>
</div>
<div class="nav-item" onclick="switchTab('settings', this)">
<i class="fas fa-cog"></i> <span data-i18n="navSetting">Setting</span>
</div>
</nav>
</div>
<!-- MODAL EDIT PROFILE -->
<div class="modal" id="profile-modal">
<div class="modal-content">
<h3 data-i18n="editProfile">Edit Profil</h3>
<div class="form-group">
<label>Nama Pengguna</label>
<input type="text" id="input-name" placeholder="Masukkan nama">
</div>
<div class="form-group">
<label>URL Avatar</label>
<input type="text" id="input-avatar" placeholder="https://...">
</div>
<div style="display:flex; gap:10px; justify-content:flex-end;">
<button class="btn btn-outline" onclick="closeProfileModal()" data-i18n="cancel">Batal</button>
<button class="btn" onclick="saveProfile()" data-i18n="save">Simpan</button>
</div>
</div>
</div>
<div class="toast" id="toast">Data Tersimpan Offline</div>
<script>
// --- DATA & STATE ---
const appState = {
lang: 'id',
user: {
name: 'Pengguna Pro',
avatar: 'https://picsum.photos/seed/user/200/200'
},
projects: [
{ id: 1, title: 'Iklan Makanan.mp4', date: '2023-10-27', type: 'video' },
{ id: 2, title: 'Edit Foto Liburan.jpg', date: '2023-10-26', type: 'image' }
],
history: []
};
const translations = {
id: {
appName: "Projeck Sampingan",
roleLabel: "Video Editor & Designer",
editProfile: "Edit Profil",
workingOn: "Sedang Dikerjakan",
templates: "Rekomendasi Tema",
newProject: "Projeck Baru",
history: "Riwayat Aktivitas",
settings: "Pengaturan",
hdMode: "Mode Kualitas HD",
offlineSave: "Simpan Offline",
maxDuration: "Durasi Maksimal",
clearData: "Hapus Data",
brightness: "Kecerahan",
contrast: "Kontras",
saturation: "Saturasi",
navHome: "Beranda",
navProject: "Projeck",
navTemplate: "Templet",
navHistory: "Riwayat",
navSetting: "Setting",
cancel: "Batal",
save: "Simpan",
toastSaved: "Proyek Berhasil Disimpan!",
toastCleared: "Data Dihapus.",
projectCreated: "Proyek Baru Dibuat."
},
en: {
appName: "Side Project App",
roleLabel: "Video Editor & Designer",
editProfile: "Edit Profile",
workingOn: "Working On",
templates: "Recommended Themes",
newProject: "New Project",
history: "Activity History",
settings: "Settings",
hdMode: "HD Quality Mode",
offlineSave: "Save Offline",
maxDuration: "Max Duration",
clearData: "Clear Data",
brightness: "Brightness",
contrast: "Contrast",
saturation: "Saturation",
navHome: "Home",
navProject: "Project",
navTemplate: "Template",
navHistory: "History",
navSetting: "Setting",
cancel: "Cancel",
save: "Save",
toastSaved: "Project Saved Successfully!",
toastCleared: "Data Cleared.",
projectCreated: "New Project Created."
},
jp: {
appName: "サイドプロジェクト",
roleLabel: "ビデオエディター",
editProfile: "プロフィール編集",
workingOn: "作業中",
templates: "おすすめテーマ",
newProject: "新しいプロジェクト",
history: "アクティビティ履歴",
settings: "設定",
hdMode: "HD品質モード",
offlineSave: "オフライン保存",
maxDuration: "最大時間",
clearData: "データ削除",
brightness: "明るさ",
contrast: "コントラスト",
saturation: "彩度",
navHome: "ホーム",
navProject: "プロジェクト",
navTemplate: "テンプレート",
navHistory: "履歴",
navSetting: "設定",
cancel: "キャンセル",
save: "保存",
toastSaved: "プロジェクトを保存しました!",
toastCleared: "データが削除されました。",
projectCreated: "新しいプロジェクトが作成されました。"
}
};
// --- INIT ---
window.onload = function() {
loadData();
renderProjects();
renderHistory();
renderTemplates(); // Generate 300 templates
updateLanguageUI();
checkNetwork();
startTimeTicker();
// Listen to network changes
window.addEventListener('online', checkNetwork);
window.addEventListener('offline', checkNetwork);
};
// --- NAVIGATION ---
function switchTab(viewId, navEl) {
// Hide all views
document.querySelectorAll('.view').forEach(el => {
if(el.id !== 'editor-view') el.classList.remove('active');
});
// Show target view
document.getElementById('view-' + viewId).classList.add('active');
// Update Nav Icons
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
if(navEl) navEl.classList.add('active');
}
function openEditor(type) {
// Hide main views temporarily
document.querySelectorAll('.view').forEach(el => el.classList.remove('active'));
document.getElementById('editor-view').classList.add('active');
// Hide bottom nav if desired, but we kept it
document.querySelector('nav').style.display = 'none';
}
function closeEditor() {
document.getElementById('editor-view').classList.remove('active');
document.getElementById('view-home').classList.add('active');
document.querySelector('nav').style.display = 'flex';
// Set first nav active
document.querySelectorAll('.nav-item').forEach(el => el.classList.remove('active'));
document.querySelectorAll('.nav-item')[0].classList.add('active');
}
// --- TEMPLATES GENERATOR (300 Items) ---
function renderTemplates() {
const container = document.getElementById('templates-grid');
container.innerHTML = ''; // Reset
// Using document fragment for performance
const fragment = document.createDocumentFragment();
for (let i = 1; i <= 300; i++) {
const div = document.createElement('div');
div.className = 'template-item';
div.innerHTML = `
<img src="https://picsum.photos/seed/${i}/150/250" loading="lazy">
<div class="template-overlay">Template ${i}</div>
`;
div.onclick = () => {
openEditor('template');
document.getElementById('preview-media').src = `https://picsum.photos/seed/${i}/400/600`;
document.getElementById('editor-title').innerText = `Edit Template ${i}`;
};
fragment.appendChild(div);
}
container.appendChild(fragment);
}
// --- EDITOR LOGIC ---
function applyFilter(type, value) {
const img = document.getElementById('preview-media');
// Get current filter string and update it
// Simplified: we just reset and apply new ones based on current sliders
// In a real app, we would track state of all sliders.
const bright = document.querySelector('input[oninput*="brightness"]').value;
const contrast = document.querySelector('input[oninput*="contrast"]').value;
const saturate = document.querySelector('input[oninput*="saturate"]').value;
img.style.filter = `brightness(${bright}%) contrast(${contrast}%) saturate(${saturate}%)`;
}
function saveProject() {
showToast(translations[appState.lang].toastSaved);
addToHistory("Project Saved: " + document.getElementById('editor-title').innerText);
saveData(); // Simpan ke offline storage
setTimeout(closeEditor, 1000);
}
// --- PROFILE LOGIC ---
function openProfileModal() {
document.getElementById('input-name').value = appState.user.name;
document.getElementById('input-avatar').value = appState.user.avatar;
document.getElementById('profile-modal').classList.add('open');
}
function closeProfileModal() {
document.getElementById('profile-modal').classList.remove('open');
}
function saveProfile() {
const newName = document.getElementById('input-name').value;
const newAvatar = document.getElementById('input-avatar').value;
if(newName) {
appState.user.name = newName;
document.getElementById('display-name').innerText = newName;
}
if(newAvatar) {
appState.user.avatar = newAvatar;
document.getElementById('user-avatar').src = newAvatar;
}
saveData();
closeProfileModal();
addToHistory("Profile Updated");
}
// --- PROJECTS LOGIC ---
function renderProjects() {
const homeList = document.getElementById('home-project-list');
const allList = document.getElementById('all-projects-list');
homeList.innerHTML = '';
allList.innerHTML = '';
appState.projects.forEach(proj => {
const html = `
<div class="project-item">
<div class="project-info">
<h4>${proj.title}</h4>
<p>${proj.date} • ${proj.type.toUpperCase()}</p>
</div>
<button class="btn" onclick="openEditor('${proj.type}')"><i class="fas fa-edit"></i></button>
</div>
`;
// Add to All
allList.innerHTML += html;
// Add to Home (limit to 2 for demo)
if(homeList.children.length < 2) {
homeList.innerHTML += html;
}
});
}
function createNewProject() {
const id = Date.now();
const newProj = {
id: id,
title: `New Project ${appState.projects.length + 1}`,
date: new Date().toISOString().split('T')[0],
type: 'video'
};
appState.projects.unshift(newProj);
renderProjects();
saveData();
showToast(translations[appState.lang].projectCreated);
addToHistory("Created New Project");
}
// --- HISTORY & TIME ---
function addToHistory(action) {
const now = new Date();
const timeStr = now.toLocaleTimeString('id-ID', {hour: '2-digit', minute:'2-digit'});
const dateStr = now.toLocaleDateString('id-ID');
appState.history.unshift({
action: action,
time: timeStr,
date: dateStr
});
renderHistory();
saveData();
}
function renderHistory() {
const list = document.getElementById('history-log');
list.innerHTML = '';
appState.history.forEach(item => {
list.innerHTML += `
<li>
<span>${item.action}</span>
<span>${item.date} - ${item.time}</span>
</li>
`;
});
}
function startTimeTicker() {
setInterval(() => {
const now = new Date();
// Update editor time simulation
const timeString = now.toLocaleTimeString('en-GB'); // HH:MM:SS
const disp = document.getElementById('current-time');
if(disp && document.getElementById('editor-view').classList.contains('active')) {
disp.innerText = timeString;
}
}, 1000);
}
// --- SETTINGS & DATA ---
function clearData() {
if(confirm("Are you sure? This will delete all local data.")) {
localStorage.removeItem('pojeckSampinganData');
location.reload();
}
}
function saveData() {
localStorage.setItem('pojeckSampinganData', JSON.stringify(appState));
}
function loadData() {
const data = localStorage.getItem('pojeckSampinganData');
if(data) {
const parsed = JSON.parse(data);
appState.user = parsed.user;
appState.projects = parsed.projects || [];
appState.history = parsed.history || [];
appState.lang = parsed.lang || 'id';
// Update UI with loaded data
document.getElementById('display-name').innerText = appState.user.name;
document.getElementById('user-avatar').src = appState.user.avatar;
document.getElementById('lang-switch').value = appState.lang;
}
}
// --- LANGUAGE ---
function changeLanguage(lang) {
appState.lang = lang;
updateLanguageUI();
saveData();
checkNetwork(); // Refresh network text
}
function updateLanguageUI() {
const t = translations[appState.lang];
document.querySelectorAll('[data-i18n]').forEach(el => {
const key = el.getAttribute('data-i18n');
if(t[key]) el.innerText = t[key];
});
}
// --- NETWORK ---
function checkNetwork() {
const netStatus = document.getElementById('net-status');
const isOnline = navigator.onLine;
if(isOnline) {
netStatus.innerHTML = '<i class="fas fa-wifi"></i>';
netStatus.className = 'network-status online';
netStatus.title = 'Online';
} else {
netStatus.innerHTML = '<i class="fas fa-wifi-slash"></i>';
netStatus.className = 'network-status offline';
netStatus.title = 'Offline';
}
}
function showToast(msg) {
const toast = document.getElementById('toast');
toast.innerText = msg;
toast.style.display = 'block';
setTimeout(() => {
toast.style.display = 'none';
}, 3000);
}
</script>
</body>
</html>7
4
263KB
343KB
126.0ms
216.0ms
393.0ms