Skip to content

Commit

Permalink
show url copied message in snackbar instead of alert
Browse files Browse the repository at this point in the history
  • Loading branch information
chrispyles committed Jul 2, 2024
1 parent c34de01 commit def32c9
Show file tree
Hide file tree
Showing 6 changed files with 85 additions and 2 deletions.
4 changes: 4 additions & 0 deletions src/app/app.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -50,3 +50,7 @@
</header>

<amaze-maze [maze]="maze" (move)="handleMove($event)" />

<div class="snack-bar" [class.visible]="snackBarText()">
{{ snackBarText() }}
</div>
14 changes: 14 additions & 0 deletions src/app/app.component.scss
Original file line number Diff line number Diff line change
Expand Up @@ -22,3 +22,17 @@ header {
display: flex;
}
}

.snack-bar {
background: rgba(255, 255, 255, 0.2);
border-radius: 0.5rem;
bottom: 2rem;
opacity: 0;
padding: 1rem;
position: absolute;
transition: opacity 0.25s;

&.visible {
opacity: 1;
}
}
42 changes: 42 additions & 0 deletions src/app/app.component.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,15 @@ describe('AppComponent', () => {
).and.returnValue(true);
};

beforeAll(() => {
jasmine.DEFAULT_TIMEOUT_INTERVAL = 10_000;
jasmine.clock().install();
});

afterAll(() => {
jasmine.clock().uninstall();
});

beforeEach(async () => {
const maze = new Maze(4, new Chooser(42));
gameStateService = jasmine.createSpyObj<GameStateService>(
Expand Down Expand Up @@ -190,5 +199,38 @@ describe('AppComponent', () => {
'http://example.com/?seed=321',
);
});

it('should show a snack bar confirming that the URL was copied', (done) => {
fixture.debugElement
.query(By.css('[data-test-id="share-maze-button"]'))
.nativeElement.click();
fixture.detectChanges();

expect(
fixture.nativeElement.querySelector('.snack-bar').textContent.trim(),
).toBe('URL copied to clipboard');
expect(
fixture.nativeElement
.querySelector('.snack-bar')
.classList.contains('visible'),
).toBeTrue();

// check that the snackbar is hidden after 2s and emptied after 3s

jasmine.clock().tick(2000);
fixture.detectChanges();
expect(
fixture.nativeElement.querySelector('.snack-bar').style.opacity,
).toBe('0');

jasmine.clock().tick(1000);
fixture.detectChanges();
expect(
fixture.nativeElement
.querySelector('.snack-bar')
.classList.contains('visible'),
).toBeFalse();
done();
});
});
});
20 changes: 19 additions & 1 deletion src/app/app.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@ import {
inject,
InjectionToken,
OnInit,
signal,
ElementRef,
} from '@angular/core';

import { MazeComponent } from './maze/maze.component';
Expand All @@ -29,13 +31,17 @@ export const WINDOW_TOKEN = new InjectionToken('window', {
changeDetection: ChangeDetectionStrategy.OnPush,
})
export class AppComponent implements OnInit {
private readonly elementRef = inject(ElementRef);
private readonly gameStateService = inject(GameStateService);

private readonly window = inject(WINDOW_TOKEN);

/** The size of the maze, defined as the number of rows/columns in the maze. */
size = 20;

/** Text to show in the snack bar. */
readonly snackBarText = signal<string | undefined>(undefined);

ngOnInit(): void {
// Set dark mode if user's OS is using it.
if (
Expand Down Expand Up @@ -94,12 +100,24 @@ export class AppComponent implements OnInit {
shareMaze(): void {
const url = this.gameStateService.getShareUrl();
navigator.clipboard.writeText(url);
alert('URL copied to clipboard'); // TODO: snackbar?
this.snackBarText.set('URL copied to clipboard');
setTimeout(() => this.closeSnackBar(), 2000);
}

/** Handles a move by the user. */
handleMove(dir: Dir): void {
if (this.gameStateService.inAnimation) return;
this.gameStateService.move(dir);
}

private closeSnackBar(): void {
// Set the opacity to 0 so the snack bar fades away before removing its text.
this.elementRef.nativeElement.querySelector('.snack-bar').style.opacity =
'0';
setTimeout(() => {
this.snackBarText.set(undefined);
this.elementRef.nativeElement.querySelector('.snack-bar').style.opacity =
'';
}, 1000);
}
}
4 changes: 4 additions & 0 deletions src/app/game-state.service.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,10 @@ describe('GameStateService', () => {
clock.install();
});

afterAll(() => {
clock.uninstall();
});

beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(GameStateService);
Expand Down
3 changes: 2 additions & 1 deletion src/styles.scss
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200');
@import url('https://fonts.googleapis.com/css2?family=Material+Symbols+Outlined:opsz,wght,FILL,[email protected],100..700,0..1,-50..200&family=Open+Sans:ital,wght@0,300..800;1,300..800');

* {
margin: 0;
Expand All @@ -20,6 +20,7 @@ body {

background: var(--background-color);
color: var(--text-color);
font-family: 'Open Sans', Arial, Helvetica, sans-serif;

&.dark-mode {
--background-color: #060606;
Expand Down

0 comments on commit def32c9

Please sign in to comment.