From 05bfda484e5c3e2ce04debdaf2731c6bb66c97b2 Mon Sep 17 00:00:00 2001 From: SkyZeroZx <73321943+SkyZeroZx@users.noreply.github.com> Date: Mon, 27 Oct 2025 13:31:44 -0500 Subject: [PATCH] refactor(devtools): Improves clipboard error feedback with snackbar and logging Enhances user experience by displaying a snackbar notification when clipboard copy fails, and logs detailed error information via the message bus (cherry picked from commit bfcaf1700589adea0c8a25206a5758fcc57574c0) --- .../transfer-state/transfer-state.component.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/devtools/projects/ng-devtools/src/lib/devtools-tabs/transfer-state/transfer-state.component.ts b/devtools/projects/ng-devtools/src/lib/devtools-tabs/transfer-state/transfer-state.component.ts index f44727977b2..f71490f7df3 100644 --- a/devtools/projects/ng-devtools/src/lib/devtools-tabs/transfer-state/transfer-state.component.ts +++ b/devtools/projects/ng-devtools/src/lib/devtools-tabs/transfer-state/transfer-state.component.ts @@ -32,6 +32,7 @@ import { import {ButtonComponent} from '../../shared/button/button.component'; import {Events, MessageBus, TransferStateValue} from '../../../../../protocol'; import {formatBytes, getFormattedValue} from '../../shared/utils/formatting'; +import {MatSnackBar, MatSnackBarModule} from '@angular/material/snack-bar'; interface TransferStateItem { key: string; @@ -47,7 +48,6 @@ export const COPY_FEEDBACK_TIMEOUT = 2000; @Component({ selector: 'ng-transfer-state', - standalone: true, imports: [ MatIcon, MatTooltip, @@ -62,6 +62,7 @@ export const COPY_FEEDBACK_TIMEOUT = 2000; MatHeaderRowDef, MatRowDef, ButtonComponent, + MatSnackBarModule, ], templateUrl: './transfer-state.component.html', styleUrls: ['./transfer-state.component.scss'], @@ -71,6 +72,8 @@ export class TransferStateComponent { private messageBus = inject(MessageBus) as MessageBus; private clipboard = inject(Clipboard); + private snackBar = inject(MatSnackBar); + readonly transferStateData = signal | null>(null); readonly error = signal(null); readonly isLoading = computed(() => !this.transferStateData() && !this.error()); @@ -171,7 +174,12 @@ export class TransferStateComponent { ); }, COPY_FEEDBACK_TIMEOUT); } catch (err) { - console.error('Failed to copy to clipboard:', err); + const message = 'Failed to copy to clipboard'; + const errorDetail = + err instanceof Error ? `${err.name}: ${err.message}` : JSON.stringify(err); + + this.snackBar.open(message, 'Dismiss', {duration: 3000}); + this.messageBus.emit('log', [{level: 'error', message: `${message}: ${errorDetail}`}]); } } }