tengri/Content/Toasts/Components/AC_ToastSystem.ts

287 lines
9.0 KiB
TypeScript

// Toasts/Components/AC_ToastSystem.ts
import type { S_ToastMessage } from '#root/Toasts/Structs/S_ToastMessage.ts';
import type { WBP_Toast } from '#root/Toasts/UI/WBP_Toast.ts';
import { WBP_ToastContainer } from '#root/Toasts/UI/WBP_ToastContainer.ts';
import { ActorComponent } from '#root/UE/ActorComponent.ts';
import { CreateWidget } from '#root/UE/CteateWidget.ts';
import type { Float } from '#root/UE/Float.ts';
import type { Integer } from '#root/UE/Integer.ts';
import { SystemLibrary } from '#root/UE/SystemLibrary.ts';
import type { Text } from '#root/UE/Text.ts';
import { UEArray } from '#root/UE/UEArray.ts';
import { E_MessageType } from '#root/UI/Enums/E_MessageType.ts';
/**
* Toast Notification System Component
* Manages temporary status messages with automatic positioning and lifecycle
* Provides visual feedback for debug operations and system events
*/
export class AC_ToastSystem extends ActorComponent {
// ════════════════════════════════════════════════════════════════════════════════════════
// FUNCTIONS
// ════════════════════════════════════════════════════════════════════════════════════════
/**
* Check if toast system should process updates this frame
* @returns True if system is initialized and enabled
* @pure
* @category Toast Management
*/
private ShouldProcessToasts(): boolean {
/**
* Validate system state and settings
*/
return this.IsInitialized && this.IsEnabled;
}
/**
* Remove expired toasts from the system
* @category Toast Lifecycle
*/
private RemoveExpiredToasts(): void {
let i = 0;
/**
* Check if there are more toasts to process
*/
const HasMoreToastsToCheck = (activeToastsLength: Integer): boolean =>
i < activeToastsLength;
while (HasMoreToastsToCheck(this.ActiveToasts.length)) {
/**
* Check if toast has exceeded its display duration
*/
const IsToastExpired = (
currentTime: Float,
createdTime: Float,
duration: Float
): boolean => currentTime - createdTime > duration;
const el = this.ActiveToasts.Get(i);
if (
IsToastExpired(
SystemLibrary.GetGameTimeInSeconds(),
el.CreatedTime,
el.Duration
)
) {
const widget = this.ToastWidgets.Get(i);
if (SystemLibrary.IsValid(widget)) {
if (SystemLibrary.IsValid(this.ToastContainer)) {
this.ToastContainer.RemoveToast(widget);
}
}
this.ActiveToasts.RemoveIndex(i);
this.ToastWidgets.RemoveIndex(i);
} else {
i++;
}
}
}
/**
* Enforce maximum visible toasts limit
* Removes oldest toasts when limit is exceeded
* @category Toast Lifecycle
*/
private EnforceToastLimit(): void {
/**
* Check if current toast count exceeds maximum allowed
*/
const ExceedsToastLimit = (
activeToastsLength: Integer,
maxVisibleToasts: Integer
): boolean => activeToastsLength >= maxVisibleToasts;
while (ExceedsToastLimit(this.ActiveToasts.length, this.MaxVisibleToasts)) {
const widget = this.ToastWidgets.Get(0);
if (SystemLibrary.IsValid(widget)) {
if (SystemLibrary.IsValid(this.ToastContainer)) {
this.ToastContainer.RemoveToast(widget);
}
}
this.ActiveToasts.RemoveIndex(0);
this.ToastWidgets.RemoveIndex(0);
}
}
/**
* Create and display a new toast message
* @param Message - Text to display in the toast
* @param Type - Type of toast (affects color and styling)
* @param Duration - How long to display toast (optional, uses default)
* @returns Toast ID for tracking
* @example
* // Create success toast
* ShowToast("Test passed!", E_MessageType.Success, 2.0)
* // Create error toast with default duration
* ShowToast("Test failed!", E_MessageType.Error)
* @category Toast Creation
*/
public ShowToast(
Message: Text = '',
Type: E_MessageType = E_MessageType.Info,
Duration: Float = 5
): Integer {
if (this.ShouldProcessToasts()) {
const currentTime = SystemLibrary.GetGameTimeInSeconds();
const newToast: S_ToastMessage = {
ID: this.NextToastID++,
Message,
Type,
Duration,
CreatedTime: currentTime,
};
this.EnforceToastLimit();
if (SystemLibrary.IsValid(this.ToastContainer)) {
const toastWidget = this.ToastContainer.AddToast(Message, Type);
if (SystemLibrary.IsValid(toastWidget)) {
this.ActiveToasts.Add(newToast);
this.ToastWidgets.Add(toastWidget);
this.LogToConsole(Type, Message);
return newToast.ID;
} else {
return -1;
}
}
}
this.LogToConsole(Type, Message);
return -1;
}
/**
* Main update loop for toast system
* Removes expired toasts automatically
* @category System Main Loop
*/
public UpdateToastSystem(): void {
if (this.ShouldProcessToasts()) {
this.RemoveExpiredToasts();
}
}
/**
* Get system state and configuration for testing purposes
* Provides read-only access to private configuration and active widgets
* @returns Object containing toast widgets array and system configuration
* @category Testing
*/
public GetTestData(): {
ToastWidgets: UEArray<WBP_Toast>;
MaxVisibleToasts: Integer;
IsEnabled: boolean;
} {
return {
ToastWidgets: this.ToastWidgets,
MaxVisibleToasts: this.MaxVisibleToasts,
IsEnabled: this.IsEnabled,
};
}
/**
* Initialize toast system with container widget
* @example
* // Initialize toast system in main character
* this.ToastSystemComponent.InitializeToastSystem();
* @category System Setup
*/
public InitializeToastSystem(): void {
this.ToastContainer = CreateWidget(WBP_ToastContainer);
this.ToastContainer.InitializeContainer();
this.IsInitialized = true;
this.NextToastID = 1;
}
/**
* Log toast message to console if enabled
* @param Type - Message type for formatting
* @param Message - Message text to log
* @category System Utilities
*/
public LogToConsole(Type: E_MessageType, Message: Text): void {
if (this.AlsoLogToConsole) {
SystemLibrary.PrintString(`[${Type}] ${Message}`, false);
}
}
// ════════════════════════════════════════════════════════════════════════════════════════
// VARIABLES
// ════════════════════════════════════════════════════════════════════════════════════════
/**
* Maximum number of simultaneously visible toast notifications
* When limit is exceeded, oldest toasts are automatically removed
* @default 5
* @range 1-10 recommended
* @category System Config
* @instanceEditable true
*/
private readonly MaxVisibleToasts: Integer = 5;
/**
* Duplicate all toast messages to console output for debugging
* Format: [MessageType] Message text
* @default true
* @recommendation Set false in production builds for performance
* @category System Config
* @instanceEditable true
*/
private readonly AlsoLogToConsole: boolean = true;
/**
* Master switch for the entire toast system
* When disabled: ShowToast() returns -1, widgets are not created
* LogToConsole still works if AlsoLogToConsole is true
* @default true
* @category System Config
* @instanceEditable true
*/
private readonly IsEnabled: boolean = true;
/**
* System initialization state flag
* Set to true after successful InitializeToastSystem call
* @category System State
*/
private IsInitialized: boolean = false;
/**
* Next unique ID for new toasts
* Incremented for each new toast
* @category System State
*/
private NextToastID: Integer = 1;
/**
* Toast container widget that handles positioning and layout
* @category Container Management
*/
private ToastContainer: WBP_ToastContainer | null = null;
/**
* Array of currently active toast messages
* Contains all visible toasts with metadata
* @category Toast Management
*/
private ActiveToasts: UEArray<S_ToastMessage> = new UEArray([]);
/**
* Array of toast widget instances
* Corresponds to ActiveToasts array for UI display
* @category Widget Management
*/
private ToastWidgets: UEArray<WBP_Toast> = new UEArray([]);
}