Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 71 additions & 7 deletions src/lib/components/instances/ServersTab.svelte
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,9 @@
let working = $state(false);
let querying = $state(false);
let error = $state("");
let copying = $state(false);
let copyResult = $state<{ address: string; success: boolean } | null>(null);
let copyTimer: ReturnType<typeof setTimeout> | undefined;
let search = $state("");
let page = $state(0);
let selectedIndex = $state<number | null>(null);
Expand Down Expand Up @@ -165,9 +168,29 @@
onDestroy(() => {
alive = false;
generation++;
clearTimeout(copyTimer);
resources.dispose();
});

async function copyAddress(address: string) {
if (copying) return;
copying = true;
copyResult = null;
clearTimeout(copyTimer);
try {
await navigator.clipboard.writeText(address);
if (!alive) return;
copyResult = { address, success: true };
copyTimer = setTimeout(() => {
copyResult = null;
}, 2000);
} catch {
if (alive) copyResult = { address, success: false };
} finally {
if (alive) copying = false;
}
}

function showModal(action: "add" | "edit" | "delete") {
if (disabled || running || (action !== "add" && !selected)) return;
modalAction = action;
Expand Down Expand Up @@ -327,8 +350,8 @@
/>{/if}
</div>
<div class="server-label">
<strong>{server.name}</strong><span class="ip-span blurred"
>{server.address}</span
<strong>{server.name}</strong><span
class="ip-span blurred">{server.address}</span
><small class:online={status?.online}
>{statusLabel(status)}{#if status?.online}
· {playerCount(status)} · {status.ping} ms{/if}</small
Expand Down Expand Up @@ -357,7 +380,37 @@
</p>{/if}
<dl>
<dt>{t("servers.address")}</dt>
<dd class="blurred">{selected.address}</dd>
<dd>
<div class="server-address">
<span class="blurred">{selected.address}</span>
<button
type="button"
class="copy-address"
disabled={copying}
onclick={() =>
selected &&
void copyAddress(selected.address)}
><Icon name="ui:copy" size={15} />{t(
"servers.copyIp",
)}</button
>
</div>
{#if copyResult?.address === selected.address}
<p
class="hint"
class:error={!copyResult.success}
role={copyResult.success
? "status"
: "alert"}
>
{t(
copyResult.success
? "servers.ipCopied"
: "servers.copyFailed",
)}
</p>
{/if}
</dd>
<dt>{t("servers.status")}</dt>
<dd>{statusLabel(selectedStatus)}</dd>
{#if selectedStatus?.online}
Expand Down Expand Up @@ -548,6 +601,7 @@
cursor: pointer;
}
.actions button,
.copy-address,
.connect {
display: flex;
align-items: center;
Expand Down Expand Up @@ -649,16 +703,26 @@
color: var(--text-secondary);
font-size: 0.8rem;
}
.ip-span,
dd.blurred {
.blurred {
filter: blur(4px);
transition: filter 0.2s ease;
user-select: none;
}
.ip-span:hover,
dd.blurred:hover {
.blurred:hover {
filter: blur(0);
}
.server-address {
display: flex;
align-items: center;
flex-wrap: wrap;
gap: 8px;
}
.server-address .blurred {
min-width: 0;
}
.copy-address {
flex-shrink: 0;
}
.server-label .online {
color: var(--accent-primary);
}
Expand Down
3 changes: 3 additions & 0 deletions src/lib/i18n/en-US.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"name": "Server name",
"address": "Address",
"addressHint": "Domain or IP, with an optional port. For IPv6 with a port, use [address]:port.",
"copyIp": "Copy IP",
"ipCopied": "IP copied",
"copyFailed": "Could not copy the IP to the clipboard.",
"resourcePacks": "Server resource packs",
"prompt": "Prompt",
"enabled": "Accept",
Expand Down
3 changes: 3 additions & 0 deletions src/lib/i18n/es-ES.json
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@
"name": "Nombre del servidor",
"address": "Dirección",
"addressHint": "Dominio o IP, con puerto opcional. Para IPv6 con puerto, usa [dirección]:puerto.",
"copyIp": "Copiar IP",
"ipCopied": "IP copiada",
"copyFailed": "No se pudo copiar la IP al portapapeles.",
"resourcePacks": "Paquetes de recursos del servidor",
"prompt": "Preguntar",
"enabled": "Aceptar",
Expand Down
Loading