mac permissions overhaul
This commit is contained in:
@@ -2580,6 +2580,28 @@ tbody tr:hover {
|
||||
.cv-pill-system { background: rgba(239, 68, 68, 0.12); color: #fca5a5; border-color: rgba(239, 68, 68, 0.3); }
|
||||
.cv-pill-ti { background: rgba(168, 85, 247, 0.12); color: #d8b4fe; border-color: rgba(168, 85, 247, 0.3); }
|
||||
.cv-pill-muted { background: rgba(245, 158, 11, 0.12); color: #fcd34d; border-color: rgba(245, 158, 11, 0.3); }
|
||||
.cv-pill-macperm.is-ok { background: rgba(16, 185, 129, 0.12); color: #86efac; border-color: rgba(16, 185, 129, 0.3); }
|
||||
.cv-pill-macperm.is-warn { background: rgba(245, 158, 11, 0.12); color: #fcd34d; border-color: rgba(245, 158, 11, 0.3); }
|
||||
|
||||
.cv-perm-list {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
.cv-perm-chip {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
gap: 5px;
|
||||
min-height: 22px;
|
||||
padding: 2px 7px;
|
||||
border-radius: 4px;
|
||||
border: 1px solid transparent;
|
||||
font-size: 11px;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.cv-perm-chip.is-ok { background: rgba(16, 185, 129, 0.1); color: #86efac; border-color: rgba(16, 185, 129, 0.25); }
|
||||
.cv-perm-chip.is-missing { background: rgba(244, 63, 94, 0.1); color: #fda4af; border-color: rgba(244, 63, 94, 0.25); }
|
||||
|
||||
.cv-group {
|
||||
display: inline-flex;
|
||||
@@ -3348,6 +3370,16 @@ tbody tr:hover {
|
||||
}
|
||||
.cv-card-hw-bit i { color: var(--cv-text-dim); font-size: 10px; }
|
||||
|
||||
.cv-card-perms {
|
||||
margin-top: 6px;
|
||||
padding: 6px 8px;
|
||||
background: var(--cv-surface2);
|
||||
border-radius: 6px;
|
||||
}
|
||||
.cv-card-perms .cv-field {
|
||||
gap: 5px;
|
||||
}
|
||||
|
||||
.cv-cpu-badge {
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
|
||||
@@ -200,6 +200,46 @@ function batteryHtml(client, { compact = false } = {}) {
|
||||
</span>`;
|
||||
}
|
||||
|
||||
function isMacClient(client) {
|
||||
const os = String(client?.os || "").toLowerCase();
|
||||
return os.includes("mac") || os.includes("darwin");
|
||||
}
|
||||
|
||||
const MAC_PERMISSION_LABELS = [
|
||||
["accessibility", "Accessibility"],
|
||||
["screenRecording", "Screen Recording"],
|
||||
["fullDiskAccess", "Full Disk Access"],
|
||||
];
|
||||
|
||||
function macPermissionState(client) {
|
||||
if (!isMacClient(client) || !client.permissions || typeof client.permissions !== "object") return null;
|
||||
const items = MAC_PERMISSION_LABELS
|
||||
.filter(([key]) => typeof client.permissions[key] === "boolean")
|
||||
.map(([key, label]) => ({ key, label, granted: client.permissions[key] === true }));
|
||||
if (!items.length) return null;
|
||||
const missing = items.filter((item) => !item.granted);
|
||||
return { items, missing };
|
||||
}
|
||||
|
||||
function macPermissionBadgeHtml(client) {
|
||||
const state = macPermissionState(client);
|
||||
if (!state) return "";
|
||||
const title = state.items.map((item) => `${item.label}: ${item.granted ? "granted" : "missing"}`).join(" · ");
|
||||
const ok = state.missing.length === 0;
|
||||
return `<span class="cv-mini-pill cv-pill-macperm ${ok ? "is-ok" : "is-warn"}" title="${escapeHtml(title)}"><i class="fa-solid ${ok ? "fa-key" : "fa-triangle-exclamation"}"></i></span>`;
|
||||
}
|
||||
|
||||
function macPermissionDetailHtml(client) {
|
||||
const state = macPermissionState(client);
|
||||
if (!state) return "";
|
||||
const chips = state.items.map((item) => `
|
||||
<span class="cv-perm-chip ${item.granted ? "is-ok" : "is-missing"}">
|
||||
<i class="fa-solid ${item.granted ? "fa-check" : "fa-xmark"}"></i>${escapeHtml(item.label)}
|
||||
</span>
|
||||
`).join("");
|
||||
return `<div class="cv-field cv-field-wide"><span class="cv-field-label">macOS Permissions</span><span class="cv-field-value cv-perm-list">${chips}</span></div>`;
|
||||
}
|
||||
|
||||
function shortOsLabel(osRaw = "") {
|
||||
const badge = osBadge(osRaw || "");
|
||||
if (badge?.label && badge.label !== "Linux" && badge.label !== "Windows") return badge.label;
|
||||
@@ -536,7 +576,7 @@ export function createRenderer({
|
||||
}
|
||||
|
||||
function cardDigest(c) {
|
||||
return `${currentDisplayDigest}|${currentLayout}|${c.id}|${!!c.online}|${c.lastSeen}|${c.pingMs}|${c.host}|${c.user}|${c.os}|${c.arch}|${c.version}|${c.monitors}|${c.country}|${c.nickname}|${c.customTag}|${c.customTagNote}|${!!c.bookmarked}|${!!c.isAdmin}|${c.elevation}|${c.cpu}|${c.gpu}|${c.ram}|${c.batteryPercent}|${c.batteryCharging}|${c.hwid}|${c.disconnectReason}|${c.disconnectDetail}|${c.groupId}|${c.groupName}|${c.groupColor}|${!!c.notificationsMuted}`;
|
||||
return `${currentDisplayDigest}|${currentLayout}|${c.id}|${!!c.online}|${c.lastSeen}|${c.pingMs}|${c.host}|${c.user}|${c.os}|${c.arch}|${c.version}|${c.monitors}|${c.country}|${c.nickname}|${c.customTag}|${c.customTagNote}|${!!c.bookmarked}|${!!c.isAdmin}|${c.elevation}|${JSON.stringify(c.permissions || {})}|${c.cpu}|${c.gpu}|${c.ram}|${c.batteryPercent}|${c.batteryCharging}|${c.hwid}|${c.disconnectReason}|${c.disconnectDetail}|${c.groupId}|${c.groupName}|${c.groupColor}|${!!c.notificationsMuted}`;
|
||||
}
|
||||
|
||||
function cardThumbDigest(c) {
|
||||
@@ -795,6 +835,7 @@ export function createRenderer({
|
||||
${client.isAdmin ? `<span class="cv-mini-pill cv-pill-admin" title="Admin"><i class="fa-solid fa-shield-halved"></i></span>` : ""}
|
||||
${client.elevation === "system" ? `<span class="cv-mini-pill cv-pill-system" title="SYSTEM"><i class="fa-solid fa-gear"></i></span>` : ""}
|
||||
${client.elevation === "trustedinstaller" ? `<span class="cv-mini-pill cv-pill-ti" title="TrustedInstaller"><i class="fa-solid fa-lock"></i></span>` : ""}
|
||||
${macPermissionBadgeHtml(client)}
|
||||
${client.notificationsMuted ? `<span class="cv-mini-pill cv-pill-muted" title="Notifications muted"><i class="fa-solid fa-bell-slash"></i></span>` : ""}
|
||||
</div>
|
||||
${showField("user") ? `<div class="cv-user-line"><i class="fa-solid fa-user"></i> ${escapeHtml(userLine)}</div>` : ""}
|
||||
@@ -823,6 +864,7 @@ export function createRenderer({
|
||||
${showHardware ? `<div class="cv-field"><span class="cv-field-label">CPU</span><span class="cv-field-value">${cpuHtml}</span></div>` : ""}
|
||||
${showHardware ? `<div class="cv-field"><span class="cv-field-label">RAM</span><span class="cv-field-value">${escapeHtml(client.ram || "—")}</span></div>` : ""}
|
||||
${batteryIndicator ? `<div class="cv-field"><span class="cv-field-label">Battery</span><span class="cv-field-value">${batteryIndicator}</span></div>` : ""}
|
||||
${macPermissionDetailHtml(client)}
|
||||
${showHardware && client.gpu ? `<div class="cv-field cv-field-wide"><span class="cv-field-label">GPU</span><span class="cv-field-value">${escapeHtml(client.gpu)}</span></div>` : ""}
|
||||
${showField("version") && !verLatest && client.version ? `<div class="cv-field"><span class="cv-field-label">Version</span><span class="cv-field-value cv-warn">v${escapeHtml(client.version)} (outdated)</span></div>` : ""}
|
||||
</div>
|
||||
@@ -872,6 +914,7 @@ export function createRenderer({
|
||||
${client.isAdmin ? `<span class="cv-mini-pill cv-pill-admin" title="Admin"><i class="fa-solid fa-shield-halved"></i></span>` : ""}
|
||||
${client.elevation === "system" ? `<span class="cv-mini-pill cv-pill-system" title="SYSTEM"><i class="fa-solid fa-gear"></i></span>` : ""}
|
||||
${client.elevation === "trustedinstaller" ? `<span class="cv-mini-pill cv-pill-ti" title="TI"><i class="fa-solid fa-lock"></i></span>` : ""}
|
||||
${macPermissionBadgeHtml(client)}
|
||||
${client.notificationsMuted ? `<span class="cv-mini-pill cv-pill-muted" title="Notifications muted"><i class="fa-solid fa-bell-slash"></i></span>` : ""}
|
||||
</span>
|
||||
${userMeta ? `<span class="cv-user-line cv-mono">${userMeta}</span>` : ""}
|
||||
@@ -919,6 +962,7 @@ export function createRenderer({
|
||||
const showHardware = showField("hardware");
|
||||
const cpuHtml = showHardware && client.cpu ? cpuBadgeHtml(client.cpu) : "";
|
||||
const batteryIndicator = showField("battery") ? batteryHtml(client, { compact: true }) : "";
|
||||
const macPermDetail = macPermissionDetailHtml(client);
|
||||
|
||||
const metaParts = [
|
||||
showField("system") ? `<span class="cv-card-meta-bit cv-tone-${os.tone}"><i class="fa ${os.icon}"></i> ${escapeHtml(shortOsLabel(client.os))}</span>` : "",
|
||||
@@ -931,6 +975,7 @@ export function createRenderer({
|
||||
client.isAdmin ? `<span class="cv-mini-pill cv-pill-admin" title="Admin"><i class="fa-solid fa-shield-halved"></i></span>` : "",
|
||||
client.elevation === "system" ? `<span class="cv-mini-pill cv-pill-system" title="SYSTEM"><i class="fa-solid fa-gear"></i></span>` : "",
|
||||
client.elevation === "trustedinstaller" ? `<span class="cv-mini-pill cv-pill-ti" title="TrustedInstaller"><i class="fa-solid fa-lock"></i></span>` : "",
|
||||
macPermissionBadgeHtml(client),
|
||||
client.notificationsMuted ? `<span class="cv-mini-pill cv-pill-muted" title="Notifications muted"><i class="fa-solid fa-bell-slash"></i></span>` : "",
|
||||
].join("");
|
||||
|
||||
@@ -975,6 +1020,7 @@ export function createRenderer({
|
||||
${showHardware && client.ram ? `<span class="cv-card-hw-bit"><i class="fa-solid fa-memory"></i> ${escapeHtml(client.ram)}</span>` : ""}
|
||||
${batteryIndicator}
|
||||
</div>` : ""}
|
||||
${macPermDetail ? `<div class="cv-card-perms">${macPermDetail}</div>` : ""}
|
||||
<div class="cv-card-actions">
|
||||
${isViewer ? "" : `<button class="command-btn cv-btn-primary cv-btn-flex" data-id="${escapeHtml(client.id)}"><i class="fa-solid fa-terminal"></i><span>Commands</span></button>`}
|
||||
<button class="cv-icon-btn cv-ping-btn" title="Ping" ${client.online ? "" : "disabled"}><i class="fa-solid fa-satellite-dish"></i></button>
|
||||
|
||||
@@ -29,8 +29,16 @@ export type Hello = {
|
||||
monitors: number;
|
||||
monitorInfo?: { width: number; height: number }[];
|
||||
country?: string;
|
||||
hwid?: string;
|
||||
inMemory?: boolean;
|
||||
cpu?: string;
|
||||
gpu?: string;
|
||||
ram?: string;
|
||||
batteryPercent?: number;
|
||||
batteryCharging?: boolean;
|
||||
isAdmin?: boolean;
|
||||
elevation?: string;
|
||||
permissions?: Record<string, boolean>;
|
||||
publicKey?: string;
|
||||
signature?: string;
|
||||
publicIP?: string;
|
||||
|
||||
Reference in New Issue
Block a user