Leif/vibe jabroni at large#14
Conversation
There was a problem hiding this comment.
Pull Request Overview
This pull request adds window resizing functionality and introduces three new application windows (Launchpad, Notepad, and Tetris) to create a desktop-like interface with a dynamic dock system.
Key Changes
- Implemented a new
ResizableDirectiveto enable window resizing with 8-direction handles - Migrated window dimensions from plain properties to Angular signals for reactive state management
- Added three new windows: Launchpad (app launcher), Notepad (markdown editor), and Tetris (game)
- Introduced a dynamic dock that displays icons for open windows
Reviewed Changes
Copilot reviewed 23 out of 24 changed files in this pull request and generated 26 comments.
Show a summary per file
| File | Description |
|---|---|
| src/app/enums/window-types.enum.ts | Added new window types (LAUNCHPAD, NOTEPAD, TETRIS) to support new application windows |
| src/app/directives/resizable.directive.ts | New directive implementing 8-direction window resizing with dynamically created resize handles |
| src/app/directives/draggable.directive.ts | Enhanced to prevent drag conflicts with resize handles and added viewport boundary constraints |
| src/app/components/windows/tetris-window/* | New Tetris game component with full game logic, scoring, and level progression |
| src/app/components/windows/notepad-window/* | New markdown notepad component with live preview and basic markdown parsing |
| src/app/components/windows/launchpad-window/* | New launchpad component serving as an app launcher with icon grid |
| src/app/components/windows/float-window/* | Updated base component to use signals for width/height and added resize event handling |
| src/app/components/windows/settings-window/* | Updated to use signal-based dimensions and added resizable directive |
| src/app/components/windows/player-window/* | Updated to use signal-based dimensions and added resizable directive |
| src/app/components/windows/gallery-window/* | Updated to use signal-based dimensions and added resizable directive |
| src/app/components/main-view/* | Added dock management system that dynamically updates based on open windows |
| bun.lock | Added configVersion property to lock file |
| angular.json | Disabled analytics collection |
Comments suppressed due to low confidence (2)
src/app/directives/draggable.directive.ts:122
- The directive uses
@HostListenerdecorators which violates Angular best practices. According to the guidelines,@HostListenerand@HostBindingdecorators should not be used. Instead, host bindings should be placed inside thehostobject of the@Directivedecorator.
@HostListener('mousedown', ['$event'])
onMouseDown(event: MouseEvent) {
// Check if the mousedown event is on a resize handle - if so, don't drag
const target = event.target as HTMLElement;
if (target.className && typeof target.className === 'string' && target.className.includes('resize-handle')) {
return; // Don't drag if clicking on a resize handle
}
// Check if the mousedown event is on the drag handle (the header)
const handle = this.draggableElement.querySelector('.drag-handle');
if (handle && !handle.contains(event.target as Node)) {
return; // Don't drag if the click is not on the handle
}
// Bring the window to the front by setting a new z-index.
this.draggableElement.style.zIndex = this.zIndexManager.getNextZIndex().toString();
this.isDragging = true;
this.startX = event.clientX;
this.startY = event.clientY;
const transform = this.draggableElement.style.transform;
const translateMatch = transform.match(/translate\(([^,]+)px, ([^,]+)px\)/);
if (translateMatch) {
this.initialX = parseInt(translateMatch[1], 10);
this.initialY = parseInt(translateMatch[2], 10);
}
// this.draggableElement.style.cursor = 'grabbing';
event.preventDefault();
}
@HostListener('document:mousemove', ['$event'])
onMouseMove(event: MouseEvent) {
if (!this.isDragging) return;
const dx = event.clientX - this.startX;
const dy = event.clientY - this.startY;
// Calculate new position
let newX = this.initialX + dx;
let newY = this.initialY + dy;
// Get element dimensions
const elementRect = this.draggableElement.getBoundingClientRect();
const elementWidth = elementRect.width;
const elementHeight = elementRect.height;
// Get viewport dimensions
const viewportWidth = window.innerWidth;
const viewportHeight = window.innerHeight;
// Minimum visible area (in pixels) - keep at least 50px of the header visible
const minVisibleWidth = Math.min(elementWidth, 100);
const minVisibleHeight = 50;
// Constrain horizontal position
// Allow dragging left but keep some of the window visible on the right
const minX = -(elementWidth - minVisibleWidth);
// Allow dragging right but keep some of the window visible on the left
const maxX = viewportWidth - minVisibleWidth;
newX = Math.max(minX, Math.min(newX, maxX));
// Constrain vertical position
// Don't allow dragging above the top (keep header visible)
const minY = 0;
// Allow dragging down but keep some of the window visible at the top
const maxY = viewportHeight - minVisibleHeight;
newY = Math.max(minY, Math.min(newY, maxY));
this.draggableElement.style.transform = `translate(${newX}px, ${newY}px)`;
}
@HostListener('document:mouseup')
onMouseUp() {
src/app/components/main-view/main-view.component.ts:206
- Variable 'appType' is of type string, but it is compared to 'undefined' of type undefined.
if (appType && typeof appType === 'string' && appType !== undefined) {
| @HostListener('window:keydown', ['$event']) | ||
| handleKeyPress(event: KeyboardEvent) { | ||
| if (this.isGameOver() || this.isPaused()) return; | ||
|
|
||
| switch (event.key) { | ||
| case 'ArrowLeft': | ||
| event.preventDefault(); | ||
| this.movePiece(-1, 0); | ||
| break; | ||
| case 'ArrowRight': | ||
| event.preventDefault(); | ||
| this.movePiece(1, 0); | ||
| break; | ||
| case 'ArrowDown': | ||
| event.preventDefault(); | ||
| this.movePiece(0, 1); | ||
| break; | ||
| case 'ArrowUp': | ||
| case ' ': | ||
| event.preventDefault(); | ||
| this.rotatePiece(); | ||
| break; | ||
| case 'p': | ||
| case 'P': | ||
| event.preventDefault(); | ||
| this.togglePause(); | ||
| break; | ||
| } | ||
| } |
There was a problem hiding this comment.
The component uses @HostListener decorator which violates Angular best practices. According to the guidelines, @HostListener and @HostBinding decorators should not be used. Instead, host bindings should be placed inside the host object of the @Component decorator.
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
| <div appDraggable appResizable (windowResize)="onResize($event)" #elementWithDrag [style.width.px]="width()" [style.height.px]="height()" class="float-window"> | ||
|
|
||
| <!-- Header acts as the drag handle --> | ||
| <div class="drag-handle" [ngClass]="{'cursor-grab': !isDragging, 'cursor-grabbing': isDragging}" (mousedown)="isDragging = true" (mouseup)="isDragging = false"> |
There was a problem hiding this comment.
The template uses ngClass which violates Angular best practices. According to the guidelines, ngClass should not be used - use class bindings instead. Replace [ngClass]="{'cursor-grab': !isDragging, 'cursor-grabbing': isDragging}" with [class.cursor-grab]="!isDragging" [class.cursor-grabbing]="isDragging".
There was a problem hiding this comment.
@copilot open a new pull request to apply changes based on this feedback
|
|
||
| onAppClick(appType: WindowTypes) { | ||
| // Emit the app type through the close event emitter | ||
| this.closeEvent.emit(appType as any); |
There was a problem hiding this comment.
Using as any type assertion defeats TypeScript's type safety. Instead of casting to any, the proper solution is to either: 1) define a separate output event for app selection, or 2) modify the closeEvent emitter in FloatWindow to accept an optional parameter of type WindowTypes | void. The current implementation obscures the actual API contract.
| constructor(private sanitizer: DomSanitizer) { | ||
| super(); | ||
|
|
||
| this.title = 'Markdown Notepad'; | ||
| this.width.set(600); | ||
| this.height.set(500); | ||
| } |
There was a problem hiding this comment.
The component should use the inject() function instead of constructor injection for consistency with Angular modern practices. The DomSanitizer should be injected using inject() as demonstrated in the coding guidelines.
| @Component({ | ||
| selector: 'app-notepad-window', | ||
| imports: [CommonModule, DraggableDirective, FormsModule, MatIconModule, MatButtonModule, MatTooltipModule], | ||
| templateUrl: 'notepad-window.component.html', | ||
| styleUrls: ['notepad-window.component.scss'] | ||
| }) |
There was a problem hiding this comment.
The component should set changeDetection: ChangeDetectionStrategy.OnPush in the @Component decorator according to Angular best practices. This is especially important for components using signals, as it improves performance by leveraging Angular's signal-based change detection.
| } | ||
|
|
||
| private updateDockItems() { | ||
| const currentDockItems = this.dockItems(); |
There was a problem hiding this comment.
Unused variable currentDockItems.
| const currentDockItems = this.dockItems(); |
| @@ -1,23 +1,39 @@ | |||
| import { CommonModule } from '@angular/common'; | |||
| import { Component, EventEmitter, Input, Output, ViewChild } from '@angular/core'; | |||
| import { Component, EventEmitter, Input, Output, ViewChild, signal, effect } from '@angular/core'; | |||
There was a problem hiding this comment.
Unused import effect.
| import { Component, EventEmitter, Input, Output, ViewChild, signal, effect } from '@angular/core'; | |
| import { Component, EventEmitter, Input, Output, ViewChild, signal } from '@angular/core'; |
| import { DraggableDirective } from '../../../directives/draggable.directive'; | ||
| import { CommonModule } from '@angular/common'; | ||
| import { FormsModule } from '@angular/forms'; | ||
| import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; |
There was a problem hiding this comment.
Unused import SafeHtml.
| import { DomSanitizer, SafeHtml } from '@angular/platform-browser'; | |
| import { DomSanitizer } from '@angular/platform-browser'; |
| const elementHeight = elementRect.height; | ||
|
|
There was a problem hiding this comment.
Unused variable elementHeight.
| const elementHeight = elementRect.height; |
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Leif/vibe jabroni at large (#14) * Add vibe code * Add code to use launchpad and active applets * Update src/app/components/main-view/main-view.component.ts Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --------- Co-authored-by: 0xLeif <leif.algo@pm.me> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> * Enhances UI with login and theming features Adds a login prompt component for user authentication and improves the application's visual appeal by introducing a theme switcher, and new theme options. Also includes refactoring of the main view and gallery window components for better aesthetics and usability. The addition of CommonJS dependencies addresses compatibility issues. --------- Co-authored-by: 0xLeif <leif.algo@pm.me> Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* New Design WIP
Creation of a desktop look & feel for the website and new components
* Enhances UI with Material Design and new theme
Adds Angular Material for improved UI components and introduces a new dark theme ("Raven's Shadow") for a more modern look.
The changes include:
- Installation of Angular Material and CDK
- Creation of a new scss file for dark theme variables
- Implementation of a macOS-style dock for accessing key application features.
- Introduction of dynamic window positioning to prevent overlap.
These enhancements provide a better user experience and a more visually appealing interface.
* Improves site theming and UI structure
Refactors the site to use Angular Material theming, providing light, dark, and custom themes.
Introduces a theme switcher component for easy theme selection.
Updates the main view and floating window components to leverage the new theme structure.
Adds a SoundCloud player component.
* Enhances theming and adds authentication
Improves theming capabilities by adding a black and orange theme with custom CSS variables and improves theme switching.
Implements user authentication by introducing a login prompt
(still only mocked)
* Integrates Pera Wallet for authentication
Replaces username/password authentication with Pera Wallet Connect.
Adds a login prompt component that uses Pera Wallet to connect to user's account and authenticate using Algorand.
The user's account address is stored in memory to manage sessions.
Adds handling of wallet connection, disconnection and reconnection on app init.
Includes polyfills and dependencies required to run Pera Wallet in the browser.
* Enhances draggable directive with viewport constraints
Improves the draggable directive to constrain elements within the viewport, ensuring the drag handle remains visible.
Adds a development-only login bypass button for easier testing.
* Gaspar/vibe jabronii (#17)
* Leif/vibe jabroni at large (#14)
* Add vibe code
* Add code to use launchpad and active applets
* Update src/app/components/main-view/main-view.component.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enhances UI with login and theming features
Adds a login prompt component for user authentication and improves the application's visual appeal by introducing a theme switcher, and new theme options.
Also includes refactoring of the main view and gallery window components for better aesthetics and usability.
The addition of CommonJS dependencies addresses compatibility issues.
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Refactors codebase to use modern Angular practices
Modernizes the application by adopting Angular's recommended best practices, including:
- Uses `input()` and `output()` functions instead of decorators for component inputs and outputs.
- Introduces signals for component state management.
- Updates `MainViewComponent` to use `setInput` for dynamic component creation.
- Deletes obsolete `README.md` and `.claude/CLAUDE.md` files and replaces them with new versions providing improved documentation.
* Improves window resizing from north/west directions
Fixes an issue where resizing windows from the north or west
directions would not maintain the window's position correctly.
The resizable directive now calculates and emits the absolute
position (translate values) along with the new dimensions
during a resize event.
The draggable directive has been updated with an adjustPosition
method that updates the element's transform and internal state
to reflect this new position.
This allows the window to maintain its visual position
while being resized.
* Replaces Material UI with NES.css styling
Migrates the UI components to utilize a pixel-art style through NES.css and a custom icon font.
This commit removes Material UI dependencies and restructures components like the login prompt and main view to align with the new aesthetic.
Adds a pixel-art style guide and a generic icon component for consistency.
Font files are added to public folder.
* Implements initial site structure and styling
Sets up the basic structure for the new website, including:
- Configures Tailwind CSS for styling
- Adds basic page layout and windowing system
Includes initial implementation of a basic pixel art icon set and other styling elements
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* New Design WIP
Creation of a desktop look & feel for the website and new components
* Enhances UI with Material Design and new theme
Adds Angular Material for improved UI components and introduces a new dark theme ("Raven's Shadow") for a more modern look.
The changes include:
- Installation of Angular Material and CDK
- Creation of a new scss file for dark theme variables
- Implementation of a macOS-style dock for accessing key application features.
- Introduction of dynamic window positioning to prevent overlap.
These enhancements provide a better user experience and a more visually appealing interface.
* Improves site theming and UI structure
Refactors the site to use Angular Material theming, providing light, dark, and custom themes.
Introduces a theme switcher component for easy theme selection.
Updates the main view and floating window components to leverage the new theme structure.
Adds a SoundCloud player component.
* Enhances theming and adds authentication
Improves theming capabilities by adding a black and orange theme with custom CSS variables and improves theme switching.
Implements user authentication by introducing a login prompt
(still only mocked)
* Integrates Pera Wallet for authentication
Replaces username/password authentication with Pera Wallet Connect.
Adds a login prompt component that uses Pera Wallet to connect to user's account and authenticate using Algorand.
The user's account address is stored in memory to manage sessions.
Adds handling of wallet connection, disconnection and reconnection on app init.
Includes polyfills and dependencies required to run Pera Wallet in the browser.
* Enhances draggable directive with viewport constraints
Improves the draggable directive to constrain elements within the viewport, ensuring the drag handle remains visible.
Adds a development-only login bypass button for easier testing.
* Gaspar/vibe jabronii (#17)
* Leif/vibe jabroni at large (#14)
* Add vibe code
* Add code to use launchpad and active applets
* Update src/app/components/main-view/main-view.component.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enhances UI with login and theming features
Adds a login prompt component for user authentication and improves the application's visual appeal by introducing a theme switcher, and new theme options.
Also includes refactoring of the main view and gallery window components for better aesthetics and usability.
The addition of CommonJS dependencies addresses compatibility issues.
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Refactors codebase to use modern Angular practices
Modernizes the application by adopting Angular's recommended best practices, including:
- Uses `input()` and `output()` functions instead of decorators for component inputs and outputs.
- Introduces signals for component state management.
- Updates `MainViewComponent` to use `setInput` for dynamic component creation.
- Deletes obsolete `README.md` and `.claude/CLAUDE.md` files and replaces them with new versions providing improved documentation.
* Improves window resizing from north/west directions
Fixes an issue where resizing windows from the north or west
directions would not maintain the window's position correctly.
The resizable directive now calculates and emits the absolute
position (translate values) along with the new dimensions
during a resize event.
The draggable directive has been updated with an adjustPosition
method that updates the element's transform and internal state
to reflect this new position.
This allows the window to maintain its visual position
while being resized.
* Replaces Material UI with NES.css styling
Migrates the UI components to utilize a pixel-art style through NES.css and a custom icon font.
This commit removes Material UI dependencies and restructures components like the login prompt and main view to align with the new aesthetic.
Adds a pixel-art style guide and a generic icon component for consistency.
Font files are added to public folder.
* Implements initial site structure and styling
Sets up the basic structure for the new website, including:
- Configures Tailwind CSS for styling
- Adds basic page layout and windowing system
Includes initial implementation of a basic pixel art icon set and other styling elements
* Gaspar/new site (#19)
* New Design WIP
Creation of a desktop look & feel for the website and new components
* Enhances UI with Material Design and new theme
Adds Angular Material for improved UI components and introduces a new dark theme ("Raven's Shadow") for a more modern look.
The changes include:
- Installation of Angular Material and CDK
- Creation of a new scss file for dark theme variables
- Implementation of a macOS-style dock for accessing key application features.
- Introduction of dynamic window positioning to prevent overlap.
These enhancements provide a better user experience and a more visually appealing interface.
* Improves site theming and UI structure
Refactors the site to use Angular Material theming, providing light, dark, and custom themes.
Introduces a theme switcher component for easy theme selection.
Updates the main view and floating window components to leverage the new theme structure.
Adds a SoundCloud player component.
* Enhances theming and adds authentication
Improves theming capabilities by adding a black and orange theme with custom CSS variables and improves theme switching.
Implements user authentication by introducing a login prompt
(still only mocked)
* Integrates Pera Wallet for authentication
Replaces username/password authentication with Pera Wallet Connect.
Adds a login prompt component that uses Pera Wallet to connect to user's account and authenticate using Algorand.
The user's account address is stored in memory to manage sessions.
Adds handling of wallet connection, disconnection and reconnection on app init.
Includes polyfills and dependencies required to run Pera Wallet in the browser.
* Enhances draggable directive with viewport constraints
Improves the draggable directive to constrain elements within the viewport, ensuring the drag handle remains visible.
Adds a development-only login bypass button for easier testing.
* Gaspar/vibe jabronii (#17)
* Leif/vibe jabroni at large (#14)
* Add vibe code
* Add code to use launchpad and active applets
* Update src/app/components/main-view/main-view.component.ts
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Enhances UI with login and theming features
Adds a login prompt component for user authentication and improves the application's visual appeal by introducing a theme switcher, and new theme options.
Also includes refactoring of the main view and gallery window components for better aesthetics and usability.
The addition of CommonJS dependencies addresses compatibility issues.
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Refactors codebase to use modern Angular practices
Modernizes the application by adopting Angular's recommended best practices, including:
- Uses `input()` and `output()` functions instead of decorators for component inputs and outputs.
- Introduces signals for component state management.
- Updates `MainViewComponent` to use `setInput` for dynamic component creation.
- Deletes obsolete `README.md` and `.claude/CLAUDE.md` files and replaces them with new versions providing improved documentation.
* Improves window resizing from north/west directions
Fixes an issue where resizing windows from the north or west
directions would not maintain the window's position correctly.
The resizable directive now calculates and emits the absolute
position (translate values) along with the new dimensions
during a resize event.
The draggable directive has been updated with an adjustPosition
method that updates the element's transform and internal state
to reflect this new position.
This allows the window to maintain its visual position
while being resized.
* Replaces Material UI with NES.css styling
Migrates the UI components to utilize a pixel-art style through NES.css and a custom icon font.
This commit removes Material UI dependencies and restructures components like the login prompt and main view to align with the new aesthetic.
Adds a pixel-art style guide and a generic icon component for consistency.
Font files are added to public folder.
* Implements initial site structure and styling
Sets up the basic structure for the new website, including:
- Configures Tailwind CSS for styling
- Adds basic page layout and windowing system
Includes initial implementation of a basic pixel art icon set and other styling elements
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
* Adjusts bundle size budget and font loading
Updates the bundle size budget to accommodate the current application size and prevent false warnings/errors.
Adds information about bundle size, large dependencies, and future optimization options to the documentation.
Removes the pixelart-icons font from `index.html` and includes it via `angular.json` for better build management.
* Adds user account section to settings
Implements the user account section within the settings window, providing information about the user's login status and wallet address.
Enables the passing of authentication and user address information to the settings window.
* Enhances app with user authentication overlay
Adds a boot overlay with progress animation, and a login overlay
to enhance the user experience. Migrates the Login Window to an overlay.
Includes new sound effects and a service to manage them, with a setting
to toggle click sounds.
Updates the Main View to manage login state and overlay visibility.
Improves theming by integrating Tailwind CSS variables and utility classes,
modernizing the app's appearance.
Adds a Navbar component and integrates it into About and Mono windows.
Minor bug fixes and UI tweaks included.
* Enhances user settings and asset handling
Refactors asset loading and user settings persistence.
- Implements lazy loading for algosdk in `AssetService` to improve initial load time, trading off initial delay for blockchain features.
- Introduces volume control in settings and persists in local storage.
- Introduces `UserService` and API endpoints for saving user settings to Corvid NFTs.
---------
Co-authored-by: 0xLeif <leif.algo@pm.me>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
No description provided.