feat(api,userbot,frontend): rename session device from the web ui
This commit is contained in:
@@ -85,6 +85,16 @@ export function cancelLogin(loginId: string): Promise<void> {
|
||||
return request<void>(`/accounts/login/${loginId}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
export function renameAccountDevice(
|
||||
accountId: number,
|
||||
deviceModel: string
|
||||
): Promise<Account> {
|
||||
return request<Account>(`/accounts/${accountId}/device`, {
|
||||
method: "PATCH",
|
||||
body: { device_model: deviceModel },
|
||||
});
|
||||
}
|
||||
|
||||
export function logoutAccount(accountId: number): Promise<void> {
|
||||
return request<void>(`/accounts/${accountId}`, { method: "DELETE" });
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@ export type JobStatus =
|
||||
|
||||
export interface Account {
|
||||
account_id: number;
|
||||
device_model: string | null;
|
||||
is_active: boolean;
|
||||
label: string | null;
|
||||
phone: string | null;
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import { Dialog } from "bits-ui";
|
||||
import { ripple } from "$lib/actions/ripple";
|
||||
import { ApiError } from "$lib/api/client";
|
||||
import AddAccountDialog from "$lib/components/settings/AddAccountDialog.svelte";
|
||||
import SettingsItem from "$lib/components/settings/SettingsItem.svelte";
|
||||
import Avatar from "$lib/components/ui/Avatar.svelte";
|
||||
@@ -17,10 +18,42 @@
|
||||
)
|
||||
);
|
||||
|
||||
const DEVICE_LIMIT = 32;
|
||||
const DEFAULT_DEVICE = "Beavergram";
|
||||
|
||||
let adding = $state(false);
|
||||
let confirming = $state(false);
|
||||
let renaming = $state(false);
|
||||
let deviceName = $state("");
|
||||
let busy = $state(false);
|
||||
|
||||
const deviceLabel = $derived(current?.device_model ?? DEFAULT_DEVICE);
|
||||
|
||||
function openRename() {
|
||||
deviceName = deviceLabel;
|
||||
renaming = true;
|
||||
}
|
||||
|
||||
async function rename(event: SubmitEvent) {
|
||||
event.preventDefault();
|
||||
const value = deviceName.trim();
|
||||
if (!(current && value) || busy) {
|
||||
return;
|
||||
}
|
||||
busy = true;
|
||||
try {
|
||||
await accounts.renameDevice(current.account_id, value);
|
||||
renaming = false;
|
||||
toasts.success("Имя устройства обновлено");
|
||||
} catch (error) {
|
||||
toasts.error(
|
||||
error instanceof ApiError ? error.detail : "Не удалось переименовать"
|
||||
);
|
||||
} finally {
|
||||
busy = false;
|
||||
}
|
||||
}
|
||||
|
||||
async function logout() {
|
||||
if (!current || busy) {
|
||||
return;
|
||||
@@ -81,6 +114,14 @@
|
||||
{/if}
|
||||
|
||||
<div class="actions">
|
||||
{#if current?.is_active}
|
||||
<SettingsItem
|
||||
icon="active-sessions"
|
||||
label="Имя устройства"
|
||||
value={deviceLabel}
|
||||
onclick={openRename}
|
||||
/>
|
||||
{/if}
|
||||
<SettingsItem
|
||||
icon="add-user"
|
||||
label="Добавить аккаунт"
|
||||
@@ -102,6 +143,50 @@
|
||||
|
||||
<AddAccountDialog bind:open={adding} />
|
||||
|
||||
<Dialog.Root bind:open={renaming}>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay class="dialog-overlay" />
|
||||
<Dialog.Content class="dialog-content">
|
||||
<header class="dialog-head">
|
||||
<Dialog.Title class="dialog-title">Имя устройства</Dialog.Title>
|
||||
<Dialog.Close class="dialog-close" aria-label="Закрыть">
|
||||
<Icon name="close" size="1.25rem" />
|
||||
</Dialog.Close>
|
||||
</header>
|
||||
<form onsubmit={rename}>
|
||||
<div class="dialog-body">
|
||||
<p class="confirm-text">
|
||||
Так сессия называется в списке устройств Telegram. Чтобы имя
|
||||
применилось, соединение переподключится — сбор сообщений прервётся
|
||||
на пару секунд.
|
||||
</p>
|
||||
<div class="input-group">
|
||||
<input
|
||||
id="device-name"
|
||||
class="form-control"
|
||||
type="text"
|
||||
maxlength={DEVICE_LIMIT}
|
||||
placeholder={DEFAULT_DEVICE}
|
||||
bind:value={deviceName}
|
||||
>
|
||||
<label for="device-name">Название</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="dialog-actions">
|
||||
<Button
|
||||
type="submit"
|
||||
pill
|
||||
loading={busy}
|
||||
disabled={busy || deviceName.trim().length === 0}
|
||||
>
|
||||
Сохранить
|
||||
</Button>
|
||||
</div>
|
||||
</form>
|
||||
</Dialog.Content>
|
||||
</Dialog.Portal>
|
||||
</Dialog.Root>
|
||||
|
||||
<Dialog.Root bind:open={confirming}>
|
||||
<Dialog.Portal>
|
||||
<Dialog.Overlay class="dialog-overlay" />
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
import { browser } from "$app/environment";
|
||||
import { listAccounts, logoutAccount } from "$lib/api/endpoints";
|
||||
import {
|
||||
listAccounts,
|
||||
logoutAccount,
|
||||
renameAccountDevice,
|
||||
} from "$lib/api/endpoints";
|
||||
import type { Account } from "$lib/api/types";
|
||||
|
||||
const STORAGE_KEY = "bg.account";
|
||||
@@ -63,6 +67,12 @@ function createAccounts() {
|
||||
},
|
||||
load,
|
||||
select,
|
||||
async renameDevice(id: number, deviceModel: string) {
|
||||
const updated = await renameAccountDevice(id, deviceModel);
|
||||
list = list.map((account) =>
|
||||
account.account_id === id ? updated : account
|
||||
);
|
||||
},
|
||||
async logout(id: number) {
|
||||
await logoutAccount(id);
|
||||
if (id === selectedId) {
|
||||
|
||||
Reference in New Issue
Block a user