zizo007's picture
حوله الى تطبيق سطح مكتب بواجهة مستخدم سهلة
d5fc852 verified
Raw
History Blame Contribute Delete
12.2 kB
// Desktop application script for SpotSync Alpha
// Tab switching functionality for code preview
function showTab(tabName) {
// Hide all tabs
document.getElementById('main-tab')?.classList.add('hidden');
document.getElementById('watcher-tab')?.classList.add('hidden');
document.getElementById('executor-tab')?.classList.add('hidden');
document.getElementById('models-tab')?.classList.add('hidden');
document.getElementById('security-tab')?.classList.add('hidden');
// Show selected tab
document.getElementById(`${tabName}-tab`)?.classList.remove('hidden');
// Update active tab button styles
const tabButtons = document.querySelectorAll('[onclick^="showTab"]');
tabButtons.forEach(button => {
if (button.textContent.includes(tabName)) {
button.classList.remove('text-gray-400', 'hover:text-gray-200');
button.classList.add('border-cyan-500', 'text-cyan-300');
button.classList.add('tab-active');
} else {
button.classList.remove('border-cyan-500', 'text-cyan-300', 'tab-active');
button.classList.add('text-gray-400', 'hover:text-gray-200');
}
});
}
// Copy code to clipboard
function copyCode() {
const activeTab = document.querySelector('#code-container > pre:not(.hidden)');
if (!activeTab) return;
const codeText = activeTab.textContent;
// Use Electron's clipboard API if available
if (typeof require !== 'undefined') {
const { clipboard } = require('electron');
clipboard.writeText(codeText);
showDesktopNotification('Code copied to clipboard');
} else {
navigator.clipboard.writeText(codeText).then(() => {
showDesktopNotification('Code copied to clipboard');
});
}
}
// Show desktop notification
function showDesktopNotification(message, type = 'info') {
// Create notification element
const notification = document.createElement('div');
notification.className = 'tray-notification desktop-fade-in';
const icon = type === 'success' ? 'check-circle' : type === 'error' ? 'alert-circle' : 'info';
const color = type === 'success' ? 'text-green-400' : type === 'error' ? 'text-red-400' : 'text-cyan-400';
notification.innerHTML = `
<div class="flex items-start gap-3">
<i data-feather="${icon}" class="w-5 h-5 ${color}"></i>
<div class="flex-1">
<p class="text-sm font-medium text-gray-100">${message}</p>
<p class="text-xs text-gray-400 mt-1">Just now</p>
</div>
<button onclick="this.parentElement.parentElement.remove()" class="text-gray-400 hover:text-gray-200">
<i data-feather="x" class="w-4 h-4"></i>
</button>
</div>
`;
document.body.appendChild(notification);
feather.replace();
// Show notification
setTimeout(() => notification.classList.add('show'), 10);
// Auto remove after 5 seconds
setTimeout(() => {
if (notification.parentElement) {
notification.classList.remove('show');
setTimeout(() => {
if (notification.parentElement) {
notification.remove();
}
}, 300);
}
}, 5000);
}
// Simulate live trade data
function simulateLiveTrades() {
const tradeFeed = document.getElementById('trade-feed');
if (!tradeFeed) return;
const trades = [
{ symbol: 'BTCUSDT', side: 'BUY', quantity: 0.05, price: '64320.50', time: new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) },
{ symbol: 'ETHUSDT', side: 'SELL', quantity: 1.20, price: '3415.75', time: new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) },
{ symbol: 'SOLUSDT', side: 'BUY', quantity: 12.50, price: '185.30', time: new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) },
{ symbol: 'ADAUSDT', side: 'BUY', quantity: 500, price: '0.6420', time: new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) },
{ symbol: 'BNBUSDT', side: 'SELL', quantity: 3.20, price: '420.10', time: new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}) }
];
const trade = trades[Math.floor(Math.random() * trades.length)];
const sideClass = trade.side === 'BUY' ? 'text-green-400' : 'text-red-400';
const sideIcon = trade.side === 'BUY' ? 'trending-up' : 'trending-down';
const tradeElement = document.createElement('div');
tradeElement.className = 'flex items-center justify-between p-3 bg-gray-800/50 rounded-lg desktop-fade-in';
tradeElement.innerHTML = `
<div class="flex items-center gap-3">
<i data-feather="${sideIcon}" class="w-4 h-4 ${sideClass}"></i>
<span class="font-semibold">${trade.symbol}</span>
<span class="text-gray-400">${trade.quantity} @ ${trade.price}</span>
</div>
<span class="text-sm text-gray-400">${trade.time}</span>
`;
if (tradeFeed.children.length >= 5) {
tradeFeed.removeChild(tradeFeed.lastChild);
}
tradeFeed.insertBefore(tradeElement, tradeFeed.firstChild);
feather.replace();
}
// Update system metrics periodically
function updateMetrics() {
const metrics = {
'uptime': '99.8%',
'followers': '3',
'trades': `${Math.floor(Math.random() * 10 + 40)}`,
'success': `${(Math.random() * 2 + 97.5).toFixed(1)}%`
};
for (const [key, value] of Object.entries(metrics)) {
const element = document.getElementById(`metric-${key}`);
if (element) {
element.textContent = value;
}
}
}
// Toggle engine status
function toggleEngineStatus() {
const button = document.querySelector('button:has(i[data-feather="pause"])');
const statusLight = document.querySelector('.relative .w-3.h-3');
if (button.innerHTML.includes('Pause')) {
button.innerHTML = '<i data-feather="play" class="w-3 h-3"></i> Start Engine';
if (statusLight) {
statusLight.classList.remove('bg-green-500');
statusLight.classList.add('bg-yellow-500');
}
showDesktopNotification('Trading engine paused', 'info');
} else {
button.innerHTML = '<i data-feather="pause" class="w-3 h-3"></i> Pause Engine';
if (statusLight) {
statusLight.classList.remove('bg-yellow-500');
statusLight.classList.add('bg-green-500');
}
showDesktopNotification('Trading engine started', 'success');
}
feather.replace();
}
// Export logs function
function exportLogs() {
showDesktopNotification('Exporting trade logs to CSV...', 'info');
// Simulate export process
setTimeout(() => {
showDesktopNotification('Logs exported successfully to Downloads folder', 'success');
}, 1500);
}
// Add new follower
function addFollower() {
showDesktopNotification('Opening follower configuration wizard...', 'info');
// In a real app, this would open a modal or new window
setTimeout(() => {
const followers = parseInt(document.getElementById('metric-followers').textContent);
document.getElementById('metric-followers').textContent = followers + 1;
showDesktopNotification('New follower added successfully', 'success');
}, 1000);
}
// Initialize desktop context menu
function initContextMenu() {
document.addEventListener('contextmenu', function(e) {
e.preventDefault();
// Remove existing context menu
const existingMenu = document.getElementById('context-menu');
if (existingMenu) {
existingMenu.remove();
}
// Create new context menu
const contextMenu = document.createElement('div');
contextMenu.id = 'context-menu';
contextMenu.className = 'context-menu';
contextMenu.style.position = 'fixed';
contextMenu.style.left = `${e.pageX}px`;
contextMenu.style.top = `${e.pageY}px`;
// Menu items based on target
const menuItems = [
{ label: 'Copy', icon: 'copy', action: () => copyCode() },
{ label: 'Refresh', icon: 'refresh-cw', action: () => window.location.reload() },
{ label: 'Inspect Element', icon: 'code', action: () => {
if (typeof require !== 'undefined') {
const { remote } = require('electron');
remote.getCurrentWindow().webContents.openDevTools();
}
}},
{ label: 'Export Data', icon: 'download', action: () => exportLogs() }
];
menuItems.forEach(item => {
const menuItem = document.createElement('div');
menuItem.className = 'context-menu-item flex items-center gap-2';
menuItem.innerHTML = `
<i data-feather="${item.icon}" class="w-3 h-3"></i>
<span>${item.label}</span>
`;
menuItem.addEventListener('click', () => {
item.action();
contextMenu.remove();
});
contextMenu.appendChild(menuItem);
});
document.body.appendChild(contextMenu);
feather.replace();
// Close menu when clicking elsewhere
document.addEventListener('click', function closeMenu() {
contextMenu.remove();
document.removeEventListener('click', closeMenu);
});
});
}
// Initialize all animations and effects
function initAnimations() {
const elements = document.querySelectorAll('.desktop-fade-in');
elements.forEach((element, index) => {
element.style.animationDelay = `${index * 0.1}s`;
});
}
// Initialize everything when the DOM is loaded
document.addEventListener('DOMContentLoaded', function() {
// Initialize Feather icons
feather.replace();
// Initialize components
initAnimations();
initContextMenu();
// Set up intervals for dynamic updates
setInterval(simulateLiveTrades, 5000);
setInterval(updateMetrics, 3000);
// Start with first tab active
showTab('main');
// Add event listeners for desktop buttons
document.querySelector('button:has(i[data-feather="play"])')?.addEventListener('click', toggleEngineStatus);
document.querySelector('button:has(i[data-feather="user-plus"])')?.addEventListener('click', addFollower);
document.querySelector('button:has(i[data-feather="download"])')?.addEventListener('click', exportLogs);
// Add keyboard shortcuts for desktop
document.addEventListener('keydown', function(e) {
// Ctrl/Cmd + 1-5 to switch tabs
if ((e.ctrlKey || e.metaKey) && e.key >= '1' && e.key <= '5') {
const tabNames = ['main', 'watcher', 'executor', 'models', 'security'];
const index = parseInt(e.key) - 1;
if (tabNames[index]) {
showTab(tabNames[index]);
e.preventDefault();
}
}
// Ctrl/Cmd + E to toggle engine
if ((e.ctrlKey || e.metaKey) && e.key === 'e') {
toggleEngineStatus();
e.preventDefault();
}
// Ctrl/Cmd + N to add follower
if ((e.ctrlKey || e.metaKey) && e.key === 'n') {
addFollower();
e.preventDefault();
}
// Ctrl/Cmd + S to export logs
if ((e.ctrlKey || e.metaKey) && e.key === 's') {
exportLogs();
e.preventDefault();
}
// F12 for dev tools
if (e.key === 'F12') {
if (typeof require !== 'undefined') {
const { remote } = require('electron');
remote.getCurrentWindow().webContents.openDevTools();
e.preventDefault();
}
}
});
// Show welcome notification
setTimeout(() => {
showDesktopNotification('SpotSync Alpha Desktop is running in system tray', 'info');
}, 1000);
});