Added UI
@@ -11,7 +11,8 @@ files {
|
|||||||
'html/index.html',
|
'html/index.html',
|
||||||
'html/style.css',
|
'html/style.css',
|
||||||
'html/app.js',
|
'html/app.js',
|
||||||
'html/img/apps/*'
|
'html/img/apps/*',
|
||||||
|
'html/img/wallpapers/*'
|
||||||
}
|
}
|
||||||
|
|
||||||
client_script 'client.lua'
|
client_script 'client.lua'
|
||||||
|
|||||||
75
html/app.js
@@ -0,0 +1,75 @@
|
|||||||
|
let dragging = false
|
||||||
|
let offsetX = 0;
|
||||||
|
let offsetY = 0;
|
||||||
|
|
||||||
|
const closeBtn = document.getElementById('closeBtn');
|
||||||
|
const phone = document.getElementById('phone');
|
||||||
|
const topbar = document.getElementById('topbar');
|
||||||
|
|
||||||
|
phone.classList.add('absolute', 'top-20', 'left-20');
|
||||||
|
topbar.classList.add('cursor-grab');
|
||||||
|
|
||||||
|
topbar.addEventListener('mousedown', e => {
|
||||||
|
if (e.target.closest('button') || e.target.closest('span')) return;
|
||||||
|
dragging = true;
|
||||||
|
topbar.classList.add('cursor-grabbing');
|
||||||
|
topbar.classList.remove('cursor-grab');
|
||||||
|
|
||||||
|
const rect = phone.getBoundingClientRect();
|
||||||
|
offsetX = e.clientX - rect.left;
|
||||||
|
offsetY = e.clientY - rect.top;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', e => {
|
||||||
|
if (!dragging) return;
|
||||||
|
phone.style.left = `${e.clientX - offsetX}px`;
|
||||||
|
phone.style.top = `${e.clientY - offsetY}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mouseup', () => {
|
||||||
|
if (!dragging) return;
|
||||||
|
dragging = false;
|
||||||
|
topbar.classList.remove('cursor-grabbing');
|
||||||
|
topbar.classList.add('cursor-grab');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
const d = event.data;
|
||||||
|
if (!d) return;
|
||||||
|
|
||||||
|
if (d.action === 'toggle') {
|
||||||
|
if (d.open) {
|
||||||
|
phone.classList.remove('hidden');
|
||||||
|
updateTime();
|
||||||
|
} else {
|
||||||
|
phone.classList.add('hidden');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
closeBtn?.addEventListener('click', () => {
|
||||||
|
phone.classList.add('hidden');
|
||||||
|
|
||||||
|
const parentResource = getParentResourceName();
|
||||||
|
fetch(`https://${parentResource}/close`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
function updateTime() {
|
||||||
|
const t = document.getElementById('time');
|
||||||
|
const now = new Date();
|
||||||
|
const hh = String(now.getHours()).padStart(2, '0');
|
||||||
|
const mm = String(now.getMinutes()).padStart(2, '0');
|
||||||
|
t.innerText = hh + ':' + mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function getParentResourceName() {
|
||||||
|
try {
|
||||||
|
return new URL(document.location).searchParams.get('parent') || window.parentResource || 'gb-phone';
|
||||||
|
} catch {
|
||||||
|
return 'gb-phone';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
BIN
html/img/apps/browser.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
html/img/apps/camera.png
Normal file
|
After Width: | Height: | Size: 4.8 KiB |
|
Before Width: | Height: | Size: 19 KiB |
BIN
html/img/apps/mail.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 22 KiB After Width: | Height: | Size: 4.8 KiB |
BIN
html/img/apps/music.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
BIN
html/img/apps/phone.png
Normal file
|
After Width: | Height: | Size: 4.4 KiB |
BIN
html/img/apps/photos.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
html/img/apps/settings.png
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
html/img/wallpapers/wallpaper-01.png
Normal file
|
After Width: | Height: | Size: 3.0 MiB |
BIN
html/img/wallpapers/wallpaper-02.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
@@ -3,12 +3,83 @@
|
|||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="UTF-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||||
<title>Phone</title>
|
<title>Phone UI</title>
|
||||||
<link rel="stylesheet" href="style.css">
|
|
||||||
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
<script src="https://cdn.jsdelivr.net/npm/@tailwindcss/browser@4"></script>
|
||||||
|
<link rel="stylesheet" href="style.css">
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body class="bg-gray-100 flex items-center justify-center min-h-screen">
|
||||||
|
|
||||||
|
<!-- Phone Container -->
|
||||||
|
<div id="phone" class="~hidden w-72 h-[600px] rounded-3xl shadow-lg flex flex-col overflow-hidden">
|
||||||
|
|
||||||
|
<!-- Top Bar -->
|
||||||
|
<div id="topbar" class="h-12 bg-gray-200 flex items-center justify-between px-4 relative z-20">
|
||||||
|
<span id="time" class="text-xs text-gray-700">9:41</span>
|
||||||
|
<div class="flex space-x-1">
|
||||||
|
<span class="w-3 h-3 bg-gray-700 rounded-full"></span>
|
||||||
|
<span class="w-3 h-3 bg-gray-700 rounded-full"></span>
|
||||||
|
<span class="w-3 h-3 bg-gray-700 rounded-full"></span>
|
||||||
|
</div>
|
||||||
|
<button class="app flex flex-col items-center justify-center bg-gray-100/70 rounded-xl p-2 hover:bg-blue-100/80 transition transform hover:scale-105">
|
||||||
|
×
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Wallpaper -->
|
||||||
|
<div id="wallpaper" class="absolute inset-0 bg-cover bg-center"></div>
|
||||||
|
|
||||||
|
<!-- Homescreen App Grid -->
|
||||||
|
<div class="flex-1 p-3 overflow-y-auto relative z-10">
|
||||||
|
<div class="grid grid-cols-4 gap-3">
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-blue-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/messages.png" alt="Messages" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Messages</span>
|
||||||
|
</button>
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-green-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/camera.png" alt="Camera" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Camera</span>
|
||||||
|
</button>
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-yellow-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/photos.png" alt="Photos" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Photos</span>
|
||||||
|
</button>
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-purple-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/settings.png" alt="Settings" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Settings</span>
|
||||||
|
</button>
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-red-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/mail.png" alt="Mail" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Mail</span>
|
||||||
|
</button>
|
||||||
|
<button class="app text-white flex flex-col items-center justify-center rounded-xl p-2 hover:bg-pink-100 transition transform hover:scale-105">
|
||||||
|
<img src="img/apps/music.png" alt="Music" class="w-10 h-10 mb-1"/>
|
||||||
|
<span class="text-xs">Music</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!-- Dock -->
|
||||||
|
<div class="h-20 bg-gray-200 flex justify-around items-center p-2 rounded-t-3xl relative z-10">
|
||||||
|
<button class="flex flex-col items-center text-gray-600 hover:text-blue-500">
|
||||||
|
<img src="img/apps/phone.png" class="w-8 h-8 mb-1"/>
|
||||||
|
<span class="text-xs">Phone</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center text-gray-600 hover:text-blue-500">
|
||||||
|
<img src="img/apps/messages.png" class="w-8 h-8 mb-1"/>
|
||||||
|
<span class="text-xs">Messages</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center text-gray-600 hover:text-blue-500">
|
||||||
|
<img src="img/apps/browser.png" class="w-8 h-8 mb-1"/>
|
||||||
|
<span class="text-xs">Browser</span>
|
||||||
|
</button>
|
||||||
|
<button class="flex flex-col items-center text-gray-600 hover:text-blue-500">
|
||||||
|
<img src="img/apps/settings.png" class="w-8 h-8 mb-1"/>
|
||||||
|
<span class="text-xs">Settings</span>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
</div>
|
||||||
|
|
||||||
<script src="app.js"></script>
|
<script src="app.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
#wallpaper {
|
||||||
|
background-image: url('img/wallpapers/wallpaper-02.png');
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
}
|
||||||
103
html/test.js
Normal file
@@ -0,0 +1,103 @@
|
|||||||
|
let dragging = false;
|
||||||
|
let offsetX = 0;
|
||||||
|
let offsetY = 0;
|
||||||
|
|
||||||
|
const phoneEl = document.getElementById('phone');
|
||||||
|
|
||||||
|
phoneEl.addEventListener('mousedown', e => {
|
||||||
|
if (e.target.closest('.message-input') || e.target.closest('input') || e.target.closest('button')) return;
|
||||||
|
dragging = true;
|
||||||
|
phoneEl.classList.add('dragging');
|
||||||
|
const rect = phoneEl.getBoundingClientRect();
|
||||||
|
offsetX = e.clientX - rect.left;
|
||||||
|
offsetY = e.clientY - rect.top;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mousemove', e => {
|
||||||
|
if (!dragging) return;
|
||||||
|
phoneEl.style.left = `${e.clientX - offsetX}px`;
|
||||||
|
phoneEl.style.top = `${e.clientY - offsetY}px`;
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('mouseup', () => {
|
||||||
|
if (!dragging) return;
|
||||||
|
dragging = false;
|
||||||
|
phoneEl.classList.remove('dragging');
|
||||||
|
});
|
||||||
|
|
||||||
|
window.addEventListener('message', function(event) {
|
||||||
|
const d = event.data;
|
||||||
|
if (!d) return;
|
||||||
|
|
||||||
|
if (d.action === 'toggle') {
|
||||||
|
const phone = document.getElementById('phone');
|
||||||
|
if (d.open) {
|
||||||
|
phone.classList.remove('hidden');
|
||||||
|
updateTime();
|
||||||
|
} else {
|
||||||
|
phone.classList.add('hidden');
|
||||||
|
}
|
||||||
|
} else if (d.action === 'receiveMessage') {
|
||||||
|
appendMessage(d.from, d.message, 'from');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('closeBtn').addEventListener('click', function() {
|
||||||
|
fetch(`https://${GetParentResourceName()}/close`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({})
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('messagesApp').addEventListener('click', function() {
|
||||||
|
document.getElementById('home').style.display = 'none';
|
||||||
|
document.getElementById('messages').style.display = 'flex';
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('sendBtn').addEventListener('click', sendMessage);
|
||||||
|
|
||||||
|
document.getElementById('msgInput').addEventListener('keydown', function(e) {
|
||||||
|
if (e.key === 'Enter') sendMessage();
|
||||||
|
});
|
||||||
|
|
||||||
|
function sendMessage() {
|
||||||
|
const input = document.getElementById('msgInput');
|
||||||
|
const v = input.value.trim();
|
||||||
|
if (!v) return;
|
||||||
|
|
||||||
|
appendMessage('You', v, 'me');
|
||||||
|
|
||||||
|
fetch(`https://${GetParentResourceName()}/sendMessage`, {
|
||||||
|
method: 'POST',
|
||||||
|
headers: { 'Content-Type': 'application/json' },
|
||||||
|
body: JSON.stringify({ message: v })
|
||||||
|
}).then(res => res.json()).then(() => {
|
||||||
|
input.value = '';
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function appendMessage(sender, text, cls) {
|
||||||
|
const list = document.getElementById('messagesList');
|
||||||
|
const el = document.createElement('div');
|
||||||
|
el.className = 'msg ' + (cls || '');
|
||||||
|
el.innerText = sender + ': ' + text;
|
||||||
|
list.appendChild(el);
|
||||||
|
list.scrollTop = list.scrollHeight;
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateTime() {
|
||||||
|
const t = document.getElementById('time');
|
||||||
|
const now = new Date();
|
||||||
|
const hh = String(now.getHours()).padStart(2, '0');
|
||||||
|
const mm = String(now.getMinutes()).padStart(2, '0');
|
||||||
|
t.innerText = hh + ':' + mm;
|
||||||
|
}
|
||||||
|
|
||||||
|
function GetParentResourceName() {
|
||||||
|
try {
|
||||||
|
return new URL(document.location).searchParams.get('parent') || window.parentResource || 'gb-phone';
|
||||||
|
} catch (e) {
|
||||||
|
return 'gb-phone';
|
||||||
|
}
|
||||||
|
}
|
||||||