diff --git a/src/api/syncthing-api.ts b/src/api/syncthing-api.ts index ad2baba..2de3c04 100644 --- a/src/api/syncthing-api.ts +++ b/src/api/syncthing-api.ts @@ -16,8 +16,16 @@ export interface SyncthingFolder { paused?: boolean; } +export interface SyncthingDevice { + deviceID: string; + name: string; + address: string[]; + paused: boolean; +} + export interface SyncthingConfig { folders: SyncthingFolder[]; + devices: SyncthingDevice[]; } export interface SyncthingFolderStats { @@ -136,6 +144,18 @@ export class SyncthingAPI { return config.folders; } + static async getDevices( + url: string, + apiKey: string, + ): Promise { + const config = await this.request( + url, + apiKey, + "/rest/config", + ); + return config.devices; + } + // --- Folder Operations --- static async getFolderStats( diff --git a/src/main.ts b/src/main.ts index ac79d5e..20aebcd 100644 --- a/src/main.ts +++ b/src/main.ts @@ -42,6 +42,8 @@ export default class SyncthingController extends Plugin { public connectedDevices: number = 0; public currentStatus: SyncStatus = "desconhecido"; public isPaused: boolean = false; + public deviceMap: Map = new Map(); + public connectedDeviceNames: string[] = []; get apiUrl(): string { const protocol = this.settings.useHttps ? "https://" : "http://"; @@ -487,17 +489,48 @@ export default class SyncthingController extends Plugin { } } + async fetchDeviceMap() { + try { + const devices = await SyncthingAPI.getDevices( + this.apiUrl, + this.settings.syncthingApiKey, + ); + this.deviceMap.clear(); + devices.forEach((device) => { + // Use label/name if available, otherwise fallback to ID + const name = device.name || device.deviceID.substring(0, 7); + this.deviceMap.set(device.deviceID, name); + }); + } catch (e) { + Logger.error( + LOG_MODULES.MAIN, + "Erro ao buscar mapa de dispositivos", + e, + ); + } + } + async atualizarContagemDispositivos() { try { + // Ensure map is populated/updated + if (this.deviceMap.size === 0) { + await this.fetchDeviceMap(); + } + const connections = await SyncthingAPI.getConnections( this.apiUrl, this.settings.syncthingApiKey, ); const devices = connections.connections || {}; - const count = Object.values(devices).filter( - (d: { connected: boolean }) => d.connected, - ).length; - this.connectedDevices = count; + const connectedIDs = Object.keys(devices).filter( + (id) => devices[id].connected, + ); + + this.connectedDevices = connectedIDs.length; + this.connectedDeviceNames = connectedIDs.map((id) => { + return this.deviceMap.get(id) || id.substring(0, 7); + }); + this.atualizarTodosVisuais(); } catch { // Fail silently diff --git a/src/ui/view.ts b/src/ui/view.ts index 0244b4c..2e8bcd2 100644 --- a/src/ui/view.ts +++ b/src/ui/view.ts @@ -117,12 +117,35 @@ export class SyncthingView extends ItemView { t("info_last_sync"), this.plugin.lastSyncTime, ); + // 3.1 Devices Row (Badges) this.createRow( infoContainer, "monitor", t("info_devices"), - this.plugin.connectedDevices.toString(), + "", // Value empty, we will append badges ); + // Get the last row's value container to append badges + const rows = infoContainer.querySelectorAll(".st-info-row"); + const lastRow = rows[rows.length - 1]; + const valueDiv = lastRow.querySelector(".st-info-value"); + + if (valueDiv) { + valueDiv.empty(); // Clear text + // Ensure flex wrap for multiple badges + valueDiv.addClass("st-badges-container"); + + const deviceNames = this.plugin.connectedDeviceNames; + if (deviceNames.length === 0) { + valueDiv.setText("0"); + } else { + deviceNames.forEach((name) => { + valueDiv.createSpan({ + cls: "st-device-badge", + text: name, + }); + }); + } + } const folderDisplay = this.plugin.settings.syncthingFolderLabel || "Default"; diff --git a/styles.css b/styles.css index a2e98c0..1300454 100644 --- a/styles.css +++ b/styles.css @@ -257,7 +257,7 @@ } .st-history-container { - max-height: 200px; + max-height: 50vh; overflow-y: auto; border: 1px solid var(--background-modifier-border); border-radius: 4px; @@ -472,3 +472,22 @@ color: var(--text-success) !important; opacity: 1 !important; } + +/* --- Badges de Dispositivos --- */ +.st-badges-container { + display: flex; + flex-wrap: wrap; + gap: 4px; + justify-content: flex-end; /* Alinha badges à direita */ + max-width: 60%; /* Evita ocupar toda a linha se o label for longo */ +} + +.st-device-badge { + font-size: 0.75em; + background-color: var(--background-modifier-border); + color: var(--text-normal); + padding: 2px 6px; + border-radius: 4px; + border: 1px solid var(--background-modifier-border-hover); + white-space: nowrap; +}