Redesign UI like Driver Navigator + fix CMD window
UI changes: - Top title bar with logo, app name, and system status LED - Toolbar with 4 icon tabs: Scan, Drivers, Download, System - Scan page with computer SVG illustration, stats, and big SCAN NOW button - Step indicator bar: Scan Devices > Review Drivers > Install Updates - Driver list with per-row progress bars, Download + Install buttons - "Update All Drivers" CTA bar at bottom when outdated drivers found - Windows Update tab with pending/installed sections - System Info tab with resource bars - Footer with About/Help buttons Backend fixes: - Add cmdutil.HiddenCommand() using CREATE_NO_WINDOW (0x08000000) - All PowerShell subprocesses now run without visible console window - Build with -ldflags "-H windowsgui" to hide main CMD window Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
16
internal/cmdutil/cmdutil.go
Normal file
16
internal/cmdutil/cmdutil.go
Normal file
@@ -0,0 +1,16 @@
|
||||
package cmdutil
|
||||
|
||||
import (
|
||||
"os/exec"
|
||||
"syscall"
|
||||
)
|
||||
|
||||
// HiddenCommand creates an exec.Cmd that runs without showing a console window.
|
||||
// This prevents PowerShell/cmd flashing when the app runs as a GUI application.
|
||||
func HiddenCommand(name string, args ...string) *exec.Cmd {
|
||||
cmd := exec.Command(name, args...)
|
||||
cmd.SysProcAttr = &syscall.SysProcAttr{
|
||||
CreationFlags: 0x08000000, // CREATE_NO_WINDOW
|
||||
}
|
||||
return cmd
|
||||
}
|
||||
@@ -2,9 +2,10 @@ package drivers
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mumur/driver-booster/internal/cmdutil"
|
||||
)
|
||||
|
||||
type Driver struct {
|
||||
@@ -63,7 +64,7 @@ func (s *Scanner) enumDriversPnP() []Driver {
|
||||
psScript := `
|
||||
Get-CimInstance Win32_PnPSignedDriver | Where-Object { $_.DeviceName -ne $null } | Select-Object -First 100 DeviceName, DeviceClass, Manufacturer, DriverVersion, DriverDate, InfName, IsSigned, Status | ConvertTo-Json -Compress
|
||||
`
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
out, err := cmdutil.HiddenCommand("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
if err != nil {
|
||||
return []Driver{}
|
||||
}
|
||||
|
||||
@@ -2,11 +2,12 @@ package sysinfo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os/exec"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"unsafe"
|
||||
|
||||
"github.com/mumur/driver-booster/internal/cmdutil"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -117,7 +118,7 @@ func getComputerName() string {
|
||||
}
|
||||
|
||||
func getCPUName() string {
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command",
|
||||
out, err := cmdutil.HiddenCommand("powershell", "-NoProfile", "-Command",
|
||||
"(Get-CimInstance Win32_Processor).Name").Output()
|
||||
if err != nil {
|
||||
return "Unknown CPU"
|
||||
@@ -126,7 +127,7 @@ func getCPUName() string {
|
||||
}
|
||||
|
||||
func getWindowsProductName() string {
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command",
|
||||
out, err := cmdutil.HiddenCommand("powershell", "-NoProfile", "-Command",
|
||||
"(Get-CimInstance Win32_OperatingSystem).Caption").Output()
|
||||
if err != nil {
|
||||
return "Windows"
|
||||
|
||||
@@ -2,8 +2,9 @@ package winupdate
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"os/exec"
|
||||
"time"
|
||||
|
||||
"github.com/mumur/driver-booster/internal/cmdutil"
|
||||
)
|
||||
|
||||
type Update struct {
|
||||
@@ -101,7 +102,7 @@ try {
|
||||
Pending = $pending
|
||||
} | ConvertTo-Json -Depth 3 -Compress
|
||||
`
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
out, err := cmdutil.HiddenCommand("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
if err != nil {
|
||||
result.Error = "Failed to check updates: " + err.Error()
|
||||
result.CheckTime = time.Since(start).Round(time.Millisecond).String()
|
||||
@@ -193,7 +194,7 @@ if ($ToInstall.Count -gt 0) {
|
||||
Write-Output "No updates to install."
|
||||
}
|
||||
`
|
||||
out, err := exec.Command("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
out, err := cmdutil.HiddenCommand("powershell", "-NoProfile", "-Command", psScript).Output()
|
||||
if err != nil {
|
||||
return InstallResult{
|
||||
Success: false,
|
||||
|
||||
406
ui/app.js
406
ui/app.js
@@ -1,307 +1,266 @@
|
||||
/* ============================================================
|
||||
Driver Booster Pro - Application Logic
|
||||
Driver Navigator Style: tabs, driver rows, action buttons
|
||||
============================================================ */
|
||||
|
||||
const App = {
|
||||
state: {
|
||||
sysInfo: null,
|
||||
drivers: null,
|
||||
updates: null,
|
||||
},
|
||||
var App = {
|
||||
state: { sysInfo:null, drivers:null, updates:null },
|
||||
|
||||
init() {
|
||||
this.setupNavigation();
|
||||
init: function() {
|
||||
this.setupTabs();
|
||||
this.setupFilters();
|
||||
this.refreshSysInfo();
|
||||
// Re-render Lucide icons after DOM mutations
|
||||
this.refreshIcons();
|
||||
},
|
||||
|
||||
refreshIcons() {
|
||||
if (window.lucide) {
|
||||
lucide.createIcons();
|
||||
}
|
||||
refreshIcons: function() {
|
||||
if (window.lucide) lucide.createIcons();
|
||||
},
|
||||
|
||||
// ---- Navigation ----
|
||||
setupNavigation() {
|
||||
document.querySelectorAll('.nav-item[data-page]').forEach(function(item) {
|
||||
item.addEventListener('click', function() {
|
||||
var page = item.dataset.page;
|
||||
document.querySelectorAll('.nav-item').forEach(function(n) { n.classList.remove('active'); });
|
||||
item.classList.add('active');
|
||||
document.querySelectorAll('.page').forEach(function(p) { p.classList.remove('active'); });
|
||||
var target = document.getElementById('page-' + page);
|
||||
// ---- Tab Navigation ----
|
||||
setupTabs: function() {
|
||||
var self = this;
|
||||
document.querySelectorAll('.toolbar-tab').forEach(function(tab) {
|
||||
tab.addEventListener('click', function() {
|
||||
var id = tab.dataset.tab;
|
||||
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
||||
tab.classList.add('active');
|
||||
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
||||
var target = document.getElementById('tab-' + id);
|
||||
if (target) target.classList.add('active');
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
// ---- Filters ----
|
||||
setupFilters() {
|
||||
// ---- Filter Pills ----
|
||||
setupFilters: function() {
|
||||
var self = this;
|
||||
document.querySelectorAll('.filter-btn').forEach(function(btn) {
|
||||
document.querySelectorAll('.pill').forEach(function(btn) {
|
||||
btn.addEventListener('click', function() {
|
||||
document.querySelectorAll('.filter-btn').forEach(function(b) { b.classList.remove('active'); });
|
||||
document.querySelectorAll('.pill').forEach(function(b){ b.classList.remove('active'); });
|
||||
btn.classList.add('active');
|
||||
self.filterDrivers(btn.dataset.filter);
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
filterDrivers(filter) {
|
||||
document.querySelectorAll('.driver-card').forEach(function(card) {
|
||||
var show = filter === 'all' ||
|
||||
(filter === 'outdated' && card.classList.contains('outdated')) ||
|
||||
(filter === 'error' && card.classList.contains('error')) ||
|
||||
(filter === 'signed' && card.dataset.signed === 'true');
|
||||
card.style.display = show ? '' : 'none';
|
||||
filterDrivers: function(f) {
|
||||
document.querySelectorAll('.drv-row').forEach(function(row) {
|
||||
var show = f === 'all' ||
|
||||
(f === 'outdated' && row.classList.contains('outdated')) ||
|
||||
(f === 'error' && row.classList.contains('error')) ||
|
||||
(f === 'signed' && row.dataset.signed === 'true');
|
||||
row.style.display = show ? '' : 'none';
|
||||
});
|
||||
},
|
||||
|
||||
// ---- Loading ----
|
||||
showLoading(text) {
|
||||
showLoading: function(text) {
|
||||
document.getElementById('loading-text').textContent = text;
|
||||
document.getElementById('loading-overlay').style.display = 'flex';
|
||||
this.refreshIcons();
|
||||
},
|
||||
|
||||
hideLoading() {
|
||||
hideLoading: function() {
|
||||
document.getElementById('loading-overlay').style.display = 'none';
|
||||
},
|
||||
|
||||
// ---- System Info ----
|
||||
async refreshSysInfo() {
|
||||
refreshSysInfo: function() {
|
||||
var self = this;
|
||||
this.showLoading('Collecting system information...');
|
||||
try {
|
||||
var res = await fetch('/api/sysinfo');
|
||||
var info = await res.json();
|
||||
this.state.sysInfo = info;
|
||||
this.renderSysInfo(info);
|
||||
this.updateDashboardResources(info);
|
||||
} catch (e) {
|
||||
console.error('Failed to get sysinfo:', e);
|
||||
}
|
||||
this.hideLoading();
|
||||
fetch('/api/sysinfo').then(function(r){ return r.json(); }).then(function(info) {
|
||||
self.state.sysInfo = info;
|
||||
self.renderSysInfo(info);
|
||||
self.hideLoading();
|
||||
}).catch(function(e) {
|
||||
console.error(e);
|
||||
self.hideLoading();
|
||||
});
|
||||
},
|
||||
|
||||
renderSysInfo(info) {
|
||||
this.setText('sys-name', info.computerName);
|
||||
this.setText('sys-os', info.osName);
|
||||
this.setText('sys-version', info.osVersion);
|
||||
this.setText('sys-build', info.osBuild);
|
||||
this.setText('sys-arch', info.architecture);
|
||||
this.setText('sys-cpu', info.cpuName);
|
||||
this.setText('sys-cores', info.cpuCores);
|
||||
this.setText('sys-ram-total', info.totalRam);
|
||||
this.setText('sys-ram-used', info.usedRam);
|
||||
this.setText('sys-ram-free', info.freeRam);
|
||||
this.setText('sys-ram-pct', (info.ramPercent || 0) + '%');
|
||||
this.setText('sys-disk-total', info.diskTotal);
|
||||
this.setText('sys-disk-used', info.diskUsed);
|
||||
this.setText('sys-disk-free', info.diskFree);
|
||||
this.setText('sys-disk-pct', (info.diskPercent || 0) + '%');
|
||||
renderSysInfo: function(d) {
|
||||
this.set('sys-name', d.computerName);
|
||||
this.set('sys-os', d.osName);
|
||||
this.set('sys-version', d.osVersion);
|
||||
this.set('sys-build', d.osBuild);
|
||||
this.set('sys-arch', d.architecture);
|
||||
this.set('sys-cpu', d.cpuName);
|
||||
this.set('sys-cores', d.cpuCores);
|
||||
this.set('sys-ram-total', d.totalRam);
|
||||
this.set('sys-ram-used', d.usedRam);
|
||||
this.set('sys-ram-free', d.freeRam);
|
||||
this.set('sys-ram-pct', (d.ramPercent||0)+'%');
|
||||
this.set('sys-disk-total', d.diskTotal);
|
||||
this.set('sys-disk-used', d.diskUsed);
|
||||
this.set('sys-disk-free', d.diskFree);
|
||||
this.set('sys-disk-pct', (d.diskPercent||0)+'%');
|
||||
var rb = document.getElementById('sys-ram-bar');
|
||||
var db = document.getElementById('sys-disk-bar');
|
||||
if(rb) rb.style.width = (d.ramPercent||0)+'%';
|
||||
if(db) db.style.width = (d.diskPercent||0)+'%';
|
||||
},
|
||||
|
||||
updateDashboardResources(info) {
|
||||
this.setText('dash-ram-percent', (info.ramPercent || 0) + '%');
|
||||
this.setText('dash-ram-detail', (info.usedRam || '--') + ' / ' + (info.totalRam || '--'));
|
||||
document.getElementById('dash-ram-bar').style.width = (info.ramPercent || 0) + '%';
|
||||
this.setText('dash-disk-detail', (info.diskUsed || '--') + ' / ' + (info.diskTotal || '--'));
|
||||
document.getElementById('dash-disk-bar').style.width = (info.diskPercent || 0) + '%';
|
||||
|
||||
// Warn color for high usage
|
||||
var ramBar = document.getElementById('dash-ram-bar');
|
||||
var diskBar = document.getElementById('dash-disk-bar');
|
||||
if (info.ramPercent > 80) {
|
||||
ramBar.style.background = 'linear-gradient(90deg, #f59e0b, #ef4444)';
|
||||
} else {
|
||||
ramBar.style.background = '';
|
||||
}
|
||||
if (info.diskPercent > 85) {
|
||||
diskBar.style.background = 'linear-gradient(90deg, #f59e0b, #ef4444)';
|
||||
} else {
|
||||
diskBar.style.background = '';
|
||||
}
|
||||
},
|
||||
|
||||
// ---- Drivers ----
|
||||
async scanDrivers() {
|
||||
// ---- Driver Scan ----
|
||||
scanDrivers: function() {
|
||||
var self = this;
|
||||
this.showLoading('Scanning drivers... This may take a moment.');
|
||||
try {
|
||||
var res = await fetch('/api/drivers/scan');
|
||||
var result = await res.json();
|
||||
this.state.drivers = result;
|
||||
this.renderDrivers(result);
|
||||
this.updateDashboardDrivers(result);
|
||||
} catch (e) {
|
||||
console.error('Failed to scan drivers:', e);
|
||||
}
|
||||
this.hideLoading();
|
||||
// Switch to drivers tab
|
||||
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
||||
document.querySelector('[data-tab="drivers"]').classList.add('active');
|
||||
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
||||
document.getElementById('tab-drivers').classList.add('active');
|
||||
|
||||
// Update steps
|
||||
this.setStep(2);
|
||||
|
||||
fetch('/api/drivers/scan').then(function(r){ return r.json(); }).then(function(result) {
|
||||
self.state.drivers = result;
|
||||
self.renderDrivers(result);
|
||||
self.updateScanStats(result);
|
||||
self.hideLoading();
|
||||
}).catch(function(e) {
|
||||
console.error(e);
|
||||
self.hideLoading();
|
||||
});
|
||||
},
|
||||
|
||||
renderDrivers(result) {
|
||||
document.getElementById('driver-summary').style.display = 'flex';
|
||||
document.getElementById('driver-filters').style.display = 'flex';
|
||||
this.setText('drv-total', result.totalCount);
|
||||
this.setText('drv-outdated', result.outdatedCount);
|
||||
this.setText('drv-errors', result.errorCount);
|
||||
this.setText('drv-time', result.scanTime);
|
||||
updateScanStats: function(r) {
|
||||
this.set('scan-stat-total', r.totalCount);
|
||||
this.set('scan-stat-outdated', r.outdatedCount);
|
||||
this.set('scan-stat-errors', r.errorCount);
|
||||
},
|
||||
|
||||
renderDrivers: function(result) {
|
||||
document.getElementById('driver-result-count').style.display = 'block';
|
||||
document.getElementById('driver-filter-strip').style.display = 'flex';
|
||||
this.set('drv-total-2', result.totalCount);
|
||||
this.set('drv-outdated-2', result.outdatedCount);
|
||||
this.set('drv-time-2', result.scanTime);
|
||||
|
||||
var list = document.getElementById('driver-list');
|
||||
if (!result.drivers || result.drivers.length === 0) {
|
||||
list.innerHTML =
|
||||
'<div class="empty-state">' +
|
||||
'<div class="empty-icon"><i data-lucide="search-x"></i></div>' +
|
||||
'<h3>No Drivers Found</h3>' +
|
||||
'<p>No driver information was returned.</p>' +
|
||||
'</div>';
|
||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="search-x"></i><p>No drivers found</p></div>';
|
||||
this.refreshIcons();
|
||||
return;
|
||||
}
|
||||
|
||||
var self = this;
|
||||
list.innerHTML = result.drivers.map(function(d) {
|
||||
var classes = ['driver-card'];
|
||||
if (d.needsUpdate) classes.push('outdated');
|
||||
if (d.status === 'Error' || d.status === 'Degraded') classes.push('error');
|
||||
var cls = ['drv-row'];
|
||||
if (d.needsUpdate) cls.push('outdated');
|
||||
if (d.status === 'Error' || d.status === 'Degraded') cls.push('error');
|
||||
|
||||
var iconName = self.getClassIconName(d.deviceClass);
|
||||
var icon = self.driverIcon(d.deviceClass);
|
||||
var barClass = d.needsUpdate ? 'warn' : (d.status === 'Error' ? 'err' : 'ok');
|
||||
|
||||
var badges = '';
|
||||
if (d.isSigned) {
|
||||
badges += '<span class="badge badge-signed"><i data-lucide="shield-check"></i> Signed</span>';
|
||||
} else {
|
||||
badges += '<span class="badge badge-unsigned"><i data-lucide="shield-x"></i> Unsigned</span>';
|
||||
}
|
||||
if (d.needsUpdate) {
|
||||
badges += '<span class="badge badge-outdated"><i data-lucide="clock"></i> Outdated</span>';
|
||||
} else {
|
||||
badges += '<span class="badge badge-ok"><i data-lucide="circle-check"></i> OK</span>';
|
||||
}
|
||||
var signBadge = d.isSigned
|
||||
? '<span class="drv-badge signed"><i data-lucide="shield-check"></i> Signed</span>'
|
||||
: '<span class="drv-badge unsigned"><i data-lucide="shield-x"></i></span>';
|
||||
|
||||
return '<div class="' + classes.join(' ') + '" data-signed="' + d.isSigned + '">' +
|
||||
'<div class="driver-class-icon"><i data-lucide="' + iconName + '"></i></div>' +
|
||||
'<div class="driver-info">' +
|
||||
'<div class="driver-name">' + self.esc(d.deviceName) + '</div>' +
|
||||
'<div class="driver-meta">' +
|
||||
self.esc(d.manufacturer || 'Unknown') +
|
||||
' <span class="driver-meta-sep">·</span> v' + self.esc(d.driverVersion || '?') +
|
||||
' <span class="driver-meta-sep">·</span> ' + self.esc(d.driverDate) +
|
||||
var actionBtn = d.needsUpdate
|
||||
? '<button class="drv-btn install-btn"><i data-lucide="download"></i> Download</button>' +
|
||||
'<button class="drv-btn"><i data-lucide="play"></i> Install</button>'
|
||||
: '<button class="drv-btn installed-btn"><i data-lucide="circle-check"></i> Up to date</button>';
|
||||
|
||||
return '<div class="' + cls.join(' ') + '" data-signed="' + d.isSigned + '">' +
|
||||
'<div class="drv-icon"><i data-lucide="' + icon + '"></i></div>' +
|
||||
'<div class="drv-info">' +
|
||||
'<div class="drv-name">' + self.esc(d.deviceName) + '</div>' +
|
||||
'<div class="drv-meta">' + self.esc(d.manufacturer||'Unknown') + ' · v' + self.esc(d.driverVersion||'?') + ' · ' + self.esc(d.driverDate) + ' ' + signBadge + '</div>' +
|
||||
'</div>' +
|
||||
'<div class="drv-progress">' +
|
||||
'<div class="drv-bar"><div class="drv-bar-fill ' + barClass + '"></div></div>' +
|
||||
'</div>' +
|
||||
'<div class="driver-badges">' + badges + '</div>' +
|
||||
'<div class="drv-actions">' + actionBtn + '</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
|
||||
// Show CTA if there are outdated drivers
|
||||
var cta = document.getElementById('cta-update-all');
|
||||
if (result.outdatedCount > 0) {
|
||||
cta.style.display = 'flex';
|
||||
this.set('cta-count', result.outdatedCount);
|
||||
} else {
|
||||
cta.style.display = 'none';
|
||||
}
|
||||
|
||||
this.refreshIcons();
|
||||
},
|
||||
|
||||
updateDashboardDrivers(result) {
|
||||
this.setText('dash-driver-count', result.totalCount);
|
||||
this.setText('dash-outdated-count', result.outdatedCount);
|
||||
},
|
||||
|
||||
getClassIconName(cls) {
|
||||
driverIcon: function(cls) {
|
||||
if (!cls) return 'package';
|
||||
var upper = cls.toUpperCase();
|
||||
var map = {
|
||||
'DISPLAY': 'monitor',
|
||||
'MEDIA': 'volume-2',
|
||||
'AUDIO': 'volume-2',
|
||||
'SOUND': 'volume-2',
|
||||
'NET': 'wifi',
|
||||
'NETWORK': 'wifi',
|
||||
'USB': 'usb',
|
||||
'HID': 'mouse',
|
||||
'KEYBOARD': 'keyboard',
|
||||
'DISK': 'hard-drive',
|
||||
'STORAGE': 'hard-drive',
|
||||
'PROCESSOR': 'cpu',
|
||||
'SYSTEM': 'settings',
|
||||
'BLUETOOTH': 'bluetooth',
|
||||
'CAMERA': 'camera',
|
||||
'IMAGE': 'camera',
|
||||
'PRINT': 'printer',
|
||||
'BATTERY': 'battery-charging',
|
||||
'BIOMETRIC': 'fingerprint',
|
||||
'FIRMWARE': 'circuit-board',
|
||||
'SECURITY': 'shield',
|
||||
'SENSOR': 'thermometer',
|
||||
var u = cls.toUpperCase();
|
||||
var m = {
|
||||
'DISPLAY':'monitor','MEDIA':'volume-2','AUDIO':'volume-2','SOUND':'volume-2',
|
||||
'NET':'wifi','NETWORK':'wifi','USB':'usb','HID':'mouse','KEYBOARD':'keyboard',
|
||||
'DISK':'hard-drive','STORAGE':'hard-drive','PROCESSOR':'cpu','SYSTEM':'settings',
|
||||
'BLUETOOTH':'bluetooth','CAMERA':'camera','IMAGE':'camera','PRINT':'printer',
|
||||
'BATTERY':'battery-charging','FIRMWARE':'circuit-board','SECURITY':'shield',
|
||||
'SENSOR':'thermometer'
|
||||
};
|
||||
for (var key in map) {
|
||||
if (upper.indexOf(key) !== -1) return map[key];
|
||||
}
|
||||
for (var k in m) { if (u.indexOf(k) !== -1) return m[k]; }
|
||||
return 'package';
|
||||
},
|
||||
|
||||
// ---- Updates ----
|
||||
async checkUpdates() {
|
||||
// ---- Windows Update ----
|
||||
checkUpdates: function() {
|
||||
var self = this;
|
||||
this.showLoading('Checking for Windows updates...');
|
||||
try {
|
||||
var res = await fetch('/api/updates/check');
|
||||
var result = await res.json();
|
||||
this.state.updates = result;
|
||||
this.renderUpdates(result);
|
||||
this.setText('dash-update-count', result.pendingCount);
|
||||
} catch (e) {
|
||||
console.error('Failed to check updates:', e);
|
||||
}
|
||||
this.hideLoading();
|
||||
// Switch to updates tab
|
||||
document.querySelectorAll('.toolbar-tab').forEach(function(t){ t.classList.remove('active'); });
|
||||
document.querySelector('[data-tab="updates"]').classList.add('active');
|
||||
document.querySelectorAll('.tab-page').forEach(function(p){ p.classList.remove('active'); });
|
||||
document.getElementById('tab-updates').classList.add('active');
|
||||
|
||||
fetch('/api/updates/check').then(function(r){ return r.json(); }).then(function(result) {
|
||||
self.state.updates = result;
|
||||
self.renderUpdates(result);
|
||||
self.hideLoading();
|
||||
}).catch(function(e) {
|
||||
console.error(e);
|
||||
self.hideLoading();
|
||||
});
|
||||
},
|
||||
|
||||
renderUpdates(result) {
|
||||
renderUpdates: function(result) {
|
||||
var list = document.getElementById('update-list');
|
||||
|
||||
if (result.error) {
|
||||
list.innerHTML =
|
||||
'<div class="empty-state">' +
|
||||
'<div class="empty-icon"><i data-lucide="alert-circle"></i></div>' +
|
||||
'<h3>Error</h3>' +
|
||||
'<p style="color:var(--danger)">' + this.esc(result.error) + '</p>' +
|
||||
'</div>';
|
||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="alert-circle"></i><p style="color:var(--red)">' + this.esc(result.error) + '</p></div>';
|
||||
this.refreshIcons();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!result.updates || result.updates.length === 0) {
|
||||
list.innerHTML =
|
||||
'<div class="empty-state">' +
|
||||
'<div class="empty-icon"><i data-lucide="circle-check"></i></div>' +
|
||||
'<h3>All Up to Date</h3>' +
|
||||
'<p>Your system is fully updated.</p>' +
|
||||
'</div>';
|
||||
list.innerHTML = '<div class="placeholder-msg"><i data-lucide="circle-check"></i><p>Your system is fully up to date!</p></div>';
|
||||
this.refreshIcons();
|
||||
return;
|
||||
}
|
||||
|
||||
var pending = result.updates.filter(function(u) { return !u.isInstalled; });
|
||||
var installed = result.updates.filter(function(u) { return u.isInstalled; });
|
||||
var pending = result.updates.filter(function(u){return !u.isInstalled;});
|
||||
var installed = result.updates.filter(function(u){return u.isInstalled;});
|
||||
var self = this;
|
||||
var html = '';
|
||||
|
||||
if (pending.length > 0) {
|
||||
html += '<div class="update-section-title pending"><i data-lucide="download"></i> Pending Updates (' + pending.length + ')</div>';
|
||||
html += '<div class="upd-section pend"><i data-lucide="download"></i> Pending (' + pending.length + ')</div>';
|
||||
html += pending.map(function(u) {
|
||||
return '<div class="update-card pending">' +
|
||||
'<div class="update-title">' + self.esc(u.title) + '</div>' +
|
||||
'<div class="update-meta">' +
|
||||
(u.kbArticle ? '<span class="update-tag"><i data-lucide="file-text"></i> ' + self.esc(u.kbArticle) + '</span>' : '') +
|
||||
(u.category ? '<span class="update-tag"><i data-lucide="folder"></i> ' + self.esc(u.category) + '</span>' : '') +
|
||||
(u.size ? '<span class="update-tag"><i data-lucide="hard-drive"></i> ' + self.esc(u.size) + '</span>' : '') +
|
||||
(u.severity && u.severity !== 'Unspecified' ? '<span class="update-tag"><i data-lucide="alert-triangle"></i> ' + self.esc(u.severity) + '</span>' : '') +
|
||||
(u.isMandatory ? '<span class="update-tag" style="color:var(--danger)"><i data-lucide="alert-circle"></i> Mandatory</span>' : '') +
|
||||
return '<div class="upd-row pending">' +
|
||||
'<div class="upd-title">' + self.esc(u.title) + '</div>' +
|
||||
'<div class="upd-meta">' +
|
||||
(u.kbArticle ? '<span class="upd-tag"><i data-lucide="file-text"></i> '+self.esc(u.kbArticle)+'</span>' : '') +
|
||||
(u.category ? '<span class="upd-tag"><i data-lucide="folder"></i> '+self.esc(u.category)+'</span>' : '') +
|
||||
(u.size ? '<span class="upd-tag"><i data-lucide="hard-drive"></i> '+self.esc(u.size)+'</span>' : '') +
|
||||
(u.severity && u.severity !== 'Unspecified' ? '<span class="upd-tag"><i data-lucide="alert-triangle"></i> '+self.esc(u.severity)+'</span>' : '') +
|
||||
'</div>' +
|
||||
'</div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
if (installed.length > 0) {
|
||||
html += '<div class="update-section-title installed"><i data-lucide="check-circle"></i> Recently Installed (' + installed.length + ')</div>';
|
||||
html += '<div class="upd-section inst"><i data-lucide="check-circle"></i> Recently Installed (' + installed.length + ')</div>';
|
||||
html += installed.map(function(u) {
|
||||
return '<div class="update-card installed">' +
|
||||
'<div class="update-title">' + self.esc(u.title) + '</div>' +
|
||||
'</div>';
|
||||
return '<div class="upd-row done"><div class="upd-title">' + self.esc(u.title) + '</div></div>';
|
||||
}).join('');
|
||||
}
|
||||
|
||||
@@ -309,21 +268,28 @@ const App = {
|
||||
this.refreshIcons();
|
||||
},
|
||||
|
||||
// ---- Utility ----
|
||||
setText(id, value) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) el.textContent = (value != null && value !== '') ? value : '--';
|
||||
// ---- Step bar ----
|
||||
setStep: function(n) {
|
||||
for (var i = 1; i <= 3; i++) {
|
||||
var el = document.getElementById('step-' + i);
|
||||
if (!el) continue;
|
||||
el.classList.remove('active', 'done');
|
||||
if (i < n) el.classList.add('done');
|
||||
if (i === n) el.classList.add('active');
|
||||
}
|
||||
},
|
||||
|
||||
esc(str) {
|
||||
if (!str) return '';
|
||||
var div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
// ---- Helpers ----
|
||||
set: function(id, val) {
|
||||
var el = document.getElementById(id);
|
||||
if (el) el.textContent = (val != null && val !== '') ? val : '--';
|
||||
},
|
||||
esc: function(s) {
|
||||
if (!s) return '';
|
||||
var d = document.createElement('div');
|
||||
d.textContent = s;
|
||||
return d.innerHTML;
|
||||
}
|
||||
};
|
||||
|
||||
// Boot
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
App.init();
|
||||
});
|
||||
document.addEventListener('DOMContentLoaded', function() { App.init(); });
|
||||
|
||||
490
ui/index.html
490
ui/index.html
@@ -8,342 +8,257 @@
|
||||
<script src="https://unpkg.com/lucide@latest/dist/umd/lucide.min.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
<!-- Animated background -->
|
||||
<div class="bg-grid"></div>
|
||||
<div class="bg-glow bg-glow-1"></div>
|
||||
<div class="bg-glow bg-glow-2"></div>
|
||||
|
||||
<div class="app">
|
||||
<!-- Sidebar -->
|
||||
<nav class="sidebar">
|
||||
<div class="sidebar-header">
|
||||
<div class="logo">
|
||||
<div class="logo-icon">
|
||||
<!-- Title Bar -->
|
||||
<div class="titlebar">
|
||||
<div class="titlebar-left">
|
||||
<div class="app-logo">
|
||||
<i data-lucide="shield-check"></i>
|
||||
</div>
|
||||
<div class="logo-text-wrap">
|
||||
<span class="logo-text">Driver Booster</span>
|
||||
<span class="logo-sub">System Toolkit</span>
|
||||
<div class="app-title">
|
||||
<span class="app-name">DRIVER BOOSTER</span>
|
||||
<span class="app-edition">PRO</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="titlebar-right">
|
||||
<div class="sys-status" id="sys-status">
|
||||
<div class="status-led"></div>
|
||||
<span>System Protected</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="nav-section-label">Main</div>
|
||||
<ul class="nav-items">
|
||||
<li class="nav-item active" data-page="dashboard">
|
||||
<i data-lucide="layout-dashboard"></i>
|
||||
<span>Dashboard</span>
|
||||
<div class="nav-indicator"></div>
|
||||
</li>
|
||||
<li class="nav-item" data-page="drivers">
|
||||
<!-- Toolbar Tabs -->
|
||||
<div class="toolbar">
|
||||
<button class="toolbar-tab active" data-tab="scan">
|
||||
<div class="tab-icon-wrap scan-icon-wrap">
|
||||
<i data-lucide="scan-search"></i>
|
||||
</div>
|
||||
<span>Scan</span>
|
||||
</button>
|
||||
<button class="toolbar-tab" data-tab="drivers">
|
||||
<div class="tab-icon-wrap drivers-icon-wrap">
|
||||
<i data-lucide="cpu"></i>
|
||||
</div>
|
||||
<span>Drivers</span>
|
||||
<div class="nav-indicator"></div>
|
||||
</li>
|
||||
<li class="nav-item" data-page="updates">
|
||||
</button>
|
||||
<button class="toolbar-tab" data-tab="updates">
|
||||
<div class="tab-icon-wrap updates-icon-wrap">
|
||||
<i data-lucide="download-cloud"></i>
|
||||
<span>Windows Update</span>
|
||||
<div class="nav-indicator"></div>
|
||||
</li>
|
||||
<li class="nav-item" data-page="system">
|
||||
<i data-lucide="monitor"></i>
|
||||
<span>System Info</span>
|
||||
<div class="nav-indicator"></div>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="nav-section-label">Tools</div>
|
||||
<ul class="nav-items">
|
||||
<li class="nav-item" data-page="dashboard" onclick="App.scanDrivers()">
|
||||
<i data-lucide="scan-search"></i>
|
||||
<span>Quick Scan</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<div class="sidebar-footer">
|
||||
<div class="app-status" id="app-status">
|
||||
<div class="status-dot online"></div>
|
||||
<span>System Online</span>
|
||||
</div>
|
||||
<div class="version-badge">v1.0.0</div>
|
||||
<span>Download</span>
|
||||
</button>
|
||||
<button class="toolbar-tab" data-tab="system">
|
||||
<div class="tab-icon-wrap settings-icon-wrap">
|
||||
<i data-lucide="monitor-cog"></i>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<!-- Main Content -->
|
||||
<main class="content">
|
||||
<!-- Dashboard Page -->
|
||||
<div class="page active" id="page-dashboard">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1><i data-lucide="layout-dashboard" class="page-icon"></i> Dashboard</h1>
|
||||
<p class="subtitle">Monitor your system health at a glance</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="icon-btn" onclick="App.refreshSysInfo()" title="Refresh">
|
||||
<i data-lucide="refresh-cw"></i>
|
||||
<span>System</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="stats-grid">
|
||||
<div class="stat-card stat-drivers">
|
||||
<div class="stat-card-bg"></div>
|
||||
<div class="stat-icon">
|
||||
<!-- Content Area -->
|
||||
<div class="content-area">
|
||||
|
||||
<!-- ====== SCAN TAB ====== -->
|
||||
<div class="tab-page active" id="tab-scan">
|
||||
<div class="scan-hero">
|
||||
<div class="scan-illustration">
|
||||
<!-- Computer SVG Illustration -->
|
||||
<svg viewBox="0 0 200 180" class="computer-svg">
|
||||
<defs>
|
||||
<linearGradient id="screen-grad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#1e40af"/>
|
||||
<stop offset="100%" stop-color="#3b82f6"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="body-grad" x1="0" y1="0" x2="0" y2="1">
|
||||
<stop offset="0%" stop-color="#e2e8f0"/>
|
||||
<stop offset="100%" stop-color="#cbd5e1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="shield-grad" x1="0" y1="0" x2="1" y2="1">
|
||||
<stop offset="0%" stop-color="#10b981"/>
|
||||
<stop offset="100%" stop-color="#059669"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<!-- Monitor -->
|
||||
<rect x="30" y="10" width="140" height="100" rx="8" fill="url(#body-grad)" stroke="#94a3b8" stroke-width="2"/>
|
||||
<rect x="38" y="18" width="124" height="76" rx="4" fill="url(#screen-grad)"/>
|
||||
<!-- Screen content lines -->
|
||||
<rect x="50" y="34" width="60" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
||||
<rect x="50" y="44" width="80" height="4" rx="2" fill="rgba(255,255,255,0.2)"/>
|
||||
<rect x="50" y="54" width="45" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
||||
<rect x="50" y="64" width="70" height="4" rx="2" fill="rgba(255,255,255,0.2)"/>
|
||||
<rect x="50" y="74" width="55" height="4" rx="2" fill="rgba(255,255,255,0.3)"/>
|
||||
<!-- Check marks -->
|
||||
<circle cx="46" cy="36" r="3" fill="#10b981"/>
|
||||
<circle cx="46" cy="46" r="3" fill="#10b981"/>
|
||||
<circle cx="46" cy="56" r="3" fill="#10b981"/>
|
||||
<circle cx="46" cy="66" r="3" fill="#f59e0b"/>
|
||||
<circle cx="46" cy="76" r="3" fill="#ef4444"/>
|
||||
<!-- Stand -->
|
||||
<rect x="85" y="110" width="30" height="12" rx="2" fill="#94a3b8"/>
|
||||
<rect x="70" y="120" width="60" height="6" rx="3" fill="#94a3b8"/>
|
||||
<!-- Shield overlay -->
|
||||
<path d="M145 55 L145 35 C145 35 155 30 165 35 C175 30 185 35 185 35 L185 55 C185 70 165 82 165 82 C165 82 145 70 145 55Z" fill="url(#shield-grad)" opacity="0.9"/>
|
||||
<polyline points="157,55 163,62 175,48" fill="none" stroke="white" stroke-width="3" stroke-linecap="round" stroke-linejoin="round"/>
|
||||
</svg>
|
||||
</div>
|
||||
<div class="scan-info">
|
||||
<h2>Scan Your System</h2>
|
||||
<p>Detect outdated, missing, and faulty drivers. Keep your PC running at peak performance.</p>
|
||||
<div class="scan-stats" id="scan-stats">
|
||||
<div class="mini-stat">
|
||||
<i data-lucide="cpu"></i>
|
||||
<span id="scan-stat-total">--</span>
|
||||
<label>Drivers</label>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<span class="stat-value" id="dash-driver-count">--</span>
|
||||
<span class="stat-label">Total Drivers</span>
|
||||
</div>
|
||||
<div class="stat-trend">
|
||||
<i data-lucide="layers"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card stat-outdated">
|
||||
<div class="stat-card-bg"></div>
|
||||
<div class="stat-icon">
|
||||
<div class="mini-stat warn">
|
||||
<i data-lucide="alert-triangle"></i>
|
||||
<span id="scan-stat-outdated">--</span>
|
||||
<label>Outdated</label>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<span class="stat-value" id="dash-outdated-count">--</span>
|
||||
<span class="stat-label">Outdated</span>
|
||||
</div>
|
||||
<div class="stat-trend">
|
||||
<i data-lucide="triangle-alert"></i>
|
||||
<div class="mini-stat danger">
|
||||
<i data-lucide="x-circle"></i>
|
||||
<span id="scan-stat-errors">--</span>
|
||||
<label>Errors</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card stat-updates">
|
||||
<div class="stat-card-bg"></div>
|
||||
<div class="stat-icon">
|
||||
<i data-lucide="download-cloud"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<span class="stat-value" id="dash-update-count">--</span>
|
||||
<span class="stat-label">Pending Updates</span>
|
||||
</div>
|
||||
<div class="stat-trend">
|
||||
<i data-lucide="cloud-download"></i>
|
||||
</div>
|
||||
</div>
|
||||
<div class="stat-card stat-ram">
|
||||
<div class="stat-card-bg"></div>
|
||||
<div class="stat-icon">
|
||||
<i data-lucide="memory-stick"></i>
|
||||
</div>
|
||||
<div class="stat-info">
|
||||
<span class="stat-value" id="dash-ram-percent">--</span>
|
||||
<span class="stat-label">RAM Usage</span>
|
||||
</div>
|
||||
<div class="stat-trend">
|
||||
<i data-lucide="activity"></i>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="dashboard-panels">
|
||||
<div class="panel glass-panel">
|
||||
<div class="panel-header">
|
||||
<div class="panel-title">
|
||||
<i data-lucide="zap"></i>
|
||||
<h3>Quick Actions</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="quick-actions">
|
||||
<button class="action-btn primary" onclick="App.scanDrivers()">
|
||||
<div class="action-btn-icon"><i data-lucide="scan-search"></i></div>
|
||||
<div class="action-btn-text">
|
||||
<span class="action-btn-title">Scan Drivers</span>
|
||||
<span class="action-btn-desc">Detect outdated & missing drivers</span>
|
||||
</div>
|
||||
<i data-lucide="chevron-right" class="action-arrow"></i>
|
||||
</button>
|
||||
<button class="action-btn blue" onclick="App.checkUpdates()">
|
||||
<div class="action-btn-icon"><i data-lucide="cloud-download"></i></div>
|
||||
<div class="action-btn-text">
|
||||
<span class="action-btn-title">Check Updates</span>
|
||||
<span class="action-btn-desc">Search for Windows updates</span>
|
||||
</div>
|
||||
<i data-lucide="chevron-right" class="action-arrow"></i>
|
||||
</button>
|
||||
<button class="action-btn green" onclick="App.refreshSysInfo()">
|
||||
<div class="action-btn-icon"><i data-lucide="monitor-check"></i></div>
|
||||
<div class="action-btn-text">
|
||||
<span class="action-btn-title">System Health</span>
|
||||
<span class="action-btn-desc">Refresh system information</span>
|
||||
</div>
|
||||
<i data-lucide="chevron-right" class="action-arrow"></i>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel glass-panel">
|
||||
<div class="panel-header">
|
||||
<div class="panel-title">
|
||||
<i data-lucide="gauge"></i>
|
||||
<h3>System Resources</h3>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-bars">
|
||||
<div class="resource-item">
|
||||
<div class="resource-header">
|
||||
<div class="resource-label-group">
|
||||
<i data-lucide="memory-stick" class="resource-icon"></i>
|
||||
<span class="resource-name">Memory (RAM)</span>
|
||||
</div>
|
||||
<span class="resource-value" id="dash-ram-detail">-- / --</span>
|
||||
</div>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill ram-fill" id="dash-ram-bar" style="width: 0%">
|
||||
<div class="progress-shine"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="resource-item">
|
||||
<div class="resource-header">
|
||||
<div class="resource-label-group">
|
||||
<i data-lucide="hard-drive" class="resource-icon"></i>
|
||||
<span class="resource-name">Storage (C:)</span>
|
||||
</div>
|
||||
<span class="resource-value" id="dash-disk-detail">-- / --</span>
|
||||
</div>
|
||||
<div class="progress-bar">
|
||||
<div class="progress-fill disk-fill" id="dash-disk-bar" style="width: 0%">
|
||||
<div class="progress-shine"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Drivers Page -->
|
||||
<div class="page" id="page-drivers">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1><i data-lucide="cpu" class="page-icon"></i> Driver Manager</h1>
|
||||
<p class="subtitle">Scan and manage your system drivers</p>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="action-btn primary compact" onclick="App.scanDrivers()">
|
||||
<button class="big-scan-btn" id="btn-scan" onclick="App.scanDrivers()">
|
||||
<i data-lucide="scan-search"></i>
|
||||
<span>Scan Now</span>
|
||||
<span>SCAN NOW</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="driver-summary glass-panel" id="driver-summary" style="display:none">
|
||||
<div class="summary-item">
|
||||
<i data-lucide="layers" class="sum-icon"></i>
|
||||
<strong id="drv-total">0</strong> <span>Total</span>
|
||||
|
||||
<!-- Step Indicator -->
|
||||
<div class="step-bar">
|
||||
<div class="step active" id="step-1">
|
||||
<div class="step-num">1</div>
|
||||
<span>Scan Devices</span>
|
||||
</div>
|
||||
<div class="summary-item warning">
|
||||
<i data-lucide="alert-triangle" class="sum-icon"></i>
|
||||
<strong id="drv-outdated">0</strong> <span>Outdated</span>
|
||||
<div class="step-line"></div>
|
||||
<div class="step" id="step-2">
|
||||
<div class="step-num">2</div>
|
||||
<span>Review Drivers</span>
|
||||
</div>
|
||||
<div class="summary-item error">
|
||||
<i data-lucide="alert-circle" class="sum-icon"></i>
|
||||
<strong id="drv-errors">0</strong> <span>Errors</span>
|
||||
</div>
|
||||
<div class="summary-item muted">
|
||||
<i data-lucide="timer" class="sum-icon"></i>
|
||||
<span id="drv-time">--</span>
|
||||
</div>
|
||||
</div>
|
||||
<div class="filter-bar" id="driver-filters" style="display:none">
|
||||
<button class="filter-btn active" data-filter="all"><i data-lucide="list"></i> All</button>
|
||||
<button class="filter-btn" data-filter="outdated"><i data-lucide="alert-triangle"></i> Outdated</button>
|
||||
<button class="filter-btn" data-filter="error"><i data-lucide="x-circle"></i> Errors</button>
|
||||
<button class="filter-btn" data-filter="signed"><i data-lucide="shield-check"></i> Signed</button>
|
||||
</div>
|
||||
<div id="driver-list" class="driver-list">
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon"><i data-lucide="cpu"></i></div>
|
||||
<h3>No Scan Results</h3>
|
||||
<p>Click <strong>Scan Now</strong> to detect installed drivers</p>
|
||||
<div class="step-line"></div>
|
||||
<div class="step" id="step-3">
|
||||
<div class="step-num">3</div>
|
||||
<span>Install Updates</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Updates Page -->
|
||||
<div class="page" id="page-updates">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1><i data-lucide="download-cloud" class="page-icon"></i> Windows Update</h1>
|
||||
<p class="subtitle">Keep your system up to date</p>
|
||||
<!-- ====== DRIVERS TAB ====== -->
|
||||
<div class="tab-page" id="tab-drivers">
|
||||
<div class="tab-header">
|
||||
<div class="tab-header-left">
|
||||
<h2><i data-lucide="cpu"></i> Installed Drivers</h2>
|
||||
<div class="result-count" id="driver-result-count" style="display:none">
|
||||
<span id="drv-total-2">0</span> found •
|
||||
<span class="warn-text" id="drv-outdated-2">0</span> outdated •
|
||||
scanned in <span id="drv-time-2">--</span>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="action-btn primary compact" onclick="App.checkUpdates()">
|
||||
<i data-lucide="refresh-cw"></i>
|
||||
<span>Check Now</span>
|
||||
</div>
|
||||
<button class="header-btn" onclick="App.scanDrivers()">
|
||||
<i data-lucide="refresh-cw"></i> Rescan
|
||||
</button>
|
||||
</div>
|
||||
<div class="filter-strip" id="driver-filter-strip" style="display:none">
|
||||
<button class="pill active" data-filter="all">All</button>
|
||||
<button class="pill" data-filter="outdated"><i data-lucide="alert-triangle"></i> Outdated</button>
|
||||
<button class="pill" data-filter="error"><i data-lucide="x-circle"></i> Errors</button>
|
||||
<button class="pill" data-filter="signed"><i data-lucide="shield-check"></i> Signed</button>
|
||||
</div>
|
||||
<div class="driver-scroll" id="driver-list">
|
||||
<div class="placeholder-msg">
|
||||
<i data-lucide="scan-search"></i>
|
||||
<p>Click <strong>Scan</strong> to detect your drivers</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- Update All CTA -->
|
||||
<div class="cta-bar" id="cta-update-all" style="display:none">
|
||||
<button class="cta-btn" onclick="App.scanDrivers()">
|
||||
<i data-lucide="download"></i>
|
||||
<span>Update All Drivers</span>
|
||||
<span class="cta-count" id="cta-count">0</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="update-list" class="update-list">
|
||||
<div class="empty-state">
|
||||
<div class="empty-icon"><i data-lucide="cloud-download"></i></div>
|
||||
<h3>No Updates Checked</h3>
|
||||
<p>Click <strong>Check Now</strong> to search for Windows updates</p>
|
||||
|
||||
<!-- ====== UPDATES TAB ====== -->
|
||||
<div class="tab-page" id="tab-updates">
|
||||
<div class="tab-header">
|
||||
<div class="tab-header-left">
|
||||
<h2><i data-lucide="download-cloud"></i> Windows Update</h2>
|
||||
</div>
|
||||
<button class="header-btn" onclick="App.checkUpdates()">
|
||||
<i data-lucide="refresh-cw"></i> Check Now
|
||||
</button>
|
||||
</div>
|
||||
<div class="driver-scroll" id="update-list">
|
||||
<div class="placeholder-msg">
|
||||
<i data-lucide="cloud-download"></i>
|
||||
<p>Click <strong>Check Now</strong> to search for updates</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- System Info Page -->
|
||||
<div class="page" id="page-system">
|
||||
<div class="page-header">
|
||||
<div>
|
||||
<h1><i data-lucide="monitor" class="page-icon"></i> System Information</h1>
|
||||
<p class="subtitle">Detailed hardware and software overview</p>
|
||||
<!-- ====== SYSTEM TAB ====== -->
|
||||
<div class="tab-page" id="tab-system">
|
||||
<div class="tab-header">
|
||||
<div class="tab-header-left">
|
||||
<h2><i data-lucide="monitor-cog"></i> System Information</h2>
|
||||
</div>
|
||||
<div class="header-actions">
|
||||
<button class="action-btn primary compact" onclick="App.refreshSysInfo()">
|
||||
<i data-lucide="refresh-cw"></i>
|
||||
<span>Refresh</span>
|
||||
<button class="header-btn" onclick="App.refreshSysInfo()">
|
||||
<i data-lucide="refresh-cw"></i> Refresh
|
||||
</button>
|
||||
</div>
|
||||
<div class="sys-grid">
|
||||
<div class="sys-card">
|
||||
<div class="sys-card-head"><i data-lucide="laptop"></i> Computer</div>
|
||||
<div class="sys-row"><span>Name</span><span id="sys-name">--</span></div>
|
||||
<div class="sys-row"><span>OS</span><span id="sys-os">--</span></div>
|
||||
<div class="sys-row"><span>Version</span><span id="sys-version">--</span></div>
|
||||
<div class="sys-row"><span>Build</span><span id="sys-build">--</span></div>
|
||||
<div class="sys-row"><span>Arch</span><span id="sys-arch">--</span></div>
|
||||
</div>
|
||||
<div class="sysinfo-grid" id="sysinfo-grid">
|
||||
<div class="info-card glass-panel">
|
||||
<div class="info-card-header">
|
||||
<i data-lucide="laptop"></i>
|
||||
<h4>Computer</h4>
|
||||
<div class="sys-card">
|
||||
<div class="sys-card-head"><i data-lucide="cpu"></i> Processor</div>
|
||||
<div class="sys-row"><span>CPU</span><span id="sys-cpu">--</span></div>
|
||||
<div class="sys-row"><span>Cores</span><span id="sys-cores">--</span></div>
|
||||
</div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="tag"></i> Name</span><span class="info-val" id="sys-name">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="app-window"></i> OS</span><span class="info-val" id="sys-os">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="hash"></i> Version</span><span class="info-val" id="sys-version">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="wrench"></i> Build</span><span class="info-val" id="sys-build">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="boxes"></i> Architecture</span><span class="info-val" id="sys-arch">--</span></div>
|
||||
<div class="sys-card">
|
||||
<div class="sys-card-head"><i data-lucide="memory-stick"></i> Memory</div>
|
||||
<div class="sys-row"><span>Total</span><span id="sys-ram-total">--</span></div>
|
||||
<div class="sys-row"><span>Used</span><span id="sys-ram-used">--</span></div>
|
||||
<div class="sys-row"><span>Free</span><span id="sys-ram-free">--</span></div>
|
||||
<div class="sys-row"><span>Usage</span><span id="sys-ram-pct">--</span></div>
|
||||
<div class="sys-bar-wrap">
|
||||
<div class="sys-bar"><div class="sys-bar-fill ram-bar" id="sys-ram-bar" style="width:0%"></div></div>
|
||||
</div>
|
||||
<div class="info-card glass-panel">
|
||||
<div class="info-card-header">
|
||||
<i data-lucide="cpu"></i>
|
||||
<h4>Processor</h4>
|
||||
</div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="microchip"></i> CPU</span><span class="info-val" id="sys-cpu">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="layers"></i> Cores</span><span class="info-val" id="sys-cores">--</span></div>
|
||||
</div>
|
||||
<div class="info-card glass-panel">
|
||||
<div class="info-card-header">
|
||||
<i data-lucide="memory-stick"></i>
|
||||
<h4>Memory</h4>
|
||||
</div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="database"></i> Total</span><span class="info-val" id="sys-ram-total">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="flame"></i> Used</span><span class="info-val" id="sys-ram-used">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="leaf"></i> Free</span><span class="info-val" id="sys-ram-free">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="percent"></i> Usage</span><span class="info-val" id="sys-ram-pct">--</span></div>
|
||||
</div>
|
||||
<div class="info-card glass-panel">
|
||||
<div class="info-card-header">
|
||||
<i data-lucide="hard-drive"></i>
|
||||
<h4>Storage (C:)</h4>
|
||||
</div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="database"></i> Total</span><span class="info-val" id="sys-disk-total">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="flame"></i> Used</span><span class="info-val" id="sys-disk-used">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="leaf"></i> Free</span><span class="info-val" id="sys-disk-free">--</span></div>
|
||||
<div class="info-row"><span class="info-key"><i data-lucide="percent"></i> Usage</span><span class="info-val" id="sys-disk-pct">--</span></div>
|
||||
<div class="sys-card">
|
||||
<div class="sys-card-head"><i data-lucide="hard-drive"></i> Storage (C:)</div>
|
||||
<div class="sys-row"><span>Total</span><span id="sys-disk-total">--</span></div>
|
||||
<div class="sys-row"><span>Used</span><span id="sys-disk-used">--</span></div>
|
||||
<div class="sys-row"><span>Free</span><span id="sys-disk-free">--</span></div>
|
||||
<div class="sys-row"><span>Usage</span><span id="sys-disk-pct">--</span></div>
|
||||
<div class="sys-bar-wrap">
|
||||
<div class="sys-bar"><div class="sys-bar-fill disk-bar" id="sys-disk-bar" style="width:0%"></div></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</main>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Footer -->
|
||||
<div class="app-footer">
|
||||
<span>Driver Booster Pro v1.0.0</span>
|
||||
<span class="footer-right">
|
||||
<button class="footer-btn" onclick="App.refreshSysInfo()"><i data-lucide="info"></i> About</button>
|
||||
<button class="footer-btn"><i data-lucide="life-buoy"></i> Help</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Loading Overlay -->
|
||||
@@ -354,7 +269,6 @@
|
||||
<i data-lucide="shield-check" class="spinner-icon"></i>
|
||||
</div>
|
||||
<p class="loading-title" id="loading-text">Scanning...</p>
|
||||
<p class="loading-sub">Please wait while we analyze your system</p>
|
||||
<div class="loading-dots"><span></span><span></span><span></span></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
1353
ui/style.css
1353
ui/style.css
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user