DEV Community

Cover image for Angular Konami Service
Michael Richins
Michael Richins

Posted on

Angular Konami Service

Do you want the perfect easter egg for you website?

I have used this on several websites of mine. At the last company I worked for, I could use it and choose a user. Their webpage would then be mirrored for 5 minutes. It was a small company and it got a lot of laughs. I have used it to toggle development mode, show/hide settings, or even pair this with and Angular Can Activate Guard and disallow routes that haven't had the code put in.

Service

import { isPlatformBrowser } from '@angular/common';
import {
  EventEmitter,
  inject,
  Injectable,
  Output,
  PLATFORM_ID,
} from '@angular/core';

@Injectable({ providedIn: 'root' })
export class KonamiService {
  #inputSequence: Array<string> = [];
  #konamiCode: Array<string> = [
    'ArrowUp',
    'ArrowUp',
    'ArrowDown',
    'ArrowDown',
    'ArrowLeft',
    'ArrowRight',
    'ArrowLeft',
    'ArrowRight',
    'b',
    'a',
  ];
  #platformId: {} = inject(PLATFORM_ID);
  #successful: boolean = false;

  get successful(): boolean {
    return this.#successful;
  }

  @Output() konamiCodeActivated = new EventEmitter<void>();

  constructor() {
    this.initialize();
  }

  initialize() {
    if (isPlatformBrowser(this.#platformId)) {
      this.#addWindowKeydownHandler();
    }
  }

  destroy() {
    this.#removeWindowKeydownHandler();
  }

  #addWindowKeydownHandler() {
    window.addEventListener(
      'keydown',
      this.#handleWindowKeydownEvent.bind(this)
    );
  }

  #removeWindowKeydownHandler() {
    window.removeEventListener(
      'keydown',
      this.#handleWindowKeydownEvent.bind(this)
    );
  }

  #handleWindowKeydownEvent(event: KeyboardEvent) {
    this.#inputSequence.push(event.key);

    if (this.#inputSequence.length > this.#konamiCode.length) {
      this.#inputSequence.shift();
    }

    const inputArray = this.#inputSequence.join(',');
    const konamiArray = this.#konamiCode.join(',');

    if (inputArray === konamiArray) {
      this.konamiCodeActivated.emit();
      this.#inputSequence = [];
      this.#successful = true;
    } else {
      this.#successful = false;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Guard (Optional)

import { KonamiService } from '$shared/services/konami.service';
import { inject, Injectable } from '@angular/core';
import { CanActivate, GuardResult, MaybeAsync } from '@angular/router';
import { map, take } from 'rxjs';

@Injectable({ providedIn: 'root' })
export class KonamiGuard implements CanActivate {
  #konamiService: KonamiService = inject(KonamiService);

  canActivate(): MaybeAsync<GuardResult> {
    if (this.#konamiService.successful) {
      return true;
    } else {
      return false;
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

Use

import { Component, inject, OnDestroy, OnInit } from '@angular/core';
import { Subscription } from 'rxjs';
import { KonamiService } from '$shared/services/konami.service';

@Component({
  selector: 'app-home-route',
  templateUrl: 'home.page.html',
  styleUrl: 'home.page.scss',
})
export class HomePage implements OnInit, OnDestroy {
  #konamiService: KonamiService = inject(KonamiService);
  #subs: Array<Subscription> = [];

  ngOnInit() {
    this.#subs = [
      ...this.#subs,
      this.#konamiService.konamiCodeActivated.subscribe(() => {
        // DO SOMETHING HERE
      }),
    ];
  }

  ngOnDestroy() {
    this.#subs.forEach((sub) => sub.unsubscribe);
  }
}
Enter fullscreen mode Exit fullscreen mode

SurveyJS custom survey software

JavaScript UI Libraries for Surveys and Forms

SurveyJS lets you build a JSON-based form management system that integrates with any backend, giving you full control over your data and no user limits. Includes support for custom question types, skip logic, integrated CCS editor, PDF export, real-time analytics & more.

Learn more

Top comments (0)

nextjs tutorial video

Youtube Tutorial Series 📺

So you built a Next.js app, but you need a clear view of the entire operation flow to be able to identify performance bottlenecks before you launch. But how do you get started? Get the essentials on tracing for Next.js from @nikolovlazar in this video series 👀

Watch the Youtube series

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay