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
5 changes: 5 additions & 0 deletions src/app/app-routing.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,11 @@ const routes: Routes = [
loadComponent: () =>
import("./overlays/map-breakdown/map-breakdown").then((m) => m.MapBreakdown),
},
{
path: "toast",
loadComponent: () =>
import("./components/shopping/toast/toast-component").then((m) => m.ToastComponent),
},
];

@NgModule({
Expand Down
36 changes: 36 additions & 0 deletions src/app/components/shopping/toast/toast-component.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
@keyframes swish {
from {
clip-path: inset(0 100% 0 0);
}
to {
clip-path: inset(0 0 0 0);
}
}

.animate-swish {
animation: swish 300ms ease-in-out forwards;
will-change: clip-path, width;
}

.animate-swish-out {
animation: swish 300ms ease-in-out reverse forwards;
will-change: clip-path, width;
}

.bg-fade-defender {
background: linear-gradient(
to right,
rgba(var(--defender-color-rgb), 0.5) 10%,
rgba(var(--defender-color-rgb), 0.25) 40%,
transparent
);
}

.bg-fade-attacker {
background: linear-gradient(
to right,
rgba(var(--attacker-color-rgb), 0.5) 10%,
rgba(var(--attacker-color-rgb), 0.25) 40%,
transparent
);
}
55 changes: 55 additions & 0 deletions src/app/components/shopping/toast/toast-component.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
@if(this.dataModel.match().roundPhase === "shopping") {
<div
class="vw-900 vh-270 animate-duration-300 animate-style-keep relative overflow-hidden"
[class.hidden]="hide"
[class.animate-swish]="inAnimation"
[class.animate-swish-out]="outAnimation"
>
<div class="relative top-0 left-0 flex w-full items-center justify-center">
<div class="vh-270 relative flex items-center">
<div class="bg-timer/85 rounded-md">
<div class="flex h-27.5 w-215 flex-row gap-6 rounded-md" [class]="'bg-fade-' + teamSite()">
@if (toastInfo().selectedTeam !== "none") {
<div class="flex w-27.5 shrink-0 items-center justify-center rounded-l-md">
<img
[src]="toastInfo().selectedTeam === 'left' ? dataModel.teams()[0].teamUrl : dataModel.teams()[1].teamUrl"
class="vw-60 h-auto object-contain"
/>
</div>
} @else {
<div></div>
}
<div
class="flex flex-col gap-1 overflow-hidden"
[class]="toastInfo().title === '' ? 'self-center' : ''"
>
@if(toastInfo().title !== "") {
<span
class="mt-2 flex text-2xl font-bold text-white"
[class]="toastInfo().eventLogoEnabled ? 'w-147.5' : 'w-174'"
>
{{ toastInfo().title }}
</span>
}
<span
class="flex justify-center self-center text-white"
[class]="(toastInfo().selectedTeam === 'none' ? toastInfo().eventLogoEnabled ? 'w-175.5' : 'w-201.5' : toastInfo().eventLogoEnabled ? 'w-147.5' : 'w-174') +
' ' +
(toastInfo().title !== '' ? 'text-xl' : 'text-2xl')"
>
{{ toastInfo().message }}
</span>
</div>
@if (toastInfo().eventLogoEnabled) {
<div class="flex w-27.5 shrink-0 items-center justify-center rounded-md">
<img [src]="tournamentIconUrl()" class="vw-60 h-auto object-contain" />
</div>
} @else {
<div></div>
}
</div>
</div>
</div>
</div>
</div>
}
63 changes: 63 additions & 0 deletions src/app/components/shopping/toast/toast-component.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { Component, computed, effect, inject, signal } from "@angular/core";
import { DataModelService } from "../../../services/dataModel.service";

@Component({
selector: "app-toast",
imports: [],
templateUrl: "./toast-component.html",
styleUrl: "./toast-component.css",
})
export class ToastComponent {
dataModel = inject(DataModelService);

toastInfo = signal(Object.assign({}, this.dataModel.toastInfo()));

shouldHide = computed(
() => !this.dataModel.toastInfo().active || !(this.dataModel.match().roundPhase === "shopping"),
);

teamSite = computed(() => {
if (this.dataModel.match().teams[this.toastInfo().selectedTeam == "left" ? 0 : 1].isAttacking) {
return "attacker";
} else {
return "defender";
}
});

tournamentIconUrl = computed(() => {
const logo = this.dataModel.tournamentInfo().logoUrl;
if (logo && logo !== "") return logo;
else return "assets/misc/logo.webp";
});

hide = true;
inAnimation = false;
outAnimation = false;

hideAnimationEffect = effect(() => {
if (this.shouldHide()) {
this.outAnimation = true;
setTimeout(() => {
this.outAnimation = false;
this.hide = true;
}, 300);
} else {
this.outAnimation = false;
this.hide = false;
this.inAnimation = true;
setTimeout(() => {
this.inAnimation = false;
}, 300);
}
});

delayEndToastEffect = effect(() => {
if (this.shouldHide()) {
setTimeout(() => {
this.toastInfo.set(Object.assign({}, this.dataModel.toastInfo()));
}, 350);
} else {
this.toastInfo.set(Object.assign({}, this.dataModel.toastInfo()));
}
});
}
2 changes: 2 additions & 0 deletions src/app/overlays/match-overlay/match-overlay.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,5 @@

<app-endround class="pos-x-center pos-y-140 absolute"></app-endround>
<app-timeout class="pos-x-center pos-y-250 absolute"></app-timeout>

<app-toast class="pos-x-center pos-y-400 absolute"></app-toast>
2 changes: 2 additions & 0 deletions src/app/overlays/match-overlay/match-overlay.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ import { EndroundBannerComponent } from "../../components/combat/endround-banner
import { TimeoutComponent } from "../../components/common/timeout/timeout.component";
import { TopBackgroundComponent } from "../../components/top/match/background/background.component";
import { OneVersusOneComponent } from "../../components/combat/1v1/1v1.component";
import { ToastComponent } from "../../components/shopping/toast/toast-component";

@Component({
selector: "app-match-overlay",
Expand All @@ -34,6 +35,7 @@ import { OneVersusOneComponent } from "../../components/combat/1v1/1v1.component
TimeoutComponent,
TopBackgroundComponent,
OneVersusOneComponent,
ToastComponent,
],
templateUrl: "./match-overlay.component.html",
styleUrl: "./match-overlay.component.css",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,14 @@ export class TestingAgentSelectComponent implements OnInit {
sponsors: [],
},
},
toastInfo: {
active: false,
duration: 10000,
title: "",
message: "",
selectedTeam: "none",
eventLogoEnabled: false,
},
timeoutState: {
techPause: false,
leftTeam: false,
Expand Down
1 change: 1 addition & 0 deletions src/app/overlays/testing/testing.component.html
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
</button>
<button (click)="toggleInterface()">Toggle Interface</button>
<button (click)="switchBackground()">Switch Background</button>
<button (click)="showToast()">Show/Hide Toast</button>
</div>

<!-- team buttons -->
Expand Down
50 changes: 50 additions & 0 deletions src/app/overlays/testing/testing.component.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import { IMatchData } from "../../services/Types";
})
export class TestingComponent implements OnInit {
dataModel = inject(DataModelService);
private toastTimerRef?: ReturnType<typeof setTimeout>;
match: IMatchData = initialMatchData;

bgCounter = 1;
Expand Down Expand Up @@ -99,6 +100,14 @@ export class TestingComponent implements OnInit {
sponsors: [],
},
},
toastInfo: {
active: false,
duration: 10000,
title: "",
message: "",
selectedTeam: "none",
eventLogoEnabled: false,
},
teams: [
{
players: [
Expand Down Expand Up @@ -815,4 +824,45 @@ export class TestingComponent implements OnInit {
return ret;
});
}

showToast() {
const currentlyActive = this.dataModel.match().toastInfo.active;

if (currentlyActive) {
// Deactivate immediately (mimics pressing the hotkey again)
clearTimeout(this.toastTimerRef);
this.toastTimerRef = undefined;
this.dataModel.match.update((v) => {
const ret = v;
ret.toastInfo.active = false;
return ret;
});
} else {
// Activate
this.dataModel.match.update((v) => {
const ret = v;
ret.toastInfo.active = true;
ret.toastInfo.title = "Spezial Spectra Developer Announcement";
ret.toastInfo.message =
"This is a live toast preview with the biggest changes. Thanks for using Spectra!";
ret.toastInfo.selectedTeam = "left";
ret.toastInfo.duration = null;
ret.toastInfo.eventLogoEnabled = true;
return ret;
});

const duration = this.dataModel.match().toastInfo.duration;
if (duration !== null) {
clearTimeout(this.toastTimerRef);
this.toastTimerRef = setTimeout(() => {
this.dataModel.match.update((v) => {
const ret = v;
ret.toastInfo.active = false;
return ret;
});
this.toastTimerRef = undefined;
}, duration);
}
}
}
}
10 changes: 10 additions & 0 deletions src/app/services/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ export interface IMatchData {
switchRound: number;
firstOtRound: number;
attackersWon: boolean;
toastInfo: IToastInfo;
}

export interface ITeamData {
Expand Down Expand Up @@ -84,6 +85,15 @@ export interface ITimeoutState {
timeRemaining: number;
}

export interface IToastInfo {
active: boolean;
title: string;
message: string;
duration: number | null;
eventLogoEnabled: boolean;
selectedTeam: "left" | "right" | "none";
}

//#endregion
//#region Tools

Expand Down
9 changes: 9 additions & 0 deletions src/app/services/dataModel.service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ export class DataModelService {
public readonly sponsorInfo = computed(() => this.match().tools.sponsorInfo);
public readonly watermarkInfo = computed(() => this.match().tools.watermarkInfo);
public readonly tournamentInfo = computed(() => this.match().tools.tournamentInfo);
public toastInfo = computed(() => this.match().toastInfo, { equal: () => false });
public readonly playercamsInfo = computed(() => this.match().tools.playercamsInfo, {
equal: () => false,
});
Expand Down Expand Up @@ -195,6 +196,14 @@ export const initialMatchData: IMatchData = {
sponsors: [],
},
},
toastInfo: {
active: false,
duration: 10000,
title: "",
message: "",
eventLogoEnabled: true,
selectedTeam: "none",
},
timeoutState: {
techPause: false,
leftTeam: false,
Expand Down
Loading