diff --git a/frontend/src/components/AccountList.vue b/frontend/src/components/AccountList.vue index 62d7230..f1f6abb 100644 --- a/frontend/src/components/AccountList.vue +++ b/frontend/src/components/AccountList.vue @@ -3,7 +3,7 @@ import { onMounted, ref } from "vue"; import { api } from "../api/client"; import { useSessionStore, type User } from "../stores/session"; import { appLink } from "../router/links"; -import OneTimeLink from "./OneTimeLink.vue"; +import OneTimeSecret from "./OneTimeSecret.vue"; import { useRowAction, useLoad } from "../composables/useAction"; // Admin: the accounts on this instance, and a password reset link for any of them @@ -45,9 +45,9 @@ onMounted(() => {

People

- diff --git a/frontend/src/components/InviteList.vue b/frontend/src/components/InviteList.vue index e977e71..31eb7a8 100644 --- a/frontend/src/components/InviteList.vue +++ b/frontend/src/components/InviteList.vue @@ -5,7 +5,7 @@ import { errorMessage } from "../api/errors"; import { appLink } from "../router/links"; import BaseButton from "./BaseButton.vue"; import BaseInput from "./BaseInput.vue"; -import OneTimeLink from "./OneTimeLink.vue"; +import OneTimeSecret from "./OneTimeSecret.vue"; import { toastOnFailure, useLoad } from "../composables/useAction"; // Admin: invite one person to register while registration stays closed (#5172). @@ -97,9 +97,9 @@ onMounted(() => {
- diff --git a/frontend/src/components/OneTimeLink.vue b/frontend/src/components/OneTimeSecret.vue similarity index 61% rename from frontend/src/components/OneTimeLink.vue rename to frontend/src/components/OneTimeSecret.vue index 0c5847a..f219837 100644 --- a/frontend/src/components/OneTimeLink.vue +++ b/frontend/src/components/OneTimeSecret.vue @@ -2,22 +2,27 @@ import { useUiStore } from "../stores/ui"; import Icon from "./Icon.vue"; -// A link carrying a token the server keeps only a hash of, so this is the one time -// it can be shown: invites (#5172) and password reset links (#5173). +// A secret the server keeps only a hash of, so this is the one time it can be shown: +// invite links (#5172), password reset links (#5173) and device tokens. -const props = defineProps<{ - link: string; - /** What the link is, shown above it. */ - note: string; -}>(); +const props = withDefaults( + defineProps<{ + value: string; + /** What it is, shown above it. */ + note: string; + /** What to call it on the copy button and in the toast. */ + noun?: "link" | "token"; + }>(), + { noun: "link" }, +); const emit = defineEmits<{ done: [] }>(); const ui = useUiStore(); async function copy() { try { - await navigator.clipboard.writeText(props.link); - ui.showToast("Link copied."); + await navigator.clipboard.writeText(props.value); + ui.showToast(props.noun === "token" ? "Token copied." : "Link copied."); } catch { ui.showToast("Couldn't copy — select and copy it manually."); } @@ -31,9 +36,15 @@ async function copy() {
{{ link }}{{ value }} +
diff --git a/frontend/src/views/AccountView.vue b/frontend/src/views/AccountView.vue index 95fb316..3f8145f 100644 --- a/frontend/src/views/AccountView.vue +++ b/frontend/src/views/AccountView.vue @@ -8,6 +8,7 @@ import BaseButton from "../components/BaseButton.vue"; import BaseInput from "../components/BaseInput.vue"; import ClientDownloads from "../components/ClientDownloads.vue"; import Icon from "../components/Icon.vue"; +import OneTimeSecret from "../components/OneTimeSecret.vue"; import PageHeader from "../components/PageHeader.vue"; import { errorMessage } from "../api/errors"; import { formatDateTime } from "../notes/datetime"; @@ -71,15 +72,6 @@ async function link() { } } -async function copyToken() { - try { - await navigator.clipboard.writeText(freshToken.value); - ui.showToast("Token copied to clipboard."); - } catch { - ui.showToast("Couldn't copy — select and copy it manually."); - } -} - async function revoke(id: string, name: string) { if (!window.confirm(`Revoke "${name}"? That device will need to link again to sync.`)) return; try { @@ -147,37 +139,14 @@ onMounted(() => { Hides itself when the server holds none. --> - -
-

- Copy this token now — it won't be shown again. -

-
- {{ freshToken }} - -
- -
+ class="mb-6" + :value="freshToken" + noun="token" + note="This device's token." + @done="freshToken = ''" + />